Issue #852: Implement Assign method on TTableColumnList and friends, TDBObject.LoadDetails and .UnloadDetails, and cross fingers that assigning details to Mainform.FActiveDbObj reduces the number of internal queries

This commit is contained in:
Ansgar Becker
2020-01-16 07:40:30 +01:00
parent 94cd1d84ed
commit 1c39075d7c
7 changed files with 121 additions and 51 deletions

View File

@@ -53,7 +53,11 @@ type
property Connection: TDBConnection read FConnection;
end;
PTableColumn = ^TTableColumn;
TTableColumnList = TObjectList<TTableColumn>;
TTableColumnList = class(TObjectList<TTableColumn>)
public
Loaded: Boolean;
procedure Assign(Source: TTableColumnList);
end;
TTableKey = class(TPersistent)
private
@@ -71,7 +75,11 @@ type
function SQLCode: String;
property ImageIndex: Integer read GetImageIndex;
end;
TTableKeyList = TObjectList<TTableKey>;
TTableKeyList = class(TObjectList<TTableKey>)
public
Loaded: Boolean;
procedure Assign(Source: TTableKeyList);
end;
// Helper object to manage foreign keys in a TObjectList
TForeignKey = class(TPersistent)
@@ -86,7 +94,11 @@ type
procedure Assign(Source: TPersistent); override;
function SQLCode(IncludeSymbolName: Boolean): String;
end;
TForeignKeyList = TObjectList<TForeignKey>;
TForeignKeyList = class(TObjectList<TForeignKey>)
public
Loaded: Boolean;
procedure Assign(Source: TForeignKeyList);
end;
TRoutineParam = class(TObject)
public
@@ -97,7 +109,7 @@ type
TDBObject = class(TPersistent)
private
FCreateCode: String;
FCreateCodeFetched: Boolean;
FCreateCodeLoaded: Boolean;
FWasSelected: Boolean;
FConnection: TDBConnection;
FTableColumns: TTableColumnList;
@@ -107,7 +119,6 @@ type
function GetImageIndex: Integer;
function GetOverlayImageIndex: Integer;
function GetPath: String;
procedure SetCreateCode(Value: String);
function GetTableColumns: TTableColumnList;
function GetTableKeys: TTableKeyList;
function GetTableForeignKeys: TForeignKeyList;
@@ -123,6 +134,8 @@ type
NodeType, GroupType: TListNodeType;
constructor Create(OwnerConnection: TDBConnection);
procedure Assign(Source: TPersistent); override;
procedure LoadDetails;
procedure UnloadDetails;
procedure Drop;
function IsSameAs(CompareTo: TDBObject): Boolean;
function QuotedDatabase(AlwaysQuote: Boolean=True): String;
@@ -136,7 +149,7 @@ type
property ImageIndex: Integer read GetImageIndex;
property OverlayImageIndex: Integer read GetOverlayImageIndex;
property Path: String read GetPath;
property CreateCode: String read GetCreateCode write SetCreateCode;
property CreateCode: String read GetCreateCode;
property WasSelected: Boolean read FWasSelected write FWasSelected;
property Connection: TDBConnection read FConnection;
property TableColumns: TTableColumnList read GetTableColumns;
@@ -4748,6 +4761,7 @@ begin
end;
KeyQuery.Next;
end;
KeyQuery.Free;
end;
@@ -4780,6 +4794,7 @@ begin
NewKey.SubParts.Add(KeyQuery.Col('Sub_part'));
KeyQuery.Next;
end;
KeyQuery.Free;
end;
@@ -8398,8 +8413,14 @@ begin
CheckSum := -1;
CreateOptions := '';
FCreateCode := '';
FCreateCodeFetched := False;
FCreateCodeLoaded := False;
FConnection := OwnerConnection;
FTableColumns := TTableColumnList.Create;
FTableColumns.Loaded := False;
FTableKeys := TTableKeyList.Create;
FTableKeys.Loaded := False;
FTableForeignKeys := TForeignKeyList.Create;
FTableForeignKeys.Loaded := False;
end;
@@ -8424,16 +8445,52 @@ begin
Size := s.Size;
ArgTypes := s.ArgTypes;
FCreateCode := s.FCreateCode;
FCreateCodeFetched := s.FCreateCodeFetched;
// This is wrong - need to be copy-assigned
FTableColumns := s.FTableColumns;
FTableKeys := s.FTableKeys;
FTableForeignKeys := s.FTableForeignKeys;
FCreateCodeLoaded := s.FCreateCodeLoaded;
FTableColumns.Assign(s.FTableColumns);
FTableKeys.Assign(s.FTableKeys);
FTableForeignKeys.Assign(s.FTableForeignKeys);
end else
inherited;
end;
procedure TDBObject.LoadDetails;
var
t: TTableColumnList;
k: TTableKeyList;
f: TForeignKeyList;
begin
case NodeType of
lntTable: begin
// Load columns and keys, so later assigned copies of this object have them too
t := GetTableColumns;
t.Free;
k := GetTableKeys;
k.Free;
f := GetTableForeignKeys;
f.Free;
GetCreateCode;
end;
else begin
GetCreateCode;
end;
end;
end;
procedure TDBObject.UnloadDetails;
begin
FTableColumns.Clear;
FTableColumns.Loaded := False;
FTableKeys.Clear;
FTableKeys.Loaded := False;
FTableForeignKeys.Clear;
FTableForeignKeys.Loaded := False;
FCreateCode := '';
FCreateCodeLoaded := False;
end;
function TDBObject.IsSameAs(CompareTo: TDBObject): Boolean;
begin
if (not Assigned(CompareTo)) or (CompareTo = nil) then begin
@@ -8545,8 +8602,9 @@ end;
function TDBObject.GetCreateCode: String;
begin
if not FCreateCodeFetched then try
CreateCode := Connection.GetCreateCode(Self);
if not FCreateCodeLoaded then try
FCreateCode := Connection.GetCreateCode(Self);
FCreateCodeLoaded := True;
except on E:Exception do
Connection.Log(lcError, E.Message);
end;
@@ -8583,13 +8641,6 @@ begin
end;
procedure TDBObject.SetCreateCode(Value: String);
begin
// When manually clearing CreateCode from outside, also reset indicator for fetch attempt
FCreateCode := Value;
FCreateCodeFetched := Value <> '';
end;
function TDBObject.QuotedDatabase(AlwaysQuote: Boolean=True): String;
begin
if FConnection.Parameters.NetTypeGroup = ngPgSQL then
@@ -8641,51 +8692,36 @@ end;
function TDBObject.GetTableColumns: TTableColumnList;
var
Col, ColCopy: TTableColumn;
begin
// Return columns from table object
if not Assigned(FTableColumns) then begin
if not FTableColumns.Loaded then begin
FTableColumns := Connection.GetTableColumns(Self);
FTableColumns.Loaded := True;
end;
Result := TTableColumnList.Create;
for Col in FTableColumns do begin
ColCopy := TTableColumn.Create(Col.FConnection);
ColCopy.Assign(Col);
Result.Add(ColCopy);
end;
Result.Assign(FTableColumns);
end;
function TDBObject.GetTableKeys: TTableKeyList;
var
Key, KeyCopy: TTableKey;
begin
// Return keys from table object
if not Assigned(FTableKeys) then begin
if not FTableKeys.Loaded then begin
FTableKeys := Connection.GetTableKeys(Self);
FTableKeys.Loaded := True;
end;
Result := TTableKeyList.Create;
for Key in FTableKeys do begin
KeyCopy := TTableKey.Create(Key.FConnection);
KeyCopy.Assign(Key);
Result.Add(KeyCopy);
end;
Result.Assign(FTableKeys);
end;
function TDBObject.GetTableForeignKeys: TForeignKeyList;
var
Key, KeyCopy: TForeignKey;
begin
// Return foreign keys from table object
if not Assigned(FTableForeignKeys) then begin
if not FTableForeignKeys.Loaded then begin
FTableForeignKeys := Connection.GetTableForeignKeys(Self);
FTableForeignKeys.Loaded := True;
end;
Result := TForeignKeyList.Create;
for Key in FTableForeignKeys do begin
KeyCopy := TForeignKey.Create(Key.FConnection);
KeyCopy.Assign(Key);
Result.Add(KeyCopy);
end;
Result.Assign(FTableForeignKeys);
end;
@@ -8893,6 +8929,17 @@ begin
end;
end;
procedure TTableColumnList.Assign(Source: TTableColumnList);
var
Item, ItemCopy: TTableColumn;
begin
for Item in Source do begin
ItemCopy := TTableColumn.Create(Item.FConnection);
ItemCopy.Assign(Item);
Add(ItemCopy);
end;
end;
{ *** TTableKey }
@@ -8982,6 +9029,17 @@ begin
Result := Result + ' USING ' + Algorithm;
end;
procedure TTableKeyList.Assign(Source: TTableKeyList);
var
Item, ItemCopy: TTableKey;
begin
for Item in Source do begin
ItemCopy := TTableKey.Create(Item.FConnection);
ItemCopy.Assign(Item);
Add(ItemCopy);
end;
end;
@@ -9045,6 +9103,17 @@ begin
Result := Result + ' ON DELETE ' + OnDelete;
end;
procedure TForeignKeyList.Assign(Source: TForeignKeyList);
var
Item, ItemCopy: TForeignKey;
begin
for Item in Source do begin
ItemCopy := TForeignKey.Create(Item.FConnection);
ItemCopy.Assign(Item);
Add(ItemCopy);
end;
end;

View File

@@ -236,7 +236,7 @@ begin
try
MainForm.ActiveConnection.Query(sql);
DBObject.Name := editName.Text;
DBObject.CreateCode := '';
DBObject.UnloadDetails;
tabALTERcode.TabVisible := DBObject.Name <> '';
Mainform.UpdateEditorTab;
Mainform.RefreshTree(DBObject);

View File

@@ -6290,7 +6290,7 @@ begin
end;
// Update nodedata
Obj.Name := NewText;
Obj.CreateCode := '';
Obj.UnloadDetails;
// Now the active tree db has to be updated. But calling RefreshTreeDB here causes an AV
// so we do it manually here
DBTree.InvalidateChildren(FindDBNode(DBtree, Obj.Connection, Obj.Database), True);
@@ -8566,6 +8566,7 @@ begin
DBObj := Sender.GetNodeData(Node);
DBObj.WasSelected := True;
DBObj.LoadDetails;
FActiveDbObj := TDBObject.Create(DBObj.Connection);
FActiveDbObj.Assign(DBObj^);
if Assigned(Node.Parent) then

View File

@@ -513,7 +513,7 @@ begin
DBObject.Connection.Query(ComposeCreateStatement(editName.Text));
// Set editing name if create/alter query was successful
DBObject.Name := editName.Text;
DBObject.CreateCode := '';
DBObject.UnloadDetails;
FAlterRoutineType := ProcOrFunc;
if FAlterRoutineType = 'PROCEDURE' then DBObject.NodeType := lntProcedure
else DBObject.NodeType := lntFunction;

View File

@@ -435,7 +435,7 @@ begin
end;
// Set table name for altering if Apply was clicked
DBObject.Name := editName.Text;
DBObject.CreateCode := '';
DBObject.UnloadDetails;
tabALTERcode.TabVisible := DBObject.Name <> '';
Mainform.UpdateEditorTab;
MainForm.tabData.TabVisible := True;

View File

@@ -234,7 +234,7 @@ begin
end;
MainForm.ActiveConnection.Query(ComposeCreateStatement);
DBObject.Name := editName.Text;
DBObject.CreateCode := '';
DBObject.UnloadDetails;
Mainform.UpdateEditorTab;
Mainform.RefreshTree(DBObject);
Modified := False;

View File

@@ -189,7 +189,7 @@ begin
DBObject.Connection.Query('RENAME TABLE '+viewname + ' TO '+renamed);
end;
DBObject.Name := editName.Text;
DBObject.CreateCode := '';
DBObject.UnloadDetails;
Mainform.UpdateEditorTab;
Mainform.RefreshTree(DBObject);
Modified := False;