Revert a144466e7137f1c33c39c231dbeb4cd98dfc4ffa : query exact row count from tables and views. See https://www.heidisql.com/forum.php?t=37983

This commit is contained in:
Ansgar Becker
2021-06-10 07:42:50 +02:00
parent 19677fa7f0
commit 28d25e3334
3 changed files with 70 additions and 24 deletions

View File

@ -250,7 +250,7 @@ begin
nColumns: CellText := _('Columns');
nKeys: CellText := _('Indexes');
nForeignKeys: CellText := _('Foreign keys');
nData: CellText := f_('Data (%s rows)', [FormatNumber(FDBObj.RowCount)]);
nData: CellText := f_('Data (%s rows)', [FormatNumber(FDBObj.RowCount(False))]);
else raise Exception.Create(_(SUnhandledNodeIndex));
end;
if Node.Index <> nData then begin
@ -310,7 +310,7 @@ begin
end;
if ChildCount > 0 then
Include(InitialStates, ivsHasChildren);
if (ChildCount = 0) or ((Node.Index = nData) and (FDBObj.RowCount <= 0)) then
if (ChildCount = 0) or ((Node.Index = nData) and (FDBObj.RowCount(False) = 0)) then
Node.States := Node.States + [vsDisabled]
else if AppSettings.ReadBool(Option) then
Node.CheckState := csCheckedNormal;

View File

@ -144,7 +144,6 @@ type
FCreateCodeLoaded: Boolean;
FWasSelected: Boolean;
FConnection: TDBConnection;
FRowCount: Int64;
function GetObjType: String;
function GetImageIndex: Integer;
function GetOverlayImageIndex: Integer;
@ -173,7 +172,7 @@ type
function QuotedDbAndTableName(AlwaysQuote: Boolean=True): String;
function QuotedColumn(AlwaysQuote: Boolean=True): String;
function SchemaClauseIS(Prefix: String): String;
function RowCount(Reload: Boolean=False): Int64;
function RowCount(Reload: Boolean): Int64;
function GetCreateCode: String; overload;
function GetCreateCode(RemoveAutoInc, RemoveDefiner: Boolean): String; overload;
property ObjType: String read GetObjType;
@ -469,7 +468,7 @@ type
function GetCurrentUserHostCombination: String;
function GetAllUserHostCombinations: TStringList;
function DecodeAPIString(a: AnsiString): String;
function GetRowCount(Obj: TDBObject): Int64;
function GetRowCount(Obj: TDBObject): Int64; virtual; abstract;
procedure ClearCache(IncludeDBObjects: Boolean);
procedure FetchDbObjects(db: String; var Cache: TDBObjectList); virtual; abstract;
procedure SetLockedByThread(Value: TThread); virtual;
@ -605,6 +604,7 @@ type
function GetCollationTable: TDBQuery; override;
function GetCharsetTable: TDBQuery; override;
function GetCreateViewCode(Database, Name: String): String;
function GetRowCount(Obj: TDBObject): Int64; override;
procedure FetchDbObjects(db: String; var Cache: TDBObjectList); override;
procedure SetLockedByThread(Value: TThread); override;
public
@ -636,6 +636,7 @@ type
function GetAllDatabases: TStringList; override;
function GetCollationTable: TDBQuery; override;
function GetCharsetTable: TDBQuery; override;
function GetRowCount(Obj: TDBObject): Int64; override;
procedure FetchDbObjects(db: String; var Cache: TDBObjectList); override;
public
constructor Create(AOwner: TComponent); override;
@ -675,6 +676,7 @@ type
procedure Query(SQL: String; DoStoreResult: Boolean=False; LogCategory: TDBLogCategory=lcSQL); override;
function Ping(Reconnect: Boolean): Boolean; override;
function ConnectionInfo: TStringList; override;
function GetRowCount(Obj: TDBObject): Int64; override;
property LastRawResults: TPGRawResults read FLastRawResults;
property RegClasses: TOidStringPairs read FRegClasses;
function GetTableColumns(Table: TDBObject): TTableColumnList; override;
@ -713,6 +715,7 @@ type
procedure Query(SQL: String; DoStoreResult: Boolean=False; LogCategory: TDBLogCategory=lcSQL); override;
function Ping(Reconnect: Boolean): Boolean; override;
function GetCreateCode(Obj: TDBObject): String; override;
function GetRowCount(Obj: TDBObject): Int64; override;
property LastRawResults: TSQLiteRawResults read FLastRawResults;
function GetTableColumns(Table: TDBObject): TTableColumnList; override;
function GetTableKeys(Table: TDBObject): TTableKeyList; override;
@ -5716,19 +5719,63 @@ begin
end;
function TDBConnection.GetRowCount(Obj: TDBObject): Int64;
function TMySQLConnection.GetRowCount(Obj: TDBObject): Int64;
var
Rows: String;
begin
// Get row number from a mysql table
if Parameters.IsProxySQLAdmin then
Rows := GetVar('SELECT COUNT(*) FROM '+QuoteIdent(Obj.Database)+'.'+QuoteIdent(Obj.Name), 0)
else
Rows := GetVar('SHOW TABLE STATUS LIKE '+EscapeString(Obj.Name), 'Rows');
Result := MakeInt(Rows);
end;
function TAdoDBConnection.GetRowCount(Obj: TDBObject): Int64;
var
Rows: String;
begin
// Get row number from a mssql table
if ServerVersionInt >= 900 then begin
Rows := GetVar('SELECT SUM('+QuoteIdent('rows')+') FROM '+QuoteIdent('sys')+'.'+QuoteIdent('partitions')+
' WHERE '+QuoteIdent('index_id')+' IN (0, 1)'+
' AND '+QuoteIdent('object_id')+' = object_id('+EscapeString(Obj.Database+'.'+Obj.Schema+'.'+Obj.Name)+')'
);
end else begin
Rows := GetVar('SELECT COUNT(*) FROM '+Obj.QuotedDbAndTableName);
end;
Result := MakeInt(Rows);
end;
function TPgConnection.GetRowCount(Obj: TDBObject): Int64;
var
Rows: String;
begin
// Get row number from a postgres table
Rows := GetVar('SELECT '+QuoteIdent('reltuples')+'::bigint FROM '+QuoteIdent('pg_class')+
' LEFT JOIN '+QuoteIdent('pg_namespace')+
' ON ('+QuoteIdent('pg_namespace')+'.'+QuoteIdent('oid')+' = '+QuoteIdent('pg_class')+'.'+QuoteIdent('relnamespace')+')'+
' WHERE '+QuoteIdent('pg_class')+'.'+QuoteIdent('relkind')+'='+EscapeString('r')+
' AND '+QuoteIdent('pg_namespace')+'.'+QuoteIdent('nspname')+'='+EscapeString(Obj.Database)+
' AND '+QuoteIdent('pg_class')+'.'+QuoteIdent('relname')+'='+EscapeString(Obj.Name)
);
Result := MakeInt(Rows);
end;
function TSQLiteConnection.GetRowCount(Obj: TDBObject): Int64;
var
Rows: String;
begin
// Get row number from a table
if Obj.NodeType in [lntView, lntTable] then
Rows := GetVar('SELECT COUNT(*) FROM ' + Obj.QuotedDbAndTableName, 0)
else
Rows := '';
Rows := GetVar('SELECT COUNT(*) FROM '+QuoteIdent(Obj.Database)+'.'+QuoteIdent(Obj.Name), 0);
Result := MakeInt(Rows);
end;
procedure TDBConnection.Drop(Obj: TDBObject);
begin
Query('DROP '+UpperCase(Obj.ObjType)+' '+Obj.QuotedName);
@ -8757,7 +8804,6 @@ begin
Database := '';
Schema := '';
Rows := -1;
FRowCount := -1;
Size := -1;
Created := 0;
Updated := 0;
@ -8799,7 +8845,6 @@ begin
Updated := s.Updated;
Comment := s.Comment;
Rows := s.Rows;
FRowCount := s.FRowCount;
Size := s.Size;
ArgTypes := s.ArgTypes;
FCreateCode := s.FCreateCode;
@ -9030,13 +9075,12 @@ begin
Result := Connection.GetSQLSpecifity(spISSchemaCol, [Prefix]) + '=' + Connection.EscapeString(Database);
end;
function TDBObject.RowCount(Reload: Boolean=False): Int64;
function TDBObject.RowCount(Reload: Boolean): Int64;
begin
if (FRowCount = -1) or Reload then begin
if NodeType in [lntTable, lntView] then
FRowCount := Connection.GetRowCount(Self);
if (Rows = -1) or Reload then begin
Rows := Connection.GetRowCount(Self);
end;
Result := FRowCount;
Result := Rows;
end;
procedure TDBObject.Drop;

View File

@ -994,15 +994,15 @@ begin
case DBObj.Connection.Parameters.NetTypeGroup of
ngMySQL, ngPgSQL:
SQL := 'SELECT '''+DBObj.Database+''' AS '+DBObj.Connection.QuoteIdent('Database')+', '''+DBObj.Name+''' AS '+DBObj.Connection.QuoteIdent('Table')+', COUNT(*) AS '+DBObj.Connection.QuoteIdent('Found rows')+', '
+ 'CONCAT(ROUND(100 / '+IntToStr(Max(DBObj.RowCount,1))+' * COUNT(*), 1), ''%'') AS '+DBObj.Connection.QuoteIdent('Relevance')+' FROM '+DBObj.QuotedDatabase+'.'+DBObj.QuotedName+' WHERE '
+ 'CONCAT(ROUND(100 / '+IntToStr(Max(DBObj.Rows,1))+' * COUNT(*), 1), ''%'') AS '+DBObj.Connection.QuoteIdent('Relevance')+' FROM '+DBObj.QuotedDatabase+'.'+DBObj.QuotedName+' WHERE '
+ SQL;
ngMSSQL:
SQL := 'SELECT '''+DBObj.Database+''' AS '+DBObj.Connection.QuoteIdent('Database')+', '''+DBObj.Name+''' AS '+DBObj.Connection.QuoteIdent('Table')+', COUNT(*) AS '+DBObj.Connection.QuoteIdent('Found rows')+', '
+ 'CONVERT(VARCHAR(10), ROUND(100 / '+IntToStr(Max(DBObj.RowCount,1))+' * COUNT(*), 1)) + ''%'' AS '+DBObj.Connection.QuoteIdent('Relevance')+' FROM '+DBObj.QuotedDatabase+'.'+DBObj.QuotedName+' WHERE '
+ 'CONVERT(VARCHAR(10), ROUND(100 / '+IntToStr(Max(DBObj.Rows,1))+' * COUNT(*), 1)) + ''%'' AS '+DBObj.Connection.QuoteIdent('Relevance')+' FROM '+DBObj.QuotedDatabase+'.'+DBObj.QuotedName+' WHERE '
+ SQL;
ngSQLite:
SQL := 'SELECT '''+DBObj.Database+''' AS '+DBObj.Connection.QuoteIdent('Database')+', '''+DBObj.Name+''' AS '+DBObj.Connection.QuoteIdent('Table')+', COUNT(*) AS '+DBObj.Connection.QuoteIdent('Found rows')+', '
+ '(ROUND(100 / '+IntToStr(Max(DBObj.RowCount,1))+' * COUNT(*), 1) || ''%'') AS '+DBObj.Connection.QuoteIdent('Relevance')+' FROM '+DBObj.QuotedDatabase+'.'+DBObj.QuotedName+' WHERE '
+ '(ROUND(100 / '+IntToStr(Max(DBObj.Rows,1))+' * COUNT(*), 1) || ''%'') AS '+DBObj.Connection.QuoteIdent('Relevance')+' FROM '+DBObj.QuotedDatabase+'.'+DBObj.QuotedName+' WHERE '
+ SQL;
end;
AddResults(SQL, DBObj.Connection);
@ -1474,9 +1474,9 @@ const
BytesDone: Int64;
begin
LogRow := FResults.Last;
Percent := 100 / Max(DBObj.RowCount,1) * Max(RowsDone,1);
Percent := 100 / Max(DBObj.Rows,1) * Max(RowsDone,1);
Percent := Min(Percent, 100);
BytesDone := Max(DBObj.Size,0) div Max(DBObj.RowCount,1) * RowsDone;
BytesDone := Max(DBObj.Size,0) div Max(DBObj.Rows,1) * RowsDone;
FObjectSizesDoneExact := FObjectSizesDone + BytesDone;
LogRow[2] := FormatNumber(RowsDone) + ' / ' + FormatNumber(Percent, 0)+'%';
LogRow[3] := FormatTimeNumber((GetTickCount-StartTime) / 1000, True);
@ -1487,7 +1487,7 @@ begin
// Handle one table, view or whatever in SQL export mode
AddResults('SELECT '+DBObj.Connection.EscapeString(DBObj.Database)+' AS '+DBObj.Connection.QuoteIdent('Database')+', ' +
DBObj.Connection.EscapeString(DBObj.Name)+' AS '+DBObj.Connection.QuoteIdent('Table')+', ' +
IntToStr(DBObj.RowCount)+' AS '+DBObj.Connection.QuoteIdent('Rows')+', '+
IntToStr(DBObj.Rows)+' AS '+DBObj.Connection.QuoteIdent('Rows')+', '+
'0 AS '+DBObj.Connection.QuoteIdent('Duration')
, DBObj.Connection
);
@ -1712,7 +1712,9 @@ begin
if menuExportAddComments.Checked then
Output('-- '+f_('Table data not exported because this is %s table which holds its data in separate tables.', [DBObj.Engine])+CRLF+CRLF, False, True, True, False, False);
end else begin
tmp := FormatNumber(DBObj.RowCount)+' rows';
tmp := FormatNumber(DBObj.Rows)+' rows';
if LowerCase(DBObj.Engine) = 'innodb' then
tmp := '~'+tmp+' ('+_('approximately')+')';
if menuExportAddComments.Checked then
Output('-- '+f_('Dumping data for table %s.%s: %s', [DBObj.Database, DBObj.Name, tmp])+CRLF, False, True, True, False, False);
TargetDbAndObject := Quoter.QuoteIdent(DBObj.Name);