This commit is contained in:
lsv 2021-01-04 12:19:48 +05:00
commit d29b6de188
39 changed files with 1050 additions and 186 deletions

3
.gitignore vendored
View file

@ -1,6 +1,7 @@
Debug/*
x64/*
Release/*
Debug_(3.0)/*
*.sbr
*.obj
*.cod
@ -8,3 +9,5 @@ Release/*
*.7z
*.bsc
*.pdb
ctl/ctlMonitorWidget.cpp
include/ctl/ctlMonitorWidget.h

View file

@ -133,10 +133,27 @@ This text Russian language.
В родной схеме, секции как таблицы увидеть нельзя.
* мелкие улучшения
02.09.2020
- добавлена возможность копировать в буфер обмена выделенные ячейки результата запроса в формате IN списка и Where конструкций. Вызывается из контекстного меню.
- в Server status окне добавлена возможность фильтровать строки по щелчку правой кнопкой мыши.
* иправлено issues #8 (dropping overloaded procedures)
05.09.2020
- при сравнении объектов добавлена возможность исключать сравнение привелегий и комментариев.
* исправлено копирование текста запроса из под фильтра в Server status окне. При сравнении текста из колонки Client порт не учитывается.
05.12.2020
* много мелких исправлений
* добавлены некоторые новые возможности PG13. Описание в коммитах.
- добавлена проверка btree индекса. Проверка выполняется функцией bt_index_parent_check(regclass,true) из расширения amcheck.
Расширение должно быть установлено в БД к которой происходит подключение pgadmin3.
02.01.2021
- добавлена сортировка на вкладках "свойства" , "Статистика" и других.
- по секционированным таблицам в статистеке выводятся все потомки.

Binary file not shown.

View file

@ -19,13 +19,106 @@
#include "ctl/ctlListView.h"
#include "utils/misc.h"
ctlListView::ctlListView(wxWindow *p, int id, wxPoint pos, wxSize siz, long attr)
: wxListView(p, id, pos, siz, attr | wxLC_REPORT)
int wxCALLBACK
MyCompareFunction(wxIntPtr item1, wxIntPtr item2, wxIntPtr WXUNUSED(sortData))
{
// inverse the order
if (item1 < item2)
return 1;
if (item1 > item2)
return -1;
return 0;
}
ctlListView::ctlListView(wxWindow* p, int id, wxPoint pos, wxSize siz, long attr)
: wxListView(p, id, pos, siz, attr | wxLC_REPORT)
{
nosort = false;
order = 1;
prev_col = -1;
Connect(wxID_ANY, wxEVT_LIST_COL_CLICK, wxListEventHandler(ctlListView::OnSortGrid));
}
#include <map>
void ctlListView::OnSortGrid(wxListEvent& event)
{
if (!nosort) {
int col = event.GetColumn();
if (col == prev_col) order = order * -1;
int rows = GetItemCount();
wxListItem listitem;
listitem.SetMask(wxLIST_MASK_TEXT);
GetColumn(col, listitem);
wxString label = listitem.GetText();
bool issize = label == _("Size");
bool astext = true;
if (label == _("CFS fragmentation") ||
label == (_("Tuples inserted")) ||
label == (_("Tuples updated")) ||
label == (_("Tuples deleted")) ||
label == (_("Tuples HOT updated")) ||
label == (_("Live tuples")) ||
label == (_("Dead tuples")) ||
label == (_("CFS %")) ||
label == (_("Autovacuum counter")) ||
label == (_("Autoanalyze counter")) ||
label == (_("Index Scans")) ||
label == (_("Index Tuples Read")) ||
label == (_("Index Tuples Fetched")) ||
issize
) {
astext = false;
}
//sort numeric column
if (astext) {
std::multimap<wxString, int> mp;
for (int i = 0; i < rows; i++) {
wxString val = GetItemText(i, col);
mp.insert(std::pair<wxString, int>(val, i));
}
// ñîïîñòàâèì ñîðòèðîâàííûì çíà÷åíèÿì ïîñëåäîâàòåëüíîñòü ÷èñåë äëÿ ñîðòèðîâêè SortItems
std::multimap<wxString, int>::iterator it = mp.begin();
for (int i = 1; it != mp.end(); it++, i++) { // âûâîäèì èõ
int row = it->second; // row
wxListView::SetItemData(row, (long)i * order);
}
}
else
{
std::multimap<double, int> mp;
double d;
for (int i = 0; i < rows; i++) {
wxString val = GetItemText(i, col);
if (val == "NaN") val = "0";
if (val.ToCDouble(&d))
{
// ýòî ÷èñëî
}
else
{
if (issize)
if (val.Right(2) == "kB") d = d / 1024;
else if (val.Right(2) == "GB") d = d * 1024;
else if (val.Right(5) == "bytes") d = d / 1024 / 1024;
}
mp.insert(std::pair<double, int>(d, i));
}
// ñîïîñòàâèì ñîðòèðîâàííûì çíà÷åíèÿì ïîñëåäîâàòåëüíîñòü ÷èñåë äëÿ ñîðòèðîâêè SortItems
std::multimap<double, int>::iterator it = mp.begin();
for (int i = 1; it != mp.end(); it++, i++) { // âûâîäèì èõ
int row = it->second; // row
wxListView::SetItemData(row, (long)i * order);
}
}
SortItems(MyCompareFunction, 0);
Refresh();
prev_col = col;
}
}
long ctlListView::GetSelection()
{
return GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
@ -43,7 +136,7 @@ wxString ctlListView::GetText(long row, long col)
};
void ctlListView::AddColumn(const wxString &text, int size, int format)
void ctlListView::AddColumn(const wxString& text, int size, int format)
{
if (size == wxLIST_AUTOSIZE || size == wxLIST_AUTOSIZE_USEHEADER)
{
@ -56,7 +149,7 @@ void ctlListView::AddColumn(const wxString &text, int size, int format)
}
long ctlListView::AppendItem(int icon, const wxString &val, const wxString &val2, const wxString &val3, const wxString &val4)
long ctlListView::AppendItem(int icon, const wxString& val, const wxString& val2, const wxString& val3, const wxString& val4)
{
long pos = InsertItem(GetItemCount(), val, icon);
if (!val2.IsEmpty())
@ -70,7 +163,7 @@ long ctlListView::AppendItem(int icon, const wxString &val, const wxString &val2
}
void ctlListView::CreateColumns(wxImageList *images, const wxString &left, const wxString &right, int leftSize)
void ctlListView::CreateColumns(wxImageList* images, const wxString& left, const wxString& right, int leftSize)
{
int rightSize;
if (leftSize < 0)
@ -107,7 +200,7 @@ void ctlListView::CreateColumns(wxImageList *images, const wxString &left, const
}
void ctlListView::CreateColumns(wxImageList *images, const wxString &str1, const wxString &str2, const wxString &str3, int leftSize)
void ctlListView::CreateColumns(wxImageList* images, const wxString& str1, const wxString& str2, const wxString& str3, int leftSize)
{
int rightSize;
if (leftSize < 0)

View file

@ -217,10 +217,12 @@ wxString ctlSQLGrid::GetExportLine(int row, wxArrayInt cols)
if (GetNumberCols() == 0 || GetRowSize(row)==0)
return str;
wxString colsep=settings->GetCopyColSeparator();
if (generatesql) colsep=wxT(",");
if (generatesql == 2|| generatesql == 1) colsep=wxT(",");
if (generatesql == 3) colsep = wxT(" and ");
wxString qtsimbol=settings->GetCopyQuoteChar();
if (generatesql) qtsimbol=wxT("'");
if (generatesql>0) qtsimbol=wxT("'");
wxString head=wxT("insert into tbl(");
if (cols.Count()>1 && generatesql > 1) str.Append("(");
for (col = 0 ; col < cols.Count() ; col++)
{
if (col > 0)
@ -228,6 +230,7 @@ wxString ctlSQLGrid::GetExportLine(int row, wxArrayInt cols)
if (col > 0) head.Append(colsep);
head=head+GetColumnName(cols[col]);
wxString text = GetCellValue(row, cols[col]);
wxString cname = GetColumnName(cols[col]);
bool needQuote = false;
if (settings->GetCopyQuoting() == 1)
{
@ -236,22 +239,29 @@ wxString ctlSQLGrid::GetExportLine(int row, wxArrayInt cols)
else if (settings->GetCopyQuoting() == 2)
/* Quote everything */
needQuote = true;
if (text.Length()==0&&generatesql) {needQuote = false;} else
if (generatesql) needQuote = IsColText(cols[col]);
if (text.Length()==0&&generatesql>0) {needQuote = false;} else
if (generatesql>0) needQuote = IsColText(cols[col]);
if (generatesql > 0) {
if (text.Length() != 0) {
text.Replace(wxT("'"), wxT("''"));
}
else text = wxT("null");
}
if (generatesql == 3) if (text == "null") str.Append(cname).Append(" is "); else
str.Append(cname).Append("=");
if (needQuote)
str.Append(qtsimbol);
if (generatesql) {
if (text.Length()!=0) {
text.Replace(wxT("'"),wxT("''"));
} else text=wxT("null");
}
str.Append(text);
if (needQuote)
str.Append(qtsimbol);
}
if (generatesql) str=head+wxT(") values (")+str+");";
if (cols.Count() > 1 && generatesql > 1) str.Append(")");
if (generatesql == 1) str=head+wxT(") values (")+str+");";
return str;
}
@ -278,35 +288,54 @@ void ctlSQLGrid::AppendColumnHeader(wxString &str, int start, int end)
void ctlSQLGrid::AppendColumnHeader(wxString &str, wxArrayInt columns)
{
if(settings->GetColumnNames()&&!generatesql)
if(settings->GetColumnNames()|| generatesql == 2)
{
bool CopyQuoting = (settings->GetCopyQuoting() == 1 || settings->GetCopyQuoting() == 2);
size_t i;
wxString fielddelim = ",";
if (generatesql == 3) return;
if (generatesql == 1) return;
for(i = 0; i < columns.Count() ; i++)
{
long columnPos = columns.Item(i);
if(i > 0)
str.Append(settings->GetCopyColSeparator());
if (generatesql == 2) {
if (i > 0) str.Append(fielddelim);
if (i == 0 && columns.Count() > 1) str.Append("(");
str.Append(GetColumnName(columnPos));
if (i == columns.Count()-1 && columns.Count() > 1 && generatesql == 2) str.Append(") in (");
if (columns.Count() == 1 && generatesql == 2) str.Append(" in (");
if(CopyQuoting)
str.Append(settings->GetCopyQuoteChar());
str.Append(GetColumnName(columnPos));
if(CopyQuoting)
str.Append(settings->GetCopyQuoteChar());
}
else
{
if (i > 0)
str.Append(settings->GetCopyColSeparator());
if (CopyQuoting)
str.Append(settings->GetCopyQuoteChar());
str.Append(GetColumnName(columnPos));
if (CopyQuoting)
str.Append(settings->GetCopyQuoteChar());
}
}
str.Append(END_OF_LINE);
}
}
int ctlSQLGrid::Copy(bool gensql)
int compare_int(int* a, int* b)
{
wxString str,tmp;
if (*a > * b) return 1;
else if (*a < *b) return -1;
else return 0;
}
int ctlSQLGrid::Copy(int gensql)
{
wxString str,tmp,linedelim="";
int copied = 0;
size_t i;
generatesql=gensql;
if (gensql == 2) linedelim = ",";
else if(gensql == 3) linedelim = " or ";
if (GetSelectedRows().GetCount())
{
@ -319,6 +348,7 @@ int ctlSQLGrid::Copy(bool gensql)
tmp=GetExportLine(rows.Item(i));
if (tmp.IsEmpty()) continue;
str.Append(tmp);
if (i < rows.GetCount() - 1 && (generatesql > 1)) str.Append(linedelim);
if (rows.GetCount() > 1)
str.Append(END_OF_LINE);
}
@ -335,48 +365,93 @@ int ctlSQLGrid::Copy(bool gensql)
for (i = 0 ; i < numRows ; i++)
{
str.Append(GetExportLine(i, cols));
if (i<(numRows-1) && (generatesql > 1)) str.Append(linedelim);
if (numRows > 1)
str.Append(END_OF_LINE);
}
copied = numRows;
}
else if (GetSelectionBlockTopLeft().GetCount() > 0 &&
GetSelectionBlockBottomRight().GetCount() > 0)
{
unsigned int x1, x2, y1, y2;
int count = GetSelectionBlockTopLeft().GetCount();
x1 = GetSelectionBlockTopLeft()[0].GetCol();
x2 = GetSelectionBlockBottomRight()[0].GetCol();
y1 = GetSelectionBlockTopLeft()[0].GetRow();
y2 = GetSelectionBlockBottomRight()[0].GetRow();
copied = 0;
AppendColumnHeader(str, x1, x2);
for (i = y1; i <= y2; i++)
for (size_t n = 0; n < count; n++)
{
str.Append(GetExportLine(i, x1, x2));
x1 = GetSelectionBlockTopLeft()[n].GetCol();
x2 = GetSelectionBlockBottomRight()[n].GetCol();
y1 = GetSelectionBlockTopLeft()[n].GetRow();
y2 = GetSelectionBlockBottomRight()[n].GetRow();
if (y2 > y1)
str.Append(END_OF_LINE);
for (i = y1; i <= y2; i++)
{
str.Append(GetExportLine(i, x1, x2));
if (i < y2 && (generatesql > 1)) str.Append(linedelim);
if (y2 > y1)
str.Append(END_OF_LINE);
}
copied = copied+(y2 - y1 + 1);
}
copied = y2 - y1 + 1;
}
else
{
int row, col;
if (generatesql > 1) {
wxGridCellCoordsArray cord = GetSelectedCells();
int count = cord.GetCount();
int curr_row = 1000000000;
int next_row = 1000000000;
for (size_t n = 0; n < count; n++)
{
wxGridCellCoords& coords = cord[n];
if (coords.GetRow() < curr_row) curr_row = coords.GetRow();
}
while (curr_row != 1000000000)
{
wxArrayInt colsNum;
next_row = 1000000000;
for (size_t n = 0; n < count; n++)
{
wxGridCellCoords& coords = cord[n];
//wxString msg;
//msg.Printf(wxT("Êîîðäèíàòû âûáðàíûõ ÿ÷ååê row=%d col=%d.\n"), coords.GetRow(), coords.GetCol());
//wxMessageBox(msg, wxT("About coord"), wxOK | wxICON_INFORMATION, this);
int r = coords.GetRow();
if (r == curr_row) {
colsNum.Add(coords.GetCol());
}
else if (r > curr_row && r < next_row) next_row = r;
row = GetGridCursorRow();
col = GetGridCursorCol();
}
colsNum.Sort(compare_int);
if (generatesql == 2) AppendColumnHeader(str, colsNum);
str.Append(GetExportLine(curr_row, colsNum));
if ((next_row != 1000000000) && (generatesql == 3)) str.Append(linedelim);
if ((next_row != 1000000000) && (generatesql == 2)) str.Append(") or ");
str.Append(END_OF_LINE);
curr_row = next_row;
copied++;
}
}
else {
row = GetGridCursorRow();
col = GetGridCursorCol();
AppendColumnHeader(str, col, col);
AppendColumnHeader(str, col, col);
str.Append(GetExportLine(row, col, col));
copied = 1;
str.Append(GetExportLine(row, col, col));
copied = 1;
}
}
if (copied && (generatesql == 2)) str.Append(")");
if (copied && wxTheClipboard->Open())
{
wxTheClipboard->SetData(new wxTextDataObject(str));

View file

@ -486,11 +486,13 @@ bool pgConn::BackendMinimumVersion(int major, int minor)
if (!majorVersion)
{
wxString version = GetVersionString();
minorVersion = 0;
patchVersion = 0;
sscanf(version.ToAscii(), "%*s %d.%d.%d", &majorVersion, &minorVersion, &patchVersion);
isEdb = version.Upper().Matches(wxT("ENTERPRISEDB*"));
if (version.Upper().Matches(wxT("*11BETA*"))) {
majorVersion=11;
minorVersion=0;
if (!majorVersion) {
wxString vers=ExecuteScalar(wxT("SELECT current_setting('server_version_num');"));
sscanf(vers.ToAscii(), "%2d%04d", &majorVersion, &minorVersion);
}
// EnterpriseDB 8.3 beta 1 & 2 and possibly later actually have PostgreSQL 8.2 style
// catalogs. This is expected to change either before GA, but in the meantime we
@ -545,7 +547,7 @@ bool pgConn::HasFeature(int featureNo, bool forceCheck)
wxT(" JOIN pg_namespace n ON n.oid=pronamespace\n")
wxT(" WHERE proname IN ('pg_tablespace_size', 'pg_file_read', 'pg_logfile_rotate',")
wxT( " 'pg_postmaster_starttime', 'pg_terminate_backend', 'pg_reload_conf',")
wxT( " 'pgstattuple', 'pgstatindex')\n")
wxT( " 'pgstattuple', 'pgstatindex','bt_index_parent_check')\n")
wxT(" AND nspname IN ('pg_catalog', 'public')");
pgSet *set = ExecuteSet(sql);
@ -556,6 +558,7 @@ bool pgConn::HasFeature(int featureNo, bool forceCheck)
{
wxString proname = set->GetVal(wxT("proname"));
long pronargs = set->GetLong(wxT("pronargs"));
if (BackendMinimumVersion(9, 6)) features[FEATURE_FILEREAD] = true;
if (proname == wxT("pg_tablespace_size") && pronargs == 1 && set->GetLong(wxT("arg0")) == 26)
features[FEATURE_SIZE] = true;
@ -574,6 +577,8 @@ bool pgConn::HasFeature(int featureNo, bool forceCheck)
features[FEATURE_PGSTATTUPLE] = true;
else if (proname == wxT("pgstatindex") && pronargs == 1 && set->GetLong(wxT("arg0")) == 25)
features[FEATURE_PGSTATINDEX] = true;
else if (proname == wxT("bt_index_parent_check") && pronargs == 2 )
features[FEATURE_PGCHECKINDEX] = true;
set->MoveNext();
}

View file

@ -114,7 +114,7 @@ int dlgLanguage::Go(bool modal)
else
{
// create mode
if (connection->BackendMinimumVersion(8, 1))
if (connection->BackendMinimumVersion(8, 1)&&(!connection->BackendMinimumVersion(13, 0)))
{
pgSetIterator languages(connection,
wxT("SELECT tmplname FROM pg_pltemplate\n")

View file

@ -20,9 +20,8 @@
// Copyright text
#include "copyright.h"
#include "version.h"
#include "svnversion.h"
#define VERSION_WITH_DATE_AND_SVN wxT("Version ") VERSION_STR wxT(" (") __TDATE__ wxT(", rev: ") wxT(VERSION_SVN) wxT(")")
#define VERSION_WITH_DATE_AND_SVN wxT("Version ") VERSION_STR wxT(" (") __TDATE__ wxT(", rev: ") wxT("") wxT(")")
BEGIN_EVENT_TABLE(frmAbout, wxFrame)

View file

@ -315,6 +315,7 @@ void frmMain::CreateMenus()
new refreshConcurrentlyMatViewFactory(menuFactories, viewMenu, 0);
new executePgstattupleFactory(menuFactories, viewMenu, 0);
new executePgstatindexFactory(menuFactories, viewMenu, 0);
new executePgcheckindexFactory(menuFactories, viewMenu, 0);
new enabledisableRuleFactory(menuFactories, toolsMenu, 0);
new enabledisableTriggerFactory(menuFactories, toolsMenu, 0);
new enabledisableEventTriggerFactory(menuFactories, toolsMenu, 0);
@ -432,7 +433,8 @@ void frmMain::CreateMenus()
new reportObjectDependentsFactory(menuFactories, reportMenu, 0);
new reportObjectListFactory(menuFactories, reportMenu, 0);
new reportCompareFactory(menuFactories, reportMenu, 0);
choiceSelectOpts.Add(0);
choiceSelectOpts.Add(1);
toolsMenu->AppendSeparator();

View file

@ -121,6 +121,8 @@ BEGIN_EVENT_TABLE(frmQuery, pgFrame)
EVT_MENU(MNU_CLEAR, frmQuery::OnClear)
EVT_MENU(MNU_SUMMARY_COL, frmQuery::OnSummary_Column)
EVT_MENU(MNU_COPY_INSERT, frmQuery::OnCopy_Insert)
EVT_MENU(MNU_COPY_INLIST, frmQuery::OnCopy_InList)
EVT_MENU(MNU_COPY_WHERELIST, frmQuery::OnCopy_WhereList)
EVT_MENU(MNU_CLEAR_FILTER, frmQuery::OnClear_Filter)
EVT_MENU(MNU_FIND, frmQuery::OnSearchReplace)
EVT_MENU(MNU_UNDO, frmQuery::OnUndo)
@ -1544,7 +1546,7 @@ void frmQuery::OnCopy(wxCommandEvent &ev)
{
if (obj == sqlResult)
{
sqlResult->Copy(false);
sqlResult->Copy(0);
break;
}
obj = obj->GetParent();
@ -2011,6 +2013,9 @@ void frmQuery::OnLabelRightClick(wxGridEvent &event)
xmenu->Append(MNU_DELETE, _("&Delete"), _("Delete selected rows."));
xmenu->Append(MNU_SUMMARY_COL, _("Summary"), _("Summary selected cells."));
xmenu->Append(MNU_COPY_INSERT, _("Copy Insert format"), _("Copy Insert format."));
xmenu->Append(MNU_COPY_INLIST, _("IN LIST format copy"), _("Copy In list format."));
xmenu->Append(MNU_COPY_WHERELIST, _("WHERE LIST format copy"), _("Copy where list format."));
xmenu->Append(MNU_CLEAR_FILTER, _("Clear filter"), _("Clear filter"));
if ((rows.GetCount()))
@ -2033,11 +2038,29 @@ void frmQuery::OnCopy_Insert(wxCommandEvent &ev)
// if (currentControl() == sqlResult)
{
wxString s=wxT("Insert into format copy buffer.");
sqlResult->Copy(true);
sqlResult->Copy(1);
SetStatusText(s, STATUSPOS_POS);
}
}
void frmQuery::OnCellLeftDClick(wxGridEvent &event)
void frmQuery::OnCopy_InList(wxCommandEvent& ev)
{
// if (currentControl() == sqlResult)
{
wxString s = wxT("In list format copy buffer.");
sqlResult->Copy(2);
SetStatusText(s, STATUSPOS_POS);
}
}
void frmQuery::OnCopy_WhereList(wxCommandEvent& ev)
{
// if (currentControl() == sqlResult)
{
wxString s = wxT("Where list format copy buffer.");
sqlResult->Copy(3);
SetStatusText(s, STATUSPOS_POS);
}
}
void frmQuery::OnCellLeftDClick(wxGridEvent &event)
{
int row=event.GetRow();
int col=event.GetCol();

View file

@ -14,6 +14,7 @@
// App headers
#include "pgAdmin3.h"
#include <wx/file.h>
#include <wx/regex.h>
#include "frm/frmMain.h"
#include "frm/frmReport.h"
@ -1222,6 +1223,59 @@ wxString reportCompareFactory::GetNodePath(wxTreeItemId node) {
return path;
}
wxString reportCompareFactory::ApplyCompareOpts(wxString sql,int metatype) {
if (sql.IsEmpty()) return "";
bool no_comment = parent->getChoiceSelect(1);
bool no_priv = parent->getChoiceSelect(0);
if (no_comment) {
int last = 0;
while (last!=-1) {
last = sql.Find("\nCOMMENT ON");
int start = last;
int end = -1;
while (last!=-1) {
last++;
if (sql.Length() == last) { last = -1; continue; }
wxChar c = sql.GetChar(last);
if (c == '\'') {
last++;
if (sql.GetChar(last) == '\'') { continue; }
if (sql.GetChar(last) == ';') { end = last; last = -1; continue; }
}
};
if (end != -1) {
sql=sql.Remove(start, end - start+1);
last = 0;
}
}
}
if (no_priv &&(metatype != PGM_ROLE)) {
int last = 0;
while (last != -1) {
last = sql.Find("\nGRANT ");
if (last==-1) last = sql.Find("\nREVOKE ");
int start = last;
int end = -1;
while (last != -1) {
last++;
if (sql.Length() == last) { last = -1; continue; }
wxChar c = sql.GetChar(last);
if (c == ';') {
end = last; last = -1;
}
};
if (end != -1) {
sql = sql.Remove(start, end - start + 1);
last = 0;
}
}
}
return sql;
}
void reportCompareFactory::GetExpandedChildNodes(wxTreeItemId node, wxArrayString &expandedNodes, ArraySQL &list, time_t *t, wxBusyInfo *w, MyHashSQL &h_path,int lvl)
{
@ -1312,6 +1366,7 @@ void reportCompareFactory::GetExpandedChildNodes(wxTreeItemId node, wxArrayStrin
if (obj ) {
wxString s=obj->GetSql(browser);
if (obj->GetMetaType()==PGM_SEQUENCE) s="";
s = ApplyCompareOpts(s, obj->GetMetaType());
int c=browser->GetChildrenCount(child,false);
if (size>0) {
wxString srcpath(path);
@ -1492,6 +1547,7 @@ if (lastdb!=NULL) {
wxMessageBox(msg, _("Error"), wxOK | wxICON_INFORMATION);
return 0;
}
if (!parent->StartChoiceDialog()) return 0;
time_t timer=wxDateTime::GetTimeNow();
wxArrayString expandedNodes;
ArraySQL list;
@ -1499,12 +1555,14 @@ time_t timer=wxDateTime::GetTimeNow();
wxWindowDisabler disableAll;
{
#ifndef DEBUG
wxBusyInfo waiting(wxString::Format(" Îáõîä èñõîäíîé ÁÄ Path = %s ,Ñòàðòîâûé îáúåêò = %s",
browser->GetItemText(obj->GetServer()->GetId()).c_str(), obj->GetName().c_str(),parent));
// Give the UI a chance to redraw
wxSafeYield();
wxMilliSleep(50);
wxSafeYield();
#endif
// waiting->~wxBusyInfo();
GetExpandedChildNodes(obj->GetId(),expandedNodes,list,&timer, NULL,h_path,0);
}
@ -1809,7 +1867,7 @@ std::wstring reportCompareFactory::printdiff(std::wstring str1, std::wstring str
++it;
}
#ifdef _DEBUG
wxFileName fn("D:\\PostgreSQL\\cmp.txt");
wxFileName fn("cmp_debug.txt");
fn.MakeAbsolute();
wxFile file(fn.GetFullPath(), wxFile::write);

View file

@ -44,6 +44,7 @@
#include "images/terminate_backend.pngc"
#include "images/delete.pngc"
#include "images/storedata.pngc"
#include "images/sortfilterclear.pngc"
#include "images/down.pngc"
#include "images/up.pngc"
@ -83,6 +84,7 @@ BEGIN_EVENT_TABLE(frmStatus, pgFrame)
EVT_MENU(MNU_TERMINATE, frmStatus::OnTerminateBtn)
EVT_MENU(MNU_COMMIT, frmStatus::OnCommit)
EVT_MENU(MNU_ROLLBACK, frmStatus::OnRollback)
EVT_MENU(MNU_CLEAR_FILTER_SERVER_STATUS, frmStatus::OnClearFilter)
EVT_COMBOBOX(CTL_LOGCBO, frmStatus::OnLoadLogfile)
EVT_BUTTON(CTL_ROTATEBTN, frmStatus::OnRotateLogfile)
@ -91,6 +93,7 @@ BEGIN_EVENT_TABLE(frmStatus, pgFrame)
EVT_TIMER(TIMER_STATUS_ID, frmStatus::OnRefreshStatusTimer)
EVT_LIST_ITEM_SELECTED(CTL_STATUSLIST, frmStatus::OnSelStatusItem)
EVT_LIST_ITEM_DESELECTED(CTL_STATUSLIST, frmStatus::OnSelStatusItem)
EVT_LIST_ITEM_RIGHT_CLICK(CTL_STATUSLIST, frmStatus::OnRightClickStatusItem)
EVT_LIST_COL_CLICK(CTL_STATUSLIST, frmStatus::OnSortStatusGrid)
EVT_LIST_COL_RIGHT_CLICK(CTL_STATUSLIST, frmStatus::OnRightClickStatusGrid)
EVT_LIST_COL_END_DRAG(CTL_STATUSLIST, frmStatus::OnChgColSizeStatusGrid)
@ -219,6 +222,12 @@ frmStatus::frmStatus(frmMain *form, const wxString &_title, pgConn *conn) : pgFr
initquery = wxT("SET log_statement='off';SET log_duration='off';SET log_min_duration_statement=-1;");
connection->ExecuteVoid(initquery, false);
}
//pg_is_in_recovery()
wxString v = connection->ExecuteScalar(wxT("select pg_is_in_recovery()"));
isrecovery = (v == wxT("t"));
v = connection->ExecuteScalar(wxT("select current_setting('track_commit_timestamp')"));
track_commit_timestamp = (v == wxT("on"));
delete user;
}
@ -314,6 +323,9 @@ frmStatus::frmStatus(frmMain *form, const wxString &_title, pgConn *conn) : pgFr
toolBar->AddTool(MNU_COMMIT, wxEmptyString, *storedata_png_bmp, _("Commit transaction"), wxITEM_NORMAL);
toolBar->AddTool(MNU_ROLLBACK, wxEmptyString, *delete_png_bmp, _("Rollback transaction"), wxITEM_NORMAL);
toolBar->AddSeparator();
toolBar->AddTool(MNU_CLEAR_FILTER_SERVER_STATUS, wxEmptyString, *sortfilterclear_png_bmp, _("Clear filter"), wxITEM_NORMAL);
toolBar->AddSeparator();
cbLogfiles = new wxComboBox(toolBar, CTL_LOGCBO, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL,
wxCB_READONLY | wxCB_DROPDOWN);
toolBar->AddControl(cbLogfiles);
@ -344,6 +356,7 @@ frmStatus::frmStatus(frmMain *form, const wxString &_title, pgConn *conn) : pgFr
toolBar->EnableTool(MNU_TERMINATE, false);
toolBar->EnableTool(MNU_COMMIT, false);
toolBar->EnableTool(MNU_ROLLBACK, false);
toolBar->EnableTool(MNU_CLEAR_FILTER_SERVER_STATUS, false);
actionMenu->Enable(MNU_CANCEL, false);
actionMenu->Enable(MNU_TERMINATE, false);
actionMenu->Enable(MNU_COMMIT, false);
@ -1024,7 +1037,7 @@ void frmStatus::AddLogPane()
// Add the log list
logList = (ctlListView *)lstLog;
bgColor = logList->GetBackgroundColour();
// We don't need this report (but we need the pane)
// if server release is less than 8.0 or if server has no adminpack
if (!(connection->BackendMinimumVersion(8, 0) &&
@ -1640,10 +1653,22 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event)
q += wxT("false");
}
q += wxT("AS slowquery\n");
if (connection->BackendMinimumVersion(9, 6))
bool iswalsend = false;
if (connection->BackendMinimumVersion(10, 0))
{
q += wxT(",wait_event_type,wait_event,v.heap_blks_total,v.heap_blks_vacuumed,v.heap_blks_scanned,v.phase\n");
q += wxT("FROM pg_stat_activity p LEFT JOIN pg_stat_progress_vacuum v ON p.pid=v.pid ");
q += wxT(",backend_type,wait_event_type,wait_event,v.heap_blks_total,v.heap_blks_vacuumed,v.heap_blks_scanned,v.phase\n");
wxString xact="";
if (!track_commit_timestamp)
q += wxT(",coalesce(sl.xmin,sl.catalog_xmin)::text xmin_slot,':'||slot_name||'['||sl.slot_type||']' slotinfo,'LagSent:'||pg_size_pretty(pg_wal_lsn_diff(pg_last_wal_receive_lsn(),coalesce(confirmed_flush_lsn,restart_lsn)))||' LagXmin: -1'||' s' xminlag,-1 xminslotdelta\n");
else if (isrecovery)
q += wxT(",coalesce(sl.xmin,sl.catalog_xmin)::text xmin_slot,':'||slot_name||'['||sl.slot_type||']' slotinfo,'LagSent:'||pg_size_pretty(pg_wal_lsn_diff(pg_last_wal_receive_lsn(),coalesce(confirmed_flush_lsn,restart_lsn)))||' LagXmin: '||coalesce(extract(epoch from (pg_last_committed_xact()).timestamp - pg_xact_commit_timestamp(xmin))::int,0)||' s' xminlag,coalesce(extract(epoch from (pg_last_committed_xact()).timestamp - pg_xact_commit_timestamp(xmin))::int,0) xminslotdelta\n");
else
q += wxT(",coalesce(sl.xmin,sl.catalog_xmin)::text xmin_slot,':'||slot_name||'['||sl.slot_type||']' slotinfo,'LagSent:'||pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(),coalesce(confirmed_flush_lsn,restart_lsn)))||' LagXmin: '||coalesce(extract(epoch from (pg_last_committed_xact()).timestamp - pg_xact_commit_timestamp(xmin))::int,0)||' s' xminlag,coalesce(extract(epoch from (pg_last_committed_xact()).timestamp - pg_xact_commit_timestamp(xmin))::int,0) xminslotdelta\n");
q += wxT("FROM pg_stat_activity p LEFT JOIN pg_stat_progress_vacuum v ON p.pid=v.pid\n");
q += wxT("LEFT JOIN pg_replication_slots sl ON p.pid=sl.active_pid ");
iswalsend = true;
//backend_type
} else
{
q += wxT("FROM pg_stat_activity p ");
@ -1666,12 +1691,14 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event)
while (!dataSet1->Eof())
{
pid = dataSet1->GetLong(wxT("pid"));
wxString slinfo=wxEmptyString;
if (iswalsend) {
slinfo = dataSet1->GetVal(wxT("slotinfo"));
}
// Update the UI
if (pid != backend_pid)
{
pids.Add(pid);
// Add the query content to the queries array
queries.Add(dataSet1->GetVal(wxT("query")));
if (row >= statusList->GetItemCount())
{
@ -1705,7 +1732,7 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event)
str.Printf(wxT("%s %5.2f%%"), phase, proc);
app_name=str;
}
if (!slinfo.IsEmpty()) app_name += slinfo;
}
int colpos = 1;
if (connection->BackendMinimumVersion(8, 5))
@ -1735,7 +1762,9 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event)
if (connection->BackendMinimumVersion(9, 4))
{
statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("backend_xid")));
statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("backend_xmin")));
if (!slinfo.IsEmpty()) statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("xmin_slot")));
else
statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("backend_xmin")));
}
if (connection->BackendMinimumVersion(9, 6))
{
@ -1745,7 +1774,11 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event)
}
statusList->SetItem(row, colpos++, dataSet1->GetVal(wxT("blockedby")));
statusList->SetItem(row, colpos, qry);
if (!slinfo.IsEmpty()) {
statusList->SetItem(row, colpos, dataSet1->GetVal(wxT("xminlag")));
}
else
statusList->SetItem(row, colpos, qry);
// Colorize the new line
if (viewMenu->IsChecked(MNU_HIGHLIGHTSTATUS))
@ -1771,11 +1804,46 @@ void frmStatus::OnRefreshStatusTimer(wxTimerEvent &event)
blocked += dataSet1->GetVal(wxT("blockedby"));
blocked += wxT(",");
}
if (!slinfo.IsEmpty()) {
// walsender
long xmindelta = dataSet1->GetLong(wxT("xminslotdelta"));
if (xmindelta>=1800)
statusList->SetItemBackgroundColour(row,wxColour(wxT("#FF8028"))); // orange
else
statusList->SetItemBackgroundColour(row, wxColour(settings->GetIdleProcessColour())); // idle
}
if (app_name.StartsWith(wxT("pgp-s super"))||app_name.StartsWith(wxT("pgp-s manager"))) statusList->SetItemBackgroundColour(row, wxColour(settings->GetIdleProcessColour())); // idle
}
else
statusList->SetItemBackgroundColour(row, *wxWHITE);
row++;
// filter apply
bool flt = false;
for (int i = 0; i < filterColumn.size(); i++) {
int col = filterColumn[i];
wxListItem listitem;
listitem.SetMask(wxLIST_MASK_TEXT);
statusList->GetColumn(col, listitem);
wxString label = listitem.GetText();
wxString tabval=statusList->GetItemText(row, col);
wxString fval = filterValue[i];
if (label == _("Client")) {
tabval = tabval.BeforeLast(':');
fval = fval.BeforeLast(':');
}
if (tabval != fval) {
flt = true;
break;
}
}
if (!flt) {
// Add the query content to the queries array
queries.Add(dataSet1->GetVal(wxT("query")));
pids.Add(pid);
row++;
}
}
dataSet1->MoveNext();
}
@ -2244,7 +2312,12 @@ void frmStatus::OnRefreshLogTimer(wxTimerEvent &event)
if (isCurrent)
{
// check if the current logfile changed
pgSet *set = connection->ExecuteSet(wxT("SELECT pg_file_length(") + connection->qtDbString(logfileName) + wxT(") AS len"));
pgSet* set;
if ((connection->BackendMinimumVersion(10, 0)))
set = connection->ExecuteSet(wxT("select size len from pg_stat_file(") + connection->qtDbString(logfileName) + wxT(")"));
else
set = connection->ExecuteSet(wxT("SELECT pg_file_length(") + connection->qtDbString(logfileName) + wxT(") AS len"));
if (set)
{
newlen = set->GetLong(wxT("len"));
@ -2257,10 +2330,24 @@ void frmStatus::OnRefreshLogTimer(wxTimerEvent &event)
}
if (newlen > logfileLength)
{
long lastrow = logList->GetItemCount();
bool remote = lastrow-1 == logList->GetFocusedItem();
statusBar->SetStatusText(_("Refreshing log list."));
addLogFile(logfileName, logfileTimestamp, newlen, logfileLength, false);
statusBar->SetStatusText(_("Done."));
if (bgColor == logList->GetBackgroundColour()) bgColor = wxColour("#afafaf"); else
{
bgColor = logList->GetBackgroundColour();
}
if (remote) {
//logList->Select(lastrow - 1,false);
//logList->SetScrollPos(wxGA_VERTICAL, logList->GetItemCount() - 1, true);
//logList->Select(logList->GetItemCount() - 1);
logList->Focus(logList->GetItemCount() - 1);
//logList->Show
}
// as long as there was new data, the logfile is probably the current
// one so we don't need to check for rotation
return;
@ -2344,7 +2431,13 @@ void frmStatus::checkConnection()
void frmStatus::addLogFile(wxDateTime *dt, bool skipFirst)
{
pgSet *set = connection->ExecuteSet(
pgSet* set;
if (settings->GetASUTPstyle()) {
set = connection->ExecuteSet(
wxT("select current_setting('log_directory')||'/'||name filename,modification filetime,size len\n")
wxT(" FROM pg_ls_logdir() where modification = '") + DateToAnsiStr(*dt) + wxT("'::timestamp"));
} else
set = connection->ExecuteSet(
wxT("SELECT filetime, filename, pg_file_length(filename) AS len ")
wxT(" FROM pg_logdir_ls() AS A(filetime timestamp, filename text) ")
wxT(" WHERE filetime = '") + DateToAnsiStr(*dt) + wxT("'::timestamp"));
@ -2395,11 +2488,12 @@ void frmStatus::addLogFile(const wxString &filename, const wxDateTime timestamp,
else
line = savedPartialLine;
}
wxString funcname = "pg_read_file(";
if (!settings->GetASUTPstyle()) funcname = "pg_file_read(";
while (len > read)
{
statusBar->SetStatusText(_("Reading log from server..."));
pgSet *set = connection->ExecuteSet(wxT("SELECT pg_file_read(") +
pgSet *set = connection->ExecuteSet(wxT("SELECT ") + funcname +
connection->qtDbString(filename) + wxT(", ") + NumToStr(read) + wxT(", 50000)"));
if (!set)
{
@ -2417,10 +2511,13 @@ void frmStatus::addLogFile(const wxString &filename, const wxDateTime timestamp,
read += strlen(raw);
wxString str;
if (wxString(wxString(raw, wxConvLibc).wx_str(), wxConvUTF8).Len() > 0)
str = line + wxString(wxString(raw, wxConvLibc).wx_str(), wxConvUTF8);
else
str = line + wxTextBuffer::Translate(wxString(raw, set->GetConversion()), wxTextFileType_Unix);
str = line + wxTextBuffer::Translate(wxString(raw, set->GetConversion()), wxTextFileType_Unix);
//if (wxString(wxString(raw, wxConvLibc).wx_str(), wxConvUTF8).Len() > 0)
// str = line + wxString(wxString(raw, wxConvLibc).wx_str(), wxConvUTF8);
//else {
// str = line + wxTextBuffer::Translate(wxString(raw, set->GetConversion()), wxTextFileType_Unix);
//}
delete set;
@ -2563,8 +2660,11 @@ void frmStatus::addLogLine(const wxString &str, bool formatted, bool csv_log_for
}
}
if (!logFormatKnown)
if (!logFormatKnown) {
logList->AppendItem(-1, str);
if (bgColor != logList->GetBackgroundColour()) logList->SetItemBackgroundColour(row, bgColor);
}
else if ((!csv_log_format) && str.Find(':') < 0)
{
// Must be a continuation of a previous line.
@ -2847,8 +2947,9 @@ void frmStatus::addLogLine(const wxString &str, bool formatted, bool csv_log_for
int pos = rest.Find(':');
if (pos < 0)
if (pos < 0) {
logList->InsertItem(row, rest, -1);
}
else
{
logList->InsertItem(row, rest.BeforeFirst(':'), -1);
@ -2882,11 +2983,19 @@ int frmStatus::fillLogfileCombo()
cbLogfiles->Append(_("Current log"));
else
count--;
pgSet* set;
if (settings->GetASUTPstyle())
set = connection->ExecuteSet(
wxT("select name filename,modification filetime\n")
wxT(" FROM pg_ls_logdir() where name ~ '.csv'\n")
wxT(" ORDER BY modification DESC"));
else set = connection->ExecuteSet(
wxT("SELECT filename, filetime\n")
wxT(" FROM pg_logdir_ls() AS A(filetime timestamp, filename text) \n")
wxT(" ORDER BY filetime DESC"));
pgSet *set = connection->ExecuteSet(
wxT("SELECT filename, filetime\n")
wxT(" FROM pg_logdir_ls() AS A(filetime timestamp, filename text)\n")
wxT(" ORDER BY filetime DESC"));
if (set)
{
if (set->NumRows() <= count)
@ -3252,7 +3361,6 @@ void frmStatus::OnCommit(wxCommandEvent &event)
OnSelXactItem(ev);
}
void frmStatus::OnRollback(wxCommandEvent &event)
{
long item = xactList->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
@ -3513,6 +3621,51 @@ void frmStatus::SetColumnImage(ctlListView *list, int col, int image)
list->SetColumn(col, item);
}
void frmStatus::OnRightClickStatusItem(wxListEvent& event)
{
int row = event.GetIndex();
//wxString txt = event.GetText();
wxRect r;
//statusList->GetItemRect(row, r);
wxString ss = wxEmptyString;
int col = -1;
for (int cc = 0; cc < statusList->GetColumnCount();cc++) {
statusList->GetSubItemRect(row, cc, r, wxLIST_RECT_BOUNDS);
if (r.Contains(event.GetPoint())) {
ss = wxString::Format("\rBounding rect of item %ld column %d is (%d, %d)-(%d, %d)", row,cc, r.x, r.y, r.x + r.width, r.y + r.height);
col = cc;
break;
}
}
if (col == -1) return;
wxString val=statusList->GetItemText(row, col);
wxString txt = wxString::Format("gettext=%s\r index=%d\r column=%d", val.c_str(), row, col);
txt = txt + ss;
wxListItem listitem;
listitem.SetMask(wxLIST_MASK_TEXT);
statusList->GetColumn(col, listitem);
wxString label = listitem.GetText()+" = "+val;
//wxMessageBox(txt, "test", wxICON_WARNING | wxOK);
wxString hint=label;
if (filterColumn.size() > 0) hint = toolBar->GetToolShortHelp(MNU_CLEAR_FILTER_SERVER_STATUS)+"\n"+label;
filterColumn.Add(col);
filterValue.Add(val);
toolBar->SetToolShortHelp(MNU_CLEAR_FILTER_SERVER_STATUS, hint);
toolBar->EnableTool(MNU_CLEAR_FILTER_SERVER_STATUS, true);
wxTimerEvent evt;
OnRefreshStatusTimer(evt);
}
void frmStatus::OnClearFilter(wxCommandEvent& event) {
toolBar->EnableTool(MNU_CLEAR_FILTER_SERVER_STATUS, false);
toolBar->SetToolShortHelp(MNU_CLEAR_FILTER_SERVER_STATUS, "Clear filter");
filterColumn.Clear();
filterValue.Clear();
wxTimerEvent evt;
OnRefreshStatusTimer(evt);
}
void frmStatus::OnSortStatusGrid(wxListEvent &event)
{

View file

@ -21,46 +21,53 @@ class frmMain;
class ctlListView : public wxListView
{
private:
void OnSortGrid(wxListEvent& event);
bool nosort; // åñëè êòî òî ïîëüçóåòñÿ SetItemData òî íå áóäåì ñîðòèðîâàòü òàêèå ctlListView
int order, prev_col;
public:
ctlListView(wxWindow *p, int id, wxPoint pos, wxSize siz, long attr = 0);
bool SetItemData(long item, long data) {
nosort = true;
return wxListView::SetItemData(item, data);
}
ctlListView(wxWindow* p, int id, wxPoint pos, wxSize siz, long attr = 0);
long GetSelection();
wxString GetText(long row, long col = 0);
void CreateColumns(wxImageList* images, const wxString& left, const wxString& right, int leftSize = 60);
void CreateColumns(wxImageList* images, const wxString& str1, const wxString& str2, const wxString& str3, int leftSize = 60);
void CreateColumns(wxImageList *images, const wxString &left, const wxString &right, int leftSize = 60);
void CreateColumns(wxImageList *images, const wxString &str1, const wxString &str2, const wxString &str3, int leftSize = 60);
void AddColumn(const wxString& text, int size = wxLIST_AUTOSIZE_USEHEADER, int format = wxLIST_FORMAT_LEFT);
void AddColumn(const wxString &text, int size = wxLIST_AUTOSIZE_USEHEADER, int format = wxLIST_FORMAT_LEFT);
long AppendItem(int icon, const wxString &val, const wxString &val2 = wxString(), const wxString &val3 = wxString(), const wxString &val4 = wxString());
long AppendItem(const wxString &val, const wxString &val2 = wxString(), const wxString &val3 = wxString())
long AppendItem(int icon, const wxString& val, const wxString& val2 = wxString(), const wxString& val3 = wxString(), const wxString& val4 = wxString());
long AppendItem(const wxString& val, const wxString& val2 = wxString(), const wxString& val3 = wxString())
{
return AppendItem(PGICON_PROPERTY, val, val2, val3);
}
void AppendItem(const wxString &str, long l)
void AppendItem(const wxString& str, long l)
{
AppendItem(str, NumToStr(l));
}
void AppendItem(const wxString &str, double d)
void AppendItem(const wxString& str, double d)
{
AppendItem(str, NumToStr(d));
}
void AppendItem(const wxString &str, OID o)
void AppendItem(const wxString& str, OID o)
{
AppendItem(str, NumToStr(o));
}
void AppendItem(const wxString &str, const wxDateTime &d)
void AppendItem(const wxString& str, const wxDateTime& d)
{
AppendItem(str, DateToStr(d));
}
void AppendItem(const wxString &str, const wxLongLong &l)
void AppendItem(const wxString& str, const wxLongLong& l)
{
AppendItem(str, l.ToString());
}
void AppendItem(const wxString &str, const wxULongLong &l)
void AppendItem(const wxString& str, const wxULongLong& l)
{
AppendItem(str, l.ToString());
}
void AppendYesNoItem(const wxString &str, bool b)
void AppendYesNoItem(const wxString& str, bool b)
{
AppendItem(str, BoolToYesNo(b));
}
@ -69,6 +76,7 @@ public:
{
DeleteItem(GetSelection());
}
};

View file

@ -30,7 +30,7 @@ public:
{
return false;
}
int Copy(bool gensql);
int Copy(int gensql);
virtual bool CheckRowPresent(int row)
{
@ -55,7 +55,7 @@ public:
wxString GetRowLabelValue( int row );
void SetRowGroup(int row);
GroupRows *grp;
bool generatesql;
int generatesql; // 0 -íåò, 1 - insert , 2 - in_list
WX_DECLARE_STRING_HASH_MAP( int, ColKeySizeHashMap );
DECLARE_DYNAMIC_CLASS(ctlSQLGrid)

View file

@ -107,7 +107,28 @@ public:
currentObject = data;
}
bool CheckAlive();
//
bool getChoiceSelect(int index) {
for (size_t n = 0; n < choiceSelectOpts.GetCount(); n++) {
if (choiceSelectOpts[n] == index) return true;
}
return false;
}
bool StartChoiceDialog() {
choiceCmpOpts.Clear();
choiceCmpOpts.Add("Priveleges ignore");
choiceCmpOpts.Add("Comment ignore");
wxMultiChoiceDialog dialog(this,
wxT("A multi-choice convenience dialog"),
wxT("Please select several compare options"),
choiceCmpOpts);
dialog.SetSelections(choiceSelectOpts);
if (dialog.ShowModal() == wxID_OK) {
choiceSelectOpts = dialog.GetSelections();
return true;
}
return false;
}
void execSelChange(wxTreeItemId item, bool currentNode);
void Refresh(pgObject *data);
void ExecDrop(bool cascaded);
@ -203,6 +224,8 @@ private:
long msgLevel;
bool m_refreshing;
wxArrayString choiceCmpOpts;
wxArrayInt choiceSelectOpts;
wxTreeItemId denyCollapseItem;
pgObject *currentObject;

View file

@ -212,6 +212,8 @@ private:
void OnClear(wxCommandEvent &event);
void OnSummary_Column(wxCommandEvent &event);
void OnCopy_Insert(wxCommandEvent &event);
void OnCopy_InList(wxCommandEvent& event);
void OnCopy_WhereList(wxCommandEvent& event);
void OnClear_Filter(wxCommandEvent &event);
void OnSearchReplace(wxCommandEvent &event);
void OnUndo(wxCommandEvent &event);

View file

@ -141,6 +141,7 @@ private:
protected:
//reportCompareFactory(menuFactoryList *list) : actionFactory(list) {}
wxString reportCompareFactory::GetNodePath(wxTreeItemId node);
wxString ApplyCompareOpts(wxString sql, int metatype);
wxWindow *StartDialog(frmMain *form, pgObject *obj);
void reportCompareFactory::GetExpandedChildNodes(wxTreeItemId node, wxArrayString &expandedNodes, ArraySQL &list,time_t *t,wxBusyInfo *w, MyHashSQL &h_path,int lvl);
std::wstring reportCompareFactory::printdiff(std::wstring str1, std::wstring str2 );

View file

@ -50,6 +50,7 @@ enum
MNU_COMMIT,
MNU_ROLLBACK,
MNU_COPY_QUERY,
MNU_CLEAR_FILTER_SERVER_STATUS,
MNU_COPY_QUERY_PLAN,
MNU_HIGHLIGHTSTATUS,
MNU_QUERYSTATEVERBOSE,
@ -122,9 +123,10 @@ private:
long backend_pid;
int wait_event_type_col;
bool isrecovery,track_commit_timestamp;
bool loaded;
long logfileLength;
wxColour bgColor;
int currentPane;
@ -157,6 +159,8 @@ private:
wxMenu *querystatePopupMenu;
wxString queryplan;
wxArrayString queries;
wxArrayInt filterColumn;
wxArrayString filterValue;
int statusColWidth[12], lockColWidth[10], xactColWidth[5], querystateColWidth[5];
@ -198,6 +202,7 @@ private:
void SetColumnImage(ctlListView *list, int col, int image);
void OnSortStatusGrid(wxListEvent &event);
void OnRightClickStatusItem(wxListEvent& event);
void OnSortLockGrid(wxListEvent &event);
void OnSortXactGrid(wxListEvent &event);
@ -237,6 +242,7 @@ private:
void OnRotateLogfile(wxCommandEvent &event);
void OnCommit(wxCommandEvent &event);
void OnRollback(wxCommandEvent &event);
void OnClearFilter(wxCommandEvent& event);
void OnChangeDatabase(wxCommandEvent &ev);

View file

@ -77,6 +77,8 @@ enum
MNU_AUTOSELECTQUERY,
MNU_SUMMARY_COL,
MNU_COPY_INSERT,
MNU_COPY_INLIST,
MNU_COPY_WHERELIST,
MNU_CLEAR_FILTER,
MNU_AUTOROLLBACK,
MNU_AUTOCOMMIT,

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 B

View file

@ -0,0 +1,106 @@
#ifndef SORTFILTERCLEAR_PNG_H
#define SORTFILTERCLEAR_PNG_H
static const unsigned char sortfilterclear_png_data[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff,
0x61, 0x00, 0x00, 0x01, 0xb6, 0x49, 0x44, 0x41,
0x54, 0x78, 0xda, 0xa5, 0x93, 0x4b, 0x28, 0x04,
0x71, 0x1c, 0xc7, 0xbf, 0x7f, 0xb4, 0xd2, 0xa2,
0xbc, 0x72, 0x71, 0x20, 0x8f, 0x90, 0x76, 0xcb,
0xc1, 0x23, 0xef, 0x94, 0x1c, 0xb6, 0x2c, 0x89,
0x83, 0xc7, 0xd1, 0x23, 0x7b, 0x20, 0x07, 0xa5,
0x1c, 0x70, 0x44, 0x39, 0x28, 0x5c, 0x5c, 0x48,
0x49, 0xb9, 0x70, 0xd0, 0x2e, 0xa5, 0x24, 0xb6,
0x75, 0x11, 0x21, 0xd6, 0xee, 0xc5, 0x23, 0x9b,
0x57, 0xb1, 0xe6, 0xb1, 0x3b, 0xf3, 0x37, 0x33,
0x1a, 0x8d, 0xb5, 0x56, 0xda, 0xa9, 0x5f, 0xd3,
0x6f, 0xfe, 0xf3, 0xf9, 0xf4, 0xfd, 0xff, 0x66,
0xfe, 0x04, 0x61, 0x5e, 0x64, 0x71, 0x69, 0x97,
0x9e, 0x5f, 0xbc, 0xc1, 0xeb, 0x15, 0xfe, 0x05,
0xea, 0xf5, 0x91, 0xc8, 0xcd, 0x89, 0x05, 0x19,
0x1d, 0xdf, 0xa6, 0x96, 0xbe, 0x52, 0x44, 0xb2,
0x31, 0x60, 0xdf, 0x28, 0xfc, 0x7e, 0x01, 0xa2,
0x28, 0x4a, 0x77, 0x11, 0x82, 0x20, 0x28, 0xfd,
0x67, 0xf9, 0xe1, 0xf3, 0x09, 0x10, 0x44, 0x01,
0xf1, 0x89, 0x3a, 0xa4, 0xa6, 0xeb, 0x31, 0x33,
0x7b, 0xf0, 0x99, 0xc0, 0xe5, 0xe6, 0xd1, 0xd9,
0x5c, 0x02, 0xef, 0x4d, 0x14, 0x5e, 0x9f, 0x7d,
0x60, 0x59, 0x1f, 0x38, 0x8e, 0x07, 0x2b, 0x17,
0x2b, 0x17, 0x07, 0x86, 0xe1, 0xc1, 0xf1, 0x3c,
0x62, 0xe2, 0x22, 0x50, 0x50, 0x9a, 0x0c, 0xdb,
0xfe, 0x15, 0x32, 0x33, 0x74, 0x20, 0x72, 0x1c,
0x55, 0xd2, 0x66, 0x2e, 0xc2, 0x93, 0x9b, 0xe2,
0xf9, 0x81, 0x51, 0x80, 0xbf, 0xe0, 0x8e, 0xf6,
0x0a, 0x42, 0xd4, 0x3d, 0xa9, 0x92, 0x16, 0x53,
0x21, 0x6e, 0xcf, 0x38, 0x3c, 0xdc, 0xbf, 0x83,
0x79, 0x67, 0x43, 0xc2, 0xca, 0x10, 0xb5, 0x83,
0x51, 0x25, 0xe6, 0x3a, 0x03, 0x9c, 0x87, 0x2f,
0xf0, 0xdc, 0x79, 0xc1, 0x48, 0x09, 0xa2, 0xf5,
0x04, 0x86, 0xb2, 0x14, 0x6c, 0xdb, 0x5d, 0xdf,
0xe0, 0x1f, 0x02, 0xad, 0xc4, 0x32, 0xdf, 0xad,
0xf4, 0x73, 0x0d, 0x0b, 0xc8, 0x36, 0x24, 0xe0,
0xd4, 0xe3, 0xf9, 0x82, 0x1f, 0xd3, 0xb2, 0xa8,
0xbc, 0x96, 0x74, 0xed, 0x24, 0x24, 0xd8, 0x27,
0xea, 0x1f, 0xdc, 0xa0, 0xcd, 0xb5, 0x46, 0xe4,
0x75, 0xd5, 0x28, 0xbd, 0x7d, 0x72, 0x03, 0x56,
0x87, 0x13, 0xd3, 0x53, 0xa6, 0x6f, 0x70, 0xd0,
0x04, 0xaa, 0xa0, 0xb1, 0xa6, 0x00, 0xb6, 0xb5,
0x4b, 0x0c, 0x58, 0x7b, 0x95, 0x67, 0xe3, 0xad,
0xd3, 0x18, 0x59, 0xe9, 0x87, 0x16, 0x0e, 0x29,
0x30, 0x95, 0xe7, 0x62, 0x73, 0xf5, 0x5c, 0x1a,
0x22, 0x87, 0x31, 0xc7, 0xd0, 0xd7, 0x9a, 0x16,
0x56, 0x04, 0x94, 0xd2, 0x7c, 0x42, 0xc8, 0x69,
0xa0, 0xa0, 0xbe, 0x24, 0x1b, 0xeb, 0xcb, 0x27,
0xd2, 0x10, 0x79, 0x4c, 0x1c, 0x8f, 0x84, 0x14,
0x18, 0x25, 0xc1, 0x51, 0xa0, 0x60, 0x78, 0xb0,
0x0a, 0x7b, 0x5b, 0x6e, 0x54, 0x0e, 0x37, 0xfd,
0x7f, 0x0b, 0x73, 0xf3, 0x3b, 0xca, 0xf9, 0x50,
0x01, 0x19, 0x96, 0xff, 0xfb, 0x9e, 0xee, 0xea,
0xe0, 0x43, 0x94, 0x52, 0x14, 0x4b, 0x29, 0xec,
0x5a, 0x49, 0xe0, 0x8b, 0xbf, 0xad, 0x91, 0x70,
0x8f, 0xf3, 0x07, 0xda, 0x28, 0x0c, 0xf1, 0xdd,
0xa4, 0x8c, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x49,
0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
};
#include "wx/mstream.h"
static wxImage *sortfilterclear_png_img()
{
if (!wxImage::FindHandler(wxT("PNG file")))
wxImage::AddHandler(new wxPNGHandler());
static wxImage *img_sortfilterclear_png = new wxImage();
if (!img_sortfilterclear_png || !img_sortfilterclear_png->IsOk())
{
wxMemoryInputStream img_sortfilterclear_pngIS(sortfilterclear_png_data, sizeof(sortfilterclear_png_data));
img_sortfilterclear_png->LoadFile(img_sortfilterclear_pngIS, wxBITMAP_TYPE_PNG);
}
return img_sortfilterclear_png;
}
#define sortfilterclear_png_img sortfilterclear_png_img()
static wxBitmap *sortfilterclear_png_bmp()
{
static wxBitmap *bmp_sortfilterclear_png;
if (!bmp_sortfilterclear_png || !bmp_sortfilterclear_png->IsOk())
bmp_sortfilterclear_png = new wxBitmap(*sortfilterclear_png_img);
return bmp_sortfilterclear_png;
}
#define sortfilterclear_png_bmp sortfilterclear_png_bmp()
static wxIcon *sortfilterclear_png_ico()
{
static wxIcon *ico_sortfilterclear_png;
if (!ico_sortfilterclear_png || !ico_sortfilterclear_png->IsOk())
{
ico_sortfilterclear_png = new wxIcon();
ico_sortfilterclear_png->CopyFromBitmap(*sortfilterclear_png_bmp);
}
return ico_sortfilterclear_png;
}
#define sortfilterclear_png_ico sortfilterclear_png_ico()
#endif // SORTFILTERCLEAR_PNG_H

View file

@ -60,8 +60,8 @@
// Supported server minimum and maximum values.
const short SERVER_MIN_VERSION_N = 0x0804;
const wxString SERVER_MIN_VERSION_T = wxT("8.4");
const short SERVER_MAX_VERSION_N = 0x0D00;
const wxString SERVER_MAX_VERSION_T = wxT("13");
const short SERVER_MAX_VERSION_N = 0x0E00;
const wxString SERVER_MAX_VERSION_T = wxT("14");
// Supported Greenplum Database and Greenplum HAWQ minimum and maximum values.
const short GP_MIN_VERSION_N = 0x0802;
const wxString GP_MIN_VERSION_T = wxT("8.2");

View file

@ -287,6 +287,7 @@ public:
return true;
}
bool HasPgstatindex();
bool HasPgcheckindex();
protected:
void ReadColumnDetails();
@ -345,6 +346,13 @@ public:
bool CheckEnable(pgObject *obj);
bool CheckChecked(pgObject *obj);
};
class executePgcheckindexFactory : public contextActionFactory
{
public:
executePgcheckindexFactory(menuFactoryList* list, wxMenu* mnu, ctlMenuToolbar* toolbar);
wxWindow* StartDialog(frmMain* form, pgObject* obj);
bool CheckEnable(pgObject* obj);
};
#endif

View file

@ -269,6 +269,7 @@ public:
virtual void ShowTreeDetail(ctlTree *browser, frmMain *form = 0, ctlListView *properties = 0, ctlSQLBox *sqlPane = 0) = 0;
virtual void ShowStatistics(frmMain *form, ctlListView *statistics);
virtual void ShowStatisticsTables(frmMain* form, ctlListView* statistics, pgObject* obj);
virtual void ShowDependencies(frmMain *form, ctlListView *Dependencies, const wxString &where = wxEmptyString);
virtual void ShowDependents(frmMain *form, ctlListView *referencedBy, const wxString &where = wxEmptyString);
virtual pgObject *Refresh(ctlTree *browser, const wxTreeItemId item)

View file

@ -81,6 +81,15 @@ public:
{
return del;
}
bool GetIsViaRoot() const
{
return publish_via_partition_root;
}
void iSetIsViaRoot(const bool b)
{
publish_via_partition_root = b;
}
wxString GetStrOper() const
{
wxString s = wxT("");
@ -115,7 +124,7 @@ public:
private:
wxString tables, version;
bool all,ins,upd,del;
bool all,ins,upd,del, publish_via_partition_root;
};
class pgPublicationCollection : public pgDatabaseObjCollection

View file

@ -24,6 +24,7 @@ enum
FEATURE_RELOAD_CONF,
FEATURE_PGSTATTUPLE,
FEATURE_PGSTATINDEX,
FEATURE_PGCHECKINDEX,
FEATURE_FUNCTION_DEFAULTS,
FEATURE_LAST
};

View file

@ -13,9 +13,9 @@
#define VERSION_H
// Application Versions
#define VERSION_STR wxT("1.25.0 Dev ASUTP version with support PG12")
#define VERSION_NUM 1,25,0,0
#define VERSION_PACKAGE 1.25.0-dev
#define VERSION_STR wxT("1.26 Dev ASUTP support PG12")
#define VERSION_NUM 1,26,0,0
#define VERSION_PACKAGE 1.26.0-dev
#define PRERELEASE 1
// #define BUILD "..."

View file

@ -74,7 +74,7 @@
<ConfigurationType>Application</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
@ -158,6 +158,9 @@
<IncludePath>.\wxwidgets\include;$(IncludePath)</IncludePath>
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);wxwidgets\lib</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_(3.0)|x64'">
<PreBuildEventUseInBuild>false</PreBuildEventUseInBuild>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<PreBuildEvent>
<Message>Extracting source code repository version</Message>
@ -479,7 +482,7 @@
<AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
<ObjectFileName>.\Debug/</ObjectFileName>
<ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
<BrowseInformation>true</BrowseInformation>
<BrowseInformation>false</BrowseInformation>
<BrowseInformationFile>.\Debug/</BrowseInformationFile>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
@ -491,10 +494,9 @@
<AdditionalIncludeDirectories>$(WXWIN)/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<AdditionalDependencies>wxbase30ud.lib;wxbase30ud_xml.lib;wxbase30ud_net.lib;wxmsw30ud_adv.lib;wxmsw30ud_core.lib;wxmsw30ud_html.lib;wxmsw30ud_aui.lib;wxregexud.lib;wxpngd.lib;wxzlibd.lib;wxjpegd.lib;wxtiffd.lib;wxmsw30ud_stc.lib;wxmsw30ud_xrc.lib;wxexpatd.lib;libeay32MD.lib;libpq.lib;libxml2.lib;libxslt.lib;iconv.lib;comctl32.lib;rpcrt4.lib;wsock32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;oleaut32.lib;ole32.lib;shell32.lib;odbc32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>.\Debug/pgAdmin3.exe</OutputFile>
<AdditionalDependencies>wxbase30ud.lib;wxbase30ud_xml.lib;wxbase30ud_net.lib;wxmsw30ud_adv.lib;wxmsw30ud_core.lib;wxmsw30ud_html.lib;wxmsw30ud_aui.lib;wxregexud.lib;wxpngd.lib;wxzlibd.lib;wxjpegd.lib;wxtiffd.lib;wxmsw30ud_stc.lib;wxmsw30ud_xrc.lib;wxexpatd.lib;libssh2.lib;libeay32MD.lib;libpq.lib;libxml2.lib;libxslt.lib;iconv.lib;comctl32.lib;rpcrt4.lib;wsock32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;oleaut32.lib;ole32.lib;shell32.lib;odbc32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>$(OPENSSL)/lib/VC;$(WXWIN)/lib/vc_dll;$(PGDIR)/lib;$(PGBUILD)/lib;$(PGBUILD)/libxml2/lib;$(PGBUILD)/libxslt/lib;$(PGBUILD)/iconv/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>$(PROJECTDIR)/../libssh2/src/Release;$(OPENSSL)/lib/VC;$(WXWIN)/lib/vc_x64_dll;$(PGDIR)/lib;$(PGBUILD)/lib;$(PGBUILD)/libxml2/lib;$(PGBUILD)/libxslt/lib;$(PGBUILD)/iconv/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreSpecificDefaultLibraries>libcd.lib;libcid.lib;msvcrt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Debug/pgAdmin3.pdb</ProgramDatabaseFile>
@ -2236,6 +2238,7 @@
<png2c Include="include\images\slsubscription2.png" />
<png2c Include="include\images\slsubscriptions.png" />
<png2c Include="include\images\sortfilter.png" />
<png2c Include="include\images\sortfilterclear.png" />
<png2c Include="include\images\splash.png" />
<png2c Include="include\images\sql-16.png" />
<png2c Include="include\images\sql-32.png" />

View file

@ -4435,6 +4435,9 @@
<png2c Include="include\images\jobrun.png">
<Filter>include\images</Filter>
</png2c>
<png2c Include="include\images\sortfilterclear.png">
<Filter>include\images</Filter>
</png2c>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="pgAdmin3.rc" />

View file

@ -13,4 +13,14 @@
<LocalDebuggerCommandArguments>-s mi -q</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_(3.0)|x64'">
<LocalDebuggerCommandArguments>
</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_(3.0)|x64'">
<LocalDebuggerCommandArguments>
</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

View file

@ -509,7 +509,7 @@ bool pgProcedure::DropObject(wxFrame *frame, ctlTree *browser, bool cascaded)
if (!GetConnection()->BackendMinimumVersion(11, 0))
return pgFunction::DropObject(frame, browser, cascaded);
wxString sql = wxT("DROP PROCEDURE ") + this->GetSchema()->GetQuotedIdentifier() + wxT(".") + this->GetQuotedIdentifier();
wxString sql = wxT("DROP PROCEDURE ") + this->GetSchema()->GetQuotedIdentifier() + wxT(".") + this->GetQuotedIdentifier() + wxT("(") + this->GetArgSigList() + wxT(")");;
return GetDatabase()->ExecuteVoid(sql);
}

View file

@ -473,6 +473,36 @@ bool pgIndexBase::HasPgstatindex()
return GetConnection()->HasFeature(FEATURE_PGSTATINDEX);
}
bool pgIndexBase::HasPgcheckindex()
{
return GetConnection()->HasFeature(FEATURE_PGCHECKINDEX);
}
executePgcheckindexFactory::executePgcheckindexFactory(menuFactoryList* list, wxMenu* mnu, ctlMenuToolbar* toolbar) : contextActionFactory(list)
{
mnu->Append(id, _("Check Btree index"), _("Check Btree index function bt_index_parent_check(oid,true)"));
}
wxWindow* executePgcheckindexFactory::StartDialog(frmMain* form, pgObject* obj)
{
pgIndexBase* i = (pgIndexBase*)obj;
form->StartMsg(_("Check Btree index "+i->GetName()+" "));
wxString sql = "SELECT bt_index_parent_check("+i->GetOidStr()+",true);";
i->GetConnection()->ExecuteVoid(sql);
form->EndMsg(true);
return 0;
}
bool executePgcheckindexFactory::CheckEnable(pgObject* obj)
{
return obj &&
(obj->IsCreatedBy(indexFactory) || obj->IsCreatedBy(primaryKeyFactory)
|| obj->IsCreatedBy(uniqueFactory) || obj->IsCreatedBy(excludeFactory)) && ((pgIndexBase*)obj)->GetIndexType()=="btree" &&
((pgIndexBase*)obj)->HasPgcheckindex();
}
executePgstatindexFactory::executePgstatindexFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : contextActionFactory(list)
{
@ -757,4 +787,5 @@ void pgIndexBaseCollection::ShowStatistics(frmMain *form, ctlListView *statistic
delete stats;
}
statistics->SetColumnWidth(0, wxLIST_AUTOSIZE);
}

View file

@ -67,6 +67,8 @@
#include "agent/pgaSchedule.h"
#include "agent/pgaStep.h"
#include "schema/pgPartition.h"
#include "utils/pgfeatures.h"
int pgObject::GetType() const
{
@ -224,6 +226,120 @@ void pgObject::ShowStatistics(frmMain *form, ctlListView *statistics)
{
}
void pgObject::ShowStatisticsTables(frmMain* form, ctlListView* statistics, pgObject *obj)
{
wxLogInfo(wxT("Displaying statistics for tables on %s"), obj->GetSchema()->GetIdentifier().c_str());
bool tabcoll = false;
bool partcoll = false;
bool onetable = false;
if (IsCollection()) {
wxString t = obj->GetFactory()->GetTypeName();
if (t == ("Tables")
//obj->IsCreatedBy(tableFactory)
) tabcoll = true;
if ( t == ("Partitions")) partcoll = true;
}
else onetable = true;
bool hasSize = obj->GetConnection()->HasFeature(FEATURE_SIZE);
// Add the statistics view columns
statistics->ClearAll();
statistics->AddColumn(_("Table Name"));
if (hasSize)
statistics->AddColumn(_("Size"));
if (obj->GetConnection()->GetIsPgProEnt()) statistics->AddColumn(_("CFS %"));
statistics->AddColumn(_("Tuples inserted"));
statistics->AddColumn(_("Tuples updated"));
statistics->AddColumn(_("Tuples deleted"));
if (obj->GetConnection()->BackendMinimumVersion(8, 3))
{
statistics->AddColumn(_("Tuples HOT updated"));
statistics->AddColumn(_("Live tuples"));
statistics->AddColumn(_("Dead tuples"));
}
if (obj->GetConnection()->BackendMinimumVersion(8, 2))
{
statistics->AddColumn(_("Last vacuum"));
statistics->AddColumn(_("Last autovacuum"));
statistics->AddColumn(_("Last analyze"));
statistics->AddColumn(_("Last autoanalyze"));
}
if (obj->GetConnection()->BackendMinimumVersion(9, 1))
{
statistics->AddColumn(_("Vacuum counter"));
statistics->AddColumn(_("Autovacuum counter"));
statistics->AddColumn(_("Analyze counter"));
statistics->AddColumn(_("Autoanalyze counter"));
}
wxString sql = wxT("SELECT st.relname, n_tup_ins, n_tup_upd, n_tup_del");
if (obj->GetConnection()->BackendMinimumVersion(8, 3))
sql += wxT(", n_tup_hot_upd, n_live_tup, n_dead_tup");
if (obj->GetConnection()->BackendMinimumVersion(8, 2))
sql += wxT(", last_vacuum, last_autovacuum, last_analyze, last_autoanalyze");
if (obj->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");
if (obj->GetConnection()->GetIsPgProEnt()) sql += wxT(",left((cfs_fragmentation(cl.oid)*100)::text,5)::text AS cfs_ratio");
sql += wxT("\n FROM pg_stat_all_tables st")
wxT(" JOIN pg_class cl on cl.oid=st.relid\n");
if (partcoll) sql += wxT(" JOIN pg_inherits i ON (cl.oid = i.inhrelid) WHERE ");
if (tabcoll) sql += wxT(" WHERE schemaname = ")+obj->qtDbString(obj->GetSchema()->GetName());
if (partcoll) sql += wxT(" i.inhparent = ") + obj->GetOidStr();
//+ obj->qtDbString(obj->GetSchema()->GetName()) + wxT(" AND i.inhparent = ") + obj->GetOidStr()
if (onetable) sql += wxT("join (select t.relid::oid oid from pg_partition_tree(")+ (obj->GetOidStr())+wxT("::regclass) t where t.isleaf = 't') t on t.oid=cl.oid");
sql += wxT("\n ORDER BY relname");
pgSet* stats = obj->GetDatabase()->ExecuteSet(sql);
if (stats)
{
long pos = 0;
int i;
while (!stats->Eof())
{
i = 1;
statistics->InsertItem(pos, stats->GetVal(wxT("relname")), PGICON_STATISTICS);
if (hasSize)
statistics->SetItem(pos, i++, stats->GetVal(wxT("size")));
if (obj->GetConnection()->GetIsPgProEnt()) statistics->SetItem(pos, i++, stats->GetVal(wxT("cfs_ratio")));
statistics->SetItem(pos, i++, stats->GetVal(wxT("n_tup_ins")));
statistics->SetItem(pos, i++, stats->GetVal(wxT("n_tup_upd")));
statistics->SetItem(pos, i++, stats->GetVal(wxT("n_tup_del")));
if (obj->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 (obj->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 (obj->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")));
}
stats->MoveNext();
pos++;
}
delete stats;
}
statistics->SetColumnWidth(0, wxLIST_AUTOSIZE);
}
bool pgObject::UpdateIcon(ctlTree *browser)
{
@ -452,6 +568,52 @@ void pgObject::CreateListColumns(ctlListView *list, const wxString &left, const
list->AddColumn(right, list->GetSize().GetWidth() - 140);
}
wxString GetClassTableName(int metatype) {
switch (metatype)
{
case PGM_CONSTRAINT:
return "pg_constraint";
case PGM_FOREIGNKEY:
return "pg_constraint";
case PGM_PRIMARYKEY:
return "pg_constraint";
case PGM_UNIQUE:
return "pg_constraint";
case PGM_EXCLUDE:
return "pg_constraint";
case PGM_OPCLASS:
return "pg_amop";
case PGM_COLUMN:
return "pg_attribute";
case PGM_FUNCTION:
return "pg_proc";
case PGM_INDEX:
return "pg_class";
case PGM_TABLE:
return "pg_class";
case PGM_VIEW:
return "pg_class";
case PG_PARTITION:
return "pg_class";
case PGM_LANGUAGE:
return "pg_language";
case PGM_ROLE:
return "pg_authid";
case PGM_SCHEMA:
return "pg_namespace";
case PGM_SEQUENCE:
return "pg_class";
case PGM_TABLESPACE:
return "pg_tablespace";
case PGM_TRIGGER:
return "pg_trigger";
case PGM_OPFAMILY:
return "pg_opfamily";
default:
break;
}
return "";
}
void pgObject::ShowDependencies(frmMain *form, ctlListView *Dependencies, const wxString &wh)
{
@ -465,8 +627,12 @@ void pgObject::ShowDependencies(frmMain *form, ctlListView *Dependencies, const
wxString where;
if (wh.IsEmpty())
{
if(!GetOidStr().IsSameAs(wxT("0")))
if (!GetOidStr().IsSameAs(wxT("0")))
{
wxString ts = GetClassTableName(GetMetaType());
where = wxT(" WHERE dep.objid=") + GetOidStr();
if (!ts.IsEmpty()) where += " and dep.classid IN(select oid from pg_class where oid=dep.classid and relname='" + ts + "')";
}
else
return;
}
@ -510,25 +676,25 @@ void pgObject::ShowDependencies(frmMain *form, ctlListView *Dependencies, const
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")
wxT(" LEFT JOIN pg_class cl ON dep.refobjid=cl.oid\n")
wxT(" LEFT JOIN pg_attribute att ON dep.refobjid=att.attrelid AND dep.refobjsubid=att.attnum\n")
wxT(" FROM pg_depend dep join pg_class nc on nc.oid=dep.refclassid\n")
wxT(" LEFT JOIN pg_class cl ON dep.refobjid=cl.oid and nc.relname='pg_class'\n")
wxT(" LEFT JOIN pg_attribute att ON dep.refobjid=att.attrelid AND dep.refobjsubid=att.attnum and nc.relname='pg_attribute'\n")
wxT(" LEFT JOIN pg_namespace nsc ON cl.relnamespace=nsc.oid\n")
wxT(" LEFT JOIN pg_proc pr ON dep.refobjid=pr.oid\n")
wxT(" LEFT JOIN pg_proc pr ON dep.refobjid=pr.oid and nc.relname='pg_proc'\n")
wxT(" LEFT JOIN pg_namespace nsp ON pr.pronamespace=nsp.oid\n")
wxT(" LEFT JOIN pg_trigger tg ON dep.refobjid=tg.oid\n")
wxT(" LEFT JOIN pg_type ty ON dep.refobjid=ty.oid\n")
wxT(" LEFT JOIN pg_trigger tg ON dep.refobjid=tg.oid and nc.relname='pg_trigger'\n")
wxT(" LEFT JOIN pg_type ty ON dep.refobjid=ty.oid and nc.relname='pg_type'\n")
wxT(" LEFT JOIN pg_namespace nst ON ty.typnamespace=nst.oid\n")
wxT(" LEFT JOIN pg_constraint co ON dep.refobjid=co.oid\n")
wxT(" LEFT JOIN pg_constraint co ON dep.refobjid=co.oid and nc.relname='pg_constraint'\n")
wxT(" LEFT JOIN pg_class coc ON co.conrelid=coc.oid\n")
wxT(" LEFT JOIN pg_namespace nso ON co.connamespace=nso.oid\n")
wxT(" LEFT JOIN pg_rewrite rw ON dep.refobjid=rw.oid\n")
wxT(" LEFT JOIN pg_rewrite rw ON dep.refobjid=rw.oid and nc.relname='pg_rewrite'\n")
wxT(" LEFT JOIN pg_class clrw ON clrw.oid=rw.ev_class\n")
wxT(" LEFT JOIN pg_namespace nsrw ON clrw.relnamespace=nsrw.oid\n")
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_language la ON dep.refobjid=la.oid and nc.relname='pg_language'\n")
wxT(" LEFT JOIN pg_namespace ns ON dep.refobjid=ns.oid and nc.relname='pg_namespace'\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_publication_rel pub ON dep.objid=pub.oid AND pub.prpubid=dep.refobjid and nc.relname='pg_publication_rel'\n")
wxT(" LEFT JOIN pg_extension ext ON ext.oid=dep.refobjid\n")
+ where, wxT("refclassid"));
@ -627,9 +793,7 @@ void pgObject::ShowDependencies(frmMain *form, ctlListView *Dependencies, const
}
}
void pgObject::ShowDependents(frmMain *form, ctlListView *referencedBy, const wxString &wh)
void pgObject::ShowDependents(frmMain* form, ctlListView* referencedBy, const wxString& wh)
{
if (this->IsCollection())
return;
@ -640,7 +804,11 @@ void pgObject::ShowDependents(frmMain *form, ctlListView *referencedBy, const wx
wxString where;
if (wh.IsEmpty())
{
wxString ts = GetClassTableName(GetMetaType());
where = wxT(" WHERE dep.refobjid=") + GetOidStr();
if (!ts.IsEmpty()) where += " and dep.refclassid IN(select oid from pg_class where oid=dep.refclassid and relname='" + ts + "')";
}
else
where = wh;
/*
@ -681,26 +849,26 @@ void pgObject::ShowDependents(frmMain *form, ctlListView *referencedBy, const wx
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")
wxT(" LEFT JOIN pg_class cl ON dep.objid=cl.oid\n")
wxT(" LEFT JOIN pg_attribute att ON dep.objid=att.attrelid AND dep.objsubid=att.attnum\n")
wxT(" FROM pg_depend dep join pg_class nc on nc.oid=dep.classid\n")
wxT(" LEFT JOIN pg_class cl ON dep.objid=cl.oid and nc.relname='pg_class'\n")
wxT(" LEFT JOIN pg_attribute att ON dep.objid=att.attrelid AND dep.objsubid=att.attnum and nc.relname='pg_attribute'\n")
wxT(" LEFT JOIN pg_namespace nsc ON cl.relnamespace=nsc.oid\n")
wxT(" LEFT JOIN pg_proc pr ON dep.objid=pr.oid\n")
wxT(" LEFT JOIN pg_proc pr ON dep.objid=pr.oid and nc.relname='pg_proc'\n")
wxT(" LEFT JOIN pg_namespace nsp ON pr.pronamespace=nsp.oid\n")
wxT(" LEFT JOIN pg_trigger tg ON dep.objid=tg.oid\n")
wxT(" LEFT JOIN pg_type ty ON dep.objid=ty.oid\n")
wxT(" LEFT JOIN pg_trigger tg ON dep.objid=tg.oid and nc.relname='pg_trigger'\n")
wxT(" LEFT JOIN pg_type ty ON dep.objid=ty.oid and nc.relname='pg_type'\n")
wxT(" LEFT JOIN pg_namespace nst ON ty.typnamespace=nst.oid\n")
wxT(" LEFT JOIN pg_constraint co ON dep.objid=co.oid\n")
wxT(" LEFT JOIN pg_constraint co ON dep.objid=co.oid and nc.relname='pg_constraint'\n")
wxT(" LEFT JOIN pg_class coc ON co.conrelid=coc.oid\n")
wxT(" LEFT JOIN pg_namespace nso ON co.connamespace=nso.oid\n")
wxT(" LEFT JOIN pg_rewrite rw ON dep.objid=rw.oid\n")
wxT(" LEFT JOIN pg_rewrite rw ON dep.objid=rw.oid and nc.relname='pg_rewrite'\n")
wxT(" LEFT JOIN pg_class clrw ON clrw.oid=rw.ev_class\n")
wxT(" LEFT JOIN pg_namespace nsrw ON clrw.relnamespace=nsrw.oid\n")
wxT(" LEFT JOIN pg_language la ON dep.objid=la.oid\n")
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")
wxT(" LEFT JOIN pg_language la ON dep.objid=la.oid and nc.relname='pg_language'\n")
wxT(" LEFT JOIN pg_namespace ns ON dep.objid=ns.oid and nc.relname='pg_namespace'\n")
wxT(" LEFT JOIN pg_attrdef ad ON ad.oid=dep.objid and nc.relname='pg_attrdef'\n")
wxT(" LEFT JOIN pg_extension ext ON ext.oid=dep.objid and nc.relname='pg_extension'\n")
wxT(" LEFT JOIN pg_publication_rel pub ON dep.objid=pub.oid AND pub.prpubid=dep.refobjid and nc.relname='pg_publication_rel'\n")
+ where, wxT("classid"));
/*
@ -2055,7 +2223,7 @@ if (1==0) {
pgaFactory *ff=oo->GetFactory();
fn=ff->GetTypeName();
fn=oo->GetName();
if (fn==wxT("debug*history__0102")) {
if (fn==wxT("debug**info_history2")) {
fn=oo->GetFullName();
pgaFactory *ff=oo->GetFactory();
fn=ff->GetTypeName();

View file

@ -97,6 +97,8 @@ pgPartitionCollection::pgPartitionCollection(pgaFactory *factory, pgPartition *_
}
void pgPartitionCollection::ShowStatistics(frmMain *form, ctlListView *statistics)
{
ShowStatisticsTables(form, statistics, this);
return;
wxLogInfo(wxT("Displaying statistics for tables on %s"), GetSchema()->GetIdentifier().c_str());
bool hasSize = GetConnection()->HasFeature(FEATURE_SIZE);
@ -104,6 +106,9 @@ void pgPartitionCollection::ShowStatistics(frmMain *form, ctlListView *statistic
// Add the statistics view columns
statistics->ClearAll();
statistics->AddColumn(_("Table Name"));
if (hasSize)
statistics->AddColumn(_("Size"));
if (GetConnection()->GetIsPgProEnt()) statistics->AddColumn(_("CFS %"));
statistics->AddColumn(_("Tuples inserted"));
statistics->AddColumn(_("Tuples updated"));
statistics->AddColumn(_("Tuples deleted"));
@ -127,8 +132,6 @@ void pgPartitionCollection::ShowStatistics(frmMain *form, ctlListView *statistic
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))
@ -141,7 +144,7 @@ void pgPartitionCollection::ShowStatistics(frmMain *form, ctlListView *statistic
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");
if (GetConnection()->GetIsPgProEnt()) sql += wxT(",left((cfs_fragmentation(cl.oid)*100)::text,5)::text AS cfs_ratio");
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)")
@ -156,11 +159,14 @@ void pgPartitionCollection::ShowStatistics(frmMain *form, ctlListView *statistic
int i;
while (!stats->Eof())
{
i = 4;
i = 1;
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 (hasSize)
statistics->SetItem(pos, i++, stats->GetVal(wxT("size")));
if (GetConnection()->GetIsPgProEnt()) statistics->SetItem(pos, i++, stats->GetVal(wxT("cfs_ratio")));
statistics->SetItem(pos, i++, stats->GetVal(wxT("n_tup_ins")));
statistics->SetItem(pos, i++, stats->GetVal(wxT("n_tup_upd")));
statistics->SetItem(pos, i++, stats->GetVal(wxT("n_tup_del")));
if (GetConnection()->BackendMinimumVersion(8, 3))
{
statistics->SetItem(pos, i++, stats->GetVal(wxT("n_tup_hot_upd")));
@ -181,14 +187,13 @@ void pgPartitionCollection::ShowStatistics(frmMain *form, ctlListView *statistic
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;
}
statistics->SetColumnWidth(0, wxLIST_AUTOSIZE);
}
@ -254,7 +259,18 @@ pgObject *pgPartitionFactory::CreateObjects(pgCollection *coll, ctlTree *browser
query += wxT(",case when lk.relation=rel.oid then 'AccessExclusiveLock' else pg_get_expr(rel.relpartbound, rel.oid) end \n AS partexp");
query += wxT(",(select count(*)from pg_inherits ii where ii.inhparent=rel.oid)>0 AS ispartitioned");
if (collection->GetDatabase()->BackendMinimumVersion(10, 0))
{
//query += wxT(",\n pg_get_statisticsobjdef(stat_ext.oid) AS stat_stmt");
//query += wxT(",\nCASE WHEN stat_ext.stxowner<>rel.relowner then 'ALTER STATISTICS '||substring(pg_get_statisticsobjdef(stat_ext.oid) from 'ICS (.+?)\\s\\(')||' OWNER TO '||stat_ext.stxowner::regrole else null end AS alter_stmt");
query += ",(select string_agg(pg_get_statisticsobjdef(stat_ext.oid)||CASE WHEN stat_ext.stxowner<>rl.relowner then E';\\nALTER STATISTICS '||substring(pg_get_statisticsobjdef(stat_ext.oid) from 'ICS (.+?)\\s')||' OWNER TO '||stat_ext.stxowner::regrole else '' end"
;
if (collection->GetDatabase()->BackendMinimumVersion(13, 0)) {
query += "||CASE WHEN stat_ext.stxstattarget<>-1 then E';\\nALTER STATISTICS '||substring(pg_get_statisticsobjdef(stat_ext.oid) from 'ICS (.+?)\\s')||' SET STATISTICS '||stat_ext.stxstattarget else '' end";
}
query += ",E';\\n' order by stat_ext.stxrelid) stat_stmt from pg_class rl join pg_statistic_ext stat_ext on rl.oid=stat_ext.stxrelid where stat_ext.stxrelid=rel.oid) stat_stmt";
}
query += wxT(" FROM pg_class rel\n")
wxT(" JOIN pg_inherits i ON (rel.oid = i.inhrelid) \n")
wxT(" LEFT JOIN pg_locks lk ON locktype='relation' and granted=true and mode='AccessExclusiveLock' and relation=rel.oid\n")
@ -386,6 +402,11 @@ pgObject *pgPartitionFactory::CreateObjects(pgCollection *coll, ctlTree *browser
table->iSetPartKeyDef(tables->GetVal(wxT("partkeydef")));
table->iSetPartExp(tables->GetVal(wxT("partexp")));
table->iSetIsPartitioned(tables->GetBool(wxT("ispartitioned")));
wxString st = tables->GetVal(wxT("stat_stmt"));
//wxString at = tables->GetVal(wxT("alter_stmt"));
if (!st.IsEmpty()) if ((st.Right(1) != ";")) st = st + wxT(";\n");
table->iSetStatExt(st);
}
if (collection->GetConnection()->GetIsGreenplum())
{

View file

@ -110,12 +110,21 @@ wxString pgPublication::GetSql(ctlTree *browser)
if (!GetTablesStr().IsEmpty())
sql += wxT("") + GetTablesStr();
}
if (GetIsIns()&&GetIsUpd()&&GetIsDel())
if (GetIsIns()&&GetIsUpd()&&GetIsDel()&&!GetIsViaRoot())
{
} else
}
else
{
sql += wxT("\n WITH (publish = '") + GetStrOper() + wxT("')");
sql += wxT("\n WITH (");
wxString opts = wxEmptyString;
if (!(GetIsIns() && GetIsUpd() && GetIsDel())) opts =opts+ "publish = '" + GetStrOper() + wxT("'");
if (GetIsViaRoot()) {
if (!opts.IsEmpty()) opts += ",";
opts += "publish_via_partition_root = on";
}
if (!opts.IsEmpty()) opts += ")";
sql += opts;
}
sql += wxT(";\n");
@ -158,8 +167,13 @@ pgObject *pgPublicationFactory::CreateObjects(pgCollection *collection, ctlTree
{
wxString sql;
pgPublication *publication = 0;
wxString pg13="";
if (collection->GetDatabase()->BackendMinimumVersion(13, 0)) {
pg13 = ", pubviaroot";
}
sql = wxT("select x.oid,x.pubname, pg_get_userbyid(x.pubowner) AS owner, x.puballtables, x.pubinsert, x.pubupdate, x.pubdelete, obj_description(x.oid,'pg_publication') AS comment, t.t")
+ pg13 + wxT("\n")
wxT(" FROM pg_publication x\n")
wxT(" LEFT JOIN LATERAL (select string_agg(schemaname||'.'||tablename,', ') t from pg_publication_tables where pubname=x.pubname) t on true \n")
wxT(" ")
@ -183,6 +197,7 @@ pgObject *pgPublicationFactory::CreateObjects(pgCollection *collection, ctlTree
publication->iSetIsDel(publications->GetBool(wxT("pubdelete")));
//publication->iSetVersion(publications->GetVal(wxT("extversion")));
publication->iSetComment(publications->GetVal(wxT("comment")));
if (!pg13.IsEmpty()) publication->iSetIsViaRoot(publications->GetBool(wxT("pubviaroot")));
if (browser)
{

View file

@ -354,19 +354,21 @@ wxT(") aa where aa.grantee='")+GetName()+("' group by type,objname,grantee order
wxString addgrant=wxEmptyString;
while (!roles->Eof())
{
bool ad = true;
if (wxT("tables")==roles->GetVal(wxT("type")) ) {
addgrant += wxT("\nGRANT ") + roles->GetVal(wxT("priv")) + wxT(" ON TABLE ") + qtIdent(roles->GetVal(wxT("objname")).BeforeFirst('.'))+wxT(".")+qtIdent(roles->GetVal(wxT("objname")).AfterFirst('.'))
+ wxT(" TO ") + qtIdent(GetName());
}
if (wxT("routine")==roles->GetVal(wxT("type")) ) {
addgrant += wxT("\nGRANT EXECUTE ON FUNCTION ") + qtIdent(roles->GetVal(wxT("objname")).BeforeFirst('.'))+wxT(".")+qtIdent(roles->GetVal(wxT("objname")).AfterFirst('.'))
+ wxT(" TO ") + qtIdent(GetName());
}
if (wxT("schema")==roles->GetVal(wxT("type")) ) {
addgrant += wxT("\nGRANT USAGE ON SCHEMA ") + qtIdent(roles->GetVal(wxT("objname")))
+ wxT(" TO ") + qtIdent(GetName());
}
addgrant += wxT(";");
} else if (wxT("routine")==roles->GetVal(wxT("type")) ) {
addgrant += wxT("\nGRANT EXECUTE ON FUNCTION ") + qtIdent(roles->GetVal(wxT("objname")).BeforeFirst('.'))+wxT(".")+qtIdent(roles->GetVal(wxT("objname")).AfterFirst('.'))
+ wxT(" TO ") + qtIdent(GetName());
} else if (wxT("schema")==roles->GetVal(wxT("type")) ) {
addgrant += wxT("\nGRANT USAGE ON SCHEMA ") + qtIdent(roles->GetVal(wxT("objname")))
+ wxT(" TO ") + qtIdent(GetName());
}
else {
ad = false;
}
if (ad) addgrant += wxT(";");
roles->MoveNext();
}
sql += wxT("\n")+ addgrant + wxT("\n");

View file

@ -1460,6 +1460,7 @@ bool pgServer::PauseReplay()
{
SetReplayPaused(true);
wxString sql = wxT("SELECT pg_xlog_replay_pause()");
if (conn->BackendMinimumVersion(10, 0)) sql = wxT("SELECT pg_wal_replay_pause()");
return conn->ExecuteVoid(sql);
}
@ -1468,6 +1469,7 @@ bool pgServer::ResumeReplay()
{
SetReplayPaused(false);
wxString sql = wxT("SELECT pg_xlog_replay_resume()");
if (conn->BackendMinimumVersion(10, 0)) sql = wxT("SELECT pg_wal_replay_resume()");
return conn->ExecuteVoid(sql);
}

View file

@ -618,7 +618,7 @@ wxString pgTable::GetSql(ctlTree *browser)
}
}
}
wxRegEx reg("vacuum_index_cleanup=[a-z]+|vacuum_truncate=[a-z]+|parallel_workers=[0-9]+|toast_tuple_target=[0-9]+|log_autovacuum_min_duration=[0-9]+|user_catalog_table=[a-z]+");
wxRegEx reg("autovacuum_vacuum_insert_scale_factor=[0-9.]+|autovacuum_vacuum_insert_threshold=[0-9]+|vacuum_index_cleanup=[a-z]+|vacuum_truncate=[a-z]+|parallel_workers=[0-9]+|toast_tuple_target=[0-9]+|log_autovacuum_min_duration=[0-9]+|user_catalog_table=[a-z]+");
wxString relopt=GetRelOptions();
wxString o;
size_t start, len;
@ -726,7 +726,7 @@ wxString pgTable::GetSql(ctlTree *browser)
else
sql += GetGrant(wxT("arwdRxt"));
wxString st=GetStatExt();
if (!st.IsEmpty()) sql += st + wxT(";\n");
if (!st.IsEmpty()) sql += st + wxT("\n");
sql += GetCommentSql();
if (GetConnection()->BackendMinimumVersion(9, 1))
@ -1290,6 +1290,8 @@ wxString pgTableCollection::GetTranslatedMessage(int kindOfMessage) const
void pgTableCollection::ShowStatistics(frmMain *form, ctlListView *statistics)
{
ShowStatisticsTables(form, statistics, this);
return;
wxLogInfo(wxT("Displaying statistics for tables on %s"), GetSchema()->GetIdentifier().c_str());
bool hasSize = GetConnection()->HasFeature(FEATURE_SIZE);
@ -1299,6 +1301,8 @@ void pgTableCollection::ShowStatistics(frmMain *form, ctlListView *statistics)
statistics->AddColumn(_("Table Name"));
if (hasSize)
statistics->AddColumn(_("Size"), 50);
if (GetConnection()->GetIsPgProEnt()) statistics->AddColumn(_("CFS %"));
statistics->AddColumn(_("Tuples inserted"));
statistics->AddColumn(_("Tuples updated"));
@ -1335,6 +1339,7 @@ void pgTableCollection::ShowStatistics(frmMain *form, ctlListView *statistics)
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");
if (GetConnection()->GetIsPgProEnt()) sql += wxT(",left((cfs_fragmentation(cl.oid)*100)::text,5)::text AS cfs_ratio");
sql += wxT("\n FROM pg_stat_all_tables st")
wxT(" JOIN pg_class cl on cl.oid=st.relid\n")
@ -1349,13 +1354,14 @@ void pgTableCollection::ShowStatistics(frmMain *form, ctlListView *statistics)
int i;
while (!stats->Eof())
{
i = 5;
i = 1;
statistics->InsertItem(pos, stats->GetVal(wxT("relname")), PGICON_STATISTICS);
if (hasSize)
statistics->SetItem(pos, 1, stats->GetVal(wxT("size")));
statistics->SetItem(pos, 2, stats->GetVal(wxT("n_tup_ins")));
statistics->SetItem(pos, 3, stats->GetVal(wxT("n_tup_upd")));
statistics->SetItem(pos, 4, stats->GetVal(wxT("n_tup_del")));
statistics->SetItem(pos, i++, stats->GetVal(wxT("size")));
if (GetConnection()->GetIsPgProEnt()) statistics->SetItem(pos, i++, stats->GetVal(wxT("cfs_ratio")));
statistics->SetItem(pos, i++, stats->GetVal(wxT("n_tup_ins")));
statistics->SetItem(pos, i++, stats->GetVal(wxT("n_tup_upd")));
statistics->SetItem(pos, i++, stats->GetVal(wxT("n_tup_del")));
if (GetConnection()->BackendMinimumVersion(8, 3))
{
statistics->SetItem(pos, i++, stats->GetVal(wxT("n_tup_hot_upd")));
@ -1391,6 +1397,10 @@ void pgTableCollection::ShowStatistics(frmMain *form, ctlListView *statistics)
void pgTable::ShowStatistics(frmMain *form, ctlListView *statistics)
{
if (GetIsPartitioned()) {
ShowStatisticsTables(form,statistics,this);
return;
}
wxString sql =
wxT("SELECT seq_scan AS ") + qtIdent(_("Sequential Scans")) +
wxT(", seq_tup_read AS ") + qtIdent(_("Sequential Tuples Read")) +
@ -1572,8 +1582,14 @@ pgObject *pgTableFactory::CreateObjects(pgCollection *collection, ctlTree *brows
if (collection->GetDatabase()->BackendMinimumVersion(10, 0))
{
query += wxT(",\n pg_get_statisticsobjdef(stat_ext.oid) AS stat_stmt");
query += wxT(",\nCASE WHEN stat_ext.stxowner<>rel.relowner then 'ALTER STATISTICS '||substring(pg_get_statisticsobjdef(stat_ext.oid) from 'ICS (.+?)\\s\\(')||' OWNER TO '||stat_ext.stxowner::regrole else null end AS alter_stmt");
//query += wxT(",\n pg_get_statisticsobjdef(stat_ext.oid) AS stat_stmt");
//query += wxT(",\nCASE WHEN stat_ext.stxowner<>rel.relowner then 'ALTER STATISTICS '||substring(pg_get_statisticsobjdef(stat_ext.oid) from 'ICS (.+?)\\s\\(')||' OWNER TO '||stat_ext.stxowner::regrole else null end AS alter_stmt");
query += ",(select string_agg(pg_get_statisticsobjdef(stat_ext.oid)||CASE WHEN stat_ext.stxowner<>rl.relowner then E';\\nALTER STATISTICS '||substring(pg_get_statisticsobjdef(stat_ext.oid) from 'ICS (.+?)\\s')||' OWNER TO '||stat_ext.stxowner::regrole else '' end"
;
if (collection->GetDatabase()->BackendMinimumVersion(13, 0)) {
query += "||CASE WHEN stat_ext.stxstattarget<>-1 then E';\\nALTER STATISTICS '||substring(pg_get_statisticsobjdef(stat_ext.oid) from 'ICS (.+?)\\s')||' SET STATISTICS '||stat_ext.stxstattarget else '' end";
}
query += ",E';\\n' order by stat_ext.stxrelid) stat_stmt from pg_class rl join pg_statistic_ext stat_ext on rl.oid=stat_ext.stxrelid where stat_ext.stxrelid=rel.oid) stat_stmt";
}
query += wxT(" FROM pg_class rel\n")
wxT(" LEFT JOIN pg_locks lk ON locktype='relation' and granted=true and mode='AccessExclusiveLock' and relation=rel.oid\n")
@ -1591,8 +1607,6 @@ pgObject *pgTableFactory::CreateObjects(pgCollection *collection, ctlTree *brows
if (collection->GetConnection()->BackendMinimumVersion(9, 0))
query += wxT("LEFT JOIN pg_type typ ON rel.reloftype=typ.oid\n");
if (collection->GetConnection()->BackendMinimumVersion(10, 0))
query += wxT("LEFT JOIN pg_statistic_ext stat_ext ON rel.oid=stat_ext.stxrelid\n");
query += wxT(" WHERE ")+pg10+wxT(" rel.relkind IN ('r','s','t','p') AND rel.relnamespace = ") + collection->GetSchema()->GetOidStr() + wxT("\n");
@ -1733,8 +1747,8 @@ pgObject *pgTableFactory::CreateObjects(pgCollection *collection, ctlTree *brows
table->iSetPartExp(tables->GetVal(wxT("partexp")));
table->iSetIsPartitioned(tables->GetBool(wxT("ispartitioned")));
wxString st = tables->GetVal(wxT("stat_stmt"));
wxString at = tables->GetVal(wxT("alter_stmt"));
if (!st.IsEmpty()&&!at.IsEmpty()) st=st+wxT(";\n")+at;
//wxString at = tables->GetVal(wxT("alter_stmt"));
if (!st.IsEmpty()) if ((st.Right(1) != ";") ) st=st+wxT(";\n");
table->iSetStatExt(st);
}

View file

@ -9,5 +9,5 @@ REM # embed-xrc.bat - convert xrc files to c++ files
REM #
REM #######################################################################
"D:\PostgreSQL\pgadmin3\pgadmin\Debug_(3.0)\wxrc.exe" -c -o xrcDialogs.cpp *.xrc
"C:\Users\lsv\Source\Repos\wxrc\x64\Release\wxrc.exe" -c -o xrcDialogs.cpp *.xrc