pgadmin3/schema/pgEventTrigger.cpp
lsv cb11507b4f fix issues #30
Это была непонятная реализация самих разработчиков.
Там есть и другие не понятные для меня решения, к примеру
нет явного указания ENABLE [ REPLICA | ALWAYS ].
2022-10-15 14:23:15 +05:00

350 lines
No EOL
11 KiB
C++

//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// pgEventTrigger.cpp - EventTrigger class
//
//////////////////////////////////////////////////////////////////////////
// wxWindows headers
#include <wx/wx.h>
// App headers
#include "pgAdmin3.h"
#include "frm/frmMain.h"
#include "utils/misc.h"
#include "schema/pgEventTrigger.h"
#include "schema/pgFunction.h"
#include "schema/pgSchema.h"
pgEventTrigger::pgEventTrigger(const wxString &newName)
: pgDatabaseObject(eventTriggerFactory, newName)
{
eventTriggerFunction = 0;
eventTriggerFunctionSchema = 0;
}
pgEventTrigger::~pgEventTrigger()
{
if (!expandedKids && eventTriggerFunction)
{
// eventTriggerFunction wasn't appended to tree, so we need to delete it manually.
delete eventTriggerFunction;
}
delete eventTriggerFunctionSchema;
}
pgCollection *pgEventTriggerFactory::CreateCollection(pgObject *obj)
{
return new pgEventTriggerCollection(GetCollectionFactory(), (pgDatabase *)obj);
}
pgObject *pgEventTriggerFactory::CreateObjects(pgCollection *collection, ctlTree *browser, const wxString &restriction)
{
wxString sql;
pgEventTrigger *eventTrigger = 0;
sql = wxT("SELECT e.oid, e.xmin, e.evtname AS name, e.evtevent AS eventname, pg_catalog.pg_get_userbyid(e.evtowner) AS eventowner, ")
wxT(" CASE e.evtenabled WHEN 'O' THEN 'enabled' WHEN 'R' THEN 'replica' WHEN 'A' THEN 'always' WHEN 'D' THEN 'disabled' END AS enabled, ")
wxT(" e.evtfoid AS eventfuncoid, e.evtfoid::regproc AS eventfunname, array_to_string(array(select quote_literal(x) from unnest(evttags) as t(x)), ', ') AS when, ")
wxT(" pg_catalog.obj_description(e.oid, 'pg_event_trigger') AS comment, ")
wxT(" p.prosrc AS source, p.pronamespace AS schemaoid, l.lanname AS language")
wxT(" FROM pg_event_trigger e\n")
wxT(" LEFT OUTER JOIN pg_proc p ON p.oid=e.evtfoid\n")
wxT(" LEFT OUTER JOIN pg_language l ON l.oid=p.prolang\n")
wxT(" WHERE 1=1 ");
if (!restriction.IsEmpty())
sql += restriction + wxT("\n");
sql += wxT(" ORDER BY e.evtname ");
pgSet *eventTriggers = collection->GetDatabase()->ExecuteSet(sql);
if (eventTriggers)
{
while (!eventTriggers->Eof())
{
eventTrigger = new pgEventTrigger(eventTriggers->GetVal(wxT("name")));
eventTrigger->iSetDatabase(collection->GetDatabase());
eventTrigger->iSetOid(eventTriggers->GetOid(wxT("oid")));
eventTrigger->iSetXid(eventTriggers->GetOid(wxT("xmin")));
eventTrigger->iSetOwner(eventTriggers->GetVal(wxT("eventowner")));
eventTrigger->iSetFunctionOid(eventTriggers->GetOid(wxT("eventfuncoid")));
eventTrigger->iSetLanguage(eventTriggers->GetVal(wxT("language")));
eventTrigger->iSetSource(eventTriggers->GetVal(wxT("source")));
eventTrigger->iSetEventName(eventTriggers->GetVal(wxT("eventname")));
eventTrigger->iSetFunction(eventTriggers->GetVal(wxT("eventfunname")));
(eventTriggers->GetVal(wxT("enabled")) == wxT("disabled")) ? eventTrigger->iSetEnabled(false), eventTrigger->iSetEnableStatus(wxT("disabled"))
: eventTrigger->iSetEnabled(true), eventTrigger->iSetEnableStatus(eventTriggers->GetVal(wxT("enabled")));
eventTrigger->iSetComment(eventTriggers->GetVal(wxT("comment")));
eventTrigger->iSetWhen(eventTriggers->GetVal(wxT("when")));
eventTrigger->iSetSchemaOid(eventTriggers->GetOid(wxT("schemaoid")));
if (browser)
{
browser->AppendObject(collection, eventTrigger);
eventTriggers->MoveNext();
}
else
break;
}
delete eventTriggers;
}
return eventTrigger;
}
pgObject *pgEventTrigger::Refresh(ctlTree *browser, const wxTreeItemId item)
{
pgObject *eventTrigger = 0;
pgCollection *coll = browser->GetParentCollection(item);
if (coll)
{
wxString restr = wxT(" \n AND e.oid = ") + GetOidStr();
eventTrigger = eventTriggerFactory.CreateObjects(coll, 0, restr);
}
return eventTrigger;
}
void pgEventTrigger::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane)
{
if (!expandedKids && GetLanguage() != wxT("edbspl") && GetLanguage() != wxT("sql"))
{
if (browser)
{
// if no browser present, function will not be appended to tree
expandedKids = true;
}
if (eventTriggerFunction)
delete eventTriggerFunction;
wxString restr = wxT(" WHERE nsp.oid= ") + NumToStr(GetSchemaOid()) + wxT("::oid\n");
eventTriggerFunctionSchema = (pgSchema *)schemaFactory.CreateObjects((pgCollection *)browser->GetObject(GetId()), 0, restr);
// append function here
eventTriggerFunction = functionFactory.AppendFunctions(this, eventTriggerFunctionSchema, browser, wxT(" WHERE pr.oid = ") + NumToStr(functionOid) + wxT("::oid\n"));
if (eventTriggerFunction)
{
iSetFunction(eventTriggerFunction->GetQuotedFullIdentifier());
}
}
if (properties)
{
CreateListColumns(properties);
properties->AppendItem(_("Name"), GetName());
properties->AppendItem(_("OID"), GetOid());
properties->AppendItem(_("Event"), GetEventName());
properties->AppendItem(_("Function"), GetFunction());
properties->AppendItem(_("When?"), GetWhen());
properties->AppendItem(_("Enabled?"), GetEnabled() ? wxT("Yes") : wxT("No"));
properties->AppendItem(_("Comment"), firstLineOnly(GetComment()));
}
}
void pgEventTrigger::SetDirty()
{
if (expandedKids)
eventTriggerFunction = 0;
pgObject::SetDirty();
}
wxString pgEventTrigger::GetSql(ctlTree *browser)
{
if (sql.IsNull() && (this->eventTriggerFunction))
{
sql = wxT("-- Event Trigger: ") + qtIdent(GetName()) + wxT(" on database ")
+ qtIdent(((pgCollection *)browser->GetObject(GetId()))->GetDatabase()->GetName()) + wxT("\n\n")
+ wxT("-- DROP EVENT TRIGGER ") + qtIdent(GetName()) + wxT(";\n\n");
sql += wxT("CREATE EVENT TRIGGER ") + qtIdent(GetName()) + wxT(" ON ")
+ GetEventName() + (GetWhen().IsEmpty() ? wxT("") : (wxT(" WHEN TAG IN (") + GetWhen() + wxT(")\n\n")));
// Event trigger backend function don't accept any arguments.
// Hence, it's not required to get/set empty arguments.
sql += wxT(" EXECUTE PROCEDURE ") + eventTriggerFunction->GetQuotedFullIdentifier() + wxT("();\n\n");
if (!GetEnabled())
{
sql += wxT("ALTER EVENT TRIGGER ") + qtIdent(GetName()) + wxT(" DISABLE;\n");
}
if (!GetComment().IsEmpty())
sql += wxT("COMMENT ON EVENT TRIGGER ") + qtIdent(GetName()) + wxT(" IS ") + qtDbString(GetComment()) + wxT(";\n");
}
return sql;
}
wxString pgEventTrigger::GetTranslatedMessage(int kindOfMessage) const
{
wxString message = wxEmptyString;
switch (kindOfMessage)
{
case RETRIEVINGDETAILS:
message = _("Retrieving details on event trigger");
message += wxT(" ") + GetName();
break;
case REFRESHINGDETAILS:
message = _("Refreshing event trigger");
message += wxT(" ") + GetName();
break;
case DROPCASCADETITLE:
message = _("Drop event trigger cascaded?");
break;
case DROPTITLE:
message = _("Drop event trigger?");
break;
case DROPINCLUDINGDEPS:
message = wxString::Format(_("Are you sure you wish to drop event trigger \"%s\" including all objects that depend on it?"),
GetFullIdentifier().c_str());
break;
case DROPEXCLUDINGDEPS:
message = wxString::Format(_("Are you sure you wish to drop event trigger \"%s\"?"),
GetFullIdentifier().c_str());
break;
case PROPERTIESREPORT:
message = _("Event trigger properties report");
message += wxT(" - ") + GetName();
break;
case DDLREPORT:
message = _("Event trigger DDL report");
message += wxT(" - ") + GetName();
break;
case DDL:
message = _("Event trigger DDL");
break;
}
return message;
}
int pgEventTrigger::GetIconId()
{
if (GetEnabled())
return eventTriggerFactory.GetIconId();
else
return eventTriggerFactory.GetClosedIconId();
}
wxString pgEventTriggerCollection::GetTranslatedMessage(int kindOfMessage) const
{
wxString message = wxEmptyString;
switch (kindOfMessage)
{
case RETRIEVINGDETAILS:
message = _("Retrieving details on event triggers");
break;
case REFRESHINGDETAILS:
message = _("Refreshing event triggers");
break;
case OBJECTSLISTREPORT:
message = _("Event triggers list report");
break;
}
return message;
}
bool pgEventTrigger::DropObject(wxFrame *frame, ctlTree *browser, bool cascaded)
{
wxString sql = wxT("DROP EVENT TRIGGER ") + qtIdent(GetName());
if (cascaded)
sql += wxT(" CASCADE");
sql += wxT(" ;");
return GetDatabase()->ExecuteVoid(sql);
}
void pgEventTrigger::SetEnabled(ctlTree *browser, const bool b)
{
if (qtIdent(GetName()).Len() > 0 && ((enabled && !b) || (!enabled && b)))
{
wxString sql = wxT("ALTER EVENT TRIGGER ") + qtIdent(GetName()) ;
if (enabled && !b)
sql += wxT(" DISABLE");
else if (!enabled && b)
sql += wxT(" ENABLE");
GetDatabase()->ExecuteVoid(sql);
}
enabled = b;
UpdateIcon(browser);
}
bool pgEventTrigger::IsUpToDate()
{
wxString sql = wxT("SELECT xmin FROM pg_event_trigger WHERE oid = ") + this->GetOidStr();
if (!this->GetDatabase()->GetConnection() || this->GetDatabase()->ExecuteScalar(sql) != NumToStr(GetXid()))
return false;
else
return true;
}
/////////////////////////////
pgEventTriggerCollection::pgEventTriggerCollection(pgaFactory *factory, pgDatabase *db)
: pgDatabaseObjCollection(factory, db)
{
}
///////////////////////////////////////////////////
#include "images/trigger.pngc"
#include "images/triggerbad.pngc"
#include "images/triggers.pngc"
pgEventTriggerFactory::pgEventTriggerFactory()
: pgDatabaseObjFactory(__("Event Trigger"), __("New Event Trigger..."), __("Create a new Event Trigger."), trigger_png_img)
{
metaType = PGM_EVENTTRIGGER;
closedId = addIcon(triggerbad_png_img);
}
pgEventTriggerFactory eventTriggerFactory;
static pgaCollectionFactory cf(&eventTriggerFactory, __("Event Triggers"), triggers_png_img);
enabledisableEventTriggerFactory::enabledisableEventTriggerFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : contextActionFactory(list)
{
mnu->Append(id, _("Event trigger enabled?"), _("Enable or disable selected event trigger."), wxITEM_CHECK);
}
wxWindow *enabledisableEventTriggerFactory::StartDialog(frmMain *form, pgObject *obj)
{
((pgEventTrigger *)obj)->SetEnabled(form->GetBrowser(), !((pgEventTrigger *)obj)->GetEnabled());
((pgEventTrigger *)obj)->SetDirty();
wxTreeItemId item = form->GetBrowser()->GetSelection();
if (obj == form->GetBrowser()->GetObject(item))
{
form->GetBrowser()->DeleteChildren(item);
obj->ShowTreeDetail(form->GetBrowser(), 0, form->GetProperties());
form->GetSqlPane()->SetReadOnly(false);
form->GetSqlPane()->SetText(((pgEventTrigger *)obj)->GetSql(form->GetBrowser()));
form->GetSqlPane()->SetReadOnly(true);
}
form->GetMenuFactories()->CheckMenu(obj, form->GetMenuBar(), (ctlMenuToolbar *)form->GetToolBar());
return 0;
}
bool enabledisableEventTriggerFactory::CheckEnable(pgObject *obj)
{
return obj && obj->IsCreatedBy(eventTriggerFactory) && obj->CanEdit()
&& ((pgEventTrigger *)obj)->GetConnection()->BackendMinimumVersion(9, 3);
}
bool enabledisableEventTriggerFactory::CheckChecked(pgObject *obj)
{
return obj && obj->IsCreatedBy(eventTriggerFactory) && ((pgEventTrigger *)obj)->GetEnabled();
}