mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-05-15 06:05:49 -06:00
356 lines
10 KiB
C++
356 lines
10 KiB
C++
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// pgAdmin III - PostgreSQL Tools
|
|
//
|
|
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
|
|
// This software is released under the PostgreSQL Licence
|
|
//
|
|
// pgRule.cpp - Rule class
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// wxWindows headers
|
|
#include <wx/wx.h>
|
|
|
|
// App headers
|
|
#include "pgAdmin3.h"
|
|
#include "frm/frmMain.h"
|
|
#include "utils/misc.h"
|
|
#include "schema/pgRule.h"
|
|
|
|
|
|
pgRule::pgRule(pgSchema *newSchema, const wxString &newName)
|
|
: pgRuleObject(newSchema, ruleFactory, newName)
|
|
{
|
|
}
|
|
|
|
pgRule::~pgRule()
|
|
{
|
|
}
|
|
|
|
wxString pgRule::GetTranslatedMessage(int kindOfMessage) const
|
|
{
|
|
wxString message = wxEmptyString;
|
|
|
|
switch (kindOfMessage)
|
|
{
|
|
case RETRIEVINGDETAILS:
|
|
message = _("Retrieving details on rule");
|
|
message += wxT(" ") + GetName();
|
|
break;
|
|
case REFRESHINGDETAILS:
|
|
message = _("Refreshing rule");
|
|
message += wxT(" ") + GetName();
|
|
break;
|
|
case GRANTWIZARDTITLE:
|
|
message = _("Privileges for rule");
|
|
message += wxT(" ") + GetName();
|
|
break;
|
|
case DROPINCLUDINGDEPS:
|
|
message = wxString::Format(_("Are you sure you wish to drop rule \"%s\" including all objects that depend on it?"),
|
|
GetFullIdentifier().c_str());
|
|
break;
|
|
case DROPEXCLUDINGDEPS:
|
|
message = wxString::Format(_("Are you sure you wish to drop rule \"%s\"?"),
|
|
GetFullIdentifier().c_str());
|
|
break;
|
|
case DROPCASCADETITLE:
|
|
message = _("Drop rule cascaded?");
|
|
break;
|
|
case DROPTITLE:
|
|
message = _("Drop rule?");
|
|
break;
|
|
case PROPERTIESREPORT:
|
|
message = _("Rule properties report");
|
|
message += wxT(" - ") + GetName();
|
|
break;
|
|
case PROPERTIES:
|
|
message = _("Rule properties");
|
|
break;
|
|
case DDLREPORT:
|
|
message = _("Rule DDL report");
|
|
message += wxT(" - ") + GetName();
|
|
break;
|
|
case DDL:
|
|
message = _("Rule DDL");
|
|
break;
|
|
case DEPENDENCIESREPORT:
|
|
message = _("Rule dependencies report");
|
|
message += wxT(" - ") + GetName();
|
|
break;
|
|
case DEPENDENCIES:
|
|
message = _("Rule dependencies");
|
|
break;
|
|
case DEPENDENTSREPORT:
|
|
message = _("Rule dependents report");
|
|
message += wxT(" - ") + GetName();
|
|
break;
|
|
case DEPENDENTS:
|
|
message = _("Rule dependents");
|
|
break;
|
|
}
|
|
|
|
return message;
|
|
}
|
|
|
|
|
|
int pgRule::GetIconId()
|
|
{
|
|
if (GetEnabled())
|
|
return ruleFactory.GetIconId();
|
|
else
|
|
return ruleFactory.GetClosedIconId();
|
|
}
|
|
|
|
|
|
bool pgRule::DropObject(wxFrame *frame, ctlTree *browser, bool cascaded)
|
|
{
|
|
wxString sql = wxT("DROP RULE ") + GetQuotedIdentifier() + wxT(" ON ") + GetQuotedFullTable();
|
|
if (cascaded)
|
|
sql += wxT(" CASCADE");
|
|
return GetDatabase()->ExecuteVoid(sql);
|
|
}
|
|
|
|
|
|
void pgRule::SetEnabled(ctlTree *browser, 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(" RULE ") + GetQuotedIdentifier();
|
|
GetDatabase()->ExecuteVoid(sql);
|
|
}
|
|
|
|
enabled = b;
|
|
UpdateIcon(browser);
|
|
}
|
|
|
|
|
|
wxString pgRule::GetSql(ctlTree *browser)
|
|
{
|
|
if (sql.IsNull())
|
|
{
|
|
sql = wxT("-- Rule: ") + GetQuotedIdentifier() + wxT(" ON ") + GetQuotedFullTable() + wxT("\n\n")
|
|
+ wxT("-- DROP RULE ") + GetQuotedIdentifier() + wxT(" ON ") + GetQuotedFullTable() + wxT(";\n\n")
|
|
+ wxT("CREATE OR REPLACE") + GetFormattedDefinition().Mid(6) // the backend pg_get_ruledef gives CREATE only
|
|
+ wxT("\n");
|
|
|
|
if (!GetEnabled())
|
|
{
|
|
sql += wxT("ALTER TABLE ") + GetQuotedFullTable() + wxT(" ")
|
|
+ wxT("DISABLE RULE ") + GetQuotedIdentifier() + wxT(";\n");
|
|
}
|
|
|
|
if (!GetComment().IsEmpty())
|
|
sql += wxT("COMMENT ON RULE ") + GetQuotedIdentifier() + wxT(" ON ") + GetQuotedFullTable()
|
|
+ wxT(" IS ") + qtDbString(GetComment()) + wxT(";\n");
|
|
}
|
|
return sql;
|
|
}
|
|
|
|
|
|
void pgRule::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane)
|
|
{
|
|
if (properties)
|
|
{
|
|
CreateListColumns(properties);
|
|
wxString def = GetFormattedDefinition();
|
|
if (!def.IsEmpty())
|
|
{
|
|
int doPos = def.Find(wxT(" DO INSTEAD "));
|
|
if (doPos > 0)
|
|
def = def.Mid(doPos + 12).Strip(wxString::both);
|
|
else
|
|
{
|
|
doPos = def.Find(wxT(" DO "));
|
|
if (doPos > 0)
|
|
def = def.Mid(doPos + 4).Strip(wxString::both);
|
|
}
|
|
}
|
|
|
|
properties->AppendItem(_("Name"), GetName());
|
|
properties->AppendItem(_("OID"), GetOid());
|
|
properties->AppendItem(_("Event"), GetEvent());
|
|
properties->AppendItem(_("Condition"), GetCondition());
|
|
properties->AppendYesNoItem(_("Do instead?"), GetDoInstead());
|
|
properties->AppendItem(_("Definition"), firstLineOnly(def));
|
|
if (this->GetDatabase()->connection()->BackendMinimumVersion(8, 3))
|
|
properties->AppendYesNoItem(_("Enabled?"), GetEnabled());
|
|
properties->AppendYesNoItem(_("System rule?"), GetSystemObject());
|
|
properties->AppendItem(_("Comment"), firstLineOnly(GetComment()));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pgObject *pgRule::Refresh(ctlTree *browser, const wxTreeItemId item)
|
|
{
|
|
pgObject *rule = 0;
|
|
pgCollection *coll = browser->GetParentCollection(item);
|
|
if (coll)
|
|
rule = ruleFactory.CreateObjects(coll, 0, wxT("\n AND rw.oid=") + GetOidStr());
|
|
|
|
return rule;
|
|
}
|
|
|
|
|
|
pgObject *pgRuleFactory::CreateObjects(pgCollection *collection, ctlTree *browser, const wxString &restriction)
|
|
{
|
|
pgRule *rule = 0;
|
|
|
|
pgSet *rules = collection->GetDatabase()->ExecuteSet(
|
|
wxT("SELECT rw.oid, rw.*, relname, CASE WHEN relkind = 'r' THEN TRUE ELSE FALSE END AS parentistable, nspname, description,\n")
|
|
wxT(" pg_get_ruledef(rw.oid") + collection->GetDatabase()->GetPrettyOption() + wxT(") AS definition\n")
|
|
wxT(" FROM pg_rewrite rw\n")
|
|
wxT(" JOIN pg_class cl ON cl.oid=rw.ev_class\n")
|
|
wxT(" JOIN pg_namespace nsp ON nsp.oid=cl.relnamespace\n")
|
|
wxT(" LEFT OUTER JOIN pg_description des ON (des.objoid=rw.oid AND des.classoid='pg_rewrite'::regclass)\n")
|
|
wxT(" WHERE ev_class = ") + NumToStr(collection->GetOid())
|
|
+ restriction + wxT("\n")
|
|
wxT(" ORDER BY rw.rulename"));
|
|
|
|
if (rules)
|
|
{
|
|
while (!rules->Eof())
|
|
{
|
|
// 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")));
|
|
|
|
if (collection->GetDatabase()->connection()->BackendMinimumVersion(8, 3))
|
|
{
|
|
if (rules->GetVal(wxT("ev_enabled")) != wxT("D"))
|
|
rule->iSetEnabled(true);
|
|
else
|
|
rule->iSetEnabled(false);
|
|
}
|
|
|
|
rule->iSetParentIsTable(rules->GetBool(wxT("parentistable")));
|
|
rule->iSetDoInstead(rules->GetBool(wxT("is_instead")));
|
|
rule->iSetAction(rules->GetVal(wxT("ev_action")));
|
|
wxString definition = rules->GetVal(wxT("definition"));
|
|
int doPos = definition.Find(wxT(" DO "));
|
|
int wherePos = definition.Find(wxT(" WHERE "));
|
|
if (wherePos > 0 && wherePos < doPos)
|
|
rule->iSetCondition(definition.Mid(wherePos + 7, doPos - wherePos - 7));
|
|
|
|
rule->iSetDefinition(definition);
|
|
rule->iSetQuotedFullTable(collection->GetDatabase()->GetQuotedSchemaPrefix(rules->GetVal(wxT("nspname")))
|
|
+ qtIdent(rules->GetVal(wxT("relname"))));
|
|
const wxChar *evts[] = {0, wxT("SELECT"), wxT("UPDATE"), wxT("INSERT"), wxT("DELETE")};
|
|
int evno = StrToLong(rules->GetVal(wxT("ev_type")));
|
|
if (evno > 0 && evno < 5)
|
|
rule->iSetEvent(evts[evno]);
|
|
else
|
|
rule->iSetEvent(wxT("Unknown"));
|
|
|
|
if (browser)
|
|
{
|
|
browser->AppendObject(collection, rule);
|
|
rules->MoveNext();
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
delete rules;
|
|
}
|
|
return rule;
|
|
}
|
|
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
pgRuleCollection::pgRuleCollection(pgaFactory *factory, pgSchema *sch)
|
|
: pgSchemaObjCollection(factory, sch)
|
|
{
|
|
}
|
|
|
|
|
|
wxString pgRuleCollection::GetTranslatedMessage(int kindOfMessage) const
|
|
{
|
|
wxString message = wxEmptyString;
|
|
|
|
switch (kindOfMessage)
|
|
{
|
|
case RETRIEVINGDETAILS:
|
|
message = _("Retrieving details on rules");
|
|
break;
|
|
case REFRESHINGDETAILS:
|
|
message = _("Refreshing rules");
|
|
break;
|
|
case OBJECTSLISTREPORT:
|
|
message = _("Rules list report");
|
|
break;
|
|
}
|
|
|
|
return message;
|
|
}
|
|
|
|
|
|
/////////////////////////////
|
|
|
|
#include "images/rule.pngc"
|
|
#include "images/rulebad.pngc"
|
|
#include "images/rules.pngc"
|
|
|
|
pgRuleFactory::pgRuleFactory()
|
|
: pgSchemaObjFactory(__("Rule"), __("New Rule..."), __("Create a new Rule."), rule_png_img)
|
|
{
|
|
metaType = PGM_RULE;
|
|
closedId = addIcon(rulebad_png_img);
|
|
}
|
|
|
|
|
|
pgCollection *pgRuleFactory::CreateCollection(pgObject *obj)
|
|
{
|
|
return new pgRuleCollection(GetCollectionFactory(), (pgSchema *)obj);
|
|
}
|
|
|
|
pgRuleFactory ruleFactory;
|
|
static pgaCollectionFactory cf(&ruleFactory, __("Rules"), rules_png_img);
|
|
|
|
|
|
enabledisableRuleFactory::enabledisableRuleFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : contextActionFactory(list)
|
|
{
|
|
mnu->Append(id, _("Rule enabled?"), _("Enable or disable selected rule."), wxITEM_CHECK);
|
|
}
|
|
|
|
|
|
wxWindow *enabledisableRuleFactory::StartDialog(frmMain *form, pgObject *obj)
|
|
{
|
|
((pgRule *)obj)->SetEnabled(form->GetBrowser(), !((pgRule *)obj)->GetEnabled());
|
|
((pgRule *)obj)->SetDirty();
|
|
|
|
wxTreeItemId item = form->GetBrowser()->GetSelection();
|
|
if (obj == form->GetBrowser()->GetObject(item))
|
|
{
|
|
obj->ShowTreeDetail(form->GetBrowser(), 0, form->GetProperties());
|
|
form->GetSqlPane()->SetReadOnly(false);
|
|
form->GetSqlPane()->SetText(((pgRule *)obj)->GetSql(form->GetBrowser()));
|
|
form->GetSqlPane()->SetReadOnly(true);
|
|
}
|
|
form->GetMenuFactories()->CheckMenu(obj, form->GetMenuBar(), (ctlMenuToolbar *)form->GetToolBar());
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
bool enabledisableRuleFactory::CheckEnable(pgObject *obj)
|
|
{
|
|
return obj && obj->IsCreatedBy(ruleFactory)
|
|
&& ((pgRule *)obj)->GetConnection()->BackendMinimumVersion(8, 3)
|
|
&& ((pgRule *)obj)->GetParentIsTable();
|
|
}
|
|
|
|
bool enabledisableRuleFactory::CheckChecked(pgObject *obj)
|
|
{
|
|
return obj && obj->IsCreatedBy(ruleFactory) && ((pgRule *)obj)->GetEnabled();
|
|
}
|