mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-06 18:24:26 +08:00
Implement fetching multiple results from one query, e.g. from a procedure call. Fixes remaining stuff in issue #1135.
This commit is contained in:
@ -2175,24 +2175,19 @@ begin
|
|||||||
ShowStatusMsg('Executing query #'+FormatNumber(i+1)+' of '+FormatNumber(SQLBatch.Count)+' ...');
|
ShowStatusMsg('Executing query #'+FormatNumber(i+1)+' of '+FormatNumber(SQLBatch.Count)+' ...');
|
||||||
ProgressBarStatus.StepIt;
|
ProgressBarStatus.StepIt;
|
||||||
ProgressBarStatus.Repaint;
|
ProgressBarStatus.Repaint;
|
||||||
Results := TMySQLQuery.Create(Self);
|
|
||||||
Results.Connection := Connection;
|
|
||||||
Results.LogCategory := lcUserFiredSQL;
|
|
||||||
Results.SQL := SQLBatch[i].SQL;
|
|
||||||
Results.StoreResult := QueryTab.ResultTabs.Count < prefMaxQueryResults;
|
|
||||||
try
|
try
|
||||||
Results.Execute;
|
Connection.Query(SQLBatch[i].SQL, QueryTab.ResultTabs.Count < prefMaxQueryResults, lcUserFiredSQL);
|
||||||
Inc(QueryCount);
|
Inc(QueryCount);
|
||||||
Inc(SQLtime, Connection.LastQueryDuration);
|
Inc(SQLtime, Connection.LastQueryDuration);
|
||||||
Inc(SQLNetTime, Connection.LastQueryNetworkDuration);
|
Inc(SQLNetTime, Connection.LastQueryNetworkDuration);
|
||||||
Inc(RowsAffected, Connection.RowsAffected);
|
Inc(RowsAffected, Connection.RowsAffected);
|
||||||
Inc(RowsFound, Connection.RowsFound);
|
Inc(RowsFound, Connection.RowsFound);
|
||||||
if Results.StoreResult and Results.HasResult then begin
|
if (Connection.ResultCount > 0) then for Results in Connection.GetLastResults do begin
|
||||||
NewTab := TResultTab.Create;
|
NewTab := TResultTab.Create;
|
||||||
QueryTab.ResultTabs.Add(NewTab);
|
QueryTab.ResultTabs.Add(NewTab);
|
||||||
NewTab.Results := Results;
|
NewTab.Results := Results;
|
||||||
try
|
try
|
||||||
TabCaption := Results.TableName;
|
TabCaption := NewTab.Results.TableName;
|
||||||
except on E:EDatabaseError do
|
except on E:EDatabaseError do
|
||||||
TabCaption := 'Result #'+IntToStr(QueryTab.ResultTabs.Count);
|
TabCaption := 'Result #'+IntToStr(QueryTab.ResultTabs.Count);
|
||||||
end;
|
end;
|
||||||
@ -2220,8 +2215,7 @@ begin
|
|||||||
NewTab.Grid.EndUpdate;
|
NewTab.Grid.EndUpdate;
|
||||||
for j:=0 to NewTab.Grid.Header.Columns.Count-1 do
|
for j:=0 to NewTab.Grid.Header.Columns.Count-1 do
|
||||||
AutoCalcColWidth(NewTab.Grid, j);
|
AutoCalcColWidth(NewTab.Grid, j);
|
||||||
end else
|
end;
|
||||||
FreeAndNil(Results);
|
|
||||||
except
|
except
|
||||||
on E:EDatabaseError do begin
|
on E:EDatabaseError do begin
|
||||||
if actQueryStopOnErrors.Checked or (i = SQLBatch.Count - 1) then begin
|
if actQueryStopOnErrors.Checked or (i = SQLBatch.Count - 1) then begin
|
||||||
|
@ -185,6 +185,7 @@ type
|
|||||||
TMySQLDatabaseEvent = procedure(Database: String) of object;
|
TMySQLDatabaseEvent = procedure(Database: String) of object;
|
||||||
|
|
||||||
TMySQLQuery = class;
|
TMySQLQuery = class;
|
||||||
|
TMySQLQueryList = TObjectList<TMySQLQuery>;
|
||||||
TMySQLConnection = class(TComponent)
|
TMySQLConnection = class(TComponent)
|
||||||
private
|
private
|
||||||
FHandle: PMYSQL;
|
FHandle: PMYSQL;
|
||||||
@ -204,6 +205,7 @@ type
|
|||||||
FServerVersionUntouched: String;
|
FServerVersionUntouched: String;
|
||||||
FRealHostname: String;
|
FRealHostname: String;
|
||||||
FLastQueryDuration, FLastQueryNetworkDuration: Cardinal;
|
FLastQueryDuration, FLastQueryNetworkDuration: Cardinal;
|
||||||
|
FLastQuerySQL: String;
|
||||||
FIsUnicode: Boolean;
|
FIsUnicode: Boolean;
|
||||||
FTableEngines: TStringList;
|
FTableEngines: TStringList;
|
||||||
FTableEngineDefault: String;
|
FTableEngineDefault: String;
|
||||||
@ -213,6 +215,8 @@ type
|
|||||||
FDatabases: TDatabaseList;
|
FDatabases: TDatabaseList;
|
||||||
FObjectNamesInSelectedDB: TStrings;
|
FObjectNamesInSelectedDB: TStrings;
|
||||||
FPlinkProcInfo: TProcessInformation;
|
FPlinkProcInfo: TProcessInformation;
|
||||||
|
FLastResults: Array of PMYSQL_RES;
|
||||||
|
FResultCount: Integer;
|
||||||
procedure SetActive(Value: Boolean);
|
procedure SetActive(Value: Boolean);
|
||||||
procedure ClosePlink;
|
procedure ClosePlink;
|
||||||
procedure SetDatabase(Value: String);
|
procedure SetDatabase(Value: String);
|
||||||
@ -255,6 +259,7 @@ type
|
|||||||
function ParseDateTime(Str: String): TDateTime;
|
function ParseDateTime(Str: String): TDateTime;
|
||||||
function GetKeyColumns(Columns: TTableColumnList; Keys: TTableKeyList): TStringList;
|
function GetKeyColumns(Columns: TTableColumnList; Keys: TTableKeyList): TStringList;
|
||||||
function ConnectionInfo: TStringList;
|
function ConnectionInfo: TStringList;
|
||||||
|
function GetLastResults: TMySQLQueryList;
|
||||||
procedure ClearDbObjects(db: String);
|
procedure ClearDbObjects(db: String);
|
||||||
procedure ClearAllDbObjects;
|
procedure ClearAllDbObjects;
|
||||||
property Parameters: TConnectionParameters read FParameters write FParameters;
|
property Parameters: TConnectionParameters read FParameters write FParameters;
|
||||||
@ -281,6 +286,7 @@ type
|
|||||||
property CharsetList: TStringList read GetCharsetList;
|
property CharsetList: TStringList read GetCharsetList;
|
||||||
property InformationSchemaObjects: TStringList read GetInformationSchemaObjects;
|
property InformationSchemaObjects: TStringList read GetInformationSchemaObjects;
|
||||||
property ObjectNamesInSelectedDB: TStrings read FObjectNamesInSelectedDB write FObjectNamesInSelectedDB;
|
property ObjectNamesInSelectedDB: TStrings read FObjectNamesInSelectedDB write FObjectNamesInSelectedDB;
|
||||||
|
property ResultCount: Integer read FResultCount;
|
||||||
published
|
published
|
||||||
property Active: Boolean read FActive write SetActive default False;
|
property Active: Boolean read FActive write SetActive default False;
|
||||||
property Database: String read FDatabase write SetDatabase;
|
property Database: String read FDatabase write SetDatabase;
|
||||||
@ -310,7 +316,6 @@ type
|
|||||||
FCurrentRow: PMYSQL_ROW;
|
FCurrentRow: PMYSQL_ROW;
|
||||||
FCurrentUpdateRow: TRowData;
|
FCurrentUpdateRow: TRowData;
|
||||||
FEof: Boolean;
|
FEof: Boolean;
|
||||||
FLogCategory: TMySQLLogCategory;
|
|
||||||
FStoreResult: Boolean;
|
FStoreResult: Boolean;
|
||||||
FColumns: TTableColumnList;
|
FColumns: TTableColumnList;
|
||||||
FKeys: TTableKeyList;
|
FKeys: TTableKeyList;
|
||||||
@ -327,7 +332,7 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create(AOwner: TComponent); override;
|
constructor Create(AOwner: TComponent); override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure Execute(AddResult: Boolean=False);
|
procedure Execute(AddResult: Boolean=False; Res: PMYSQL_RES=nil);
|
||||||
procedure First;
|
procedure First;
|
||||||
procedure Next;
|
procedure Next;
|
||||||
function ColumnCount: Integer;
|
function ColumnCount: Integer;
|
||||||
@ -363,7 +368,6 @@ type
|
|||||||
property Eof: Boolean read FEof;
|
property Eof: Boolean read FEof;
|
||||||
property RecordCount: Int64 read FRecordCount;
|
property RecordCount: Int64 read FRecordCount;
|
||||||
property ColumnNames: TStringList read FColumnNames;
|
property ColumnNames: TStringList read FColumnNames;
|
||||||
property LogCategory: TMySQLLogCategory read FLogCategory write FLogCategory;
|
|
||||||
property StoreResult: Boolean read FStoreResult write FStoreResult;
|
property StoreResult: Boolean read FStoreResult write FStoreResult;
|
||||||
property ColumnOrgNames: TStringList read FColumnOrgNames write SetColumnOrgNames;
|
property ColumnOrgNames: TStringList read FColumnOrgNames write SetColumnOrgNames;
|
||||||
published
|
published
|
||||||
@ -631,7 +635,7 @@ end;
|
|||||||
}
|
}
|
||||||
function TMySQLConnection.Query(SQL: String; DoStoreResult: Boolean=False; LogCategory: TMySQLLogCategory=lcSQL): PMYSQL_RES;
|
function TMySQLConnection.Query(SQL: String; DoStoreResult: Boolean=False; LogCategory: TMySQLLogCategory=lcSQL): PMYSQL_RES;
|
||||||
var
|
var
|
||||||
querystatus, i: Integer;
|
querystatus: Integer;
|
||||||
NativeSQL: AnsiString;
|
NativeSQL: AnsiString;
|
||||||
TimerStart: Cardinal;
|
TimerStart: Cardinal;
|
||||||
NextResult: PMYSQL_RES;
|
NextResult: PMYSQL_RES;
|
||||||
@ -639,11 +643,14 @@ begin
|
|||||||
if not Ping then
|
if not Ping then
|
||||||
Active := True;
|
Active := True;
|
||||||
Log(LogCategory, SQL);
|
Log(LogCategory, SQL);
|
||||||
|
FLastQuerySQL := SQL;
|
||||||
if IsUnicode then
|
if IsUnicode then
|
||||||
NativeSQL := UTF8Encode(SQL)
|
NativeSQL := UTF8Encode(SQL)
|
||||||
else
|
else
|
||||||
NativeSQL := AnsiString(SQL);
|
NativeSQL := AnsiString(SQL);
|
||||||
TimerStart := GetTickCount;
|
TimerStart := GetTickCount;
|
||||||
|
SetLength(FLastResults, 0);
|
||||||
|
FResultCount := 0;
|
||||||
querystatus := mysql_real_query(FHandle, PAnsiChar(NativeSQL), Length(NativeSQL));
|
querystatus := mysql_real_query(FHandle, PAnsiChar(NativeSQL), Length(NativeSQL));
|
||||||
FLastQueryDuration := GetTickCount - TimerStart;
|
FLastQueryDuration := GetTickCount - TimerStart;
|
||||||
FLastQueryNetworkDuration := 0;
|
FLastQueryNetworkDuration := 0;
|
||||||
@ -668,20 +675,27 @@ begin
|
|||||||
FRowsFound := mysql_num_rows(Result);
|
FRowsFound := mysql_num_rows(Result);
|
||||||
FRowsAffected := 0;
|
FRowsAffected := 0;
|
||||||
Log(lcDebug, IntToStr(RowsFound)+' rows found.');
|
Log(lcDebug, IntToStr(RowsFound)+' rows found.');
|
||||||
if not DoStoreResult then begin
|
|
||||||
|
if DoStoreResult then begin
|
||||||
|
SetLength(FLastResults, 1);
|
||||||
|
FLastResults[0] := Result;
|
||||||
|
end else begin
|
||||||
mysql_free_result(Result);
|
mysql_free_result(Result);
|
||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// No support for real multi results yet, throw them away, so mysql_ping() does not crash on the *next* query.
|
// No support for real multi results yet, throw them away, so mysql_ping() does not crash on the *next* query.
|
||||||
i := 1;
|
|
||||||
while mysql_next_result(FHandle) = 0 do begin
|
while mysql_next_result(FHandle) = 0 do begin
|
||||||
Inc(i);
|
|
||||||
Log(lcDebug, 'Storing and freeing result #'+IntToStr(i)+' from multiple result set ...');
|
|
||||||
NextResult := mysql_store_result(FHandle);
|
NextResult := mysql_store_result(FHandle);
|
||||||
if NextResult <> nil then
|
if NextResult <> nil then begin
|
||||||
mysql_free_result(NextResult);
|
if DoStoreResult then begin
|
||||||
|
SetLength(FLastResults, Length(FLastResults)+1);
|
||||||
|
FLastResults[Length(FLastResults)-1] := NextResult;
|
||||||
|
end else
|
||||||
|
mysql_free_result(NextResult);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
FResultCount := Length(FLastResults);
|
||||||
|
|
||||||
end else begin
|
end else begin
|
||||||
// Query did not return a result
|
// Query did not return a result
|
||||||
@ -699,6 +713,22 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TMySQLConnection.GetLastResults: TMySQLQueryList;
|
||||||
|
var
|
||||||
|
r: TMySQLQuery;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := TMySQLQueryList.Create(False);
|
||||||
|
for i:=Low(FLastResults) to High(FLastResults) do begin
|
||||||
|
r := TMySQLQuery.Create(nil);
|
||||||
|
r.Connection := Self;
|
||||||
|
r.SQL := FLastQuerySQL;
|
||||||
|
r.Execute(True, FLastResults[i]);
|
||||||
|
Result.Add(r);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{**
|
{**
|
||||||
Set "Database" property and select that db if connected
|
Set "Database" property and select that db if connected
|
||||||
}
|
}
|
||||||
@ -1604,7 +1634,6 @@ begin
|
|||||||
FColumnOrgNames := TStringList.Create;
|
FColumnOrgNames := TStringList.Create;
|
||||||
FColumnOrgNames.CaseSensitive := True;
|
FColumnOrgNames.CaseSensitive := True;
|
||||||
FStoreResult := True;
|
FStoreResult := True;
|
||||||
FLogCategory := lcSQL;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -1635,7 +1664,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TMySQLQuery.Execute(AddResult: Boolean=False);
|
procedure TMySQLQuery.Execute(AddResult: Boolean=False; Res: PMYSQL_RES=nil);
|
||||||
var
|
var
|
||||||
i, j, NumFields: Integer;
|
i, j, NumFields: Integer;
|
||||||
NumResults: Int64;
|
NumResults: Int64;
|
||||||
@ -1643,7 +1672,10 @@ var
|
|||||||
IsBinary: Boolean;
|
IsBinary: Boolean;
|
||||||
FLastResult: PMYSQL_RES;
|
FLastResult: PMYSQL_RES;
|
||||||
begin
|
begin
|
||||||
FLastResult := Connection.Query(FSQL, FStoreResult, FLogCategory);
|
if Res <> nil then
|
||||||
|
FLastResult := Res
|
||||||
|
else
|
||||||
|
FLastResult := Connection.Query(FSQL, FStoreResult);
|
||||||
if AddResult and (Length(FResultList) = 0) then
|
if AddResult and (Length(FResultList) = 0) then
|
||||||
AddResult := False;
|
AddResult := False;
|
||||||
if AddResult then
|
if AddResult then
|
||||||
|
Reference in New Issue
Block a user