Index: pgObject.h =================================================================== RCS file: /projects/pgadmin3/src/include/pgObject.h,v retrieving revision 1.56 retrieving revision 1.57 diff -Lsrc/include/pgObject.h -Lsrc/include/pgObject.h -u -w -r1.56 -r1.57 --- src/include/pgObject.h +++ src/include/pgObject.h @@ -177,6 +177,8 @@ void iSetServer(pgServer *s) { server=s; } pgServer *GetServer() { return server; } + void FillOwned(wxTreeCtrl *browser, ctlListView *referencedBy, const wxArrayString &dblist, const wxString &query); + bool CanCreate(); bool CanDrop(); bool CanEdit() { return true; } Index: pgUser.h =================================================================== RCS file: /projects/pgadmin3/src/include/pgUser.h,v retrieving revision 1.20 retrieving revision 1.21 diff -Lsrc/include/pgUser.h -Lsrc/include/pgUser.h -u -w -r1.20 -r1.21 --- src/include/pgUser.h +++ src/include/pgUser.h @@ -51,6 +51,7 @@ int GetIcon() { return PGICON_USER; } void ShowTreeDetail(wxTreeCtrl *browser, frmMain *form=0, ctlListView *properties=0, ctlSQLBox *sqlPane=0); static pgObject *ReadObjects(pgCollection *collection, wxTreeCtrl *browser, const wxString &restriction=wxT("")); + void ShowReferencedBy(frmMain *form, ctlListView *referencedBy, const wxString &where); // virtual methods wxString GetSql(wxTreeCtrl *browser); Index: pgObject.cpp =================================================================== RCS file: /projects/pgadmin3/src/schema/pgObject.cpp,v retrieving revision 1.68 retrieving revision 1.69 diff -Lsrc/schema/pgObject.cpp -Lsrc/schema/pgObject.cpp -u -w -r1.68 -r1.69 --- src/schema/pgObject.cpp +++ src/schema/pgObject.cpp @@ -206,9 +206,11 @@ wxString typestr=set->GetVal(wxT("type")); int id; + bool dontQuote=false; switch (typestr.c_str()[0]) { + case 'c': case 's': // we don't know these; internally handled case 't': set->MoveNext(); continue; @@ -228,7 +230,7 @@ id=PG_RULE; break; } - case 'c': + case 'C': { switch (typestr.c_str()[1]) { @@ -304,7 +306,7 @@ wxT(" WHEN pr.oid IS NOT NULL THEN 'p'::text\n") wxT(" WHEN la.oid IS NOT NULL THEN 'l'::text\n") wxT(" WHEN rw.oid IS NOT NULL THEN 'R'::text\n") - wxT(" WHEN co.oid IS NOT NULL THEN 'c'::text || contype\n") + wxT(" WHEN co.oid IS NOT NULL THEN 'C'::text || contype\n") wxT(" ELSE '' END AS type,\n") wxT(" COALESCE(coc.relname, clrw.relname) AS ownertable,\n") wxT(" COALESCE(cl.relname, conname, proname, tgname, typname, lanname, rulename, ns.nspname) AS refname,\n") @@ -346,7 +348,7 @@ wxT(" WHEN pr.oid IS NOT NULL THEN 'p'::text\n") wxT(" WHEN la.oid IS NOT NULL THEN 'l'::text\n") wxT(" WHEN rw.oid IS NOT NULL THEN 'R'::text\n") - wxT(" WHEN co.oid IS NOT NULL THEN 'c'::text || contype\n") + wxT(" WHEN co.oid IS NOT NULL THEN 'C'::text || contype\n") wxT(" ELSE '' END AS type,\n") wxT(" COALESCE(coc.relname, clrw.relname) AS ownertable,\n") wxT(" COALESCE(cl.relname, conname, proname, tgname, typname, lanname, rulename, ns.nspname) AS refname,\n") @@ -618,6 +620,114 @@ } +void pgServerObject::FillOwned(wxTreeCtrl *browser, ctlListView *referencedBy, const wxArrayString &dblist, const wxString &query) +{ + pgCollection *databases; + + wxCookieType cookie; + wxTreeItemId item=browser->GetFirstChild(GetServer()->GetId(), cookie); + while (item) + { + databases = (pgCollection*)browser->GetItemData(item); + if (databases && databases->GetType() == PG_DATABASES) + break; + else + databases=0; + + item=browser->GetNextChild(GetServer()->GetId(), cookie); + } + + size_t i; + for (i=0 ; i < dblist.GetCount() ; i++) + { + wxString dbname=dblist.Item(i); + pgConn *conn=0; + pgConn *tmpConn=0; + + if (GetServer()->GetDatabaseName() == dbname) + conn = GetServer()->GetConnection(); + else + { + item=browser->GetFirstChild(databases->GetId(), cookie); + while (item) + { + pgDatabase *db=(pgDatabase*)browser->GetItemData(item); + if (db->GetType() == PG_DATABASE && db->GetName() == dbname) + { + if (db->GetConnected()) + conn = db->GetConnection(); + break; + } + item=browser->GetNextChild(databases->GetId(), cookie); + } + } + if (conn && conn->GetStatus() != PGCONN_OK) + conn=0; + + if (!conn) + { + tmpConn = new pgConn(GetServer()->GetName(), dbname, GetServer()->GetUsername(), + GetServer()->GetPassword(), GetServer()->GetPort(), GetServer()->GetSSL()); + if (tmpConn->GetStatus() == PGCONN_OK) + conn=tmpConn; + } + + if (conn) + { + pgSet *set=conn->ExecuteSet(query); + + if (set) + { + while (!set->Eof()) + { + int id=0; + + wxString relname = qtIdent(set->GetVal(wxT("nspname"))); + if (!relname.IsEmpty()) + relname += wxT("."); + relname += qtIdent(set->GetVal(wxT("relname"))); + + switch (set->GetVal(wxT("relkind")).c_str()[0]) + { + case 'r': id=PG_TABLE; break; + case 'i': id=PG_INDEX; + relname = qtIdent(set->GetVal(wxT("indname"))) + wxT(" ON ") + relname; + break; + case 'S': id=PG_SEQUENCE; break; + case 'v': id=PG_VIEW; break; + case 'c': // composite type handled in PG_TYPE + case 's': // special + case 't': // toast + break; + case 'n': id=PG_SCHEMA; break; + case 'y': id=PG_TYPE; break; + case 'd': id=PG_DOMAIN; break; + case 'C': id=PG_CONVERSION; break; + case 'p': id=PG_FUNCTION; break; + case 'T': id=PG_TRIGGERFUNCTION; break; + case 'o': id=PG_OPERATOR; + relname = set->GetVal(wxT("relname")); // unquoted + break; + } + + if (id) + { + wxString typname = typesList[id].typName; + int icon = typesList[id].typeIcon; + referencedBy->AppendItem(icon, typname, dbname, relname); + } + + set->MoveNext(); + } + delete set; + } + } + + if (tmpConn) + delete tmpConn; + } +} + ////////////////////////////////////////////////////////////// bool pgDatabaseObject::CanDrop() Index: pgUser.cpp =================================================================== RCS file: /projects/pgadmin3/src/schema/pgUser.cpp,v retrieving revision 1.33 retrieving revision 1.34 diff -Lsrc/schema/pgUser.cpp -Lsrc/schema/pgUser.cpp -u -w -r1.33 -r1.34 --- src/schema/pgUser.cpp +++ src/schema/pgUser.cpp @@ -18,7 +18,8 @@ #include "pgObject.h" #include "pgUser.h" #include "pgCollection.h" - +#include "frmMain.h" +#include "pgDefs.h" pgUser::pgUser(const wxString& newName) : pgServerObject(PG_USER, newName) @@ -82,6 +83,84 @@ } + +void pgUser::ShowReferencedBy(frmMain *form, ctlListView *referencedBy, const wxString &where) +{ + form->StartMsg(_(" Retrieving user owned objects")); + + referencedBy->ClearAll(); + referencedBy->AddColumn(_("Type"), 60); + referencedBy->AddColumn(_("Database"), 80); + referencedBy->AddColumn(_("Name"), 300); + + wxString uid=NumToStr(GetUserId()); + wxString sysoid = NumToStr(GetConnection()->GetLastSystemOID()); + + wxArrayString dblist; + + pgSet *set=GetConnection()->ExecuteSet( + wxT("SELECT 'd' as type, datname, datallowconn, datdba\n") + wxT(" FROM pg_database db\n") + wxT("UNION\n") + wxT("SELECT 'M', spcname, null, null\n") + wxT(" FROM pg_tablespace where spcowner=") + uid + wxT("\n") + wxT(" ORDER BY 1, 2")); + + if (set) + { + while (!set->Eof()) + { + wxString name=set->GetVal(wxT("datname")); + if (set->GetVal(wxT("type")) == wxT("d")) + { + if (set->GetBool(wxT("datallowconn"))) + dblist.Add(name); + if (GetUserId() == set->GetLong(wxT("datdba"))) + referencedBy->AppendItem(PGICON_DATABASE, _("Database"), name); + } + else + referencedBy->AppendItem(PGICON_TABLESPACE, _("Tablespace"), wxEmptyString, name); + + set->MoveNext(); + } + delete set; + } + + FillOwned(form->GetBrowser(), referencedBy, dblist, + wxT("SELECT cl.relkind, COALESCE(cin.nspname, cln.nspname) as nspname, COALESCE(ci.relname, cl.relname) as relname, ci.relname as indname\n") + wxT(" FROM pg_class cl\n") + wxT(" JOIN pg_namespace cln ON cl.relnamespace=cln.oid\n") + wxT(" LEFT OUTER JOIN pg_index ind ON ind.indexrelid=cl.oid\n") + wxT(" LEFT OUTER JOIN pg_class ci ON ind.indrelid=ci.oid\n") + wxT(" JOIN pg_namespace cin ON ci.relnamespace=cin.oid\n") + wxT(" WHERE cl.relowner = ") + uid + wxT(" AND cl.oid > ") + sysoid + wxT("\n") + wxT("UNION ALL\n") + wxT("SELECT 'n', null, nspname, null\n") + wxT(" FROM pg_namespace nsp WHERE nspowner = ") + uid + wxT(" AND nsp.oid > ") + sysoid + wxT("\n") + wxT("UNION ALL\n") + wxT("SELECT CASE WHEN typtype='d' THEN 'd' ELSE 'y' END, null, typname, null\n") + wxT(" FROM pg_type ty WHERE typowner = ") + uid + wxT(" AND ty.oid > ") + sysoid + wxT("\n") + wxT("UNION ALL\n") + wxT("SELECT 'C', null, conname, null\n") + wxT(" FROM pg_conversion co WHERE conowner = ") + uid + wxT(" AND co.oid > ") + sysoid + wxT("\n") + wxT("UNION ALL\n") + wxT("SELECT CASE WHEN prorettype=") + NumToStr(PGOID_TYPE_TRIGGER) + wxT(" THEN 'T' ELSE 'p' END, null, proname, null\n") + wxT(" FROM pg_proc pr WHERE proowner = ") + uid + wxT(" AND pr.oid > ") + sysoid + wxT("\n") + wxT("UNION ALL\n") + wxT("SELECT 'o', null, oprname || '('::text || ") + wxT("COALESCE(tl.typname, ''::text) || ") + wxT("CASE WHEN tl.oid IS NOT NULL AND tr.oid IS NOT NULL THEN ','::text END || ") + wxT("COALESCE(tr.typname, ''::text) || ')'::text, null\n") + wxT(" FROM pg_operator op\n") + wxT(" LEFT JOIN pg_type tl ON tl.oid=op.oprleft\n") + wxT(" LEFT JOIN pg_type tr ON tr.oid=op.oprright\n") + wxT(" WHERE oprowner = ") + uid + wxT(" AND op.oid > ") + sysoid + wxT("\n") + wxT(" ORDER BY 1,2,3")); + + form->EndMsg(); +} + + void pgUser::ShowTreeDetail(wxTreeCtrl *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane) { if (!expandedKids) Index: pgTablespace.cpp =================================================================== RCS file: /projects/pgadmin3/src/schema/pgTablespace.cpp,v retrieving revision 1.3 retrieving revision 1.4 diff -Lsrc/schema/pgTablespace.cpp -Lsrc/schema/pgTablespace.cpp -u -w -r1.3 -r1.4 --- src/schema/pgTablespace.cpp +++ src/schema/pgTablespace.cpp @@ -36,6 +36,8 @@ void pgTablespace::ShowReferencedBy(frmMain *form, ctlListView *referencedBy, const wxString &where) { + form->StartMsg(_(" Retrieving tablespace usage")); + referencedBy->ClearAll(); referencedBy->AddColumn(_("Type"), 60); referencedBy->AddColumn(_("Database"), 80); @@ -44,7 +46,6 @@ OID stdOid; wxString tsoid=GetOidStr(); - form->StartMsg(_(" Retrieving tablespace usage")); if (GetName() == wxT("default")) { stdOid=0; @@ -76,59 +77,7 @@ delete set; } - pgCollection *databases; - - wxCookieType cookie; - wxTreeItemId item=form->GetBrowser()->GetFirstChild(GetServer()->GetId(), cookie); - while (item) - { - databases = (pgCollection*)form->GetBrowser()->GetItemData(item); - if (databases && databases->GetType() == PG_DATABASES) - break; - else - databases=0; - - item=form->GetBrowser()->GetNextChild(GetServer()->GetId(), cookie); - } - - size_t i; - for (i=0 ; i < dblist.GetCount() ; i++) - { - wxString dbname=dblist.Item(i); - pgConn *conn=0; - pgConn *tmpConn=0; - - if (GetServer()->GetDatabaseName() == dbname) - conn = GetServer()->GetConnection(); - else - { - item=form->GetBrowser()->GetFirstChild(databases->GetId(), cookie); - while (item) - { - pgDatabase *db=(pgDatabase*)form->GetBrowser()->GetItemData(item); - if (db->GetType() == PG_DATABASE && db->GetName() == dbname) - { - if (db->GetConnected()) - conn = db->GetConnection(); - break; - } - item=form->GetBrowser()->GetNextChild(databases->GetId(), cookie); - } - } - if (conn && conn->GetStatus() != PGCONN_OK) - conn=0; - - if (!conn) - { - tmpConn = new pgConn(GetServer()->GetName(), dbname, GetServer()->GetUsername(), - GetServer()->GetPassword(), GetServer()->GetPort(), GetServer()->GetSSL()); - if (tmpConn->GetStatus() == PGCONN_OK) - conn=tmpConn; - } - - if (conn) - { - set=conn->ExecuteSet( + FillOwned(form->GetBrowser(), referencedBy, dblist, wxT("SELECT cl.relkind, COALESCE(cin.nspname, cln.nspname) as nspname, COALESCE(ci.relname, cl.relname) as relname, ci.relname as indname\n") wxT(" FROM pg_class cl\n") wxT(" JOIN pg_namespace cln ON cl.relnamespace=cln.oid\n") @@ -141,43 +90,6 @@ wxT(" FROM pg_namespace WHERE nsptablespace IN (") + tsoid + wxT(")\n") wxT(" ORDER BY 1,2,3")); - if (set) - { - while (!set->Eof()) - { - int id=0; - - wxString relname = qtIdent(set->GetVal(wxT("nspname"))); - if (!relname.IsEmpty()) - relname += wxT("."); - relname += qtIdent(set->GetVal(wxT("relname"))); - - switch (set->GetVal(wxT("relkind")).c_str()[0]) - { - case 'r': id=PG_TABLE; break; - case 's': id=PG_SEQUENCE; break; - case 'n': id=PG_SCHEMA; break; - case 'i': id=PG_INDEX; - relname = qtIdent(set->GetVal(wxT("indname"))) + wxT(" ON ") + relname; - break; - } - - if (id) - { - wxString typname = typesList[id].typName; - int icon = typesList[id].typeIcon; - referencedBy->AppendItem(icon, typname, dbname, relname); - } - - set->MoveNext(); - } - delete set; - } - } - - if (tmpConn) - delete tmpConn; - } form->EndMsg(); } @@ -251,8 +163,7 @@ pgSet *tablespaces = collection->GetServer()->ExecuteSet( - wxT("SELECT ts.oid, spcname, spclocation, usename FROM pg_tablespace ts\n") - wxT(" JOIN pg_user us ON us.usesysid=ts.spcowner\n") + wxT("SELECT ts.oid, spcname, spclocation, pg_get_userbyid(spcowner) as spcuser FROM pg_tablespace ts\n") + restriction + wxT(" ORDER BY spcname")); if (tablespaces) @@ -263,7 +174,7 @@ tablespace = new pgTablespace(tablespaces->GetVal(wxT("spcname"))); tablespace->iSetServer(collection->GetServer()); tablespace->iSetOid(tablespaces->GetOid(wxT("oid"))); - tablespace->iSetOwner(tablespaces->GetVal(wxT("usename"))); + tablespace->iSetOwner(tablespaces->GetVal(wxT("spcuser"))); tablespace->iSetLocation(tablespaces->GetVal(wxT("spclocation"))); Index: frmMain.cpp =================================================================== RCS file: /projects/pgadmin3/src/ui/frmMain.cpp,v retrieving revision 1.94 retrieving revision 1.95 diff -Lsrc/ui/frmMain.cpp -Lsrc/ui/frmMain.cpp -u -w -r1.94 -r1.95 --- src/ui/frmMain.cpp +++ src/ui/frmMain.cpp @@ -460,14 +460,26 @@ switch (event.GetSelection()) { case NBP_STATISTICS: + { + statistics->Freeze(); data->ShowStatistics(this, statistics); + statistics->Thaw(); break; + } case NBP_DEPENDSON: + { + dependsOn->Freeze(); data->ShowDependsOn(this, dependsOn); + dependsOn->Thaw(); break; + } case NBP_REFERENCEDBY: + { + referencedBy->Freeze(); data->ShowReferencedBy(this, referencedBy); + referencedBy->Thaw(); break; + } default: break; }