diff --git a/source/dbconnection.pas b/source/dbconnection.pas index 86a80ab3..2ecb8dd9 100644 --- a/source/dbconnection.pas +++ b/source/dbconnection.pas @@ -53,7 +53,11 @@ type property Connection: TDBConnection read FConnection; end; PTableColumn = ^TTableColumn; - TTableColumnList = TObjectList; + TTableColumnList = class(TObjectList) + 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; + TTableKeyList = class(TObjectList) + 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; + TForeignKeyList = class(TObjectList) + 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; + diff --git a/source/event_editor.pas b/source/event_editor.pas index 77207260..39196491 100644 --- a/source/event_editor.pas +++ b/source/event_editor.pas @@ -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); diff --git a/source/main.pas b/source/main.pas index d1c62f79..753bf603 100644 --- a/source/main.pas +++ b/source/main.pas @@ -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 diff --git a/source/routine_editor.pas b/source/routine_editor.pas index d43d9bc4..2b342ada 100644 --- a/source/routine_editor.pas +++ b/source/routine_editor.pas @@ -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; diff --git a/source/table_editor.pas b/source/table_editor.pas index 2fd74d80..821e9bf1 100644 --- a/source/table_editor.pas +++ b/source/table_editor.pas @@ -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; diff --git a/source/trigger_editor.pas b/source/trigger_editor.pas index 4b86d2d9..bd660618 100644 --- a/source/trigger_editor.pas +++ b/source/trigger_editor.pas @@ -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; diff --git a/source/view.pas b/source/view.pas index a8148fdc..ecc11d94 100644 --- a/source/view.pas +++ b/source/view.pas @@ -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;