pgadmin3/pro_scheduler/pgproJob.cpp
levinsv 2d9e76f826 wxWidgets 3.0
add plan view unexpand/expand
2018-12-28 22:38:43 +05:00

455 lines
13 KiB
C++
Raw Blame History

//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// pgproJob.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 "pro_scheduler/pgproJob.h"
pgproJob::pgproJob(const wxString &newName)
: pgServerObject(projobFactory, newName)
{
}
wxString pgproJob::GetTranslatedMessage(int kindOfMessage) const
{
wxString message = wxEmptyString;
switch (kindOfMessage)
{
case RETRIEVINGDETAILS:
message = _("Retrieving details on pro_scheduler job");
break;
case REFRESHINGDETAILS:
message = _("Refreshing pro_scheduler job");
break;
case PROPERTIESREPORT:
message = _("pro_scheduler job properties report");
break;
case PROPERTIES:
message = _("pgAgent job properties");
break;
case DDLREPORT:
message = _("pro_scheduler job DDL report");
break;
case DEPENDENCIESREPORT:
message = _("pro_scheduler job dependencies report");
break;
case DEPENDENCIES:
message = _("pro_scheduler job dependencies");
break;
case DEPENDENTSREPORT:
message = _("pro_scheduler job dependents report");
break;
case DEPENDENTS:
message = _("pro_scheduler 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 pgproJob::GetIconId()
{
if (GetEnabled())
if (GetStatus()==wxT("working")) return projobFactory.GetRunId();
else
return projobFactory.GetIconId();
else
return projobFactory.GetDisabledId();
}
wxMenu *pgproJob::GetNewMenu()
{
wxMenu *menu = pgObject::GetNewMenu();
if (1) // check priv.
{
//stepFactory.AppendMenu(menu);
//scheduleFactory.AppendMenu(menu);
}
return menu;
}
wxString pgproJob::GetSql(ctlTree *browser)
{
if (sql.IsNull())
{
sql = wxT("-- pro_scheduler job: ") + GetName() + wxT("\n\n");
sql += wxT("-- SELECT schedule.set_job_attributes( ") + NumToStr(GetRecId()) + wxT(", { });\n\n");
sql += wxT("SELECT schedule.create_job(")+GetConnection()->qtDbString(GetRule())+wxT(");");
}
return sql;
}
bool pgproJob::DropObject(wxFrame *frame, ctlTree *browser, bool cascaded)
{
return GetConnection()->ExecuteVoid(wxT("select schedule.drop_job(") + NumToStr(GetRecId())+wxT(")"));
}
void pgproJob::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"), GetTryName());
properties->AppendItem(_("ID"), GetRecId());
properties->AppendYesNoItem(_("Enabled"), GetEnabled());
//properties->AppendItem(_("Host agent"), GetHostAgent());
// properties->AppendItem(_("Job class"), GetJobclass());
properties->AppendItem(_("Started"), GetStarted());
properties->AppendItem(_("Finished"), GetFinished());
properties->AppendItem(_("Result"), GetStatus());
properties->AppendItem(_("Crontab"), GetCrontab());
//properties->AppendItem(_("Last result"), GetLastresult());
properties->AppendItem(_("Runas"), GetRunAs());
properties->AppendItem(_("Message"), GetMessage());
properties->AppendItem(_("Comment"), firstLineOnly(GetComment()));
}
}
pgObject *pgproJob::Refresh(ctlTree *browser, const wxTreeItemId item)
{
pgObject *job = 0;
pgObject *obj = browser->GetObject(browser->GetItemParent(item));
if (obj && obj->IsCollection())
job = projobFactory.CreateObjects((pgCollection *)obj, 0, wxT("\n WHERE c.id=") + NumToStr(GetRecId()));
GetIconId();
UpdateIcon(browser);
return job;
}
pgObject *pgproJobFactory::CreateObjects(pgCollection *collection, ctlTree *browser, const wxString &restriction)
{
pgproJob *job = 0;
pgSet *jobs = collection->GetConnection()->ExecuteSet(
wxT("with last_job as (select cron,max(started) started from schedule.get_log() b group by cron), a as (select cron,scheduled_at,started,finished,status,message from schedule.get_active_jobs()), lastj as (select b.cron,")
wxT("coalesce((select scheduled_at from a where a.cron=b.cron),b.scheduled_at) scheduled_at")
wxT(",coalesce((select started from a where a.cron=b.cron),b.started) started")
wxT(",case when (select status from a where a.cron=b.cron)='working' then null else b.finished end finished")
wxT(",coalesce((select status from a where a.cron=b.cron),b.status) status")
wxT(",coalesce((select message from a where a.cron=b.cron),b.message) message")
wxT(" from schedule.get_log() b,last_job where b.cron=last_job.cron and b.started=last_job.started")
wxT(") select j.crontab cron,* from (select c.*,null stop,l.* from schedule.get_cron() c left join lastj l on c.id=l.cron) c")
wxT(" join lateral (select crontab from jsonb_to_record(c.rule) as (d int[],h int[],wd int[],m int[],crontab text,mi int[]) ) j on true")
wxT("")
wxT("")
wxT(" ") + restriction);
if (jobs)
{
int nCols = jobs->NumCols();
while (!jobs->Eof())
{
wxString status;
status=jobs->GetVal(wxT("status"));
if (status.IsNull()) status = _("Not run");
wxString name=jobs->GetVal(wxT("name"))+wxT("(")+jobs->GetVal(wxT("id"))+wxT(")");
job = new pgproJob(name);
job->iSetStatus(status);
job->iSetTryName(jobs->GetVal(wxT("name")));
job->iSetServer(collection->GetServer());
job->iSetRecId(jobs->GetLong(wxT("id")));
job->iSetComment(jobs->GetVal(wxT("comments")));
job->iSetEnabled(jobs->GetBool(wxT("active")));
wxString tmp;
tmp = jobs->GetVal(wxT("commands"));
tmp.Replace(wxT("{"), wxT(""));
tmp.Replace(wxT("}"), wxT(""));
job->iSetCommands(tmp);
job->iSetRunAs(jobs->GetVal(wxT("run_as")));
job->iSetStarted(jobs->GetDateTime(wxT("started")));
job->iSetFinished(jobs->GetDateTime(wxT("finished")));
job->iSetCrontab(jobs->GetVal(wxT("crontab")));
//job->iSetNextrun(jobs->GetDateTime(wxT("jobnextrun")));
job->iSetMessage(jobs->GetVal(wxT("message")));
tmp=wxT("");
int columnCount=0;
for (int col = 0 ; col < nCols ; col++)
{
wxString colname=jobs->ColName(col);
wxString vl=jobs->GetVal(col);
if (vl.IsEmpty()) continue;
if (colname==wxT("id")
||colname==wxT("node")
||colname==wxT("rule")
||colname==wxT("owner")) continue;
if (colname==wxT("broken")) break;
if (columnCount)
{
tmp += wxT(", ");
}
if (colname==wxT("commands")) vl=vl.Mid(1,vl.Length()-2);
else vl=wxT("\"")+vl+wxT("\"");
tmp += wxT("\"")+colname+wxT("\"")+wxT(": ")+vl;
columnCount++;
}
job->iSetRule(wxT("{")+tmp+wxT("}"));
if (browser)
{
browser->AppendObject(collection, job);
jobs->MoveNext();
}
else
break;
}
delete jobs;
}
return job;
}
void pgproJob::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());
wxString bu=GetConnection()->ExecuteScalar(wxT("select coalesce((select pg_table_is_visible(oid) from pg_class where relname='pg_log'),false)"));
// Add the statistics view columns
statistics->ClearAll();
statistics->AddColumn(_("Log_time"), 95);
statistics->AddColumn(_("Critical"), 30);
statistics->AddColumn(_("Message"), 300);
statistics->AddColumn(_("Stage"), 40);
if ((bu==wxT("f"))||(!settings->GetASUTPstyle())||(DateToAnsiStr(GetStarted()).IsEmpty())) return ;
wxString wxDTend = DateToAnsiStr(GetFinished());
if (wxDTend.IsEmpty()) wxDTend=DateToAnsiStr(wxDateTime::Now());
sql=wxT("select log_time,detail critical,message,application_name from pg_log l where l.log_time>'") + DateToAnsiStr(GetStarted())+
wxT("'::timestamp - interval '1min' and l.log_time<='")+ wxDTend +
wxT("'::timestamp + interval '1min' and hint='")+GetTryName()+wxT("'");
pgSet *stats = GetConnection()->ExecuteSet(sql);
wxString critical;
wxDateTime startTime;
wxDateTime endTime;
if (stats)
{
while (!stats->Eof())
{
startTime.ParseDateTime(stats->GetVal(0));
//endTime.ParseDateTime(stats->GetVal(4));
critical=stats->GetVal(1);
long pos = statistics->AppendItem(DateToStr(startTime), critical, stats->GetVal(2));
statistics->SetItem(pos, 3, stats->GetVal(3));
//statistics->SetItem(pos, 4, stats->GetVal(3));
stats->MoveNext();
}
delete stats;
}
}
}
bool pgproJob::RunNow()
{
//if (!GetConnection()->ExecuteVoid(wxT("select schedule.drop_job(") + NumToStr(GetRecId())+wxT(")"))) return false;
return true;
}
pgproJobCollection::pgproJobCollection(pgaFactory *factory, pgServer *sv)
: pgServerObjCollection(factory, sv)
{
}
wxString pgproJobCollection::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;
}
void pgproJob::SetEnabled(ctlTree *browser, const bool b)
{
if (GetRecId() > 0 && ((enabled && !b) || (!enabled && b)))
{
wxString sql = wxT("select schedule.");
if (enabled && !b)
sql += wxT("deactivate_job(");
else if (!enabled && b)
sql += wxT("activate_job(");
sql += NumToStr(GetRecId())+wxT(")");
GetConnection()->ExecuteVoid(sql);
}
enabled = b;
UpdateIcon(browser);
}
dlgProperty *pgproJobFactory::CreateDialog(frmMain *frame, pgObject *node, pgObject *parent)
{
return 0;
}
/////////////////////////////
#include "images/job.pngc"
#include "images/jobs.pngc"
#include "images/jobdisabled.pngc"
#include "images/jobrun.pngc"
pgproJobFactory::pgproJobFactory()
: pgServerObjFactory(__("pgAgent Job"), __("New Job"), __("Create a new Job."), job_png_img)
{
metaType = PGM_PROJOB;
disabledId = addIcon(jobdisabled_png_img);
runId = addIcon(jobrun_png_img);
}
pgCollection *pgproJobFactory::CreateCollection(pgObject *obj)
{
return new pgproJobCollection(GetCollectionFactory(), (pgServer *)obj);
}
pgproJobFactory projobFactory;
static pgaCollectionFactory cf(&projobFactory, __("Jobs"), jobs_png_img);
prorunNowFactory::prorunNowFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : contextActionFactory(list)
{
mnu->Append(id, _("&Run now"), _("Reschedule the job to run now."));
}
wxWindow *prorunNowFactory::StartDialog(frmMain *form, pgObject *obj)
{
if (!((pgproJob *)(obj))->RunNow())
{
wxLogError(_("Failed to reschedule the job."));
}
form->Refresh(obj);
return 0;
}
bool prorunNowFactory::CheckEnable(pgObject *obj)
{
if (obj)
{
if (obj->GetMetaType() == PGM_PROJOB && !obj->IsCollection())
return true;
}
return false;
}
enabledisableJobFactory::enabledisableJobFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : contextActionFactory(list)
{
mnu->Append(id, _("Enabled?"), _("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>."), wxITEM_CHECK);
}
wxWindow *enabledisableJobFactory::StartDialog(frmMain *form, pgObject *obj)
{
((pgproJob *)obj)->SetEnabled(form->GetBrowser(), !((pgproJob *)obj)->GetEnabled());
//((pgproJob *)obj)->SetDirty();
wxTreeItemId item = form->GetBrowser()->GetSelection();
if (obj == form->GetBrowser()->GetObject(item))
{
//form->GetBrowser()->DeleteChildren(item);
obj->ShowTreeDetail(form->GetBrowser(), 0, form->GetProperties());
//form->GetSqlPane()->SetReadOnly(false);
//form->GetSqlPane()->SetText(((pgproJob *)obj)->GetSql(form->GetBrowser()));
//form->GetSqlPane()->SetReadOnly(true);
}
form->GetMenuFactories()->CheckMenu(obj, form->GetMenuBar(), (ctlMenuToolbar *)form->GetToolBar());
return 0;
}
bool enabledisableJobFactory::CheckEnable(pgObject *obj)
{
return obj && obj->IsCreatedBy(projobFactory);
}
bool enabledisableJobFactory::CheckChecked(pgObject *obj)
{
return obj && obj->IsCreatedBy(projobFactory) && ((pgproJob *)obj)->GetEnabled();
}