Limit rows per exported INSERT to 1000 for MSSQL. Introduced MaxRowsPerInsert property per connection type. 10000 for all other types. Closes #1189

This commit is contained in:
Ansgar Becker
2020-12-17 11:43:29 +01:00
parent 5e675a51d8
commit 281a53b88a
3 changed files with 17 additions and 12 deletions

View File

@ -411,6 +411,7 @@ type
FForeignKeyQueriesFailed: Boolean;
FInfSch: String;
FIdentCharsNoQuote: TSysCharSet;
FMaxRowsPerInsert: Int64;
procedure SetActive(Value: Boolean); virtual; abstract;
procedure DoBeforeConnect; virtual;
procedure DoAfterConnect; virtual;
@ -529,6 +530,7 @@ type
function GetTableColumns(Table: TDBObject): TTableColumnList; virtual;
function GetTableKeys(Table: TDBObject): TTableKeyList; virtual;
function GetTableForeignKeys(Table: TDBObject): TForeignKeyList; virtual;
property MaxRowsPerInsert: Int64 read FMaxRowsPerInsert;
published
property Active: Boolean read FActive write SetActive default False;
property Database: String read FDatabase write SetDatabase;
@ -1772,6 +1774,7 @@ begin
FInformationSchemaObjects.CaseSensitive := False;
// Characters in identifiers which don't need to be quoted
FIdentCharsNoQuote := ['A'..'Z', 'a'..'z', '0'..'9', '_'];
FMaxRowsPerInsert := 10000;
end;
@ -1802,6 +1805,7 @@ begin
for i:=0 to High(MSSQLDatatypes) do
FDatatypes[i] := MSSQLDatatypes[i];
FInfSch := 'INFORMATION_SCHEMA';
FMaxRowsPerInsert := 1000;
end;

View File

@ -454,8 +454,6 @@ var
IsEncl, IsTerm, IsLineTerm, IsEof: Boolean;
InEncl: Boolean;
OutStream: TMemoryStream;
const
MaxRowCountPerChunk = 1000;
procedure NextChar;
begin
@ -552,7 +550,7 @@ const
StreamWrite(OutStream, SQL + ')');
SQL := '';
Inc(RowCountInChunk);
if (OutStream.Size < PacketSize) and (P < ContentLen) and (RowCountInChunk < MaxRowCountPerChunk) then begin
if (OutStream.Size < PacketSize) and (P < ContentLen) and (RowCountInChunk < FConnection.MaxRowsPerInsert) then begin
SQL := SQL + ', (';
end else begin
OutStream.Position := 0;

View File

@ -1440,10 +1440,12 @@ end;
procedure TfrmTableTools.DoExport(DBObj: TDBObject);
var
IsFirstRowInChunk, NeedsDBStructure: Boolean;
NeedsDBStructure: Boolean;
InsertSizeExceeded, RowLimitExceeded: Boolean;
Struc, Header, DbDir, FinalDbName, BaseInsert, Row, TargetDbAndObject, BinContent, tmp: String;
i: Integer;
RowCount, Limit, Offset, ResultCount: Int64;
RowCount, RowCountInChunk: Int64;
Limit, Offset, ResultCount: Int64;
StartTime: Cardinal;
StrucResult, Data: TDBQuery;
ColumnList: TTableColumnList;
@ -1735,11 +1737,11 @@ begin
BaseInsert := BaseInsert + ') VALUES'+CRLF+#9+'(';
while true do begin
Output(BaseInsert, False, True, True, True, True);
IsFirstRowInChunk := True;
RowCountInChunk := 0;
while not Data.Eof do begin
Row := '';
if not IsFirstRowInChunk then
if RowCountInChunk > 0 then
Row := Row + ','+CRLF+#9+'(';
for i:=0 to Data.ColumnCount-1 do begin
if Data.ColIsVirtual(i) then
@ -1767,12 +1769,13 @@ begin
Delete(Row, Length(Row)-1, 2);
Row := Row + ')';
// Break if stream would increase over the barrier of 1MB, and throw away current row
if (not IsFirstRowInChunk)
and (ExportStream.Size - ExportStreamStartOfQueryPos + Length(Row) > updownInsertSize.Position*SIZE_KB*0.9)
then
break;
InsertSizeExceeded := ExportStream.Size - ExportStreamStartOfQueryPos + Length(Row) > updownInsertSize.Position*SIZE_KB*0.9;
// Same with MSSQL which is limited to 1000 rows per INSERT
RowLimitExceeded := RowCountInChunk >= Quoter.MaxRowsPerInsert;
if (RowCountInChunk > 0) and (InsertSizeExceeded or RowLimitExceeded) then
Break;
Inc(RowCount);
IsFirstRowInChunk := False;
Inc(RowCountInChunk);
Output(Row, False, True, True, True, True);
Data.Next;
end;