From 767754f2d44bf93b874fc2b8c0b72abb491ab37a Mon Sep 17 00:00:00 2001 From: Ansgar Becker Date: Thu, 15 May 2025 20:06:37 +0200 Subject: [PATCH] Issue #2168: select rows from table to export by its primary key columns, so PostgreSQL does not apply a random sorting --- source/tabletools.pas | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/source/tabletools.pas b/source/tabletools.pas index a268364c..a02e2ed5 100644 --- a/source/tabletools.pas +++ b/source/tabletools.pas @@ -1757,10 +1757,12 @@ var Limit, Offset, ResultCount, MaxInsertSize: Int64; StartTime: QWord; StrucResult, Data: TDBQuery; - ColumnList: TTableColumnList; + ColumnList, KeyColumns: TTableColumnList; + KeyList: TTableKeyList; Column: TTableColumn; Quoter: TDBConnection; TargetFileName, SetCharsetCode: String; + OrderBy: String; const TempDelim = '//'; AssumedAvgRowLen = 10000; @@ -2041,6 +2043,18 @@ begin TargetDbAndObject := Quoter.QuoteIdent(FinalDbName) + '.' + TargetDbAndObject; Offset := 0; RowCount := 0; + // Sort by primary key if one exists, see issue #2168 + ColumnList := DBObj.TableColumns; + KeyList := DBObj.TableKeys; + KeyColumns := DBObj.Connection.GetKeyColumns(ColumnList, KeyList); + OrderBy := ''; + for i:=0 to KeyColumns.Count-1 do begin + if i>0 then + OrderBy := OrderBy + ', '; + OrderBy := OrderBy + DBObj.Connection.QuoteIdent(KeyColumns[i].Name); + end; + if not OrderBy.IsEmpty then + OrderBy := ' ORDER BY ' + OrderBy; // Calculate limit so we select ~100MB per loop // Take care of disabled "Get full table status" session setting, where AvgRowLen is 0 Limit := Round(100 * SIZE_MB / IfThen(DBObj.AvgRowLen>0, DBObj.AvgRowLen, AssumedAvgRowLen)); @@ -2053,7 +2067,7 @@ begin Data := DBObj.Connection.GetResults( DBObj.Connection.ApplyLimitClause( 'SELECT', - '* FROM '+DBObj.QuotedDbAndTableName, + '* FROM '+DBObj.QuotedDbAndTableName + OrderBy, Limit, Offset) );