////////////////////////////////////////////////////////////////////////// // // 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 // 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(); }