diff --git a/source/dbconnection.pas b/source/dbconnection.pas index 763b15d9..c7bc8db0 100644 --- a/source/dbconnection.pas +++ b/source/dbconnection.pas @@ -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; diff --git a/source/loaddata.pas b/source/loaddata.pas index 0f7fefef..23441a45 100644 --- a/source/loaddata.pas +++ b/source/loaddata.pas @@ -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; diff --git a/source/tabletools.pas b/source/tabletools.pas index 63f4296d..a3eda3dd 100644 --- a/source/tabletools.pas +++ b/source/tabletools.pas @@ -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;