diff --git a/Release/pgAdmin3.exe b/Release/pgAdmin3.exe index 055dcd5..43d3d04 100644 Binary files a/Release/pgAdmin3.exe and b/Release/pgAdmin3.exe differ diff --git a/frm/frmQuery.cpp b/frm/frmQuery.cpp index 72fe6dd..7889b5b 100644 --- a/frm/frmQuery.cpp +++ b/frm/frmQuery.cpp @@ -663,15 +663,21 @@ frmQuery::frmQuery(frmMain *form, const wxString &_title, pgConn *_conn, const w wxString str; wxString filename; - wxString tempDir=wxStandardPaths::Get().GetTempDir()+wxT("\\"); - + wxString tempDir=wxStandardPaths::Get().GetTempDir()+wxT("\\pgadmin3\\"); + + if (!wxDirExists(tempDir)) { + wxFileName dn = tempDir; + dn.Mkdir(); + } wxString pref=_conn->GetDbname(); bool modeUnicode = settings->GetUnicodeFile(); + wxString f = wxFindFirstFile(tempDir+wxT("*.a")); while ( !f.empty() ) { - if (f.AfterLast('\\').StartsWith(wxT("Query"))||f.AfterLast('\\').StartsWith(pref)) { + filename=f.AfterLast('\\').BeforeLast('.'); + if ((f.AfterLast('\\').StartsWith(pref+wxT("."))||(filename.BeforeLast('.').IsEmpty()))) { wxUtfFile file(f, wxFile::read, modeUnicode ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT); if (file.IsOpened()) { file.Read(str); file.Close(); } @@ -684,7 +690,7 @@ frmQuery::frmQuery(frmMain *form, const wxString &_title, pgConn *_conn, const w //sqlQuery->SetFilename(lastPath); sqlQuery->SetChanged(true); //sqlQuery->SetOrigin(ORIGIN_INITIAL); - filename=f.AfterLast('\\').BeforeLast('.'); + //filename=f.AfterLast('\\').BeforeLast('.'); sqlQuery->SetTitle(filename); setExtendedTitle(); SqlBookUpdatePageTitle(); @@ -2007,7 +2013,7 @@ void frmQuery::SaveTempFile() wxString pref=conn->GetDbname(); //if (filename.StartsWith(pref)) filename+=wxT(".a"); - wxString tempDir=wxStandardPaths::Get().GetTempDir(); + wxString tempDir=wxStandardPaths::Get().GetTempDir()+wxT("\\pgadmin3"); wxUtfFile file(tempDir+wxT("\\")+filename, wxFile::write, modeUnicode ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT); if (file.IsOpened()) { @@ -3838,13 +3844,13 @@ void frmQuery::OnSqlBookTabRDown (wxAuiNotebookEvent &event) { wxString pref=conn->GetDbname()+wxT(".nametab"); wxTextEntryDialog dialog(this, - wxT("Please enter name string with prefix dbname or 'Query'\n") + wxT("Please enter name string with prefix dbname\n") , wxT("Name autosave tab window."), pref, wxOK | wxCANCEL); //setName( dlg.GetValue().wc_str() ); if (dialog.ShowModal() == wxID_OK) { - wxString tempDir=wxStandardPaths::Get().GetTempDir()+wxT("\\"); + wxString tempDir=wxStandardPaths::Get().GetTempDir()+wxT("\\pgadmin3\\"); wxString filename=sqlQuery->GetTitle(false); wxRemoveFile(tempDir+filename+wxT(".a")); wxString nt=dialog.GetValue(); @@ -3889,7 +3895,7 @@ void frmQuery::OnSqlBookPageClose(wxAuiNotebookEvent &event) SqlBookDisconnectPage(); //drop temp file - wxString tempDir=wxStandardPaths::Get().GetTempDir()+wxT("\\"); + wxString tempDir=wxStandardPaths::Get().GetTempDir()+wxT("\\pgadmin3\\"); wxString filename=sqlQuery->GetTitle(false)+wxT(".a"); if (wxFileName::FileExists(tempDir+filename)) wxRemoveFile(tempDir+filename); @@ -3969,7 +3975,7 @@ bool frmQuery::SqlBookRemovePage() SqlBookDisconnectPage(); pageidx = sqlQueryBook->GetSelection(); - wxString tempDir=wxStandardPaths::Get().GetTempDir()+wxT("\\"); + wxString tempDir=wxStandardPaths::Get().GetTempDir()+wxT("\\pgadmin3\\"); ctlSQLBox *box; box = wxDynamicCast(sqlQueryBook->GetPage(pageidx), ctlSQLBox); wxString filename=box->GetTitle(false); diff --git a/include/schema/pgPartition.h b/include/schema/pgPartition.h index e158701..0eb6564 100644 --- a/include/schema/pgPartition.h +++ b/include/schema/pgPartition.h @@ -76,6 +76,8 @@ class pgPartitionCollection : public pgTableCollection { public: pgPartitionCollection(pgaFactory *factory, pgPartition *_table); + void ShowStatistics(frmMain *form, ctlListView *statistics); + virtual bool CanCreate() { return false; diff --git a/schema/pgObject.cpp b/schema/pgObject.cpp index c824c5d..a1e76d3 100644 --- a/schema/pgObject.cpp +++ b/schema/pgObject.cpp @@ -256,13 +256,12 @@ void pgObject::ShowDependency(pgDatabase *db, ctlListView *list, const wxString // not being implemented: // - pg_index (done by pg_class) - - set = conn->ExecuteSet(query + wxT("\n") + wxString q=query + wxT("\n") wxT(" AND ") + clsorder + wxT(" IN (\n") wxT(" SELECT oid FROM pg_class\n") wxT(" WHERE relname IN ('pg_class', 'pg_constraint', 'pg_conversion', 'pg_language', 'pg_proc', 'pg_extension', \n") - wxT(" 'pg_rewrite', 'pg_namespace', 'pg_trigger', 'pg_type', 'pg_attrdef', 'pg_event_trigger'))\n") - wxT(" ORDER BY ") + clsorder + wxT(", cl.relkind")); + wxT(" ORDER BY ") + clsorder + wxT(", cl.relkind"); + set = conn->ExecuteSet(q); if (set) { @@ -503,10 +502,12 @@ void pgObject::ShowDependencies(frmMain *form, ctlListView *Dependencies, const wxT(" WHEN co.oid IS NOT NULL THEN 'C'::text || contype\n") wxT(" WHEN ad.oid IS NOT NULL THEN 'A'::text\n") wxT(" WHEN ext.oid IS NOT NULL THEN 'E'::text\n") + wxT(" WHEN pub.oid IS NOT NULL THEN 'r'::text\n") wxT(" ELSE '' END AS type,\n") wxT(" COALESCE(coc.relname, clrw.relname) AS ownertable,\n") wxT(" CASE WHEN cl.relname IS NOT NULL AND att.attname IS NOT NULL THEN cl.relname || '.' || att.attname\n") wxT(" ELSE COALESCE(ext.extname,cl.relname, co.conname, pr.proname, tg.tgname, ty.typname, la.lanname, rw.rulename, ns.nspname)\n") + wxT(" ELSE COALESCE(ext.extname,cl.relname, co.conname, pr.proname, tg.tgname, ty.typname, la.lanname, rw.rulename, ns.nspname,pub.prrelid::regclass::text)\n") wxT(" END AS refname,\n") wxT(" COALESCE(nsc.nspname, nso.nspname, nsp.nspname, nst.nspname, nsrw.nspname) AS nspname\n") wxT(" FROM pg_depend dep\n") @@ -527,6 +528,7 @@ void pgObject::ShowDependencies(frmMain *form, ctlListView *Dependencies, const wxT(" LEFT JOIN pg_language la ON dep.refobjid=la.oid\n") wxT(" LEFT JOIN pg_namespace ns ON dep.refobjid=ns.oid\n") wxT(" LEFT JOIN pg_attrdef ad ON ad.adrelid=att.attrelid AND ad.adnum=att.attnum\n") + wxT(" LEFT JOIN pg_publication_rel pub ON dep.objid=pub.oid AND pub.prpubid=dep.refobjid\n") wxT(" LEFT JOIN pg_extension ext ON ext.oid=dep.refobjid\n") + where, wxT("refclassid")); @@ -671,11 +673,12 @@ void pgObject::ShowDependents(frmMain *form, ctlListView *referencedBy, const wx 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 ad.oid IS NOT NULL THEN 'A'::text\n") + wxT(" WHEN pub.oid IS NOT NULL THEN 'r'::text\n") wxT(" WHEN ext.oid IS NOT NULL THEN 'E'::text\n") wxT(" ELSE '' END AS type,\n") wxT(" COALESCE(coc.relname, clrw.relname) AS ownertable,\n") wxT(" CASE WHEN cl.relname IS NOT NULL AND att.attname IS NOT NULL THEN cl.relname || '.' || att.attname \n") - wxT(" ELSE COALESCE(ext.extname,cl.relname, co.conname, pr.proname, tg.tgname, ty.typname, la.lanname, rw.rulename, ns.nspname) \n") + wxT(" ELSE COALESCE(ext.extname,cl.relname, co.conname, pr.proname, tg.tgname, ty.typname, la.lanname, rw.rulename, ns.nspname,pub.prrelid::regclass::text) \n") wxT(" END AS refname,\n") wxT(" COALESCE(nsc.nspname, nso.nspname, nsp.nspname, nst.nspname, nsrw.nspname) AS nspname\n") wxT(" FROM pg_depend dep\n") @@ -697,6 +700,7 @@ void pgObject::ShowDependents(frmMain *form, ctlListView *referencedBy, const wx wxT(" LEFT JOIN pg_namespace ns ON dep.objid=ns.oid\n") wxT(" LEFT JOIN pg_attrdef ad ON ad.oid=dep.objid\n") wxT(" LEFT JOIN pg_extension ext ON ext.oid=dep.objid\n") + wxT(" LEFT JOIN pg_publication_rel pub ON dep.objid=pub.oid AND pub.prpubid=dep.refobjid\n") + where, wxT("classid")); /* diff --git a/schema/pgPartition.cpp b/schema/pgPartition.cpp index 873fba3..04b5073 100644 --- a/schema/pgPartition.cpp +++ b/schema/pgPartition.cpp @@ -94,6 +94,102 @@ pgPartitionCollection::pgPartitionCollection(pgaFactory *factory, pgPartition *_ { iSetOid(_table->GetOid()); } +void pgPartitionCollection::ShowStatistics(frmMain *form, ctlListView *statistics) +{ + wxLogInfo(wxT("Displaying statistics for tables on %s"), GetSchema()->GetIdentifier().c_str()); + + bool hasSize = GetConnection()->HasFeature(FEATURE_SIZE); + + // Add the statistics view columns + statistics->ClearAll(); + statistics->AddColumn(_("Table Name")); + statistics->AddColumn(_("Tuples inserted")); + statistics->AddColumn(_("Tuples updated")); + statistics->AddColumn(_("Tuples deleted")); + if (GetConnection()->BackendMinimumVersion(8, 3)) + { + statistics->AddColumn(_("Tuples HOT updated")); + statistics->AddColumn(_("Live tuples")); + statistics->AddColumn(_("Dead tuples")); + } + if (GetConnection()->BackendMinimumVersion(8, 2)) + { + statistics->AddColumn(_("Last vacuum")); + statistics->AddColumn(_("Last autovacuum")); + statistics->AddColumn(_("Last analyze")); + statistics->AddColumn(_("Last autoanalyze")); + } + if (GetConnection()->BackendMinimumVersion(9, 1)) + { + statistics->AddColumn(_("Vacuum counter")); + statistics->AddColumn(_("Autovacuum counter")); + statistics->AddColumn(_("Analyze counter")); + statistics->AddColumn(_("Autoanalyze counter")); + } + if (hasSize) + statistics->AddColumn(_("Size"), 50); + + wxString sql = wxT("SELECT st.relname, n_tup_ins, n_tup_upd, n_tup_del"); + if (GetConnection()->BackendMinimumVersion(8, 3)) + sql += wxT(", n_tup_hot_upd, n_live_tup, n_dead_tup"); + if (GetConnection()->BackendMinimumVersion(8, 2)) + sql += wxT(", last_vacuum, last_autovacuum, last_analyze, last_autoanalyze"); + if (GetConnection()->BackendMinimumVersion(9, 1)) + sql += wxT(", vacuum_count, autovacuum_count, analyze_count, autoanalyze_count"); + if (hasSize) + sql += wxT(", pg_size_pretty(pg_relation_size(st.relid)") + wxT(" + CASE WHEN cl.reltoastrelid = 0 THEN 0 ELSE pg_relation_size(cl.reltoastrelid) + COALESCE((SELECT SUM(pg_relation_size(indexrelid)) FROM pg_index WHERE indrelid=cl.reltoastrelid)::int8, 0) END") + wxT(" + COALESCE((SELECT SUM(pg_relation_size(indexrelid)) FROM pg_index WHERE indrelid=st.relid)::int8, 0)) AS size"); + + sql += wxT("\n FROM pg_stat_all_tables st") + wxT(" JOIN pg_class cl on cl.oid=st.relid\n") + wxT(" JOIN pg_inherits i ON (cl.oid = i.inhrelid)") + wxT(" WHERE schemaname = ") + qtDbString(GetSchema()->GetName())+ wxT(" AND i.inhparent = ")+GetOidStr() + + wxT("\n ORDER BY relname"); + + pgSet *stats = GetDatabase()->ExecuteSet(sql); + + if (stats) + { + long pos = 0; + int i; + while (!stats->Eof()) + { + i = 4; + statistics->InsertItem(pos, stats->GetVal(wxT("relname")), PGICON_STATISTICS); + statistics->SetItem(pos, 1, stats->GetVal(wxT("n_tup_ins"))); + statistics->SetItem(pos, 2, stats->GetVal(wxT("n_tup_upd"))); + statistics->SetItem(pos, 3, stats->GetVal(wxT("n_tup_del"))); + if (GetConnection()->BackendMinimumVersion(8, 3)) + { + statistics->SetItem(pos, i++, stats->GetVal(wxT("n_tup_hot_upd"))); + statistics->SetItem(pos, i++, stats->GetVal(wxT("n_live_tup"))); + statistics->SetItem(pos, i++, stats->GetVal(wxT("n_dead_tup"))); + } + if (GetConnection()->BackendMinimumVersion(8, 2)) + { + statistics->SetItem(pos, i++, stats->GetVal(wxT("last_vacuum"))); + statistics->SetItem(pos, i++, stats->GetVal(wxT("last_autovacuum"))); + statistics->SetItem(pos, i++, stats->GetVal(wxT("last_analyze"))); + statistics->SetItem(pos, i++, stats->GetVal(wxT("last_autoanalyze"))); + } + if (GetConnection()->BackendMinimumVersion(9, 1)) + { + statistics->SetItem(pos, i++, stats->GetVal(wxT("vacuum_count"))); + statistics->SetItem(pos, i++, stats->GetVal(wxT("autovacuum_count"))); + statistics->SetItem(pos, i++, stats->GetVal(wxT("analyze_count"))); + statistics->SetItem(pos, i++, stats->GetVal(wxT("autoanalyze_count"))); + } + if (hasSize) + statistics->SetItem(pos, i, stats->GetVal(wxT("size"))); + stats->MoveNext(); + pos++; + } + + delete stats; + } + +} pgObject *pgPartitionFactory::CreateObjects(pgCollection *coll, ctlTree *browser, const wxString &restriction)