Add code to the schema browser to allow the user to
authordpage <dpage@a7884b65-44f6-0310-8a51-81a127f17b15>
Wed, 25 Nov 2009 17:14:04 +0000 (17:14 +0000)
committerdpage <dpage@a7884b65-44f6-0310-8a51-81a127f17b15>
Wed, 25 Nov 2009 17:14:04 +0000 (17:14 +0000)
reconnect to the server if the connection is lost.

git-svn-id: svn://svn.pgadmin.org/trunk/pgadmin3@8091 a7884b65-44f6-0310-8a51-81a127f17b15

CHANGELOG
pgadmin/db/pgConn.cpp
pgadmin/db/pgSet.cpp
pgadmin/frm/frmMain.cpp
pgadmin/include/db/pgConn.h
pgadmin/include/db/pgSet.h

index 3e273e89c7868ed8c8a6e1f6d9801995026b7a84..2c5f9519244d7fce751057ffed144c92a66eda37 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -36,6 +36,8 @@ Changes
 
 Date       Dev Ver     Change details
 ---------- --- ------  --------------
+2009-11-25 DP  1.12.0  Add code to the schema browser to allow the user to 
+                       reconnect to the server if the connection is lost.
 2009-11-25 DP  1.10.1  Don't attempt to remove rows in the edit grid if the
                        user presses the delete key when the delete button is
                        disabled.
index ffc844a523c33c0724fc606a0c96633588197344..87e2e3eb130ed2c0c35e4f1d91abe5fb69da7ac0 100644 (file)
@@ -75,7 +75,6 @@ pgConn::pgConn(const wxString& server, const wxString& database, const wxString&
     conn=0;
     noticeArg=0;
     connStatus = PGCONN_BAD;
-    dbname = database;
     
 #ifdef __WXMSW__
     struct in_addr ipaddr;
@@ -117,7 +116,6 @@ pgConn::pgConn(const wxString& server, const wxString& database, const wxString&
     wxLogInfo(wxT("Server name: %s (resolved to: %s)"), server.c_str(), hostip.c_str());
 
     // Create the connection string
-    wxString connstr;
     if (!hostname.IsEmpty()) {
       connstr.Append(wxT(" host="));
       connstr.Append(qtConnString(hostname));
@@ -165,12 +163,28 @@ pgConn::pgConn(const wxString& server, const wxString& database, const wxString&
         }
     }
     connstr.Trim(false);
-    
+       
+    dbHost = server;
+    dbHostName = hostname;
+    dbHostAddress = hostip;
+       
     // Open the connection
     wxString cleanConnStr = connstr;
     cleanConnStr.Replace(qtConnString(password), wxT("'XXXXXX'"));
     wxLogInfo(wxT("Opening connection with connection string: %s"), cleanConnStr.c_str());
+       
+       DoConnect();
+}
+       
+
+pgConn::~pgConn()
+{
+    Close();
+}
+
 
+bool pgConn::DoConnect()
+{
     wxCharBuffer cstrUTF=connstr.mb_str(wxConvUTF8);
     conn = PQconnectdb(cstrUTF);
     if (PQstatus(conn) == CONNECTION_OK)
@@ -185,10 +199,6 @@ pgConn::pgConn(const wxString& server, const wxString& database, const wxString&
         }
     }
 
-    dbHost = server;
-    dbHostName = hostname;
-    dbHostAddress = hostip;
-
     // Set client encoding to Unicode/Ascii
     if (PQstatus(conn) == CONNECTION_OK)
     {
@@ -199,15 +209,15 @@ pgConn::pgConn(const wxString& server, const wxString& database, const wxString&
         wxString sql=wxT("SET DateStyle=ISO;SELECT oid, pg_encoding_to_char(encoding) AS encoding, datlastsysoid\n")
                       wxT("  FROM pg_database WHERE ");
 
-        if (oid)
-            sql += wxT("oid = ") + NumToStr(oid);
+        if (save_oid)
+            sql += wxT("oid = ") + NumToStr(save_oid);
         else
         {
             // Note, can't use qtDbString here as we don't know the server version yet.
-            wxString db = database;
+            wxString db = save_database;
             db.Replace(wxT("\\"), wxT("\\\\"));
             db.Replace(wxT("'"), wxT("''"));
-            sql += wxT("datname=") + qtString(database);
+            sql += wxT("datname=") + qtString(save_database);
         }
         
 
@@ -238,14 +248,13 @@ pgConn::pgConn(const wxString& server, const wxString& database, const wxString&
             delete set;
         }
     }
-}
-
+    else
+        return false;
 
-pgConn::~pgConn()
-{
-    Close();
+    return true;
 }
 
+
 void pgConn::Close()
 {
     if (conn)
@@ -254,11 +263,33 @@ void pgConn::Close()
     connStatus=PGCONN_BAD;
 }
 
+
+// Reconnect to the server
+bool pgConn::Reconnect()
+{
+    // Close the existing (possibly broken) connection
+    Close();
+
+    // Reset any vars that need to be in a defined state before connecting
+    needColQuoting = false;
+
+    // Attempt the reconnect
+       if (!DoConnect())
+    {
+        wxLogError(_("Failed to re-establish the connection to the server %s"), GetName());
+        return false;
+    }
+
+    return true;
+}
+
+
 pgConn *pgConn::Duplicate()
 {
     return new pgConn(wxString(save_server), wxString(save_database), wxString(save_username), wxString(save_password), save_port, save_sslmode, save_oid);
 }
 
+
 // Return the SSL mode name
 wxString pgConn::GetSslModeName()
 {
@@ -502,9 +533,9 @@ wxString pgConn::GetName() const
 {
     wxString str;
     if (dbHost.IsEmpty())
-        str.Printf(_("%s on local socket"), dbname.c_str());
+        str.Printf(_("%s on local socket"), save_database.c_str());
     else
-        str.Printf(_("%s on %s@%s:%d"), dbname.c_str(), GetUser().c_str(), dbHost.c_str(), GetPort());
+        str.Printf(_("%s on %s@%s:%d"), save_database.c_str(), GetUser().c_str(), dbHost.c_str(), GetPort());
     return str;
 }
 
@@ -672,7 +703,7 @@ pgSet *pgConn::ExecuteSet(const wxString& sql)
             PQclear(qryRes);
         }
     }
-    return 0;
+    return new pgSet();
 }
 
 //////////////////////////////////////////////////////////////////////////
@@ -722,13 +753,7 @@ void pgConn::LogError(const bool quiet)
 bool pgConn::IsAlive()
 {
     if (GetStatus() != PGCONN_OK)
-    {
-        lastResultError.severity = wxString(wxT("FATAL"));
-        lastResultError.msg_primary = wxString(PQerrorMessage(conn), *conv);
-        lastResultError.formatted_msg = lastResultError.severity + wxT(": ") + lastResultError.msg_primary;
-        wxLogError(wxT("%s"), lastResultError.msg_primary.c_str());
         return false;
-    }
 
     PGresult *qryRes = PQexec(conn, "SELECT 1;");
     lastResultStatus = PQresultStatus(qryRes);
index 943d82238ec39025dc7ac09d68838bc0998ba640..dd7bcbdd953b02b67542a4538484019c5bd07102 100644 (file)
 #include "utils/sysLogger.h"
 #include "utils/pgDefs.h"
 
+pgSet::pgSet()
+: conv(wxConvLibc)
+{
+    conn = 0;
+    res = 0;
+    nCols = 0;
+    nRows = 0;
+    pos = 0;
+}
+
 pgSet::pgSet(PGresult *newRes, pgConn *newConn, wxMBConv &cnv, bool needColQt)
 : conv(cnv)
 {
index 2da7aa53e66c11d6c823e0c164571cf28dc3b280..e9c4a2212f17056b0b52f6dc7d1ebe7b8ffe454b 100644 (file)
@@ -762,11 +762,11 @@ bool frmMain::CheckAlive()
                                         conn->Close();
                                         if (!userInformed)
                                         {
-                                            wxMessageDialog dlg(this, _("Close database browser? If you abort, the object browser will not show accurate data."),
+                                            wxMessageDialog dlg(this, _("Do you want to attempt to reconnect to the database?"),
                                             wxString::Format(_("Connection to database %s lost."), db->GetName().c_str()), 
                                                 wxICON_EXCLAMATION|wxYES_NO|wxYES_DEFAULT);
 
-                                            closeIt = (dlg.ShowModal() == wxID_YES);
+                                            closeIt = (dlg.ShowModal() == wxID_NO);
                                             userInformed = true;
                                         }
                                         if (closeIt)
@@ -776,6 +776,29 @@ bool frmMain::CheckAlive()
                                             browser->DeleteChildren(db->GetId());
                                             db->UpdateIcon(browser);
                                         }
+                                                                               else 
+                                                                               {
+                                            // Create a server object and connect it.
+                                            wxBusyInfo waiting(wxString::Format(_("Reconnecting to database %s"),
+                                                db->GetName().c_str()), this);
+
+                                            // Give the UI a chance to redraw
+                                            wxSafeYield();
+                                            wxMilliSleep(100);
+                                            wxSafeYield();
+
+                                                                                       if (!conn->Reconnect())
+                                            {
+                                                db->Disconnect();
+                                            
+                                                browser->DeleteChildren(db->GetId());
+                                                db->UpdateIcon(browser);
+                                            }
+                                            else
+                                                // Indicate things are back to normal
+                                                userInformed = false;
+                                                                               }
+
                                     }
                                 }
                             }
@@ -792,11 +815,11 @@ bool frmMain::CheckAlive()
                     server->connection()->Close();
                     if (!userInformed)
                     {
-                        wxMessageDialog dlg(this, _("Close server browser? If you abort, the object browser will not show accurate data."),
+                        wxMessageDialog dlg(this, _("Do you want to attempt to reconnect to the server?"),
                             wxString::Format(_("Connection to server %s lost."), server->GetName().c_str()), 
                             wxICON_EXCLAMATION|wxYES_NO|wxYES_DEFAULT);
 
-                        closeIt = (dlg.ShowModal() == wxID_YES);
+                        closeIt = (dlg.ShowModal() == wxID_NO);
                         userInformed = true;
                     }
                     if (closeIt)
@@ -806,6 +829,28 @@ bool frmMain::CheckAlive()
                         execSelChange(serverItem, true);
                         browser->DeleteChildren(serverItem);
                     }
+                                       else 
+                                       {
+                        // Create a server object and connect it.
+                        wxBusyInfo waiting(wxString::Format(_("Reconnecting to server %s (%s:%d)"),
+                            server->GetDescription().c_str(), server->GetName().c_str(), server->GetPort()), this);
+
+                        // Give the UI a chance to redraw
+                        wxSafeYield();
+                        wxMilliSleep(100);
+                        wxSafeYield();
+
+                                               if (!server->connection()->Reconnect())
+                        {
+                            server->Disconnect(this);
+                            browser->SelectItem(serverItem);
+                            execSelChange(serverItem, true);
+                            browser->DeleteChildren(serverItem);
+                        }
+                        else
+                            // Indicate things are back to normal
+                            userInformed = false;
+                                       }
                 }
             }
         }
index a63321c892e660190f10625f3044ec1c3078d6a8..667405ab7afb3302ea9b4b0d1210a70d3c969528 100644 (file)
@@ -101,9 +101,10 @@ public:
     static void ExamineLibpqVersion();
     static double GetLibpqVersion() { return libpqVersion; }
 
-    static bool IsValidServerEncoding(int encid) { return pg_valid_server_encoding_id(encid); }
+    static bool IsValidServerEncoding(int encid) { return (bool)pg_valid_server_encoding_id(encid); }
 
     void Close();
+       bool Reconnect();
     bool ExecuteVoid(const wxString& sql, bool reportError = true);
     wxString ExecuteScalar(const wxString& sql);
     pgSet *ExecuteSet(const wxString& sql);
@@ -112,7 +113,7 @@ public:
     wxString GetHost() const { return dbHost; }
     wxString GetHostName() const { return dbHostName; }
     wxString GetHostAddress() const { return dbHostAddress; }
-    wxString GetDbname() const { return dbname; }
+    wxString GetDbname() const { return save_database; }
     wxString GetName() const;
     bool GetNeedUtfConnectString() { return utfConnectString; }
     int GetPort() const { return atoi(PQport(conn)); };
@@ -153,7 +154,7 @@ protected:
 
     wxMBConv *conv;
     bool needColQuoting, utfConnectString;
-    wxString dbHost, dbHostName, dbHostAddress, dbname;
+    wxString dbHost, dbHostName, dbHostAddress;
     OID lastSystemOID;
     OID dbOid;
 
@@ -164,6 +165,8 @@ protected:
     friend class pgQueryThread;
 
 private:
+       bool DoConnect();
+       
     wxString qtString(const wxString& value);
 
     bool features[32];
@@ -172,7 +175,8 @@ private:
     bool isGreenplum;
 
     wxString reservedNamespaces;
-
+       wxString connstr;
+       
     wxString save_server, save_database, save_username, save_password;
     int save_port, save_sslmode;
     OID save_oid;
index a58ce90209d05da74da565f3e4bf13be6ad45cd5..3d0ead5ebe58b02dc32ac1a1834fb0b1556ca0c4 100644 (file)
@@ -36,6 +36,7 @@ class pgConn;
 class pgSet
 {
 public:
+    pgSet();
     pgSet(PGresult *newRes, pgConn *newConn, wxMBConv &cnv, bool needColQt);
     ~pgSet();
     long NumRows() const { return nRows; }