Index: ctlSQLResult.cpp =================================================================== RCS file: /projects/pgadmin3/src/ui/ctlSQLResult.cpp,v retrieving revision 1.21 retrieving revision 1.22 diff -Lsrc/ui/ctlSQLResult.cpp -Lsrc/ui/ctlSQLResult.cpp -u -w -r1.21 -r1.22 --- src/ui/ctlSQLResult.cpp +++ src/ui/ctlSQLResult.cpp @@ -220,8 +220,7 @@ wxString ctlSQLResult::GetErrorMessage() { - wxString errmsg=wxString(PQerrorMessage(conn->connection()), wxConvUTF8); - return errmsg; + return conn->GetLastError(); } Index: dlgEditGridOptions.cpp =================================================================== RCS file: /projects/pgadmin3/src/ui/dlgEditGridOptions.cpp,v retrieving revision 1.15 retrieving revision 1.16 diff -Lsrc/ui/dlgEditGridOptions.cpp -Lsrc/ui/dlgEditGridOptions.cpp -u -w -r1.15 -r1.16 --- src/ui/dlgEditGridOptions.cpp +++ src/ui/dlgEditGridOptions.cpp @@ -294,7 +294,7 @@ } // Figure out where the error is - wxString errMsg = wxString(PQerrorMessage(connection->connection()), *conv).c_str(); + wxString errMsg = connection->GetLastError(); wxString atChar=wxT(" at character "); int chp=errMsg.Find(atChar); Index: events.cpp =================================================================== RCS file: /projects/pgadmin3/src/ui/events.cpp,v retrieving revision 1.90 retrieving revision 1.91 diff -Lsrc/ui/events.cpp -Lsrc/ui/events.cpp -u -w -r1.90 -r1.91 --- src/ui/events.cpp +++ src/ui/events.cpp @@ -340,81 +340,7 @@ void frmMain::OnCheckAlive(wxCommandEvent &event) { - bool userInformed = false; - bool closeIt; - - wxCookieType cookie; - wxTreeItemId item=browser->GetFirstChild(servers, cookie); - while (item) - { - pgServer *server=(pgServer*)browser->GetItemData(item); - if (server && server->GetType() == PG_SERVER && server->connection()) - { - if (server->connection()->IsAlive()) - { - wxCookieType cookie2; - item = browser->GetFirstChild(server->GetId(), cookie2); - while (item) - { - pgObject *obj=(pgObject*)browser->GetItemData(item); - if (obj && obj->GetType() == PG_DATABASES) - { - wxCookieType cookie3; - item = browser->GetFirstChild(obj->GetId(), cookie3); - while (item) - { - pgDatabase *db=(pgDatabase*)browser->GetItemData(item); - if (db && db->GetType() == PG_DATABASE && db->GetConnected() && db->connection()) - { - if (!db->connection()->IsAlive()) - { - if (!userInformed) - { - wxMessageDialog dlg(this, _("Close database browser? If you abort, the object browser will not show accurate data."), - wxString::Format(_("Connection to database %s lost."), db->GetName().c_str()), - wxICON_EXCLAMATION|wxYES_NO|wxYES_DEFAULT); - - closeIt = (dlg.ShowModal() == wxID_YES); - userInformed = true; - } - if (closeIt) - { - browser->DeleteChildren(db->GetId()); - browser->SetItemImage(db->GetId(), PGICON_CLOSEDDATABASE, wxTreeItemIcon_Selected); - browser->SetItemImage(db->GetId(), PGICON_CLOSEDDATABASE, wxTreeItemIcon_Selected); - db->Disconnect(); - } - } - } - item = browser->GetNextChild(obj->GetId(), cookie3); - } - } - item = browser->GetNextChild(server->GetId(), cookie2); - } - } - else - { - if (!userInformed) - { - wxMessageDialog dlg(this, _("Close server browser? If you abort, the object browser will not show accurate data."), - wxString::Format(_("Connection to server %s lost."), server->GetName().c_str()), - wxICON_EXCLAMATION|wxYES_NO|wxYES_DEFAULT); - - closeIt = (dlg.ShowModal() == wxID_YES); - userInformed = true; - } - if (closeIt) - { - browser->DeleteChildren(server->GetId()); - browser->SetItemImage(server->GetId(), PGICON_SERVERBAD, wxTreeItemIcon_Normal); - browser->SetItemImage(server->GetId(), PGICON_SERVERBAD, wxTreeItemIcon_Selected); - server->Disconnect(); - } - } - } - - item = browser->GetNextChild(servers, cookie); - } + checkAlive(); } @@ -635,24 +561,36 @@ int res = server->Connect(this); // Check the result, and handle it as appropriate - if (res == PGCONN_OK) { + switch (res) + { + case PGCONN_OK: + { wxLogInfo(wxT("pgServer object initialised as required.")); browser->AppendItem(servers, server->GetFullName(), PGICON_SERVER, -1, server); browser->Expand(servers); - - } else if (res == PGCONN_DNSERR) { + break; + } + case PGCONN_DNSERR: + { delete server; OnAddServer(ev); - - } else if (res == PGCONN_BAD) { + break; + } + case PGCONN_BAD: + case PGCONN_BROKEN: + { wxLogError(__("Error connecting to the server: %s"), server->GetLastError().c_str()); delete server; OnAddServer(ev); - - } else { + break; + } + default: + { wxLogInfo(__("pgServer object didn't initialise because the user aborted.")); delete server; + break; + } } // Reset the Servers node text @@ -779,6 +717,8 @@ canGrantWizard=true; break; case PG_TABLE: + case PG_CONSTRAINTS: + case PG_FOREIGNKEY: canIndexCheck=true; break; case PG_DATABASES: @@ -807,10 +747,8 @@ case PG_CHECK: case PG_COLUMNS: case PG_COLUMN: - case PG_CONSTRAINTS: case PG_PRIMARYKEY: case PG_UNIQUE: - case PG_FOREIGNKEY: case PG_INDEXES: case PG_INDEX: case PG_RULES: @@ -837,6 +775,12 @@ sqlbox->SetReadOnly(true); } + pgConn *conn=data->GetConnection(); + if (conn && conn->GetStatus() == PGCONN_BROKEN) + { + checkAlive(); + return; + } unsigned int i; wxMenuItem *menuItem; i=newMenu->GetMenuItemCount(); Index: frmMain.cpp =================================================================== RCS file: /projects/pgadmin3/src/ui/frmMain.cpp,v retrieving revision 1.88 retrieving revision 1.89 diff -Lsrc/ui/frmMain.cpp -Lsrc/ui/frmMain.cpp -u -w -r1.88 -r1.89 --- src/ui/frmMain.cpp +++ src/ui/frmMain.cpp @@ -509,6 +509,97 @@ frames.DeleteObject(frame); } + +bool frmMain::checkAlive() +{ + bool userInformed = false; + bool closeIt; + + wxCookieType cookie; + wxTreeItemId serverItem=browser->GetFirstChild(servers, cookie); + while (serverItem) + { + pgServer *server=(pgServer*)browser->GetItemData(serverItem); + + if (server && server->GetType() == PG_SERVER && server->connection()) + { + if (server->connection()->IsAlive()) + { + wxCookieType cookie2; + wxTreeItemId item = browser->GetFirstChild(serverItem, cookie2); + while (item) + { + pgObject *obj=(pgObject*)browser->GetItemData(item); + if (obj && obj->GetType() == PG_DATABASES) + { + wxCookieType cookie3; + item = browser->GetFirstChild(obj->GetId(), cookie3); + while (item) + { + pgDatabase *db=(pgDatabase*)browser->GetItemData(item); + if (db && db->GetType() == PG_DATABASE && db->GetConnected() && db->connection()) + { + if (!db->connection()->IsAlive() && db->connection()->GetStatus() == PGCONN_BROKEN) + { + db->connection()->Close(); + if (!userInformed) + { + wxMessageDialog dlg(this, _("Close database browser? If you abort, the object browser will not show accurate data."), + wxString::Format(_("Connection to database %s lost."), db->GetName().c_str()), + wxICON_EXCLAMATION|wxYES_NO|wxYES_DEFAULT); + + closeIt = (dlg.ShowModal() == wxID_YES); + userInformed = true; + } + if (closeIt) + { + browser->DeleteChildren(db->GetId()); + browser->SetItemImage(db->GetId(), PGICON_CLOSEDDATABASE, wxTreeItemIcon_Selected); + browser->SetItemImage(db->GetId(), PGICON_CLOSEDDATABASE, wxTreeItemIcon_Selected); + db->Disconnect(); + } + } + } + item = browser->GetNextChild(obj->GetId(), cookie3); + } + } + item = browser->GetNextChild(serverItem, cookie2); + } + } + else + { + if (server->connection()->GetStatus() == PGCONN_BROKEN) + { + server->connection()->Close(); + if (!userInformed) + { + wxMessageDialog dlg(this, _("Close server browser? If you abort, the object browser will not show accurate data."), + wxString::Format(_("Connection to server %s lost."), server->GetName().c_str()), + wxICON_EXCLAMATION|wxYES_NO|wxYES_DEFAULT); + + closeIt = (dlg.ShowModal() == wxID_YES); + userInformed = true; + } + if (closeIt) + { + + browser->SelectItem(serverItem); + browser->SetItemImage(serverItem, PGICON_SERVERBAD, wxTreeItemIcon_Normal); + browser->SetItemImage(serverItem, PGICON_SERVERBAD, wxTreeItemIcon_Selected); + server->Disconnect(); + execSelChange(serverItem, true); + browser->DeleteChildren(serverItem); + } + } + } + } + + serverItem = browser->GetNextChild(servers, cookie); + } + return userInformed; +} + + wxTreeItemId frmMain::RestoreEnvironment(pgServer *server) { wxTreeItemId item, lastItem; Index: frmMain.h =================================================================== RCS file: /projects/pgadmin3/src/include/frmMain.h,v retrieving revision 1.43 retrieving revision 1.44 diff -Lsrc/include/frmMain.h -Lsrc/include/frmMain.h -u -w -r1.43 -r1.44 --- src/include/frmMain.h +++ src/include/frmMain.h @@ -127,6 +127,7 @@ void OnCheckAlive(wxCommandEvent& event); void execSelChange(wxTreeItemId item, bool currentNode); + bool checkAlive(); void setDisplay(pgObject *data, ctlListView *props=0, ctlSQLBox *sqlbox=0); void StoreServers(); void RetrieveServers(); Index: pgConn.h =================================================================== RCS file: /projects/pgadmin3/src/include/pgConn.h,v retrieving revision 1.24 retrieving revision 1.25 diff -Lsrc/include/pgConn.h -Lsrc/include/pgConn.h -u -w -r1.24 -r1.25 --- src/include/pgConn.h +++ src/include/pgConn.h @@ -30,7 +30,8 @@ PGCONN_BAD = CONNECTION_BAD, PGCONN_REFUSED, PGCONN_DNSERR, - PGCONN_ABORTED + PGCONN_ABORTED, // connect user aborted + PGCONN_BROKEN // tcp/pipe broken }; enum @@ -51,6 +52,8 @@ public: pgConn(const wxString& server = wxT(""), const wxString& database = wxT(""), const wxString& username = wxT(""), const wxString& password = wxT(""), int port = 5432, int sslmode=0); ~pgConn(); + + void Close(); bool HasPrivilege(const wxString &objTyp, const wxString &objName, const wxString &priv); bool ExecuteVoid(const wxString& sql); wxString ExecuteScalar(const wxString& sql); @@ -65,7 +68,7 @@ int GetStatus() const; int GetLastResultStatus() const { return lastResultStatus; } bool IsAlive(); - wxString GetLastError() const { return wxString(PQerrorMessage(conn), *conv); } + wxString GetLastError() const; wxString GetVersionString(); OID GetLastSystemOID() const { return lastSystemOID; } bool BackendMinimumVersion(int major, int minor); @@ -83,9 +86,10 @@ private: PGconn *conn; int lastResultStatus; + int connStatus; int minorVersion, majorVersion; wxMBConv *conv; - bool resolvedIP, needColQuoting; + bool needColQuoting; wxString dbHost; OID lastSystemOID; Index: pgConn.cpp =================================================================== RCS file: /projects/pgadmin3/src/db/pgConn.cpp,v retrieving revision 1.47 retrieving revision 1.48 diff -Lsrc/db/pgConn.cpp -Lsrc/db/pgConn.cpp -u -w -r1.47 -r1.48 --- src/db/pgConn.cpp +++ src/db/pgConn.cpp @@ -7,7 +7,7 @@ // // pgConn.cpp - PostgreSQL Connection class // -////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// #include "pgAdmin3.h" @@ -61,6 +61,7 @@ conn=0; majorVersion=0; noticeArg=0; + connStatus = PGCONN_BAD; #ifdef __WXMSW__ struct in_addr ipaddr; @@ -75,7 +76,7 @@ host = gethostbyname(server.ToAscii()); if (host == NULL) { - resolvedIP = FALSE; + connStatus = PGCONN_DNSERR; wxLogError(__("Could not resolve hostname %s"), server.c_str()); return; } @@ -87,7 +88,6 @@ else hostip = server; - resolvedIP = TRUE; wxLogInfo(wxT("Server name: %s (resolved to: %s)"), server.c_str(), hostip.c_str()); // Create the connection string @@ -142,7 +142,7 @@ // Set client encoding to Unicode/Ascii if (PQstatus(conn) == CONNECTION_OK) { - + connStatus = PGCONN_OK; PQsetNoticeProcessor(conn, pgNoticeProcessor, this); pgSet *set=ExecuteSet( @@ -166,7 +166,7 @@ wxLogInfo(wxT("Setting client_encoding to '%s'"), encoding.c_str()); if (PQsetClientEncoding(conn, encoding.ToAscii())) - wxLogError(wxT("%s"), wxString(PQerrorMessage(conn), *conv).c_str()); + wxLogError(wxT("%s"), GetLastError().c_str()); delete set; } @@ -177,8 +177,17 @@ pgConn::~pgConn() { wxLogInfo(wxT("Destroying pgConn object")); + Close(); +} + + + +void pgConn::Close() +{ if (conn) PQfinish(conn); + conn=0; + connStatus=PGCONN_BAD; } @@ -334,19 +343,39 @@ // Info ////////////////////////////////////////////////////////////////////////// +wxString pgConn::GetLastError() const +{ + wxString errmsg; + if (conn) + errmsg=wxString(PQerrorMessage(conn), wxConvUTF8); + else + { + if (connStatus == PGCONN_BROKEN) + errmsg = _("Connection to database broken."); + else + errmsg = _("No connection to database."); + } + return errmsg; +} + + void pgConn::LogError() { if (conn) { - wxLogError(wxT("%s"), wxString(PQerrorMessage(conn), *conv).c_str()); + wxLogError(wxT("%s"), GetLastError().c_str()); + IsAlive(); +#if 0 ConnStatusType status = PQstatus(conn); if (status == CONNECTION_BAD) { PQfinish(conn); conn=0; + connStatus = PGCONN_BROKEN; } +#endif } } @@ -366,6 +395,7 @@ { PQfinish(conn); conn=0; + connStatus = PGCONN_BROKEN; return false; } @@ -375,13 +405,10 @@ int pgConn::GetStatus() const { - if(!resolvedIP) - return PGCONN_DNSERR; + if (conn) + ((pgConn*)this)->connStatus = PQstatus(conn); - if (!conn) - return PGCONN_BAD; - else - return PQstatus(conn); + return connStatus; } Index: pgSet.cpp =================================================================== RCS file: /projects/pgadmin3/src/db/pgSet.cpp,v retrieving revision 1.43 retrieving revision 1.44 diff -Lsrc/db/pgSet.cpp -Lsrc/db/pgSet.cpp -u -w -r1.43 -r1.44 --- src/db/pgSet.cpp +++ src/db/pgSet.cpp @@ -279,6 +279,7 @@ rc=-1; insertedOid = (OID)-1; conn->RegisterNoticeProcessor(pgNoticeProcessor, this); + if (conn->conn) PQsetnonblocking(conn->conn, 1); } @@ -308,7 +309,7 @@ void pgQueryThread::appendMessage(const wxString &str) { wxCriticalSectionLocker cs(criticalSection); - messages += str; + messages.Append(str); } @@ -319,10 +320,14 @@ wxLogSql(wxT("Thread Query %s"), query.c_str()); + if (!conn->conn) + return(0); if (!PQsendQuery(conn->conn, query.mb_str(*conn->conv))) + { + conn->IsAlive(); return(0); - + } int resultsRetrieved=0; PGresult *lastResult=0; while (true) Index: pgDatabase.cpp =================================================================== RCS file: /projects/pgadmin3/src/schema/pgDatabase.cpp,v retrieving revision 1.54 retrieving revision 1.55 diff -Lsrc/schema/pgDatabase.cpp -Lsrc/schema/pgDatabase.cpp -u -w -r1.54 -r1.55 --- src/schema/pgDatabase.cpp +++ src/schema/pgDatabase.cpp @@ -114,15 +114,7 @@ void pgDatabase::CheckAlive() { if (connected) - { connected = connection()->IsAlive(); - if (!connected) - { - // backend died - wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, MNU_CHECKALIVE); - wxPostEvent(GetServer()->GetParentFrame(), event); - } - } } void pgDatabase::Disconnect()