mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-14 18:12:05 +08:00
Avoid unusable main form after failed session connect. Keep the old connection alive until it is verified that the new one is available. Moves code out of PerformConnect to DoAfterConnect.
Todo: Fix reconnection logic, see bug #858
This commit is contained in:
190
source/main.pas
190
source/main.pas
@ -563,7 +563,6 @@ type
|
|||||||
procedure SynCompletionProposal1Execute(Kind: SynCompletionType;
|
procedure SynCompletionProposal1Execute(Kind: SynCompletionType;
|
||||||
Sender: TObject; var CurrentInput: WideString; var x, y: Integer;
|
Sender: TObject; var CurrentInput: WideString; var x, y: Integer;
|
||||||
var CanExecute: Boolean);
|
var CanExecute: Boolean);
|
||||||
procedure PerformConnect;
|
|
||||||
procedure pcChange(Sender: TObject);
|
procedure pcChange(Sender: TObject);
|
||||||
procedure ValidateControls(FrmIsFocussed: Boolean = true);
|
procedure ValidateControls(FrmIsFocussed: Boolean = true);
|
||||||
procedure ValidateQueryControls(FrmIsFocussed: Boolean = true);
|
procedure ValidateQueryControls(FrmIsFocussed: Boolean = true);
|
||||||
@ -1507,6 +1506,7 @@ var
|
|||||||
DefaultLastrunDate : String;
|
DefaultLastrunDate : String;
|
||||||
frm : TfrmUpdateCheck;
|
frm : TfrmUpdateCheck;
|
||||||
dlgResult: Integer;
|
dlgResult: Integer;
|
||||||
|
AutoReconnect: Boolean;
|
||||||
begin
|
begin
|
||||||
// Do an updatecheck if checked in settings
|
// Do an updatecheck if checked in settings
|
||||||
if GetRegValue(REGNAME_DO_UPDATECHECK, DEFAULT_DO_UPDATECHECK) then begin
|
if GetRegValue(REGNAME_DO_UPDATECHECK, DEFAULT_DO_UPDATECHECK) then begin
|
||||||
@ -1602,8 +1602,21 @@ begin
|
|||||||
end else
|
end else
|
||||||
Exit;
|
Exit;
|
||||||
end else begin
|
end else begin
|
||||||
|
// Temporarily disable AutoReconnect in Registry
|
||||||
|
// in case of unexpected application-termination
|
||||||
|
OpenRegistry;
|
||||||
|
AutoReconnect := GetRegValue(REGNAME_AUTORECONNECT, DEFAULT_AUTORECONNECT);
|
||||||
|
if AutoReconnect then begin
|
||||||
|
OpenRegistry;
|
||||||
|
MainReg.WriteBool( REGNAME_AUTORECONNECT, False );
|
||||||
|
end;
|
||||||
// Cannot be done in OnCreate because we need ready forms here:
|
// Cannot be done in OnCreate because we need ready forms here:
|
||||||
dlgResult := ConnectionWindow(Self);
|
dlgResult := ConnectionWindow(Self);
|
||||||
|
// Re-enable AutoReconnect in Registry!
|
||||||
|
if AutoReconnect then begin
|
||||||
|
OpenRegistry;
|
||||||
|
MainReg.WriteBool( REGNAME_AUTORECONNECT, true );
|
||||||
|
end;
|
||||||
if dlgResult = mrCancel then begin
|
if dlgResult = mrCancel then begin
|
||||||
Close;
|
Close;
|
||||||
Exit;
|
Exit;
|
||||||
@ -1617,11 +1630,40 @@ procedure TMainForm.DoAfterConnect;
|
|||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
lastUsedDB: WideString;
|
lastUsedDB: WideString;
|
||||||
|
v: String[50];
|
||||||
|
v1, v2, v3: String;
|
||||||
|
rx: TRegExpr;
|
||||||
begin
|
begin
|
||||||
// Activate logging
|
// Activate logging
|
||||||
if GetRegValue(REGNAME_LOGTOFILE, DEFAULT_LOGTOFILE) then
|
if GetRegValue(REGNAME_LOGTOFILE, DEFAULT_LOGTOFILE) then
|
||||||
ActivateFileLogging;
|
ActivateFileLogging;
|
||||||
|
|
||||||
|
time_connected := 0;
|
||||||
|
TimerConnected.Enabled := true;
|
||||||
|
LogSQL( 'Connection established with host "' + FMysqlConn.Connection.hostname +
|
||||||
|
'" on port ' + IntToStr(FMysqlConn.Connection.Port) );
|
||||||
|
LogSQL( 'Connection-ID: ' + IntToStr( MySQLConn.Connection.GetThreadId ) );
|
||||||
|
|
||||||
|
// Detect server version
|
||||||
|
// Be careful with version suffixes, for example: '4.0.31-20070605_Debian-5-log'
|
||||||
|
v := GetVar( 'SELECT VERSION()' );
|
||||||
|
rx := TRegExpr.Create;
|
||||||
|
rx.ModifierG := True;
|
||||||
|
rx.Expression := '^(\d+)\.(\d+)\.(\d+)';
|
||||||
|
if rx.Exec(v) then begin
|
||||||
|
v1 := rx.Match[1];
|
||||||
|
v2 := rx.Match[2];
|
||||||
|
v3 := rx.Match[3];
|
||||||
|
end;
|
||||||
|
rx.Free;
|
||||||
|
mysql_version := MakeInt(v1) *10000 + MakeInt(v2) *100 + MakeInt(v3);
|
||||||
|
tabHost.Caption := 'Host: '+MySQLConn.Connection.HostName;
|
||||||
|
showstatus('MySQL '+v1+'.'+v2+'.'+v3, 3);
|
||||||
|
|
||||||
|
// On Re-Connection, try to restore lost properties
|
||||||
|
if FMysqlConn.Connection.Database <> '' then
|
||||||
|
ExecUseQuery( FMysqlConn.Connection.Database );
|
||||||
|
|
||||||
DatabasesWanted := explode(';', FConn.DatabaseList);
|
DatabasesWanted := explode(';', FConn.DatabaseList);
|
||||||
if FConn.DatabaseListSort then
|
if FConn.DatabaseListSort then
|
||||||
DatabasesWanted.Sort;
|
DatabasesWanted.Sort;
|
||||||
@ -1676,9 +1718,6 @@ begin
|
|||||||
if DataGridHasChanges then
|
if DataGridHasChanges then
|
||||||
actDataPostChangesExecute(Self);
|
actDataPostChangesExecute(Self);
|
||||||
|
|
||||||
if prefLogToFile then
|
|
||||||
DeactivateFileLogging;
|
|
||||||
|
|
||||||
// Clear database and table lists
|
// Clear database and table lists
|
||||||
DBtree.ClearSelection;
|
DBtree.ClearSelection;
|
||||||
DBtree.FocusedNode := nil;
|
DBtree.FocusedNode := nil;
|
||||||
@ -1699,6 +1738,10 @@ begin
|
|||||||
FMysqlConn.Disconnect;
|
FMysqlConn.Disconnect;
|
||||||
FreeAndNil(FMysqlConn);
|
FreeAndNil(FMysqlConn);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
if prefLogToFile then
|
||||||
|
DeactivateFileLogging;
|
||||||
|
|
||||||
SetWindowConnected( false );
|
SetWindowConnected( false );
|
||||||
SetWindowName( main.discname );
|
SetWindowName( main.discname );
|
||||||
Application.Title := APPNAME;
|
Application.Title := APPNAME;
|
||||||
@ -2386,7 +2429,6 @@ begin
|
|||||||
parCompress := IntToStr(Integer(GetRegValue(REGNAME_COMPRESSED, DEFAULT_COMPRESSED, Session)));
|
parCompress := IntToStr(Integer(GetRegValue(REGNAME_COMPRESSED, DEFAULT_COMPRESSED, Session)));
|
||||||
parDatabase := Utf8Decode(GetRegValue(REGNAME_ONLYDBS, '', Session));
|
parDatabase := Utf8Decode(GetRegValue(REGNAME_ONLYDBS, '', Session));
|
||||||
parSortDatabases := IntToStr(Integer(GetRegValue(REGNAME_ONLYDBSSORTED, DEFAULT_ONLYDBSSORTED, Session)));
|
parSortDatabases := IntToStr(Integer(GetRegValue(REGNAME_ONLYDBSSORTED, DEFAULT_ONLYDBSSORTED, Session)));
|
||||||
DoDisconnect;
|
|
||||||
if InitConnection(parHost, parPort, parUser, parPass, parDatabase, parTimeout, parCompress, parSortDatabases) then begin
|
if InitConnection(parHost, parPort, parUser, parPass, parDatabase, parTimeout, parCompress, parSortDatabases) then begin
|
||||||
SessionName := Session;
|
SessionName := Session;
|
||||||
DoAfterConnect;
|
DoAfterConnect;
|
||||||
@ -2400,73 +2442,46 @@ end;
|
|||||||
}
|
}
|
||||||
function TMainform.InitConnection(parHost, parPort, parUser, parPass, parDatabase, parTimeout, parCompress, parSortDatabases: WideString): Boolean;
|
function TMainform.InitConnection(parHost, parPort, parUser, parPass, parDatabase, parTimeout, parCompress, parSortDatabases: WideString): Boolean;
|
||||||
var
|
var
|
||||||
AutoReconnect: Boolean;
|
MysqlConnection: TMysqlConn;
|
||||||
|
Profile: TOpenConnProf;
|
||||||
begin
|
begin
|
||||||
// fill structure
|
// fill structure
|
||||||
ZeroMemory (@FConn,SizeOf(FConn));
|
ZeroMemory(@Profile, SizeOf(Profile));
|
||||||
|
Profile.MysqlParams.Protocol := 'mysql';
|
||||||
with FConn do
|
Profile.MysqlParams.Host := Trim( parHost );
|
||||||
begin
|
Profile.MysqlParams.Port := StrToIntDef(parPort, DEFAULT_PORT);
|
||||||
MysqlParams.Protocol := 'mysql';
|
Profile.MysqlParams.Database := '';
|
||||||
MysqlParams.Host := Trim( parHost );
|
Profile.MysqlParams.User := parUser;
|
||||||
MysqlParams.Port := StrToIntDef(parPort, DEFAULT_PORT);
|
Profile.MysqlParams.Pass := parPass;
|
||||||
MysqlParams.Database := '';
|
|
||||||
MysqlParams.User := parUser;
|
|
||||||
MysqlParams.Pass := parPass;
|
|
||||||
|
|
||||||
// additional
|
|
||||||
if Integer(parCompress) > 0 then
|
if Integer(parCompress) > 0 then
|
||||||
MysqlParams.PrpCompress := 'true'
|
Profile.MysqlParams.PrpCompress := 'true'
|
||||||
else
|
else
|
||||||
MysqlParams.PrpCompress := 'false';
|
Profile.MysqlParams.PrpCompress := 'false';
|
||||||
|
Profile.MysqlParams.PrpTimeout := parTimeout;
|
||||||
|
Profile.MysqlParams.PrpDbless := 'true';
|
||||||
|
Profile.MysqlParams.PrpClientLocalFiles := 'true';
|
||||||
|
Profile.MysqlParams.PrpClientInteractive := 'true';
|
||||||
|
Profile.DatabaseList := parDatabase;
|
||||||
|
Profile.DatabaseListSort := Boolean(StrToIntDef(parSortDatabases, 0));
|
||||||
|
|
||||||
MysqlParams.PrpTimeout := parTimeout;
|
MysqlConnection := TMysqlConn.Create(@Profile);
|
||||||
MysqlParams.PrpDbless := 'true';
|
|
||||||
MysqlParams.PrpClientLocalFiles := 'true';
|
|
||||||
MysqlParams.PrpClientInteractive := 'true';
|
|
||||||
|
|
||||||
DatabaseList := parDatabase;
|
|
||||||
DatabaseListSort := Boolean(StrToIntDef(parSortDatabases, 0));
|
|
||||||
end;
|
|
||||||
|
|
||||||
FMysqlConn := TMysqlConn.Create(@FConn);
|
|
||||||
|
|
||||||
// attempt to establish connection
|
// attempt to establish connection
|
||||||
if FMysqlConn.Connect <> MCR_SUCCESS then begin
|
Showstatus( 'Connecting to ' + Profile.MysqlParams.Host + '...' );
|
||||||
|
if MysqlConnection.Connect <> MCR_SUCCESS then begin
|
||||||
// attempt failed -- show error
|
// attempt failed -- show error
|
||||||
MessageDlg ( 'Could not establish connection! Details:'+CRLF+CRLF+FMysqlConn.LastError, mtError, [mbOK], 0);
|
MessageDlg ( 'Could not establish connection! Details:'+CRLF+CRLF+MysqlConnection.LastError, mtError, [mbOK], 0);
|
||||||
Result := False;
|
Result := False;
|
||||||
FreeAndNil (FMysqlConn);
|
FreeAndNil(MysqlConnection);
|
||||||
Exit;
|
end else begin
|
||||||
end;
|
|
||||||
|
|
||||||
Result := True;
|
Result := True;
|
||||||
|
Profile.MysqlConn := MysqlConnection.Connection;
|
||||||
FConn.MysqlConn := FMysqlConn.Connection; // use this connection (instead of zConn)
|
if Assigned(FMysqlConn) then
|
||||||
|
DoDisconnect;
|
||||||
// Temporarily disable AutoReconnect in Registry
|
// Assign global connection objects
|
||||||
// in case of unexpected application-termination
|
FConn := Profile;
|
||||||
AutoReconnect := GetRegValue(REGNAME_AUTORECONNECT, DEFAULT_AUTORECONNECT);
|
FMysqlConn := MysqlConnection;
|
||||||
if AutoReconnect then begin
|
|
||||||
OpenRegistry;
|
|
||||||
MainReg.WriteBool( REGNAME_AUTORECONNECT, False );
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Showstatus( 'Connecting to ' + FConn.MysqlParams.Host + '...' );
|
|
||||||
|
|
||||||
try
|
|
||||||
PerformConnect();
|
|
||||||
except
|
|
||||||
TimerConnectErrorCloseWindow.Enabled := true;
|
|
||||||
Exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// Re-enable AutoReconnect in Registry!
|
|
||||||
if AutoReconnect then begin
|
|
||||||
OpenRegistry;
|
|
||||||
MainReg.WriteBool( REGNAME_AUTORECONNECT, true );
|
|
||||||
end;
|
|
||||||
|
|
||||||
ShowStatus( STATUS_MSG_READY );
|
ShowStatus( STATUS_MSG_READY );
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -3185,49 +3200,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TMainForm.PerformConnect;
|
|
||||||
var
|
|
||||||
v : String[50];
|
|
||||||
v1, v2, v3 : String;
|
|
||||||
rx : TRegExpr;
|
|
||||||
begin
|
|
||||||
try
|
|
||||||
time_connected := 0;
|
|
||||||
TimerConnected.Enabled := true;
|
|
||||||
LogSQL( 'Connection established with host "' + FMysqlConn.Connection.hostname +
|
|
||||||
'" on port ' + IntToStr(FMysqlConn.Connection.Port) );
|
|
||||||
LogSQL( 'Connection-ID: ' + IntToStr( MySQLConn.Connection.GetThreadId ) );
|
|
||||||
|
|
||||||
// Detect server version
|
|
||||||
// Be careful with version suffixes, for example: '4.0.31-20070605_Debian-5-log'
|
|
||||||
v := GetVar( 'SELECT VERSION()' );
|
|
||||||
rx := TRegExpr.Create;
|
|
||||||
rx.ModifierG := True;
|
|
||||||
rx.Expression := '^(\d+)\.(\d+)\.(\d+)';
|
|
||||||
if rx.Exec(v) then begin
|
|
||||||
v1 := rx.Match[1];
|
|
||||||
v2 := rx.Match[2];
|
|
||||||
v3 := rx.Match[3];
|
|
||||||
end;
|
|
||||||
rx.Free;
|
|
||||||
mysql_version := MakeInt(v1) *10000 + MakeInt(v2) *100 + MakeInt(v3);
|
|
||||||
tabHost.Caption := 'Host: '+MySQLConn.Connection.HostName;
|
|
||||||
showstatus('MySQL '+v1+'.'+v2+'.'+v3, 3);
|
|
||||||
|
|
||||||
// On Re-Connection, try to restore lost properties
|
|
||||||
if FMysqlConn.Connection.Database <> '' then
|
|
||||||
ExecUseQuery( FMysqlConn.Connection.Database );
|
|
||||||
except
|
|
||||||
on E: Exception do begin
|
|
||||||
LogSQL( E.Message, true );
|
|
||||||
Screen.Cursor := crDefault;
|
|
||||||
MessageDlg( E.Message, mtError, [mbOK], 0 );
|
|
||||||
raise;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
function TMainForm.GetQueryRunning: Boolean;
|
function TMainForm.GetQueryRunning: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := ( QueryRunningInterlock = 1 );
|
Result := ( QueryRunningInterlock = 1 );
|
||||||
@ -5933,18 +5905,10 @@ begin
|
|||||||
TimerConnectedTimer(self);
|
TimerConnectedTimer(self);
|
||||||
TimerHostUptime.Enabled := false;
|
TimerHostUptime.Enabled := false;
|
||||||
TimerHostUptimeTimer(self);
|
TimerHostUptimeTimer(self);
|
||||||
// 1) CheckConnection is always called from
|
|
||||||
// within an FQueryRunning-enabled block.
|
|
||||||
// 2) PerformConnect (see below) will make calls
|
|
||||||
// that open an FQueryRunning block, causing an
|
|
||||||
// error message.
|
|
||||||
//
|
|
||||||
// Therefore, flick the state of the running
|
|
||||||
// flag before running PerformConnect().
|
|
||||||
FQueryRunning := false;
|
FQueryRunning := false;
|
||||||
try
|
try
|
||||||
FMysqlConn.Connection.Reconnect;
|
FMysqlConn.Connection.Reconnect;
|
||||||
PerformConnect;
|
time_connected := 0;
|
||||||
finally
|
finally
|
||||||
FQueryRunning := true;
|
FQueryRunning := true;
|
||||||
end;
|
end;
|
||||||
|
Reference in New Issue
Block a user