pgadmin3/frm/frmMaintenance.cpp
2023-07-30 10:33:41 +05:00

313 lines
8.6 KiB
C++

//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// frmMaintenance.cpp - Maintenance options selection dialogue
//
//////////////////////////////////////////////////////////////////////////
// wxWindows headers
#include <wx/wx.h>
#include <wx/settings.h>
#include <wx/xrc/xmlres.h>
// App headers
#include "pgAdmin3.h"
#include "ctl/ctlMenuToolbar.h"
#include "frm/frmHint.h"
#include "frm/frmMaintenance.h"
#include "frm/frmMain.h"
#include "utils/sysLogger.h"
#include "schema/pgIndex.h"
// Icons
#include "images/vacuum.pngc"
BEGIN_EVENT_TABLE(frmMaintenance, ExecutionDialog)
EVT_RADIOBOX(XRCID("rbxAction"), frmMaintenance::OnAction)
END_EVENT_TABLE()
#define nbNotebook CTRL_NOTEBOOK("nbNotebook")
#define rbxAction CTRL_RADIOBOX("rbxAction")
#define chkFull CTRL_CHECKBOX("chkFull")
#define chkFreeze CTRL_CHECKBOX("chkFreeze")
#define chkAnalyze CTRL_CHECKBOX("chkAnalyze")
#define chkVerbose CTRL_CHECKBOX("chkVerbose")
#define chkDISABLE_PAGE_SKIPPING CTRL_CHECKBOX("chkDISABLE_PAGE_SKIPPING")
#define chkCONCURRENTLY CTRL_CHECKBOX("chkCONCURRENTLY")
#define stBitmap CTRL("stBitmap", wxStaticBitmap)
int global_sel_pos=-1;
frmMaintenance::frmMaintenance(frmMain *form, pgObject *obj) : ExecutionDialog(form, obj)
{
SetFont(settings->GetSystemFont());
LoadResource(form, wxT("frmMaintenance"));
RestorePosition();
SetTitle(object->GetTranslatedMessage(MAINTENANCEDIALOGTITLE));
txtMessages = CTRL_TEXT("txtMessages");
// Icon
SetIcon(*vacuum_png_ico);
// Note that under GTK+, SetMaxLength() function may only be used with single line text controls.
// (see http://docs.wxwidgets.org/2.8/wx_wxtextctrl.html#wxtextctrlsetmaxlength)
#ifndef __WXGTK__
txtMessages->SetMaxLength(0L);
#endif
bool iscomprss = false;
wxString cmd;
if (object->GetMetaType() == PGM_INDEX || object->GetMetaType() == PGM_PRIMARYKEY || object->GetMetaType() == PGM_UNIQUE)
{
rbxAction->SetSelection(2);
rbxAction->Enable(0, false);
rbxAction->Enable(1, false);
if (object->GetDatabase()->connection()->GetIsPgProEnt()) {
wxString ratio = object->GetConnection()->ExecuteScalar("select left((cfs_fragmentation("+object->GetOidStr()+")*100)::text,5)::text");
iscomprss = !(ratio == "NaN");
}
wxString sql = "SELECT \
case when(SELECT max(pronargs) FROM pg_proc WHERE proname = 'bt_index_check') = 3 then\
'bt_index_check(' || c.oid || ', true,' || i.indisunique || ')'\
when(SELECT max(pronargs) FROM pg_proc WHERE proname = 'bt_index_check') = 2 then\
'bt_index_check(' || c.oid || ', true)'\
else\
''\
end\
FROM pg_index i\
JOIN pg_opclass op ON i.indclass[0] = op.oid\
JOIN pg_am am ON op.opcmethod = am.oid\
JOIN pg_class c ON i.indexrelid = c.oid\
JOIN pg_namespace n ON c.relnamespace = n.oid\
WHERE am.amname = 'btree'\
AND c.relpersistence != 't'\
AND c.relkind = 'i' AND i.indisready AND i.indisvalid and c.oid = "+object->GetOidStr();
cmd = object->GetConnection()->ExecuteScalar(sql);
cmdcheck = cmd;
}
if (object->GetMetaType() == PGM_TABLE) {
pgTable* t = (pgTable *)object;
iscomprss = !(t->GetRatio() == "");
}
rbxAction->Enable(4, iscomprss);
rbxAction->Enable(5, !cmd.IsEmpty());
if (global_sel_pos >= 0 && rbxAction->IsItemEnabled(global_sel_pos)) {
rbxAction->SetSelection(global_sel_pos);
}
wxCommandEvent ev;
OnAction(ev);
}
frmMaintenance::~frmMaintenance()
{
SavePosition();
Abort();
}
wxString frmMaintenance::GetHelpPage() const
{
wxString page;
switch ((XRCCTRL(*(frmMaintenance *)this, "rbxAction", wxRadioBox))->GetSelection())
{
case 0:
page = wxT("pg/sql-vacuum");
break;
case 1:
page = wxT("pg/sql-analyze");
break;
case 2:
page = wxT("pg/sql-reindex");
break;
case 3:
page = wxT("pg/sql-cluster");
break;
}
return page;
}
void frmMaintenance::OnAction(wxCommandEvent &ev)
{
bool isVacuum = (rbxAction->GetSelection() == 0);
global_sel_pos=rbxAction->GetSelection();
chkFull->Enable(isVacuum);
chkFreeze->Enable(isVacuum);
chkAnalyze->Enable(isVacuum);
chkDISABLE_PAGE_SKIPPING->Enable(isVacuum && conn->BackendMinimumVersion(10, 0));
bool isReindex = (rbxAction->GetSelection() == 2);
chkCONCURRENTLY->Enable(isReindex && conn->BackendMinimumVersion(12, 0));
bool isCluster = (rbxAction->GetSelection() == 3);
if ((isCluster && !conn->BackendMinimumVersion(8, 4)))
{
chkVerbose->SetValue(false);
chkVerbose->Enable(false);
}
else
{
chkVerbose->SetValue(true);
chkVerbose->Enable(true);
}
bool isAmcheck = (rbxAction->GetSelection() == 5);
if (isAmcheck) {
}
}
wxString frmMaintenance::GetSql()
{
wxString sql;
switch (rbxAction->GetSelection())
{
case 0:
{
/* Warn about VACUUM FULL on < 9.0 */
if (chkFull->GetValue() &&
!conn->BackendMinimumVersion(9, 0))
{
if (frmHint::ShowHint(this, HINT_VACUUM_FULL) == wxID_CANCEL)
return wxEmptyString;
}
sql = wxT("VACUUM ");
wxString opt = "";
if (chkFull->GetValue())
AppendIfFilled(opt,",",wxT("FULL"));
if (chkFreeze->GetValue())
AppendIfFilled(opt,",",wxT("FREEZE"));
if (chkVerbose->GetValue())
AppendIfFilled(opt,",",wxT("VERBOSE"));
if (chkAnalyze->GetValue())
AppendIfFilled(opt,",",wxT("ANALYZE"));
if (chkDISABLE_PAGE_SKIPPING->GetValue())
AppendIfFilled(opt,",",wxT("DISABLE_PAGE_SKIPPING"));
sql += opt.IsNull() ? "" : "("+opt.Mid(1)+")";
if (object->GetMetaType() != PGM_DATABASE)
sql += object->GetQuotedFullIdentifier();
break;
}
case 1:
{
sql = wxT("ANALYZE ");
if (chkVerbose->GetValue())
sql += wxT("VERBOSE ");
if (object->GetMetaType() != PGM_DATABASE)
sql += object->GetQuotedFullIdentifier();
break;
}
case 2:
{
sql = wxT("REINDEX ");
if (chkVerbose->GetValue())
sql += wxT("(VERBOSE) ");
if (object->GetMetaType() == PGM_UNIQUE || object->GetMetaType() == PGM_PRIMARYKEY)
{
sql += wxT("INDEX ");
sql += chkCONCURRENTLY->GetValue() ? "CONCURRENTLY ": "";
sql += object->GetQuotedFullIdentifier();
}
else // Database, Tables, and Index (but not Constraintes ones)
{
sql += object->GetTypeName().Upper();
sql += chkCONCURRENTLY->GetValue() ? " CONCURRENTLY ": " ";
sql += object->GetQuotedFullIdentifier();
}
break;
}
case 3:
{
sql = wxT("CLUSTER ");
if (chkVerbose->GetValue())
sql += wxT("VERBOSE ");
if (object->GetMetaType() == PGM_TABLE)
sql += object->GetQuotedFullIdentifier();
if (object->GetMetaType() == PGM_INDEX || object->GetMetaType() == PGM_UNIQUE
|| object->GetMetaType() == PGM_PRIMARYKEY)
{
sql += object->GetSchema()->GetQuotedFullIdentifier();
if (conn->BackendMinimumVersion(8, 4))
{
sql += wxT(" USING ") + object->GetQuotedIdentifier();
}
else
{
sql += wxT(" ON ") + object->GetQuotedIdentifier();
}
}
break;
}
case 4:
{
sql = wxT("set cfs_gc_threshold = 0;select ");
sql += "cfs_gc_relation(" + object->GetOidStr() + ")";
if (object->GetMetaType() == PGM_TABLE) {
//sql += object->GetQuotedFullIdentifier();
wxString strindex= object->GetConnection()->ExecuteScalar("select string_agg('cfs_gc_relation('||indexrelid::text||')',',') from pg_index i where indrelid=" + object->GetOidStr() + " and cfs_fragmentation(indexrelid) between 0.01 and 1;");
if (strindex.Len() > 0) sql += ","+strindex;
}
break;
}
case 5: // amchek
{
sql = wxT("SET client_min_messages = DEBUG1;select ");
sql += cmdcheck;
//wxString strindex = object->GetConnection()->ExecuteScalar("select string_agg('cfs_gc_relation('||indexrelid::text||')',',') from pg_index i where indrelid=" + object->GetOidStr() + " and cfs_fragmentation(indexrelid) between 0.01 and 1;");
break;
}
}
return sql;
}
void frmMaintenance::Go()
{
chkFull->SetFocus();
Show(true);
}
maintenanceFactory::maintenanceFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : contextActionFactory(list)
{
mnu->Append(id, _("&Maintenance..."), _("Maintain the current database or table."));
toolbar->AddTool(id, wxEmptyString, GetBundleSVG(vacuum_png_bmp, "vacuum.svg", wxSize(32, 32)), _("Maintain the current database or table."), wxITEM_NORMAL);
}
wxWindow *maintenanceFactory::StartDialog(frmMain *form, pgObject *obj)
{
frmMaintenance *frm = new frmMaintenance(form, obj);
frm->Go();
return 0;
}
bool maintenanceFactory::CheckEnable(pgObject *obj)
{
return obj && obj->CanMaintenance();
}