This commit is contained in:
lsv 2020-07-07 22:19:12 +05:00
commit 9c6f9f3405
1784 changed files with 440662 additions and 0 deletions

513
agent/dlgJob.cpp Normal file
View file

@ -0,0 +1,513 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// dlgJob.cpp - PostgreSQL Job Property
//
//////////////////////////////////////////////////////////////////////////
// App headers
#include "pgAdmin3.h"
#include "utils/misc.h"
#include "agent/dlgJob.h"
#include "agent/dlgStep.h"
#include "agent/dlgSchedule.h"
#include "agent/pgaJob.h"
#include "agent/pgaStep.h"
#include "agent/pgaSchedule.h"
#include "frm/frmMain.h"
// pointer to controls
#define txtID CTRL_TEXT("txtID")
#define chkEnabled CTRL_CHECKBOX("chkEnabled")
#define cbJobclass CTRL_COMBOBOX("cbJobclass")
#define txtHostAgent CTRL_TEXT("txtHostAgent")
#define txtCreated CTRL_TEXT("txtCreated")
#define txtChanged CTRL_TEXT("txtChanged")
#define txtNextrun CTRL_TEXT("txtNextrun")
#define txtLastrun CTRL_TEXT("txtLastrun")
#define txtLastresult CTRL_TEXT("txtLastResult")
#define lstSteps CTRL_LISTVIEW("lstSteps")
#define btnChangeStep CTRL_BUTTON("btnChangeStep")
#define btnAddStep CTRL_BUTTON("btnAddStep")
#define btnRemoveStep CTRL_BUTTON("btnRemoveStep")
#define lstSchedules CTRL_LISTVIEW("lstSchedules")
#define btnChangeSchedule CTRL_BUTTON("btnChangeSchedule")
#define btnAddSchedule CTRL_BUTTON("btnAddSchedule")
#define btnRemoveSchedule CTRL_BUTTON("btnRemoveSchedule")
BEGIN_EVENT_TABLE(dlgJob, dlgAgentProperty)
EVT_CHECKBOX(XRCID("chkEnabled"), dlgProperty::OnChange)
EVT_COMBOBOX(XRCID("cbJobclass"), dlgProperty::OnChange)
EVT_TEXT(XRCID("txtHostAgent"), dlgProperty::OnChange)
EVT_LIST_ITEM_SELECTED(XRCID("lstSteps"), dlgJob::OnSelChangeStep)
EVT_BUTTON(XRCID("btnChangeStep"), dlgJob::OnChangeStep)
EVT_BUTTON(XRCID("btnAddStep"), dlgJob::OnAddStep)
EVT_BUTTON(XRCID("btnRemoveStep"), dlgJob::OnRemoveStep)
EVT_LIST_ITEM_SELECTED(XRCID("lstSchedules"), dlgJob::OnSelChangeSchedule)
EVT_BUTTON(XRCID("btnChangeSchedule"), dlgJob::OnChangeSchedule)
EVT_BUTTON(XRCID("btnAddSchedule"), dlgJob::OnAddSchedule)
EVT_BUTTON(XRCID("btnRemoveSchedule"), dlgJob::OnRemoveSchedule)
#ifdef __WXMAC__
EVT_SIZE( dlgJob::OnChangeSize)
#endif
END_EVENT_TABLE();
dlgProperty *pgaJobFactory::CreateDialog(frmMain *frame, pgObject *node, pgObject *parent)
{
return new dlgJob(this, frame, (pgaJob *)node);
}
dlgJob::dlgJob(pgaFactory *f, frmMain *frame, pgaJob *node)
: dlgAgentProperty(f, frame, wxT("dlgJob"))
{
job = node;
txtID->Disable();
txtCreated->Disable();
txtChanged->Disable();
txtNextrun->Disable();
txtLastrun->Disable();
txtLastresult->Disable();
lstSteps->CreateColumns(0, _("Step"), _("Comment"), 90);
lstSteps->AddColumn(wxT("cmd"), 0);
lstSteps->AddColumn(wxT("id"), 0);
lstSchedules->CreateColumns(0, _("Schedule"), _("Comment"), 90);
lstSchedules->AddColumn(wxT("cmd"), 0);
lstSchedules->AddColumn(wxT("id"), 0);
btnChangeStep->Disable();
btnRemoveStep->Disable();
btnChangeSchedule->Disable();
btnRemoveSchedule->Disable();
}
pgObject *dlgJob::GetObject()
{
return job;
}
#ifdef __WXMAC__
void dlgJob::OnChangeSize(wxSizeEvent &ev)
{
lstSteps->SetSize(wxDefaultCoord, wxDefaultCoord,
ev.GetSize().GetWidth(), ev.GetSize().GetHeight() - 350);
lstSchedules->SetSize(wxDefaultCoord, wxDefaultCoord,
ev.GetSize().GetWidth(), ev.GetSize().GetHeight() - 350);
if (GetAutoLayout())
{
Layout();
}
}
#endif
int dlgJob::Go(bool modal)
{
int returncode;
pgSet *jcl = connection->ExecuteSet(wxT("SELECT jclname FROM pgagent.pga_jobclass"));
if (jcl)
{
while (!jcl->Eof())
{
cbJobclass->Append(jcl->GetVal(0));
jcl->MoveNext();
}
delete jcl;
}
if (job)
{
// edit mode
recId = job->GetRecId();
txtID->SetValue(NumToStr(recId));
cbJobclass->SetValue(job->GetJobclass());
chkEnabled->SetValue(job->GetEnabled());
txtHostAgent->SetValue(job->GetHostAgent());
txtCreated->SetValue(DateToStr(job->GetCreated()));
txtChanged->SetValue(DateToStr(job->GetChanged()));
txtNextrun->SetValue(DateToStr(job->GetNextrun()));
txtLastrun->SetValue(DateToStr(job->GetLastrun()));
txtLastresult->SetValue(job->GetLastresult());
wxCookieType cookie;
pgObject *data = 0;
wxTreeItemId item, stepsItem, schedulesItem;
item = mainForm->GetBrowser()->GetFirstChild(job->GetId(), cookie);
while (item)
{
data = mainForm->GetBrowser()->GetObject(item);
if (data->GetMetaType() == PGM_STEP)
stepsItem = item;
else if (data->GetMetaType() == PGM_SCHEDULE)
schedulesItem = item;
item = mainForm->GetBrowser()->GetNextChild(job->GetId(), cookie);
}
if (stepsItem)
{
pgCollection *coll = (pgCollection *)data;
// make sure all columns are appended
coll->ShowTreeDetail(mainForm->GetBrowser());
// this is the columns collection
item = mainForm->GetBrowser()->GetFirstChild(stepsItem, cookie);
// add columns
while (item)
{
data = mainForm->GetBrowser()->GetObject(item);
if (data->IsCreatedBy(stepFactory))
{
pgaStep *step = (pgaStep *)data;
int pos = lstSteps->AppendItem(stepFactory.GetIconId(), step->GetName(), step->GetComment());
lstSteps->SetItem(pos, 3, NumToStr((long)step));
previousSteps.Add(NumToStr((long)step));
}
item = mainForm->GetBrowser()->GetNextChild(stepsItem, cookie);
}
}
if (schedulesItem)
{
pgCollection *coll = (pgCollection *)data;
// make sure all columns are appended
coll->ShowTreeDetail(mainForm->GetBrowser());
// this is the columns collection
item = mainForm->GetBrowser()->GetFirstChild(schedulesItem, cookie);
// add columns
while (item)
{
data = mainForm->GetBrowser()->GetObject(item);
if (data->IsCreatedBy(scheduleFactory))
{
pgaSchedule *schedule = (pgaSchedule *)data;
int pos = lstSchedules->AppendItem(scheduleFactory.GetIconId(), schedule->GetName(), schedule->GetComment());
lstSchedules->SetItem(pos, 3, NumToStr((long)schedule));
previousSchedules.Add(NumToStr((long)schedule));
}
item = mainForm->GetBrowser()->GetNextChild(schedulesItem, cookie);
}
}
}
else
{
// create mode
cbJobclass->SetSelection(0);
btnChangeStep->Hide();
btnChangeSchedule->Hide();
}
returncode = dlgProperty::Go(modal);
SetSqlReadOnly(true);
// This fixes a UI glitch on MacOS X
// Because of the new layout code, the Columns pane doesn't size itself properly
SetSize(GetSize().GetWidth() + 1, GetSize().GetHeight());
SetSize(GetSize().GetWidth() - 1, GetSize().GetHeight());
return returncode;
}
pgObject *dlgJob::CreateObject(pgCollection *collection)
{
pgObject *obj = jobFactory.CreateObjects(collection, 0, wxT(" WHERE jobid=") + NumToStr(recId) + wxT("\n"));
return obj;
}
void dlgJob::CheckChange()
{
bool enable = true;
wxString name = GetName();
if (job)
{
enable = txtComment->GetValue() != job->GetComment()
|| name != job->GetName()
|| chkEnabled->GetValue() != job->GetEnabled()
|| txtHostAgent->GetValue() != job->GetHostAgent();
if (!enable)
{
enable = !GetUpdateSql().IsEmpty();
}
}
if (statusBar)
statusBar->SetStatusText(wxEmptyString);
CheckValid(enable, !txtName->GetValue().IsEmpty(), _("Please specify name."));
EnableOK(enable);
}
void dlgJob::OnChangeStep(wxCommandEvent &ev)
{
long pos = lstSteps->GetSelection();
pgaStep *obj = (pgaStep *) StrToLong(lstSteps->GetText(pos, 3));
dlgStep step(&stepFactory, mainForm, obj, job);
step.CenterOnParent();
step.SetConnection(connection);
if (step.Go(true) != wxID_CANCEL)
{
lstSteps->SetItem(pos, 0, step.GetName());
lstSteps->SetItem(pos, 1, step.GetComment());
if (lstSteps->GetText(pos, 3).IsEmpty())
{
wxString *stepSql = new wxString(step.GetInsertSql());
lstSteps->SetItemData(pos, (long)stepSql);
}
else
{
wxString *stepSql = new wxString(step.GetUpdateSql());
lstSteps->SetItemData(pos, (long)stepSql);
}
CheckChange();
}
}
void dlgJob::OnSelChangeStep(wxListEvent &ev)
{
btnChangeStep->Enable();
btnRemoveStep->Enable();
}
void dlgJob::OnAddStep(wxCommandEvent &ev)
{
dlgStep step(&stepFactory, mainForm, NULL, job);
step.CenterOnParent();
step.SetConnection(connection);
if (step.Go(true) != wxID_CANCEL)
{
int pos = lstSteps->AppendItem(stepFactory.GetIconId(), step.GetName(), step.GetComment());
wxString *stepSql = new wxString(step.GetInsertSql());
lstSteps->SetItemData(pos, (long)stepSql);
CheckChange();
}
}
void dlgJob::OnRemoveStep(wxCommandEvent &ev)
{
delete (wxString *)lstSteps->GetItemData(lstSteps->GetSelection());
lstSteps->DeleteCurrentItem();
btnChangeStep->Disable();
btnRemoveStep->Disable();
CheckChange();
}
void dlgJob::OnSelChangeSchedule(wxListEvent &ev)
{
btnChangeSchedule->Enable();
btnRemoveSchedule->Enable();
}
void dlgJob::OnChangeSchedule(wxCommandEvent &ev)
{
long pos = lstSchedules->GetSelection();
pgaSchedule *obj = (pgaSchedule *) StrToLong(lstSchedules->GetText(pos, 3));
dlgSchedule schedule(&scheduleFactory, mainForm, obj, job);
schedule.CenterOnParent();
schedule.SetConnection(connection);
if (schedule.Go(true) != wxID_CANCEL)
{
lstSchedules->SetItem(pos, 0, schedule.GetName());
lstSchedules->SetItem(pos, 1, schedule.GetComment());
if (lstSchedules->GetText(pos, 3).IsEmpty())
{
wxString *scheduleSql = new wxString(schedule.GetInsertSql());
lstSchedules->SetItemData(pos, (long)scheduleSql);
}
else
{
wxString *scheduleSql = new wxString(schedule.GetUpdateSql());
lstSchedules->SetItemData(pos, (long)scheduleSql);
}
CheckChange();
}
}
void dlgJob::OnAddSchedule(wxCommandEvent &ev)
{
dlgSchedule schedule(&scheduleFactory, mainForm, NULL, job);
schedule.CenterOnParent();
schedule.SetConnection(connection);
if (schedule.Go(true) != wxID_CANCEL)
{
int pos = lstSchedules->AppendItem(scheduleFactory.GetIconId(), schedule.GetName(), schedule.GetComment());
wxString *scheduleSql = new wxString(schedule.GetInsertSql());
lstSchedules->SetItemData(pos, (long)scheduleSql);
CheckChange();
}
}
void dlgJob::OnRemoveSchedule(wxCommandEvent &ev)
{
delete (wxString *)lstSchedules->GetItemData(lstSchedules->GetSelection());
lstSchedules->DeleteCurrentItem();
btnChangeSchedule->Disable();
btnRemoveSchedule->Disable();
CheckChange();
}
wxString dlgJob::GetInsertSql()
{
wxString sql;
if (!job)
{
sql = wxT("INSERT INTO pgagent.pga_job (jobid, jobjclid, jobname, jobdesc, jobenabled, jobhostagent)\n")
wxT("SELECT <JobId>, jcl.jclid, ") + qtDbString(GetName()) +
wxT(", ") + qtDbString(txtComment->GetValue()) + wxT(", ") + BoolToStr(chkEnabled->GetValue()) +
wxT(", ") + qtDbString(txtHostAgent->GetValue()) + wxT("\n")
wxT(" FROM pgagent.pga_jobclass jcl WHERE jclname=") + qtDbString(cbJobclass->GetValue()) + wxT(";\n");
}
return sql;
}
wxString dlgJob::GetUpdateSql()
{
wxString sql, name;
name = GetName();
if (job)
{
// edit mode
wxString vars;
if (name != job->GetName())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jobname = ") + qtDbString(name));
}
if (cbJobclass->GetValue().Trim() != job->GetJobclass())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jobjclid= (SELECT jclid FROM pgagent.pga_jobclass WHERE jclname=") + qtDbString(cbJobclass->GetValue()) + wxT(")"));
}
if (chkEnabled->GetValue() != job->GetEnabled())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jobenabled = ") + BoolToStr(chkEnabled->GetValue()));
}
if (txtHostAgent->GetValue() != job->GetHostAgent())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jobhostagent = ") + qtDbString(txtHostAgent->GetValue()));
}
if (txtComment->GetValue() != job->GetComment())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jobdesc = ") + qtDbString(txtComment->GetValue()));
}
if (!vars.IsEmpty())
sql = wxT("UPDATE pgagent.pga_job SET ") + vars + wxT("\n")
wxT(" WHERE jobid=") + NumToStr(recId) + wxT(";\n");
}
else
{
// create mode
// done by GetInsertSql
}
int pos, index;
wxArrayString tmpSteps = previousSteps;
for (pos = 0 ; pos < lstSteps->GetItemCount() ; pos++)
{
wxString str = lstSteps->GetText(pos, 3);
if (!str.IsEmpty())
{
index = tmpSteps.Index(str);
if (index >= 0)
tmpSteps.RemoveAt(index);
}
if(lstSteps->GetItemData(pos))
{
str = *(wxString *)lstSteps->GetItemData(pos);
if (!str.IsEmpty())
sql += str;
}
}
for (index = 0 ; index < (int)tmpSteps.GetCount() ; index++)
{
sql += wxT("DELETE FROM pgagent.pga_jobstep WHERE jstid=")
+ NumToStr(((pgaStep *)StrToLong(tmpSteps.Item(index)))->GetRecId()) + wxT(";\n");
}
wxArrayString tmpSchedules = previousSchedules;
for (pos = 0 ; pos < lstSchedules->GetItemCount() ; pos++)
{
wxString str = lstSchedules->GetText(pos, 3);
if (!str.IsEmpty())
{
index = tmpSchedules.Index(str);
if (index >= 0)
tmpSchedules.RemoveAt(index);
}
if(lstSchedules->GetItemData(pos))
{
str = *(wxString *)lstSchedules->GetItemData(pos);
if (!str.IsEmpty())
sql += str;
}
}
for (index = 0 ; index < (int)tmpSchedules.GetCount() ; index++)
{
sql += wxT("DELETE FROM pgagent.pga_schedule WHERE jscid=")
+ NumToStr(((pgaStep *)StrToLong(tmpSchedules.Item(index)))->GetRecId()) + wxT(";\n");
}
return sql;
}

859
agent/dlgSchedule.cpp Normal file
View file

@ -0,0 +1,859 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// dlgSchedule.cpp - PostgreSQL Schedule Property
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
// App headers
#include "utils/misc.h"
#include "agent/dlgSchedule.h"
#include "agent/pgaSchedule.h"
// image for de/-select all
#include "images/check.pngc"
#include "images/uncheck.pngc"
// pointer to controls
#define txtID CTRL_TEXT("txtID")
#define chkEnabled CTRL_CHECKBOX("chkEnabled")
#define calStart CTRL_CALENDAR("calStart")
#define timStart CTRL_TIME("timStart")
#define calEnd CTRL_CALENDAR("calEnd")
#define timEnd CTRL_TIME("timEnd")
#define chkWeekdays CTRL_CHECKLISTBOX("chkWeekdays")
#define chkMonthdays CTRL_CHECKLISTBOX("chkMonthdays")
#define chkMonths CTRL_CHECKLISTBOX("chkMonths")
#define chkHours CTRL_CHECKLISTBOX("chkHours")
#define chkMinutes CTRL_CHECKLISTBOX("chkMinutes")
#define lstExceptions CTRL_LISTVIEW("lstExceptions")
#define timException CTRL_TIME("timException")
#define calException CTRL_CALENDAR("calException")
#define btnAddException CTRL_BUTTON("btnAddException")
#define btnChangeException CTRL_BUTTON("btnChangeException")
#define btnRemoveException CTRL_BUTTON("btnRemoveException")
#define btnWeekdays CTRL_BUTTON("btnWeekdays")
#define btnMonthdays CTRL_BUTTON("btnMonthdays")
#define btnMonths CTRL_BUTTON("btnMonths")
#define btnHours CTRL_BUTTON("btnHours")
#define btnMinutes CTRL_BUTTON("btnMinutes")
BEGIN_EVENT_TABLE(dlgSchedule, dlgAgentProperty)
EVT_CHECKBOX(XRCID("chkEnabled"), dlgSchedule::OnChangeCom)
EVT_CALENDAR_SEL_CHANGED(XRCID("calStart"), dlgSchedule::OnChangeCal)
EVT_TEXT(XRCID("timStart"), dlgSchedule::OnChangeCom)
EVT_CALENDAR_SEL_CHANGED(XRCID("calEnd"), dlgSchedule::OnChangeCal)
EVT_TEXT(XRCID("timEnd"), dlgSchedule::OnChangeCom)
EVT_LIST_ITEM_SELECTED(XRCID("lstExceptions"), dlgSchedule::OnSelChangeException)
EVT_BUTTON(XRCID("btnAddException"), dlgSchedule::OnAddException)
EVT_BUTTON(XRCID("btnChangeException"), dlgSchedule::OnChangeException)
EVT_BUTTON(XRCID("btnRemoveException"), dlgSchedule::OnRemoveException)
EVT_BUTTON(XRCID("btnWeekdays"), dlgSchedule::OnSelectAllWeekdays)
EVT_BUTTON(XRCID("btnMonthdays"), dlgSchedule::OnSelectAllMonthdays)
EVT_BUTTON(XRCID("btnMonths"), dlgSchedule::OnSelectAllMonths)
EVT_BUTTON(XRCID("btnHours"), dlgSchedule::OnSelectAllHours)
EVT_BUTTON(XRCID("btnMinutes"), dlgSchedule::OnSelectAllMinutes)
EVT_CHECKLISTBOX(XRCID("chkWeekdays"), dlgSchedule::OnChangeCom)
EVT_CHECKLISTBOX(XRCID("chkMonthdays"), dlgSchedule::OnChangeCom)
EVT_CHECKLISTBOX(XRCID("chkMonths"), dlgSchedule::OnChangeCom)
EVT_CHECKLISTBOX(XRCID("chkHours"), dlgSchedule::OnChangeCom)
EVT_CHECKLISTBOX(XRCID("chkMinutes"), dlgSchedule::OnChangeCom)
#ifdef __WXMAC__
EVT_SIZE( dlgSchedule::OnChangeSize)
#endif
END_EVENT_TABLE();
dlgProperty *pgaScheduleFactory::CreateDialog(frmMain *frame, pgObject *node, pgObject *parent)
{
return new dlgSchedule(this, frame, (pgaSchedule *)node, (pgaJob *)parent);
}
dlgSchedule::dlgSchedule(pgaFactory *f, frmMain *frame, pgaSchedule *node, pgaJob *j)
: dlgAgentProperty(f, frame, wxT("dlgSchedule"))
{
schedule = node;
job = j;
if (job)
jobId = job->GetRecId();
else
jobId = 0;
lstExceptions->CreateColumns(0, _("Date"), _("Time"), 90);
lstExceptions->AddColumn(wxT("dirty"), 0);
lstExceptions->AddColumn(wxT("id"), 0);
txtID->Disable();
btnChangeException->Disable();
btnRemoveException->Disable();
int i;
for (i = 0 ; i < 24 ; i++)
chkHours->Append(wxString::Format(wxT("%02d"), i));
for (i = 0 ; i < 60 ; i++)
chkMinutes->Append(wxString::Format(wxT("%02d"), i));
}
pgObject *dlgSchedule::GetObject()
{
return schedule;
}
#ifdef __WXMAC__
void dlgSchedule::OnChangeSize(wxSizeEvent &ev)
{
lstExceptions->SetSize(wxDefaultCoord, wxDefaultCoord,
ev.GetSize().GetWidth(), ev.GetSize().GetHeight() - 350);
if (GetAutoLayout())
{
Layout();
}
}
#endif
int dlgSchedule::Go(bool modal)
{
int returncode;
if (schedule)
{
// edit mode
recId = schedule->GetRecId();
txtID->SetValue(NumToStr(recId));
chkEnabled->SetValue(schedule->GetEnabled());
calStart->SetValue(schedule->GetStart().GetDateOnly());
timStart->SetTime(schedule->GetStart());
if (schedule->GetEnd().IsValid())
{
calEnd->SetValue(schedule->GetEnd().GetDateOnly());
timEnd->SetTime(schedule->GetEnd());
}
else
{
calEnd->SetValue(wxInvalidDateTime);
timEnd->SetTime(wxInvalidDateTime);
timEnd->Disable();
}
unsigned int x;
for (x = 0; x < schedule->GetMonths().Length(); x++ )
if (schedule->GetMonths()[x] == 't') chkMonths->Check(x, true);
for (x = 0; x < schedule->GetMonthdays().Length(); x++ )
if (schedule->GetMonthdays()[x] == 't') chkMonthdays->Check(x, true);
for (x = 0; x < schedule->GetWeekdays().Length(); x++ )
if (schedule->GetWeekdays()[x] == 't') chkWeekdays->Check(x, true);
for (x = 0; x < schedule->GetHours().Length(); x++ )
if (schedule->GetHours()[x] == 't') chkHours->Check(x, true);
for (x = 0; x < schedule->GetMinutes().Length(); x++ )
if (schedule->GetMinutes()[x] == 't') chkMinutes->Check(x, true);
wxString id, dateToken, timeToken;
wxDateTime val;
long pos = 0;
wxStringTokenizer tkz(schedule->GetExceptions(), wxT("|"));
while (tkz.HasMoreTokens() )
{
dateToken.Empty();
timeToken.Empty();
// First is the ID
id = tkz.GetNextToken();
// Look for a date
if (tkz.HasMoreTokens())
dateToken = tkz.GetNextToken();
// Look for a time
if (tkz.HasMoreTokens())
timeToken = tkz.GetNextToken();
if (!dateToken.IsEmpty() && !timeToken.IsEmpty())
{
val.ParseDate(dateToken);
val.ParseTime(timeToken);
pos = lstExceptions->AppendItem(0, val.FormatDate(), val.FormatTime());
}
else if (!dateToken.IsEmpty() && timeToken.IsEmpty())
{
val.ParseDate(dateToken);
pos = lstExceptions->AppendItem(0, val.FormatDate(), _("<any>"));
}
else if (dateToken.IsEmpty() && !timeToken.IsEmpty())
{
val.ParseTime(timeToken);
pos = lstExceptions->AppendItem(0, _("<any>"), val.FormatTime());
}
lstExceptions->SetItem(pos, 2, BoolToStr(false));
lstExceptions->SetItem(pos, 3, id);
}
wxNotifyEvent ev;
}
else
{
// create mode
}
// setup de-/select buttons
InitSelectAll();
returncode = dlgProperty::Go(modal);
SetSqlReadOnly(true);
return returncode;
}
pgObject *dlgSchedule::CreateObject(pgCollection *collection)
{
pgObject *obj = scheduleFactory.CreateObjects(collection, 0, wxT(" AND jscid=") + NumToStr(recId) + wxT("\n"));
return obj;
}
void dlgSchedule::OnChangeCal(wxCalendarEvent &ev)
{
CheckChange();
}
void dlgSchedule::OnChangeCom(wxCommandEvent &ev)
{
CheckChange();
}
void dlgSchedule::CheckChange()
{
timEnd->Enable(calEnd->GetValue().IsValid());
wxString name = GetName();
bool enable = true;
if (statusBar)
statusBar->SetStatusText(wxEmptyString);
InitSelectAll();
CheckValid(enable, !name.IsEmpty(), _("Please specify name."));
CheckValid(enable, calStart->GetValue().IsValid(), _("Please specify start date."));
if (enable)
{
EnableOK(!GetSql().IsEmpty());
}
else
EnableOK(false);
}
void dlgSchedule::OnSelChangeException(wxListEvent &ev)
{
int sel = lstExceptions->GetSelection();
if (sel >= 0)
{
wxString exDate = lstExceptions->GetText(sel, 0);
wxString exTime = lstExceptions->GetText(sel, 1);
wxDateTime val, null;
if (exDate == _("<any>"))
calException->SetValue(null);
else
{
val.ParseDate(exDate);
calException->SetValue(val);
}
if (exTime == _("<any>"))
timException->SetTime(null);
else
{
val.ParseTime(exTime);
timException->SetTime(val);
}
btnChangeException->Enable();
btnRemoveException->Enable();
}
}
void dlgSchedule::OnAddException(wxCommandEvent &ev)
{
if (!calException->GetValue().IsValid() && timException->GetValue().IsNull())
{
wxMessageBox(_("You must enter a valid date and/or time!"), _("Add exception"), wxICON_EXCLAMATION | wxOK, this);
return;
}
wxString exDate, exTime;
if (calException->GetValue().IsValid())
exDate = calException->GetValue().FormatDate();
else
exDate = _("<any>");
if (!timException->GetValue().IsNull())
exTime = timException->GetValue().Format();
else
exTime = _("<any>");
for (int pos = 0; pos < lstExceptions->GetItemCount(); pos++)
{
if (lstExceptions->GetText(pos, 0) == exDate &&
lstExceptions->GetText(pos, 1) == exTime)
{
wxMessageBox(_("The specified exception already exists!"), _("Add exception"), wxICON_EXCLAMATION | wxOK, this);
return;
}
if (lstExceptions->GetText(pos, 0) == exDate &&
lstExceptions->GetText(pos, 1) == _("<any>"))
{
wxMessageBox(_("An exception already exists for any time on this date!"), _("Add exception"), wxICON_EXCLAMATION | wxOK, this);
return;
}
if (lstExceptions->GetText(pos, 1) == exTime &&
lstExceptions->GetText(pos, 0) == _("<any>"))
{
wxMessageBox(_("An exception already exists for this time on any date!"), _("Add exception"), wxICON_EXCLAMATION | wxOK, this);
return;
}
}
lstExceptions->AppendItem(0, exDate, exTime);
CheckChange();
}
void dlgSchedule::OnChangeException(wxCommandEvent &ev)
{
if (!calException->GetValue().IsValid() && timException->GetValue().IsNull())
{
wxMessageBox(_("You must enter a valid date and/or time!"), _("Add exception"), wxICON_EXCLAMATION | wxOK, this);
return;
}
wxString exDate, exTime;
if (calException->GetValue().IsValid())
exDate = calException->GetValue().FormatDate();
else
exDate = _("<any>");
if (!timException->GetValue().IsNull())
exTime = timException->GetValue().Format();
else
exTime = _("<any>");
long item = lstExceptions->GetFocusedItem();
for (int pos = 0; pos < lstExceptions->GetItemCount(); pos++)
{
if (item != pos)
{
if (lstExceptions->GetText(pos, 0) == exDate &&
lstExceptions->GetText(pos, 1) == exTime)
{
wxMessageBox(_("The specified exception already exists!"), _("Add exception"), wxICON_EXCLAMATION | wxOK, this);
return;
}
if (lstExceptions->GetText(pos, 0) == exDate &&
lstExceptions->GetText(pos, 1) == _("<any>"))
{
wxMessageBox(_("An exception already exists for any time on this date!"), _("Add exception"), wxICON_EXCLAMATION | wxOK, this);
return;
}
if (lstExceptions->GetText(pos, 1) == exTime &&
lstExceptions->GetText(pos, 0) == _("<any>"))
{
wxMessageBox(_("An exception already exists for this time on any date!"), _("Add exception"), wxICON_EXCLAMATION | wxOK, this);
return;
}
}
}
lstExceptions->SetItem(item, 0, exDate);
lstExceptions->SetItem(item, 1, exTime);
lstExceptions->SetItem(item, 2, BoolToStr(true));
CheckChange();
}
void dlgSchedule::OnRemoveException(wxCommandEvent &ev)
{
if (lstExceptions->GetText(lstExceptions->GetFocusedItem(), 3) != wxEmptyString)
{
deleteExceptions.Add(lstExceptions->GetText(lstExceptions->GetFocusedItem(), 3));
}
lstExceptions->DeleteCurrentItem();
btnChangeException->Disable();
btnRemoveException->Disable();
CheckChange();
}
wxString dlgSchedule::GetComment()
{
return txtComment->GetValue();
}
wxString dlgSchedule::GetInsertSql()
{
wxString sql;
if (!schedule)
{
wxString name = GetName();
wxString jscjobid, list = wxT("NULL");
if (jobId)
jscjobid = NumToStr(jobId);
else
jscjobid = wxT("<JobId>");
// Build the various arrays of values
sql = wxT("INSERT INTO pgagent.pga_schedule (jscid, jscjobid, jscname, jscdesc, jscminutes, jschours, jscweekdays, jscmonthdays, jscmonths, jscenabled, jscstart, jscend)\n")
wxT("VALUES(<SchId>, ") + jscjobid + wxT(", ") + qtDbString(name) + wxT(", ") + qtDbString(txtComment->GetValue()) + wxT(", ")
+ wxT("'") + ChkListBox2PgArray(chkMinutes) + wxT("', ")
+ wxT("'") + ChkListBox2PgArray(chkHours) + wxT("', ")
+ wxT("'") + ChkListBox2PgArray(chkWeekdays) + wxT("', ")
+ wxT("'") + ChkListBox2PgArray(chkMonthdays) + wxT("', ")
+ wxT("'") + ChkListBox2PgArray(chkMonths) + wxT("', ")
+ BoolToStr(chkEnabled->GetValue()) + wxT(", ")
+ wxT("'") + DateToAnsiStr(calStart->GetValue() + timStart->GetValue()) + wxT("'");
if (calEnd->GetValue().IsValid())
sql += wxT(", '") + DateToAnsiStr(calEnd->GetValue() + timEnd->GetValue()) + wxT("'");
else
sql += wxT(", NULL");
sql += wxT(");\n");
}
return sql;
}
wxString dlgSchedule::GetUpdateSql()
{
wxString sql, name;
name = GetName();
if (schedule)
{
// edit mode
wxString vars;
if (name != schedule->GetName())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jscname = ") + qtDbString(name));
}
if (txtComment->GetValue() != schedule->GetComment())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jscdesc = ") + qtDbString(txtComment->GetValue()));
}
if ((!chkEnabled->IsChecked() && schedule->GetEnabled()) || (chkEnabled->IsChecked() && !schedule->GetEnabled()))
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jscenabled = ") + BoolToStr(chkEnabled->IsChecked()));
}
if (calStart->GetValue() + timStart->GetValue() != schedule->GetStart())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jscstart = '") + DateToAnsiStr(calStart->GetValue() + timStart->GetValue()) + wxT("'"));
}
if (calEnd->GetValue().IsValid())
{
if (schedule->GetEnd().IsValid())
{
if (calEnd->GetValue() + timEnd->GetValue() != schedule->GetEnd())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jscend = '") + DateToAnsiStr(calEnd->GetValue() + timEnd->GetValue()) + wxT("'"));
}
}
else
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jscend = '") + DateToAnsiStr(calEnd->GetValue() + wxTimeSpan()) + wxT("'"));
}
}
else
{
if (schedule->GetEnd().IsValid())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jscend = NULL"));
}
}
if (ChkListBox2StrArray(chkMinutes) != schedule->GetMinutes())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jscminutes = '") + ChkListBox2PgArray(chkMinutes) + wxT("'"));
}
if (ChkListBox2StrArray(chkHours) != schedule->GetHours())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jschours = '") + ChkListBox2PgArray(chkHours) + wxT("'"));
}
if (ChkListBox2StrArray(chkWeekdays) != schedule->GetWeekdays())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jscweekdays = '") + ChkListBox2PgArray(chkWeekdays) + wxT("'"));
}
if (ChkListBox2StrArray(chkMonthdays) != schedule->GetMonthdays())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jscmonthdays = '") + ChkListBox2PgArray(chkMonthdays) + wxT("'"));
}
if (ChkListBox2StrArray(chkMonths) != schedule->GetMonths())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jscmonths = '") + ChkListBox2PgArray(chkMonths) + wxT("'"));
}
if (!vars.IsEmpty())
sql = wxT("UPDATE pgagent.pga_schedule SET ") + vars + wxT("\n")
wxT(" WHERE jscid=") + NumToStr(recId) + wxT(";\n");
}
else
{
// create mode
// Handled by GetInsertSQL
}
unsigned int x = 0;
int y = 0;
wxDateTime tmpDateTime;
wxString newDate, newTime;
// Remove old exceptions
for (x = 0; x < deleteExceptions.Count(); x++)
{
sql += wxT("DELETE FROM pgagent.pga_exception\n WHERE jexid = ") + deleteExceptions[x] + wxT(";\n");
}
// Update dirty exceptions
for (y = 0; y < lstExceptions->GetItemCount(); y++)
{
if (lstExceptions->GetText(y, 2) == BoolToStr(true) &&
lstExceptions->GetText(y, 3) != wxEmptyString)
{
if (lstExceptions->GetText(y, 0) == _("<any>"))
newDate = wxT("null");
else
{
tmpDateTime.ParseFormat(lstExceptions->GetText(y, 0), wxT("%x"));
newDate = wxT("'") + tmpDateTime.FormatISODate() + wxT("'");
}
if (lstExceptions->GetText(y, 1) == _("<any>"))
newTime = wxT("null");
else
{
tmpDateTime.ParseTime(lstExceptions->GetText(y, 1));
newTime = wxT("'") + tmpDateTime.FormatISOTime() + wxT("'");
}
sql += wxT("UPDATE pgagent.pga_exception SET jexdate = ") + newDate +
wxT(", jextime = ") + newTime + wxT("\n WHERE jexid = ") +
lstExceptions->GetText(y, 3) + wxT(";\n");
}
}
// Insert new exceptions
for (y = 0; y < lstExceptions->GetItemCount(); y++)
{
if (lstExceptions->GetText(y, 2) == wxEmptyString &&
lstExceptions->GetText(y, 3) == wxEmptyString)
{
if (lstExceptions->GetText(y, 0) == _("<any>"))
newDate = wxT("null");
else
{
tmpDateTime.ParseFormat(lstExceptions->GetText(y, 0), wxT("%x"));
newDate = wxT("'") + tmpDateTime.FormatISODate() + wxT("'");
}
if (lstExceptions->GetText(y, 1) == _("<any>"))
newTime = wxT("null");
else
{
tmpDateTime.ParseTime(lstExceptions->GetText(y, 1));
newTime = wxT("'") + tmpDateTime.FormatISOTime() + wxT("'");
}
sql += wxT("INSERT INTO pgagent.pga_exception (jexscid, jexdate, jextime)\n VALUES (")
+ NumToStr(recId) + wxT(", ") + newDate + wxT(", ") + newTime + wxT(");\n");
}
}
return sql;
}
const wxString dlgSchedule::ChkListBox2PgArray(wxCheckListBox *lb)
{
wxString res = wxT("{");
for (unsigned int x = 0; x < lb->GetCount(); x++)
{
if (lb->IsChecked(x))
res += wxT("t,");
else
res += wxT("f,");
}
if (res.Length() > 1)
res.RemoveLast();
res += wxT("}");
return res;
}
const wxString dlgSchedule::ChkListBox2StrArray(wxCheckListBox *lb)
{
wxString res;
for (unsigned int x = 0; x < lb->GetCount(); x++)
{
if (lb->IsChecked(x))
res += wxT("t");
else
res += wxT("f");
}
return res;
}
void dlgSchedule::OnSelectAll(wxCommandEvent &ev, int origin)
{
bool check = false;
wxBitmapButton *btn;
wxCheckListBox *lb;
wxString tooltip;
switch (origin)
{
case 1:
btn = ((wxBitmapButton *)btnWeekdays);
lb = chkWeekdays;
break;
case 2:
btn = ((wxBitmapButton *)btnMonthdays);
lb = chkMonthdays;
break;
case 3:
btn = ((wxBitmapButton *)btnMonths);
lb = chkMonths;
break;
case 4:
btn = ((wxBitmapButton *)btnHours);
lb = chkHours;
break;
case 5:
btn = ((wxBitmapButton *)btnMinutes);
lb = chkMinutes;
break;
default:
return;
break;
}
for (unsigned int x = 0; x < lb->GetCount(); x++)
{
if (!lb->IsChecked(x))
{
check = true;
break;
}
}
for (unsigned int x = 0; x < lb->GetCount(); x++)
{
lb->Check(x, check);
}
CheckChange();
}
void dlgSchedule::InitSelectAll()
{
bool check = false;
wxBitmapButton *btn;
wxCheckListBox *lb;
wxString tooltip;
btn = ((wxBitmapButton *)btnWeekdays);
lb = chkWeekdays;
for (unsigned int x = 0; x < lb->GetCount(); x++)
{
if (!lb->IsChecked(x))
{
check = true;
break;
}
}
if (check)
{
btn->SetBitmapLabel(*check_png_bmp);
tooltip = _("Select all week days");
}
else
{
btn->SetBitmapLabel(*uncheck_png_bmp);
tooltip = _("Deselect all week days");
}
btn->SetToolTip(tooltip);
check = false;
btn = ((wxBitmapButton *)btnMonthdays);
lb = chkMonthdays;
for (unsigned int x = 0; x < lb->GetCount(); x++)
{
if (!lb->IsChecked(x))
{
check = true;
break;
}
}
if (check)
{
btn->SetBitmapLabel(*check_png_bmp);
tooltip = _("Select all month days");
}
else
{
btn->SetBitmapLabel(*uncheck_png_bmp);
tooltip = _("Deselect all month days");
}
btn->SetToolTip(tooltip);
check = false;
btn = ((wxBitmapButton *)btnMonths);
lb = chkMonths;
for (unsigned int x = 0; x < lb->GetCount(); x++)
{
if (!lb->IsChecked(x))
{
check = true;
break;
}
}
if (check)
{
btn->SetBitmapLabel(*check_png_bmp);
tooltip = _("Select all months");
}
else
{
btn->SetBitmapLabel(*uncheck_png_bmp);
tooltip = _("Deselect all months");
}
btn->SetToolTip(tooltip);
check = false;
btn = ((wxBitmapButton *)btnHours);
lb = chkHours;
for (unsigned int x = 0; x < lb->GetCount(); x++)
{
if (!lb->IsChecked(x))
{
check = true;
break;
}
}
if (check)
{
btn->SetBitmapLabel(*check_png_bmp);
tooltip = _("Select all hours");
}
else
{
btn->SetBitmapLabel(*uncheck_png_bmp);
tooltip = _("Deselect all hours");
}
btn->SetToolTip(tooltip);
check = false;
btn = ((wxBitmapButton *)btnMinutes);
lb = chkMinutes;
for (unsigned int x = 0; x < lb->GetCount(); x++)
{
if (!lb->IsChecked(x))
{
check = true;
break;
}
}
if (check)
{
btn->SetBitmapLabel(*check_png_bmp);
tooltip = _("Select all minutes");
}
else
{
btn->SetBitmapLabel(*uncheck_png_bmp);
tooltip = _("Deselect all minutes");
}
btn->SetToolTip(tooltip);
}

483
agent/dlgStep.cpp Normal file
View file

@ -0,0 +1,483 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// dlgStep.cpp - PostgreSQL Step Property
//
//////////////////////////////////////////////////////////////////////////
// App headers
#include "pgAdmin3.h"
#include "utils/misc.h"
#include "agent/dlgStep.h"
#include "agent/pgaStep.h"
#include "dlg/dlgSelectDatabase.h"
#include "schema/pgTable.h"
// pointer to controls
#define txtID CTRL_TEXT("txtID")
#define chkEnabled CTRL_CHECKBOX("chkEnabled")
#define rbxKind CTRL_RADIOBOX("rbxKind")
#define rbxOnError CTRL_RADIOBOX("rbxOnError")
#define pnlDefinition CTRL_PANEL("pnlDefinition")
#define txtSqlBox CTRL_TEXT("txtSqlBox")
#define cbDatabase CTRL_COMBOBOX2("cbDatabase")
#define txtConnStr CTRL_TEXT("txtConnStr")
#define btnSelDatabase CTRL_BUTTON("btnSelDatabase")
#define rbRemoteConn CTRL_RADIOBUTTON("rbRemoteConn")
#define rbLocalConn CTRL_RADIOBUTTON("rbLocalConn")
#define CTL_SQLBOX 188
BEGIN_EVENT_TABLE(dlgStep, dlgAgentProperty)
EVT_CHECKBOX(XRCID("chkEnabled"), dlgProperty::OnChange)
EVT_COMBOBOX(XRCID("cbDatabase"), dlgProperty::OnChange)
EVT_RADIOBOX(XRCID("rbxKind"), dlgProperty::OnChange)
EVT_RADIOBOX(XRCID("rbxOnError"), dlgProperty::OnChange)
EVT_TEXT(XRCID("txtConnStr"), dlgProperty::OnChange)
EVT_STC_MODIFIED(CTL_SQLBOX, dlgProperty::OnChangeStc)
EVT_BUTTON(XRCID("btnSelDatabase"), dlgStep::OnSelectDatabase)
EVT_RADIOBUTTON(XRCID("rbRemoteConn"), dlgStep::OnSelRemoteConn)
EVT_RADIOBUTTON(XRCID("rbLocalConn"), dlgStep::OnSelLocalConn)
END_EVENT_TABLE();
dlgProperty *pgaStepFactory::CreateDialog(frmMain *frame, pgObject *node, pgObject *parent)
{
return new dlgStep(this, frame, (pgaStep *)node, (pgaJob *)parent);
}
dlgStep::dlgStep(pgaFactory *f, frmMain *frame, pgaStep *node, pgaJob *j)
: dlgAgentProperty(f, frame, wxT("dlgStep"))
{
step = node;
job = j;
if (job)
jobId = job->GetRecId();
else
jobId = 0;
sqlBox = new ctlSQLBox(pnlDefinition, CTL_SQLBOX, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxSUNKEN_BORDER | wxTE_RICH2);
wxWindow *placeholder = CTRL_TEXT("txtSqlBox");
wxSizer *sizer = placeholder->GetContainingSizer();
sizer->Add(sqlBox, 1, wxRIGHT | wxGROW, 5);
sizer->Detach(placeholder);
delete placeholder;
sizer->Layout();
txtID->Disable();
}
pgObject *dlgStep::GetObject()
{
return step;
}
int dlgStep::Go(bool modal)
{
int returncode;
hasConnStrSupport = connection->TableHasColumn(wxT("pgagent"), wxT("pga_jobstep"), wxT("jstconnstr"));
cbDatabase->Append(wxT(" "));
cbDatabase->SetSelection(0);
pgSet *db = connection->ExecuteSet(wxT("SELECT datname FROM pg_database"));
if (db)
{
while (!db->Eof())
{
cbDatabase->Append(db->GetVal(0));
db->MoveNext();
}
delete db;
}
if (step)
{
// edit mode
recId = step->GetRecId();
txtID->SetValue(NumToStr(recId));
if (step->HasConnectionString())
{
rbRemoteConn->SetValue(true);
txtConnStr->Enable(true);
txtConnStr->ChangeValue(step->GetConnStr());
btnSelDatabase->Enable(true);
cbDatabase->Enable(false);
}
else
{
rbLocalConn->SetValue(true);
if (step->GetDbname().IsEmpty())
cbDatabase->SetSelection(0);
else
cbDatabase->SetValue(step->GetDbname());
}
rbxKind->SetSelection(wxString(wxT("sb")).Find(step->GetKindChar()));
rbxOnError->SetSelection(wxString(wxT("fsi")).Find(step->GetOnErrorChar()));
sqlBox->SetText(step->GetCode());
chkEnabled->SetValue(step->GetEnabled());
}
else
{
// create mode
rbLocalConn->SetValue(true);
cbDatabase->Enable(true);
btnSelDatabase->Enable(false);
txtConnStr->Enable(false);
if (!hasConnStrSupport)
rbLocalConn->Enable(false);
}
returncode = dlgProperty::Go(modal);
SetSqlReadOnly(true);
return returncode;
}
pgObject *dlgStep::CreateObject(pgCollection *collection)
{
wxString name = GetName();
pgObject *obj = stepFactory.CreateObjects(collection, 0, wxT(" AND jstid=") + NumToStr(recId) + wxT("\n"));
return obj;
}
void dlgStep::CheckChange()
{
wxString name = GetName();
bool enable;
if (step)
{
enable = name != step->GetName()
|| chkEnabled->GetValue() != step->GetEnabled()
|| rbxKind->GetSelection() != wxString(wxT("sb")).Find(step->GetKindChar())
|| rbxOnError->GetSelection() != wxString(wxT("fsi")).Find(step->GetOnErrorChar())
|| txtComment->GetValue() != step->GetComment()
|| sqlBox->GetText() != step->GetCode();
if (!enable && rbxKind->GetSelection() == 0)
{
if (hasConnStrSupport)
{
if (step->HasConnectionString())
{
if (rbRemoteConn->GetValue())
enable = txtConnStr->GetValue().Trim() != step->GetConnStr();
else
enable = true;
}
else
{
if (rbRemoteConn->GetValue())
enable = true;
else
enable = cbDatabase->GetValue().Trim() != step->GetDbname();
}
}
else
{
enable = cbDatabase->GetValue().Trim() != step->GetDbname();
}
}
}
else
{
enable = true;
}
if (statusBar)
statusBar->SetStatusText(wxEmptyString);
CheckValid(enable, !name.IsEmpty(), _("Please specify name."));
CheckValid(enable, sqlBox->GetLength() > 0, _("Please specify code to execute."));
// Disable/enable the database combo
if (rbxKind->GetSelection() == 1)
{
rbRemoteConn->Enable(false);
rbLocalConn->Enable(false);
// I don't see any reason to make
// the database combobox selection to 0
//cbDatabase->SetSelection(0);
txtConnStr->Enable(false);
btnSelDatabase->Enable(false);
cbDatabase->Enable(false);
}
else
{
if (hasConnStrSupport)
{
rbRemoteConn->Enable(true);
rbLocalConn->Enable(true);
if (rbRemoteConn->GetValue())
{
wxString validConnStr;
btnSelDatabase->Enable(true);
txtConnStr->Enable(true);
cbDatabase->Enable(false);
CheckValid(enable, !txtConnStr->GetValue().Trim().IsEmpty(), _("Please select a connection string."));
CheckValid(enable, dlgSelectDatabase::getValidConnectionString(txtConnStr->GetValue().Trim(), validConnStr), _("Please enter a valid connection string"));
}
else
{
cbDatabase->Enable(true);
btnSelDatabase->Enable(false);
txtConnStr->Enable(false);
CheckValid(enable, !cbDatabase->GetValue().Trim().IsEmpty(), _("Please select a database."));
}
}
else
{
cbDatabase->Enable(true);
// Make sure both radio buttons are disabled
rbRemoteConn->Enable(false);
rbLocalConn->Enable(false);
CheckValid(enable, !cbDatabase->GetValue().Trim().IsEmpty(), _("Please select a database."));
}
}
EnableOK(enable);
}
wxString dlgStep::GetComment()
{
return txtComment->GetValue();
}
wxString dlgStep::GetInsertSql()
{
wxString sql;
if (!step)
{
wxString name = GetName();
wxString kind = wxT("sb")[rbxKind->GetSelection()];
wxString onerror = wxT("fsi")[rbxOnError->GetSelection()];
wxString db, connstr;
wxString jstjobid;
if (jobId)
jstjobid = NumToStr(jobId);
else
jstjobid = wxT("<JobId>");
// SQL script expected
if (rbxKind->GetSelection() == 0)
{
if (hasConnStrSupport && rbRemoteConn->GetValue())
{
connstr = qtDbString(txtConnStr->GetValue().Trim());
db = wxT("''");
}
else
{
db = qtDbString(cbDatabase->GetValue().Trim());
connstr = wxT("''");
}
}
else
{
db = wxT("''");
connstr = wxT("''");
}
sql = wxT("INSERT INTO pgagent.pga_jobstep (jstid, jstjobid, jstname, jstdesc, jstenabled, jstkind, jstonerror, jstcode, jstdbname");
if (hasConnStrSupport)
sql += wxT(", jstconnstr");
sql += wxT(")\n ") \
wxT("SELECT <StpId>, ") + jstjobid + wxT(", ") + qtDbString(name) + wxT(", ") + qtDbString(txtComment->GetValue()) + wxT(", ")
+ BoolToStr(chkEnabled->GetValue()) + wxT(", ") + qtDbString(kind) + wxT(", ")
+ qtDbString(onerror) + wxT(", ") + qtDbString(sqlBox->GetText()) + wxT(", ") + db;
if (hasConnStrSupport)
{
sql += wxT(", ") + connstr;
}
sql += wxT(";\n");
}
return sql;
}
wxString dlgStep::GetUpdateSql()
{
wxString sql;
if (step)
{
// edit mode
wxString name = GetName();
wxString kind = wxT("sb")[rbxKind->GetSelection()];
wxString vars;
if (name != step->GetName())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jstname=") + qtDbString(name));
}
if (chkEnabled->GetValue() != step->GetEnabled())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jstenabled=") + BoolToStr(chkEnabled->GetValue()));
}
if (hasConnStrSupport && kind == wxT("s"))
{
if (rbRemoteConn->GetValue())
{
if (step->HasConnectionString())
{
if (txtConnStr->GetValue().Trim() != step->GetConnStr())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jstconnstr=") + qtDbString(txtConnStr->GetValue().Trim()));
}
}
else
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jstconnstr=") + qtDbString(txtConnStr->GetValue().Trim()) + wxT(", "));
vars.Append(wxT("jstdbname=''"));
}
}
else
{
if (step->HasConnectionString())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jstdbname=") + qtDbString(cbDatabase->GetValue().Trim()) + wxT(", "));
vars.Append(wxT("jstconnstr=''"));
}
else
{
if (cbDatabase->GetValue().Trim() != step->GetDbname())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jstdbname=") + qtDbString(cbDatabase->GetValue().Trim()));
}
}
}
}
else if (kind == wxT("s"))
{
if (cbDatabase->GetValue().Trim() != step->GetDbname())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jstdbname=") + qtDbString(cbDatabase->GetValue().Trim()));
}
}
else
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jstdbname=''"));
if (hasConnStrSupport)
vars.Append(wxT(", jstconnstr=''"));
}
if (rbxKind->GetSelection() != kind)
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jstkind=") + qtDbString(kind));
}
if (rbxOnError->GetSelection() != wxString(wxT("fsi")).Find(step->GetOnErrorChar()))
{
wxString onerror = wxT("fsi")[rbxOnError->GetSelection()];
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jstonerror='") + onerror + wxT("'"));
}
if (txtComment->GetValue() != step->GetComment())
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jstdesc=") + qtDbString(txtComment->GetValue()));
}
if (sqlBox->GetText() != step->GetCode())
{
{
if (!vars.IsEmpty())
vars.Append(wxT(", "));
vars.Append(wxT("jstcode=") + qtDbString(sqlBox->GetText()));
}
}
if (!vars.IsEmpty())
sql = wxT("UPDATE pgagent.pga_jobstep\n")
wxT(" SET ") + vars + wxT("\n")
wxT(" WHERE jstid=") + NumToStr(step->GetRecId()) +
wxT(";\n");
}
else
{
// create mode; handled by GetInsertSql()
}
return sql;
}
bool dlgStep::IsUpToDate()
{
if (step && !step->IsUpToDate())
return false;
else
return true;
}
void dlgStep::OnSelectDatabase(wxCommandEvent &ev)
{
dlgSelectDatabase dlgSD(this, wxID_ANY);
if (dlgSD.ShowModal() == wxID_OK)
{
wxString strConnStr = dlgSD.getConnInfo();
if (!strConnStr.IsEmpty())
txtConnStr->SetValue(strConnStr);
}
}
void dlgStep::OnSelRemoteConn(wxCommandEvent &ev)
{
if (rbRemoteConn->GetValue())
{
cbDatabase->Enable(false);
btnSelDatabase->Enable(true);
txtConnStr->Enable(true);
}
dlgProperty::OnChange(ev);
}
void dlgStep::OnSelLocalConn(wxCommandEvent &ev)
{
if (rbLocalConn->GetValue())
{
cbDatabase->Enable(true);
btnSelDatabase->Enable(false);
txtConnStr->Enable(false);
}
dlgProperty::OnChange(ev);
}

23
agent/module.mk Normal file
View file

@ -0,0 +1,23 @@
#######################################################################
#
# pgAdmin III - PostgreSQL Tools
#
# Copyright (C) 2002 - 2016, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
# module.mk - pgadmin/agent/ Makefile fragment
#
#######################################################################
pgadmin3_SOURCES += \
agent/dlgJob.cpp \
agent/dlgSchedule.cpp \
agent/dlgStep.cpp \
agent/pgaJob.cpp \
agent/pgaSchedule.cpp \
agent/pgaStep.cpp
EXTRA_DIST += \
agent/module.mk

397
agent/pgaJob.cpp Normal file
View file

@ -0,0 +1,397 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// pgaJob.h - PostgreSQL Agent Job
//
//////////////////////////////////////////////////////////////////////////
// wxWindows headers
#include <wx/wx.h>
// App headers
#include "pgAdmin3.h"
#include "utils/misc.h"
#include "frm/frmMain.h"
#include "schema/pgObject.h"
#include "schema/pgCollection.h"
#include "schema/pgDatabase.h"
#include "agent/pgaJob.h"
#include "agent/pgaStep.h"
#include "agent/pgaSchedule.h"
pgaJob::pgaJob(const wxString &newName)
: pgServerObject(jobFactory, newName)
{
}
wxString pgaJob::GetTranslatedMessage(int kindOfMessage) const
{
wxString message = wxEmptyString;
switch (kindOfMessage)
{
case RETRIEVINGDETAILS:
message = _("Retrieving details on pgAgent job");
break;
case REFRESHINGDETAILS:
message = _("Refreshing pgAgent job");
break;
case PROPERTIESREPORT:
message = _("pgAgent job properties report");
break;
case PROPERTIES:
message = _("pgAgent job properties");
break;
case DDLREPORT:
message = _("pgAgent job DDL report");
break;
case DEPENDENCIESREPORT:
message = _("pgAgent job dependencies report");
break;
case DEPENDENCIES:
message = _("pgAgent job dependencies");
break;
case DEPENDENTSREPORT:
message = _("pgAgent job dependents report");
break;
case DEPENDENTS:
message = _("pgAgent job dependents");
break;
case DROPEXCLUDINGDEPS:
message = wxString::Format(_("Are you sure you wish to drop job \"%s\"?"),
GetFullIdentifier().c_str());
break;
case DROPTITLE:
message = _("Drop job?");
break;
}
if (!message.IsEmpty() && !(kindOfMessage == DROPEXCLUDINGDEPS || kindOfMessage == DROPTITLE))
message += wxT(" - ") + GetName();
return message;
}
int pgaJob::GetIconId()
{
if (GetEnabled())
return jobFactory.GetIconId();
else
return jobFactory.GetDisabledId();
}
wxMenu *pgaJob::GetNewMenu()
{
wxMenu *menu = pgObject::GetNewMenu();
if (1) // check priv.
{
stepFactory.AppendMenu(menu);
scheduleFactory.AppendMenu(menu);
}
return menu;
}
bool pgaJob::DropObject(wxFrame *frame, ctlTree *browser, bool cascaded)
{
return GetConnection()->ExecuteVoid(wxT("DELETE FROM pgagent.pga_job WHERE jobid=") + NumToStr(GetRecId()));
}
void pgaJob::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane)
{
if (!expandedKids)
{
expandedKids = true;
browser->RemoveDummyChild(this);
// Log
wxLogInfo(wxT("Adding child objects to Job."));
browser->AppendCollection(this, scheduleFactory);
browser->AppendCollection(this, stepFactory);
}
if (properties)
{
CreateListColumns(properties);
properties->AppendItem(_("Name"), GetName());
properties->AppendItem(_("ID"), GetRecId());
properties->AppendYesNoItem(_("Enabled"), GetEnabled());
properties->AppendItem(_("Host agent"), GetHostAgent());
properties->AppendItem(_("Job class"), GetJobclass());
properties->AppendItem(_("Created"), GetCreated());
properties->AppendItem(_("Changed"), GetChanged());
properties->AppendItem(_("Next run"), GetNextrun());
properties->AppendItem(_("Last run"), GetLastrun());
properties->AppendItem(_("Last result"), GetLastresult());
if (!GetCurrentAgent().IsEmpty())
properties->AppendItem(_("Running at"), GetCurrentAgent());
else
properties->AppendItem(_("Running at"), _("Not currently running"));
properties->AppendItem(_("Comment"), firstLineOnly(GetComment()));
}
}
pgObject *pgaJob::Refresh(ctlTree *browser, const wxTreeItemId item)
{
pgObject *job = 0;
pgObject *obj = browser->GetObject(browser->GetItemParent(item));
if (obj && obj->IsCollection())
job = jobFactory.CreateObjects((pgCollection *)obj, 0, wxT("\n WHERE j.jobid=") + NumToStr(GetRecId()));
return job;
}
pgObject *pgaJobFactory::CreateObjects(pgCollection *collection, ctlTree *browser, const wxString &restriction)
{
pgaJob *job = 0;
pgSet *jobs = collection->GetConnection()->ExecuteSet(
wxT("SELECT j.*, cl.*, ag.*, sub.jlgstatus AS joblastresult ")
wxT(" FROM pgagent.pga_job j JOIN")
wxT(" pgagent.pga_jobclass cl ON cl.jclid=jobjclid LEFT OUTER JOIN")
wxT(" pgagent.pga_jobagent ag ON ag.jagpid=jobagentid LEFT OUTER JOIN")
wxT(" (SELECT DISTINCT ON (jlgjobid) jlgstatus, jlgjobid")
wxT(" FROM pgagent.pga_joblog")
wxT(" ORDER BY jlgjobid, jlgid desc) sub ON sub.jlgjobid = j.jobid ")
+ restriction +
wxT("ORDER BY jobname;"));
if (jobs)
{
while (!jobs->Eof())
{
wxString status;
if (jobs->GetVal(wxT("joblastresult")) == wxT("r"))
status = _("Running");
else if (jobs->GetVal(wxT("joblastresult")) == wxT("s"))
status = _("Successful");
else if (jobs->GetVal(wxT("joblastresult")) == wxT("f"))
status = _("Failed");
else if (jobs->GetVal(wxT("joblastresult")) == wxT("d"))
status = _("Aborted");
else if (jobs->GetVal(wxT("joblastresult")) == wxT("i"))
status = _("No steps");
else
status = _("Unknown");
job = new pgaJob(jobs->GetVal(wxT("jobname")));
job->iSetServer(collection->GetServer());
job->iSetRecId(jobs->GetLong(wxT("jobid")));
job->iSetComment(jobs->GetVal(wxT("jobdesc")));
job->iSetEnabled(jobs->GetBool(wxT("jobenabled")));
job->iSetJobclass(jobs->GetVal(wxT("jclname")));
job->iSetHostAgent(jobs->GetVal(wxT("jobhostagent")));
job->iSetCreated(jobs->GetDateTime(wxT("jobcreated")));
job->iSetChanged(jobs->GetDateTime(wxT("jobchanged")));
job->iSetNextrun(jobs->GetDateTime(wxT("jobnextrun")));
job->iSetLastrun(jobs->GetDateTime(wxT("joblastrun")));
job->iSetLastresult(status);
job->iSetCurrentAgent(jobs->GetVal(wxT("jagstation")));
if (browser)
{
browser->AppendObject(collection, job);
jobs->MoveNext();
}
else
break;
}
delete jobs;
}
return job;
}
void pgaJob::ShowStatistics(frmMain *form, ctlListView *statistics)
{
wxString sql =
wxT("SELECT jlgid")
wxT(", jlgstatus")
wxT(", jlgstart")
wxT(", jlgduration")
wxT(", (jlgstart + jlgduration) AS endtime")
wxT(" FROM pgagent.pga_joblog\n")
wxT(" WHERE jlgjobid = ") + NumToStr(GetRecId()) +
wxT(" ORDER BY jlgstart DESC") +
wxT(" LIMIT ") + NumToStr(settings->GetMaxRows());
if (statistics)
{
wxLogInfo(wxT("Displaying statistics for job %s"), GetFullIdentifier().c_str());
// Add the statistics view columns
statistics->ClearAll();
statistics->AddColumn(_("Run"), 50);
statistics->AddColumn(_("Status"), 60);
statistics->AddColumn(_("Start time"), 95);
statistics->AddColumn(_("End time"), 95);
statistics->AddColumn(_("Duration"), 70);
pgSet *stats = GetConnection()->ExecuteSet(sql);
wxString status;
wxDateTime startTime;
wxDateTime endTime;
if (stats)
{
while (!stats->Eof())
{
if (stats->GetVal(1) == wxT("r"))
status = _("Running");
else if (stats->GetVal(1) == wxT("s"))
status = _("Successful");
else if (stats->GetVal(1) == wxT("f"))
status = _("Failed");
else if (stats->GetVal(1) == wxT("d"))
status = _("Aborted");
else if (stats->GetVal(1) == wxT("i"))
status = _("No steps");
else
status = _("Unknown");
startTime.ParseDateTime(stats->GetVal(2));
endTime.ParseDateTime(stats->GetVal(4));
long pos = statistics->AppendItem(stats->GetVal(0), status, startTime.Format());
if (stats->GetVal(4).Length() > 0)
statistics->SetItem(pos, 3, endTime.Format());
statistics->SetItem(pos, 4, stats->GetVal(3));
stats->MoveNext();
}
delete stats;
}
}
}
bool pgaJob::RunNow()
{
if (!GetConnection()->ExecuteVoid(wxT("UPDATE pgagent.pga_job SET jobnextrun = now() WHERE jobid=") + NumToStr(GetRecId())))
return false;
return true;
}
pgaJobCollection::pgaJobCollection(pgaFactory *factory, pgServer *sv)
: pgServerObjCollection(factory, sv)
{
}
wxString pgaJobCollection::GetTranslatedMessage(int kindOfMessage) const
{
wxString message = wxEmptyString;
switch (kindOfMessage)
{
case RETRIEVINGDETAILS:
message = _("Retrieving details on pgAgent jobs");
break;
case REFRESHINGDETAILS:
message = _("Refreshing pgAgent jobs");
break;
case OBJECTSLISTREPORT:
message = _("pgAgent jobs list report");
break;
}
return message;
}
pgaJobObject::pgaJobObject(pgaJob *_job, pgaFactory &factory, const wxString &newName)
: pgServerObject(factory, newName)
{
job = _job;
server = job->GetServer();
}
pgaJobObjCollection::pgaJobObjCollection(pgaFactory *factory, pgaJob *_job)
: pgServerObjCollection(factory, _job->GetServer())
{
job = _job;
}
bool pgaJobObjCollection::CanCreate()
{
return job->CanCreate();
}
pgCollection *pgaJobObjFactory::CreateCollection(pgObject *obj)
{
return new pgaJobObjCollection(GetCollectionFactory(), (pgaJob *)obj);
}
/////////////////////////////
#include "images/job.pngc"
#include "images/jobs.pngc"
#include "images/jobdisabled.pngc"
pgaJobFactory::pgaJobFactory()
: pgServerObjFactory(__("pgAgent Job"), __("New Job"), __("Create a new Job."), job_png_img)
{
metaType = PGM_JOB;
disabledId = addIcon(jobdisabled_png_img);
}
pgCollection *pgaJobFactory::CreateCollection(pgObject *obj)
{
return new pgaJobCollection(GetCollectionFactory(), (pgServer *)obj);
}
pgaJobFactory jobFactory;
static pgaCollectionFactory cf(&jobFactory, __("Jobs"), jobs_png_img);
runNowFactory::runNowFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : contextActionFactory(list)
{
mnu->Append(id, _("&Run now"), _("Reschedule the job to run now."));
}
wxWindow *runNowFactory::StartDialog(frmMain *form, pgObject *obj)
{
if (!((pgaJob *)(obj))->RunNow())
{
wxLogError(_("Failed to reschedule the job."));
}
form->Refresh(obj);
return 0;
}
bool runNowFactory::CheckEnable(pgObject *obj)
{
if (obj)
{
if (obj->GetMetaType() == PGM_JOB && !obj->IsCollection())
return true;
}
return false;
}

576
agent/pgaSchedule.cpp Normal file
View file

@ -0,0 +1,576 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// pgaSchedule.cpp - PostgreSQL Agent Schedule
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
// wxWindows headers
#include <wx/wx.h>
#include <wx/arrimpl.cpp>
// App headers
#include "utils/misc.h"
#include "schema/pgObject.h"
#include "schema/pgDatabase.h"
#include "schema/pgCollection.h"
#include "agent/pgaSchedule.h"
#include "agent/pgaStep.h"
#include "agent/pgaSchedule.h"
pgaSchedule::pgaSchedule(pgCollection *_collection, const wxString &newName)
: pgaJobObject(_collection->GetJob(), scheduleFactory, newName)
{
}
wxString pgaSchedule::GetTranslatedMessage(int kindOfMessage) const
{
wxString message = wxEmptyString;
switch (kindOfMessage)
{
case RETRIEVINGDETAILS:
message = _("Retrieving details on pgAgent schedule");
break;
case REFRESHINGDETAILS:
message = _("Refreshing pgAgent schedule");
break;
case PROPERTIESREPORT:
message = _("pgAgent schedule properties report");
break;
case PROPERTIES:
message = _("pgAgent schedule properties");
break;
case DDLREPORT:
message = _("pgAgent schedule DDL report");
break;
case DEPENDENCIESREPORT:
message = _("pgAgent schedule dependencies report");
break;
case DEPENDENCIES:
message = _("pgAgent schedule dependencies");
break;
case DEPENDENTSREPORT:
message = _("pgAgent schedule dependents report");
break;
case DEPENDENTS:
message = _("pgAgent schedule dependents");
break;
case DROPEXCLUDINGDEPS:
message = wxString::Format(_("Are you sure you wish to drop schedule \"%s\"?"),
GetFullIdentifier().c_str());
break;
case DROPTITLE:
message = _("Drop schedule?");
break;
}
if (!message.IsEmpty() && !(kindOfMessage == DROPEXCLUDINGDEPS || kindOfMessage == DROPTITLE))
message += wxT(" - ") + GetName();
return message;
}
bool pgaSchedule::DropObject(wxFrame *frame, ctlTree *browser, bool cascaded)
{
return GetConnection()->ExecuteVoid(wxT("DELETE FROM pgagent.pga_schedule WHERE jscid=") + NumToStr(GetRecId()));
}
void pgaSchedule::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane)
{
if (!expandedKids)
{
expandedKids = true;
}
if (properties)
{
CreateListColumns(properties);
properties->AppendItem(_("Name"), GetName());
properties->AppendItem(_("ID"), GetRecId());
properties->AppendYesNoItem(_("Enabled"), GetEnabled());
properties->AppendItem(_("Start date"), GetStart());
properties->AppendItem(_("End date"), GetEnd());
properties->AppendItem(_("Minutes"), GetMinutesString());
properties->AppendItem(_("Hours"), GetHoursString());
properties->AppendItem(_("Weekdays"), GetWeekdaysString());
properties->AppendItem(_("Monthdays"), GetMonthdaysString());
properties->AppendItem(_("Months"), GetMonthsString());
properties->AppendItem(_("Exceptions"), GetExceptionsString());
properties->AppendItem(_("Comment"), firstLineOnly(GetComment()));
}
}
pgObject *pgaSchedule::Refresh(ctlTree *browser, const wxTreeItemId item)
{
pgObject *schedule = 0;
pgCollection *coll = browser->GetParentCollection(item);
if (coll)
schedule = scheduleFactory.CreateObjects(coll, 0, wxT("\n AND jscid=") + NumToStr(GetRecId()));
return schedule;
}
pgObject *pgaScheduleFactory::CreateObjects(pgCollection *collection, ctlTree *browser, const wxString &restriction)
{
pgaSchedule *schedule = 0;
wxString tmp;
pgSet *schedules = collection->GetConnection()->ExecuteSet(
wxT("SELECT * FROM pgagent.pga_schedule\n")
wxT(" WHERE jscjobid=") + NumToStr(collection->GetJob()->GetRecId()) + wxT("\n")
+ restriction +
wxT(" ORDER BY jscname"));
if (schedules)
{
while (!schedules->Eof())
{
schedule = new pgaSchedule(collection, schedules->GetVal(wxT("jscname")));
schedule->iSetRecId(schedules->GetLong(wxT("jscid")));
schedule->iSetStart(schedules->GetDateTime(wxT("jscstart")));
schedule->iSetEnd(schedules->GetDateTime(wxT("jscend")));
schedule->iSetEnabled(schedules->GetBool(wxT("jscenabled")));
tmp = schedules->GetVal(wxT("jscminutes"));
tmp.Replace(wxT("{"), wxT(""));
tmp.Replace(wxT("}"), wxT(""));
tmp.Replace(wxT(","), wxT(""));
schedule->iSetMinutes(tmp);
tmp = schedules->GetVal(wxT("jschours"));
tmp.Replace(wxT("{"), wxT(""));
tmp.Replace(wxT("}"), wxT(""));
tmp.Replace(wxT(","), wxT(""));
schedule->iSetHours(tmp);
tmp = schedules->GetVal(wxT("jscweekdays"));
tmp.Replace(wxT("{"), wxT(""));
tmp.Replace(wxT("}"), wxT(""));
tmp.Replace(wxT(","), wxT(""));
schedule->iSetWeekdays(tmp);
tmp = schedules->GetVal(wxT("jscmonthdays"));
tmp.Replace(wxT("{"), wxT(""));
tmp.Replace(wxT("}"), wxT(""));
tmp.Replace(wxT(","), wxT(""));
schedule->iSetMonthdays(tmp);
tmp = schedules->GetVal(wxT("jscmonths"));
tmp.Replace(wxT("{"), wxT(""));
tmp.Replace(wxT("}"), wxT(""));
tmp.Replace(wxT(","), wxT(""));
schedule->iSetMonths(tmp);
schedule->iSetComment(schedules->GetVal(wxT("jscdesc")));
pgSet *exceptions = collection->GetConnection()->ExecuteSet(
wxT("SELECT * FROM pgagent.pga_exception\n")
wxT(" WHERE jexscid=") + NumToStr(schedule->GetRecId()) + wxT("\n"));
tmp.Empty();
if (exceptions)
{
while (!exceptions->Eof())
{
tmp += exceptions->GetVal(wxT("jexid"));
tmp += wxT("|");
tmp += exceptions->GetVal(wxT("jexdate"));
tmp += wxT("|");
tmp += exceptions->GetVal(wxT("jextime"));
tmp += wxT("|");
exceptions->MoveNext();
}
}
schedule->iSetExceptions(tmp);
delete exceptions;
if (browser)
{
browser->AppendObject(collection, schedule);
schedules->MoveNext();
}
else
break;
}
delete schedules;
}
return schedule;
}
wxString pgaSchedule::GetMinutesString()
{
size_t x = 0;
bool isWildcard = true;
wxString res, tmp;
for (x = 0; x <= minutes.Length(); x++)
{
if (minutes[x] == 't')
{
tmp.Printf(wxT("%.2d, "), (int)x);
res += tmp;
isWildcard = false;
}
}
if (isWildcard)
{
res = _("Every minute");
}
else
{
if (res.Length() > 2)
{
res.RemoveLast();
res.RemoveLast();
}
}
return res;
}
wxString pgaSchedule::GetHoursString()
{
size_t x = 0;
bool isWildcard = true;
wxString res, tmp;
for (x = 0; x <= hours.Length(); x++)
{
if (hours[x] == 't')
{
tmp.Printf(wxT("%.2d, "), (int)x);
res += tmp;
isWildcard = false;
}
}
if (isWildcard)
{
res = _("Every hour");
}
else
{
if (res.Length() > 2)
{
res.RemoveLast();
res.RemoveLast();
}
}
return res;
}
wxString pgaSchedule::GetWeekdaysString()
{
size_t x = 0;
bool isWildcard = true;
wxString res;
for (x = 0; x <= weekdays.Length(); x++)
{
if (weekdays[x] == 't')
{
switch (x)
{
case 0:
res += _("Sunday");
res += wxT(", ");
break;
case 1:
res += _("Monday");
res += wxT(", ");
break;
case 2:
res += _("Tuesday");
res += wxT(", ");
break;
case 3:
res += _("Wednesday");
res += wxT(", ");
break;
case 4:
res += _("Thursday");
res += wxT(", ");
break;
case 5:
res += _("Friday");
res += wxT(", ");
break;
case 6:
res += _("Saturday");
res += wxT(", ");
break;
default:
res += _("The mythical 8th day!");
res += wxT(", ");
break;
}
isWildcard = false;
}
}
if (isWildcard)
{
res = _("Any day of the week");
}
else
{
if (res.Length() > 2)
{
res.RemoveLast();
res.RemoveLast();
}
}
return res;
}
wxString pgaSchedule::GetMonthdaysString()
{
size_t x = 0;
bool isWildcard = true;
wxString res, tmp;
for (x = 0; x <= monthdays.Length(); x++)
{
if (monthdays[x] == 't')
{
if (x < 31)
{
tmp.Printf(wxT("%.2d, "), (int)(x + 1));
res += tmp;
}
else
{
res += _("Last day");
res += wxT(", ");
}
isWildcard = false;
}
}
if (isWildcard)
{
res = _("Every day");
}
else
{
if (res.Length() > 2)
{
res.RemoveLast();
res.RemoveLast();
}
}
return res;
}
wxString pgaSchedule::GetMonthsString()
{
size_t x = 0;
bool isWildcard = true;
wxString res;
for (x = 0; x <= months.Length(); x++)
{
if (months[x] == 't')
{
switch (x)
{
case 0:
res += _("January");
res += wxT(", ");
break;
case 1:
res += _("February");
res += wxT(", ");
break;
case 2:
res += _("March");
res += wxT(", ");
break;
case 3:
res += _("April");
res += wxT(", ");
break;
case 4:
res += _("May");
res += wxT(", ");
break;
case 5:
res += _("June");
res += wxT(", ");
break;
case 6:
res += _("July");
res += wxT(", ");
break;
case 7:
res += _("August");
res += wxT(", ");
break;
case 8:
res += _("September");
res += wxT(", ");
break;
case 9:
res += _("October");
res += wxT(", ");
break;
case 10:
res += _("November");
res += wxT(", ");
break;
case 11:
res += _("December");
res += wxT(", ");
break;
default:
res += _("The mythical 13th month!");
res += wxT(", ");
break;
}
isWildcard = false;
}
}
if (isWildcard)
{
res = _("Every month");
}
else
{
if (res.Length() > 2)
{
res.RemoveLast();
res.RemoveLast();
}
}
return res;
}
wxString pgaSchedule::GetExceptionsString()
{
wxString tmp, token, dateToken, timeToken;
wxDateTime val;
wxStringTokenizer tkz(exceptions, wxT("|"));
while (tkz.HasMoreTokens() )
{
dateToken.Empty();
timeToken.Empty();
// First is the ID which can be ignored
token = tkz.GetNextToken();
// Look for a date
if (tkz.HasMoreTokens())
dateToken = tkz.GetNextToken();
// Look for a time
if (tkz.HasMoreTokens())
timeToken = tkz.GetNextToken();
if (tmp.IsEmpty())
tmp += wxT("[");
else
tmp += wxT(", [");
if (!dateToken.IsEmpty() && !timeToken.IsEmpty())
{
val.ParseDate(dateToken);
val.ParseTime(timeToken);
tmp += val.Format();
}
else if (!dateToken.IsEmpty() && timeToken.IsEmpty())
{
val.ParseDate(dateToken);
tmp += val.FormatDate();
}
else if (dateToken.IsEmpty() && !timeToken.IsEmpty())
{
val.ParseTime(timeToken);
tmp += val.FormatTime();
}
tmp += wxT("]");
}
return tmp;
}
/////////////////////////////
pgaScheduleCollection::pgaScheduleCollection(pgaFactory *factory, pgaJob *job)
: pgaJobObjCollection(factory, job)
{
}
wxString pgaScheduleCollection::GetTranslatedMessage(int kindOfMessage) const
{
wxString message = wxEmptyString;
switch (kindOfMessage)
{
case RETRIEVINGDETAILS:
message = _("Retrieving details on pgAgent schedules");
break;
case REFRESHINGDETAILS:
message = _("Refreshing pgAgent schedules");
break;
case OBJECTSLISTREPORT:
message = _("pgAgent schedules list report");
break;
}
return message;
}
/////////////////////////////
#include "images/schedule.pngc"
#include "images/schedules.pngc"
pgaScheduleFactory::pgaScheduleFactory()
: pgaJobObjFactory(__("Schedule"), __("New Schedule"), __("Create a new Schedule."), schedule_png_img)
{
metaType = PGM_SCHEDULE;
}
pgCollection *pgaScheduleFactory::CreateCollection(pgObject *obj)
{
return new pgaScheduleCollection(GetCollectionFactory(), (pgaJob *)obj);
}
pgaScheduleFactory scheduleFactory;
static pgaCollectionFactory cf(&scheduleFactory, __("Schedules"), schedules_png_img);

327
agent/pgaStep.cpp Normal file
View file

@ -0,0 +1,327 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// pgaStep.cpp - PostgreSQL Agent Step
//
//////////////////////////////////////////////////////////////////////////
// wxWindows headers
#include <wx/wx.h>
// App headers
#include "pgAdmin3.h"
#include "utils/misc.h"
#include "schema/pgObject.h"
#include "schema/pgDatabase.h"
#include "schema/pgCollection.h"
#include "agent/pgaStep.h"
#include "agent/pgaSchedule.h"
pgaStep::pgaStep(pgCollection *_collection, const wxString &newName)
: pgaJobObject(_collection->GetJob(), stepFactory, newName)
{
}
wxString pgaStep::GetTranslatedMessage(int kindOfMessage) const
{
wxString message = wxEmptyString;
switch (kindOfMessage)
{
case RETRIEVINGDETAILS:
message = _("Retrieving details on pgAgent step");
break;
case REFRESHINGDETAILS:
message = _("Refreshing pgAgent step");
break;
case PROPERTIESREPORT:
message = _("pgAgent step properties report");
break;
case PROPERTIES:
message = _("pgAgent step properties");
break;
case DDLREPORT:
message = _("pgAgent step DDL report");
break;
case DEPENDENCIESREPORT:
message = _("pgAgent step dependencies report");
break;
case DEPENDENCIES:
message = _("pgAgent step dependencies");
break;
case DEPENDENTSREPORT:
message = _("pgAgent step dependents report");
break;
case DEPENDENTS:
message = _("pgAgent step dependents");
break;
case DROPEXCLUDINGDEPS:
message = wxString::Format(_("Are you sure you wish to drop step \"%s\"?"),
GetFullIdentifier().c_str());
break;
case DROPTITLE:
message = _("Drop step?");
break;
}
if (!message.IsEmpty() && !(kindOfMessage == DROPEXCLUDINGDEPS || kindOfMessage == DROPTITLE))
message += wxT(" - ") + GetName();
return message;
}
bool pgaStep::IsUpToDate()
{
wxString sql = wxT("SELECT xmin FROM pgagent.pga_jobstep WHERE jstid = ") + NumToStr(GetRecId());
if (!GetConnection() || GetConnection()->ExecuteScalar(sql) != NumToStr(GetXid()))
return false;
else
return true;
}
bool pgaStep::DropObject(wxFrame *frame, ctlTree *browser, bool cascaded)
{
return GetConnection()->ExecuteVoid(wxT("DELETE FROM pgagent.pga_jobstep WHERE jstid=") + NumToStr(GetRecId()));
}
void pgaStep::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane)
{
if (!expandedKids)
{
expandedKids = true;
}
if (properties)
{
CreateListColumns(properties);
properties->AppendItem(_("Name"), GetName());
properties->AppendItem(_("ID"), GetRecId());
properties->AppendYesNoItem(_("Enabled"), GetEnabled());
properties->AppendItem(_("Kind"), GetKind());
if (GetConnStr().IsEmpty())
properties->AppendItem(_("Database"), GetDbname());
else
properties->AppendItem(_("Connection String"), GetConnStr());
properties->AppendItem(_("Code"), GetCode());
properties->AppendItem(_("On error"), GetOnError());
properties->AppendItem(_("Comment"), firstLineOnly(GetComment()));
}
}
pgObject *pgaStep::Refresh(ctlTree *browser, const wxTreeItemId item)
{
pgObject *step = 0;
pgCollection *coll = browser->GetParentCollection(item);
if (coll)
step = stepFactory.CreateObjects(coll, 0, wxT("\n AND jstid=") + NumToStr(GetRecId()));
return step;
}
pgObject *pgaStepFactory::CreateObjects(pgCollection *collection, ctlTree *browser, const wxString &restriction)
{
pgaStep *step = 0;
pgSet *steps = collection->GetConnection()->ExecuteSet(
wxT("SELECT xmin, * FROM pgagent.pga_jobstep\n")
wxT(" WHERE jstjobid=") + NumToStr(collection->GetJob()->GetRecId()) + wxT("\n")
+ restriction +
wxT(" ORDER BY jstname"));
if (steps)
{
while (!steps->Eof())
{
step = new pgaStep(collection, steps->GetVal(wxT("jstname")));
step->iSetRecId(steps->GetLong(wxT("jstid")));
step->iSetXid(steps->GetOid(wxT("xmin")));
step->iSetDbname(steps->GetVal(wxT("jstdbname")));
if (steps->HasColumn(wxT("jstconnstr")))
step->iSetConnStr(steps->GetVal(wxT("jstconnstr")));
step->iSetCode(steps->GetVal(wxT("jstcode")));
step->iSetEnabled(steps->GetBool(wxT("jstenabled")));
wxChar kindc = *steps->GetVal(wxT("jstkind")).c_str();
wxString kinds;
switch (kindc)
{
case 'b':
kinds = _("Batch");
break;
case 's':
kinds = wxT("SQL");
break;
}
step->iSetKindChar(kindc);
step->iSetKind(kinds);
wxChar onerrc = *steps->GetVal(wxT("jstonerror")).c_str();
wxString onerrs;
switch (onerrc)
{
case 's':
onerrs = _("Succeed");
break;
case 'f':
onerrs = _("Fail");
break;
case 'i':
onerrs = _("Ignore");
break;
}
step->iSetOnErrorChar(onerrc);
step->iSetOnError(onerrs);
step->iSetComment(steps->GetVal(wxT("jstdesc")));
if (browser)
{
browser->AppendObject(collection, step);
steps->MoveNext();
}
else
break;
}
delete steps;
}
return step;
}
void pgaStep::ShowStatistics(frmMain *form, ctlListView *statistics)
{
wxString sql =
wxT("SELECT jsljlgid")
wxT(", jslstatus")
wxT(", jslresult")
wxT(", jslstart")
wxT(", jslduration")
wxT(", (jslstart + jslduration) AS endtime")
wxT(", jsloutput")
wxT(" FROM pgagent.pga_jobsteplog\n")
wxT(" WHERE jsljstid = ") + NumToStr(GetRecId()) +
wxT(" ORDER BY jslstart DESC")
wxT(" LIMIT ") + NumToStr(settings->GetMaxRows());
if (statistics)
{
wxLogInfo(wxT("Displaying statistics for job %s"), GetFullIdentifier().c_str());
// Add the statistics view columns
statistics->ClearAll();
statistics->AddColumn(_("Run"), 50);
statistics->AddColumn(_("Status"), 60);
statistics->AddColumn(_("Result"), 60);
statistics->AddColumn(_("Start time"), 95);
statistics->AddColumn(_("End time"), 95);
statistics->AddColumn(_("Duration"), 70);
statistics->AddColumn(_("Output"), 200);
pgSet *stats = GetConnection()->ExecuteSet(sql);
wxString status;
wxDateTime startTime;
wxDateTime endTime;
if (stats)
{
while (!stats->Eof())
{
if (stats->GetVal(1) == wxT("r"))
status = _("Running");
else if (stats->GetVal(1) == wxT("s"))
status = _("Successful");
else if (stats->GetVal(1) == wxT("f"))
status = _("Failed");
else if (stats->GetVal(1) == wxT("i"))
status = _("Ignored");
else if (stats->GetVal(1) == wxT("d"))
status = _("Aborted");
else
status = _("Unknown");
startTime.ParseDateTime(stats->GetVal(3));
endTime.ParseDateTime(stats->GetVal(5));
long pos = statistics->AppendItem(stats->GetVal(0), status, stats->GetVal(2));
statistics->SetItem(pos, 3, startTime.Format());
if (stats->GetVal(5).Length() > 0)
statistics->SetItem(pos, 4, endTime.Format());
statistics->SetItem(pos, 5, stats->GetVal(4));
statistics->SetItem(pos, 6, stats->GetVal(6));
stats->MoveNext();
}
delete stats;
}
}
}
/////////////////////////////
pgaStepCollection::pgaStepCollection(pgaFactory *factory, pgaJob *job)
: pgaJobObjCollection(factory, job)
{
}
wxString pgaStepCollection::GetTranslatedMessage(int kindOfMessage) const
{
wxString message = wxEmptyString;
switch (kindOfMessage)
{
case RETRIEVINGDETAILS:
message = _("Retrieving details on pgAgent steps");
break;
case REFRESHINGDETAILS:
message = _("Refreshing pgAgent steps");
break;
case OBJECTSLISTREPORT:
message = _("pgAgent steps list report");
break;
}
return message;
}
/////////////////////////////
#include "images/step.pngc"
#include "images/steps.pngc"
pgaStepFactory::pgaStepFactory()
: pgaJobObjFactory(__("Step"), __("New Step"), __("Create a new Step."), step_png_img)
{
metaType = PGM_STEP;
}
pgCollection *pgaStepFactory::CreateCollection(pgObject *obj)
{
return new pgaStepCollection(GetCollectionFactory(), (pgaJob *)obj);
}
pgaStepFactory stepFactory;
static pgaCollectionFactory cf(&stepFactory, __("Steps"), steps_png_img);