From 7c09940fd3f7c2b2c6ad07bcc91d1aa890c5a705 Mon Sep 17 00:00:00 2001
From: Jasmin Dizdarevic <jasmin.dizdarevic@gmail.com>
Date: Fri, 15 Jul 2011 00:49:01 +0200
Subject: [PATCH 3/3] Added GUI for email notification in dlgJob and file option in dlgStep (pgAgent 4)

---
 pgadmin/agent/dlgJob.cpp       |   83 ++++++++++++++++++++++++++++++++++++---
 pgadmin/agent/dlgStep.cpp      |    5 +-
 pgadmin/agent/pgaJob.cpp       |   53 ++++++++++++++++++++-----
 pgadmin/agent/pgaStep.cpp      |    3 +
 pgadmin/db/pgConn.cpp          |   48 +++++++++++++++++++++++
 pgadmin/include/agent/pgaJob.h |   19 +++++++++-
 pgadmin/include/db/pgConn.h    |    3 +
 pgadmin/ui/dlgJob.xrc          |   32 ++++++++++++++-
 pgadmin/ui/dlgStep.xrc         |    1 +
 9 files changed, 225 insertions(+), 22 deletions(-)

diff --git a/pgadmin/agent/dlgJob.cpp b/pgadmin/agent/dlgJob.cpp
index ed27461..12a6b41 100644
--- a/pgadmin/agent/dlgJob.cpp
+++ b/pgadmin/agent/dlgJob.cpp
@@ -26,6 +26,8 @@
 #define	txtID				CTRL_TEXT("txtID")
 #define chkEnabled          CTRL_CHECKBOX("chkEnabled")
 #define cbJobclass          CTRL_COMBOBOX("cbJobclass")
+#define txtEmailNotRecp		CTRL_TEXT("txtEmailNotRecp")
+#define cbEmailNotType		CTRL_COMBOBOX("cbEmailNotType")
 #define txtHostAgent        CTRL_TEXT("txtHostAgent")
 #define txtCreated          CTRL_TEXT("txtCreated")
 #define txtChanged          CTRL_TEXT("txtChanged")
@@ -47,7 +49,9 @@
 BEGIN_EVENT_TABLE(dlgJob, dlgAgentProperty)
 	EVT_CHECKBOX(XRCID("chkEnabled"),               dlgProperty::OnChange)
 	EVT_COMBOBOX(XRCID("cbJobclass"),               dlgProperty::OnChange)
+	EVT_COMBOBOX(XRCID("cbEmailNotType"),           dlgProperty::OnChange)
 	EVT_TEXT(XRCID("txtHostAgent"),                 dlgProperty::OnChange)
+	EVT_TEXT(XRCID("txtEmailNotRecp"),              dlgProperty::OnChange)
 
 	EVT_LIST_ITEM_SELECTED(XRCID("lstSteps"),       dlgJob::OnSelChangeStep)
 	EVT_BUTTON(XRCID("btnChangeStep"),              dlgJob::OnChangeStep)
@@ -131,6 +135,25 @@ int dlgJob::Go(bool modal)
 		}
 		delete jcl;
 	}
+	if(connection->pgAgentMinimumSchemaVersion(4)) 
+	{
+		pgSet *mnk = connection->ExecuteSet(wxT("SELECT jmntypename FROM pgagent.pga_jobmailnottype"));
+		if(mnk) 
+		{
+			while(!mnk->Eof()) 
+			{				
+				cbEmailNotType->Append(mnk->GetVal(0));				
+				mnk->MoveNext();
+			}
+			delete mnk;
+		}
+				
+	}
+	else 
+	{
+		txtEmailNotRecp->Disable();
+		cbEmailNotType->Disable();
+	}
 
 	if (job)
 	{
@@ -146,6 +169,12 @@ int dlgJob::Go(bool modal)
 		txtLastrun->SetValue(DateToStr(job->GetLastrun()));
 		txtLastresult->SetValue(job->GetLastresult());
 
+		if(connection->pgAgentMinimumSchemaVersion(4)) 
+		{
+			txtEmailNotRecp->SetValue(job->GetEmailNotRecp()); 
+			cbEmailNotType->SetValue(job->GetEmailNotType());
+		}
+
 		wxCookieType cookie;
 		pgObject *data = 0;
 
@@ -212,6 +241,7 @@ int dlgJob::Go(bool modal)
 	{
 		// create mode
 		cbJobclass->SetSelection(0);
+		cbEmailNotType->SetSelection(0);
 		btnChangeStep->Hide();
 		btnChangeSchedule->Hide();
 	}
@@ -245,7 +275,9 @@ void dlgJob::CheckChange()
 		enable  =  txtComment->GetValue() != job->GetComment()
 		           || name != job->GetName()
 		           || chkEnabled->GetValue() != job->GetEnabled()
-		           || txtHostAgent->GetValue() != job->GetHostAgent();
+		           || txtHostAgent->GetValue() != job->GetHostAgent()
+				   || txtEmailNotRecp->GetValue() != job->GetEmailNotRecp();
+
 		if (!enable)
 		{
 			enable = !GetUpdateSql().IsEmpty();
@@ -256,7 +288,18 @@ void dlgJob::CheckChange()
 		statusBar->SetStatusText(wxEmptyString);
 
 	CheckValid(enable, !txtName->GetValue().IsEmpty(), _("Please specify name."));
-
+	if(connection->pgAgentMinimumSchemaVersion(4))
+	{
+		wxString pgAgentHostMail = connection->CheckpgAgentMailFeature(txtHostAgent->GetValue());
+		bool bMailOk = pgAgentHostMail == wxT("OK");
+		if(cbEmailNotType->GetValue() != wxT("None"))
+		{
+			if(!bMailOk)
+				CheckValid(enable, false, wxString::Format(wxT("You've specified email notification, but the host agents aren't configured properly: %s"), pgAgentHostMail));
+			if(txtEmailNotRecp->GetValue().IsEmpty())
+				CheckValid(enable, false, _("You've specified an email notification, but no recipients"));
+		}
+	}
 	EnableOK(enable);
 }
 
@@ -395,11 +438,25 @@ wxString dlgJob::GetInsertSql()
 
 	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");
+		if(connection->pgAgentMinimumSchemaVersion(4)) 
+		{
+			sql = wxT("INSERT INTO pgagent.pga_job (jobid, jobjclid, jobname, jobdesc, jobenabled, jobhostagent, jobmailnotrecp, jobmailnottype)\n")			  
+				  wxT("SELECT <JobId>, jcl.jclid, ") + qtDbString(GetName()) + 
+				  wxT(", ") + qtDbString(txtComment->GetValue()) + wxT(", ") + BoolToStr(chkEnabled->GetValue()) + 
+				  wxT(", ") + qtDbString(txtHostAgent->GetValue()) +
+				  wxT(", ") + qtDbString(txtEmailNotRecp->GetValue()) +
+				  wxT(", (SELECT jmntypeid FROM pgagent.pga_jobmailnottype WHERE jmntypename = ") + qtDbString(cbEmailNotType->GetValue()) + wxT(")\n")
+				  wxT("  FROM pgagent.pga_jobclass jcl WHERE jclname=") + qtDbString(cbJobclass->GetValue()) + wxT(";\n");
+		}
+		else 
+		{
+			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;
 }
@@ -445,6 +502,18 @@ wxString dlgJob::GetUpdateSql()
 				vars.Append(wxT(", "));
 			vars.Append(wxT("jobdesc = ") + qtDbString(txtComment->GetValue()));
 		}
+		if(connection->pgAgentMinimumSchemaVersion(4) && txtEmailNotRecp->GetValue() != job->GetEmailNotRecp()) 
+		{
+			if(!vars.IsEmpty())
+				vars.Append(wxT(", "));
+			vars.Append(wxT("jobmailnotrecp = ") + qtDbString(txtEmailNotRecp->GetValue()));
+		}
+		if(connection->pgAgentMinimumSchemaVersion(4) && cbEmailNotType->GetValue() != job->GetEmailNotType()) 
+		{
+			if(!vars.IsEmpty())
+				vars.Append(wxT(", "));
+			vars.Append(wxT("jobmailnottype= (SELECT jmntypeid FROM pgagent.pga_jobmailnottype WHERE jmntypename=") + qtDbString(cbEmailNotType->GetValue()) + wxT(")"));
+		}
 
 		if (!vars.IsEmpty())
 			sql = wxT("UPDATE pgagent.pga_job SET ") + vars + wxT("\n")
diff --git a/pgadmin/agent/dlgStep.cpp b/pgadmin/agent/dlgStep.cpp
index 9da98a5..7543749 100644
--- a/pgadmin/agent/dlgStep.cpp
+++ b/pgadmin/agent/dlgStep.cpp
@@ -101,6 +101,7 @@ int dlgStep::Go(bool modal)
 		delete db;
 	}
 
+	rbxKind->Enable(2, connection->pgAgentMinimumSchemaVersion(4));
 	if (step)
 	{
 		// edit mode
@@ -124,7 +125,7 @@ int dlgStep::Go(bool modal)
 				cbDatabase->SetValue(step->GetDbname());
 		}
 
-		rbxKind->SetSelection(wxString(wxT("sb")).Find(step->GetKindChar()));
+		rbxKind->SetSelection(wxString(wxT("sbf")).Find(step->GetKindChar()));
 		rbxOnError->SetSelection(wxString(wxT("fsi")).Find(step->GetOnErrorChar()));
 		sqlBox->SetText(step->GetCode());
 
@@ -272,7 +273,7 @@ wxString dlgStep::GetInsertSql()
 	if (!step)
 	{
 		wxString name = GetName();
-		wxString kind = wxT("sb")[rbxKind->GetSelection()];
+		wxString kind = wxT("sbf")[rbxKind->GetSelection()];
 		wxString onerror = wxT("fsi")[rbxOnError->GetSelection()];
 		wxString db, connstr;
 		wxString jstjobid;
diff --git a/pgadmin/agent/pgaJob.cpp b/pgadmin/agent/pgaJob.cpp
index ad28a7a..cc55cfb 100644
--- a/pgadmin/agent/pgaJob.cpp
+++ b/pgadmin/agent/pgaJob.cpp
@@ -126,6 +126,17 @@ void pgaJob::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *proper
 		properties->AppendItem(_("Next run"), GetNextrun());
 		properties->AppendItem(_("Last run"), GetLastrun());
 		properties->AppendItem(_("Last result"), GetLastresult());
+		if(GetConnection()->pgAgentMinimumSchemaVersion(4)) 
+		{
+			properties->AppendItem(_("Email notification on"), GetEmailNotType());
+			properties->AppendItem(_("Email recipients"), GetEmailNotRecp());
+
+			if(GetEmailNotType() != wxT("None") && !GetEmailNotRecp().IsEmpty()) 
+			{
+				wxString pgAgentMailStatus = GetConnection()->CheckpgAgentMailFeature(GetHostAgent());
+				properties->AppendItem(_("pgAgent email configuration"), (pgAgentMailStatus != wxT("OK")) ? wxString::Format(wxT("Not configured on: %s"), pgAgentMailStatus) : pgAgentMailStatus);
+			}
+		}
 		if (!GetCurrentAgent().IsEmpty())
 			properties->AppendItem(_("Running at"), GetCurrentAgent());
 		else
@@ -154,17 +165,35 @@ pgObject *pgaJobFactory::CreateObjects(pgCollection *collection, ctlTree *browse
 {
 	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;"));
+	wxString jobSql;
+	
+	if(collection->GetConnection()->pgAgentMinimumSchemaVersion(4)) {
+		//Email notification
+		jobSql = wxT("SELECT j.*, cl.*, ag.*, sub.jlgstatus AS joblastresult, nt.jmntypename as mailnotkindname ")
+				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 ")
+				wxT("  LEFT OUTER JOIN pgagent.pga_jobmailnottype nt ON j.jobmailnottype = nt.jmntypeid ")
+				+ restriction +
+				wxT("ORDER BY jobname;");
+	}
+	else {
+			jobSql = 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;");
+	}
+	
 
+	pgSet *jobs= collection->GetConnection()->ExecuteSet(jobSql);
 	if (jobs)
 	{
 		while (!jobs->Eof())
@@ -196,6 +225,10 @@ pgObject *pgaJobFactory::CreateObjects(pgCollection *collection, ctlTree *browse
 			job->iSetNextrun(jobs->GetDateTime(wxT("jobnextrun")));
 			job->iSetLastrun(jobs->GetDateTime(wxT("joblastrun")));
 			job->iSetLastresult(status);
+			if(collection->GetConnection()->pgAgentMinimumSchemaVersion(4)) {
+				job->iSetEmailNotRecp(jobs->GetVal(wxT("jobmailnotrecp")));
+				job->iSetEmailNotType(jobs->GetVal(wxT("mailnotkindname")));
+			}
 			job->iSetCurrentAgent(jobs->GetVal(wxT("jagstation")));
 
 			if (browser)
diff --git a/pgadmin/agent/pgaStep.cpp b/pgadmin/agent/pgaStep.cpp
index f3871be..56dbc7b 100644
--- a/pgadmin/agent/pgaStep.cpp
+++ b/pgadmin/agent/pgaStep.cpp
@@ -158,6 +158,9 @@ pgObject *pgaStepFactory::CreateObjects(pgCollection *collection, ctlTree *brows
 				case 's':
 					kinds = wxT("SQL");
 					break;
+				case 'f':
+					kinds = wxT("File");
+				break;
 			}
 			step->iSetKindChar(kindc);
 			step->iSetKind(kinds);
diff --git a/pgadmin/db/pgConn.cpp b/pgadmin/db/pgConn.cpp
index af85778..65a2dc3 100644
--- a/pgadmin/db/pgConn.cpp
+++ b/pgadmin/db/pgConn.cpp
@@ -530,6 +530,54 @@ bool pgConn::HasFeature(int featureNo, bool forceCheck)
 		return false;
 	return features[featureNo];
 }
+bool pgConn::pgAgentMinimumSchemaVersion(const int version) {
+
+	if(schemaVersionCache < 0) 
+	{		
+		schemaVersionCache = StrToLong(ExecuteScalar(wxT("SELECT pgagent.pgagent_schema_version()")));			 
+	}
+	
+	return (schemaVersionCache >= version);
+
+}
+
+wxString pgConn::CheckpgAgentMailFeature(const wxString host) {
+	/* retuns "", if every registered agent has the required version
+	/* otherwise a list of agents, that doesn't match */
+	wxString retVal, stmt;
+	
+	if(host == wxT(""))
+	{
+		stmt = wxT("SELECT jagstation from pgagent.pga_jobagent WHERE jagemailconfigured = false");
+	}
+	else 
+	{
+		stmt = wxT("SELECT jagstation from pgagent.pga_jobagent WHERE jagemailconfigured = false AND jagstation = '") + host + wxT("'");
+	}
+	
+	pgSet *agents = ExecuteSet(stmt);
+	if(agents) {
+		if(agents->NumRows() == 0)
+		{
+			retVal = wxT("OK");
+		}
+		else {
+			while(!agents->Eof())
+			{
+				retVal += agents->GetVal(0) + wxT(", ");
+				agents->MoveNext();
+			}
+			
+			retVal = retVal.substr(0, retVal.Len()-2);
+		}
+
+		delete agents;
+	}						
+	
+	
+	return retVal;
+
+}
 
 
 // Encrypt a password using the appropriate encoding conversion
diff --git a/pgadmin/include/agent/pgaJob.h b/pgadmin/include/agent/pgaJob.h
index 5452778..e6ddbbd 100644
--- a/pgadmin/include/agent/pgaJob.h
+++ b/pgadmin/include/agent/pgaJob.h
@@ -124,6 +124,23 @@ public:
 	{
 		recId = l;
 	}
+	void iSetEmailNotRecp(const wxString &s)
+	{
+		emailnotrecp = s;
+	}
+	wxString GetEmailNotRecp() const
+	{
+		return emailnotrecp;
+	}
+	void iSetEmailNotType(const wxString &s)
+	{
+		emailnottype = s;
+	}
+	wxString GetEmailNotType() const
+	{
+		return emailnottype;
+	}
+
 	bool RunNow();
 
 	wxMenu *GetNewMenu();
@@ -156,7 +173,7 @@ public:
 private:
 	bool enabled;
 	wxDateTime created, changed, nextrun, lastrun;
-	wxString lastresult, jobclass, currentAgent, hostAgent;
+	wxString lastresult, jobclass, currentAgent, hostAgent, emailnotrecp, emailnottype;
 	long recId;
 };
 
diff --git a/pgadmin/include/db/pgConn.h b/pgadmin/include/db/pgConn.h
index cdacbba..2a64ebf 100644
--- a/pgadmin/include/db/pgConn.h
+++ b/pgadmin/include/db/pgConn.h
@@ -244,6 +244,8 @@ public:
 	void Reset();
 
 	bool TableHasColumn(wxString schemaname, wxString tblname, const wxString &colname);
+	bool pgAgentMinimumSchemaVersion(const int version);
+	wxString CheckpgAgentMailFeature(const wxString host);
 
 protected:
 	PGconn *conn;
@@ -283,6 +285,7 @@ private:
 	wxString save_sslcert, save_sslkey, save_sslrootcert, save_sslcrl;
 	int save_port, save_sslmode;
 	OID save_oid;
+	int schemaVersionCache;
 };
 
 #endif
diff --git a/pgadmin/ui/dlgJob.xrc b/pgadmin/ui/dlgJob.xrc
index e1563df..29dba02 100644
--- a/pgadmin/ui/dlgJob.xrc
+++ b/pgadmin/ui/dlgJob.xrc
@@ -17,10 +17,10 @@
             <object class="wxPanel" name="pnlProperties">
               <object class="wxFlexGridSizer">
                 <cols>2</cols>
-                <rows>11</rows>
+                <rows>13</rows>
                 <vgap>5</vgap>
                 <hgap>5</hgap>
-                <growablerows>10</growablerows>
+                <growablerows>12</growablerows>
                 <growablecols>1</growablecols>
                 <object class="sizeritem">
                   <object class="wxStaticText" name="stName">
@@ -92,6 +92,34 @@
                   <border>4</border>
                 </object>
                 <object class="sizeritem">
+                  <object class="wxStaticText" name="stEmailNotType">
+                    <label>Email notification on</label>
+                  </object>
+                  <flag>wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                  <border>4</border>
+                </object>
+                <object class="sizeritem">
+                  <object class="wxComboBox" name="cbEmailNotType">
+                    <content/>
+                    <style>wxCB_READONLY|wxCB_DROPDOWN</style>
+                  </object>
+                  <flag>wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                  <border>4</border>
+                </object>
+                <object class="sizeritem">
+                  <object class="wxStaticText" name="stEmailNotRecp">
+                    <label>Email recipients</label>
+                  </object>
+                  <flag>wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                  <border>4</border>
+                </object>
+                <object class="sizeritem">
+                  <object class="wxTextCtrl" name="txtEmailNotRecp">
+                  </object>
+                  <flag>wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                  <border>4</border>
+                </object>
+                <object class="sizeritem">
                   <object class="wxStaticText" name="stCreated">
                     <label>Created</label>
                   </object>
diff --git a/pgadmin/ui/dlgStep.xrc b/pgadmin/ui/dlgStep.xrc
index 37b5dd5..a43a147 100644
--- a/pgadmin/ui/dlgStep.xrc
+++ b/pgadmin/ui/dlgStep.xrc
@@ -157,6 +157,7 @@
                     <content>
                       <item>SQL</item>
                       <item>Batch</item>
+                      <item>File</item>
                     </content>
                     <selection>0</selection>
                     <label>Kind</label>
-- 
1.7.4.msysgit.0

