diff --git a/.gitignore b/.gitignore index 16c8d23ce..6e26b109c 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,5 @@ __recovery *.mo *.po *.res -out/Backups/* \ No newline at end of file +out/Backups/* +out/* \ No newline at end of file diff --git a/source/main.dfm b/source/main.dfm index 7604805c3..4a8da3b68 100644 --- a/source/main.dfm +++ b/source/main.dfm @@ -2374,6 +2374,14 @@ object MainForm: TMainForm ImageName = 'icons8-close-button' OnExecute = actExitApplicationExecute end + object actFollowForeignKey: TAction + Category = 'Various' + Caption = 'Follow Foreign Key' + Enabled = False + Hint = 'Follow foreign key to the linked table' + ImageIndex = 61 + OnExecute = actFollowForeignKeyExecute + end object actCopy: TAction Category = 'Various' Caption = '&Copy' @@ -3916,6 +3924,9 @@ object MainForm: TMainForm object OpenURL1: TMenuItem Action = actDataOpenUrl end + object FollowForeignKey: TMenuItem + Action = actFollowForeignKey + end object N4a: TMenuItem Caption = '-' end diff --git a/source/main.pas b/source/main.pas index 3f3cbf8e4..cd416e0c9 100644 --- a/source/main.pas +++ b/source/main.pas @@ -190,6 +190,7 @@ TMainForm = class(TExtForm) MainMenuFile: TMenuItem; FileNewItem: TMenuItem; MainMenuHelp: TMenuItem; + FollowForeignKey: TMenuItem; N1: TMenuItem; FileExitItem: TMenuItem; menuAbout: TMenuItem; @@ -198,6 +199,7 @@ TMainForm = class(TExtForm) PasteItem: TMenuItem; StatusBar: TStatusBar; ActionList1: TActionList; + actFollowForeignKey: TAction; actCopy: TAction; actPaste: TAction; actNewWindow: TAction; @@ -954,6 +956,7 @@ TMainForm = class(TExtForm) procedure ListTablesInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates); procedure AnyGridAfterPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas); + procedure actFollowForeignKeyExecute(Sender: TObject); procedure actCopyOrCutExecute(Sender: TObject); procedure actPasteExecute(Sender: TObject); procedure actSelectAllExecute(Sender: TObject); @@ -7675,7 +7678,7 @@ procedure TMainForm.popupDataGridPopup(Sender: TObject); Grid: TVirtualStringTree; Results: TDBQuery; i: Integer; - Col, Value: String; + Col, Value, FocusedColumnName: String; CellFocused, InDataGrid, HasNullValue, HasNotNullValue: Boolean; RowNumber: PInt64; Node: PVirtualNode; @@ -7683,6 +7686,7 @@ procedure TMainForm.popupDataGridPopup(Sender: TObject); IncludedValues: TStringList; Act: TAction; Datatype: TDBDatatype; + ForeignKey: TForeignKey; const CLPBRD : String = 'CLIPBOARD'; begin @@ -7845,6 +7849,18 @@ procedure TMainForm.popupDataGridPopup(Sender: TObject); Act.Caption := StrEllipsis(Act.Hint, 100); end; + actFollowForeignKey.Enabled := False; + if (InDataGrid) then begin + FocusedColumnName := Results.ColumnOrgNames[Grid.FocusedColumn]; + //find foreign key for current column + for ForeignKey in ActiveDBObj.TableForeignKeys do begin + i := ForeignKey.Columns.IndexOf(FocusedColumnName); + if i > -1 then begin + actFollowForeignKey.Enabled := True; + break; + end; + end; + end; end; @@ -10321,7 +10337,6 @@ procedure TMainForm.AnyGridChange(Sender: TBaseVirtualTree; Node: PVirtualNode); UpdateLineCharPanel; end; - procedure TMainForm.AnyGridKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); var g: TVirtualStringTree; @@ -11252,6 +11267,64 @@ procedure TMainForm.HostListBeforeCellPaint(Sender: TBaseVirtualTree; TargetCanv end; +procedure TMainForm.actFollowForeignKeyExecute(Sender: TObject); +var + CurrentControl: TWinControl; + Grid: TVirtualStringTree; + Results: TDBQuery; + RowNum: PInt64; + FocusedValue, FocusedColumnName, ForeignColumnName, ReferenceTable: String; + ForeignKey: TForeignKey; + i: Integer; + PDBObj: PDBObject; + DBObj: TDBObject; + Node: PVirtualNode; + Datatype: TDBDatatype; +begin + CurrentControl := Screen.ActiveControl; + Grid := CurrentControl as TVirtualStringTree; + Results := GridResult(Grid); + RowNum := Grid.GetNodeData(Grid.FocusedNode); + Results.RecNo := RowNum^; + FocusedColumnName := Results.ColumnOrgNames[Grid.FocusedColumn]; + + //find foreign key for current column + for ForeignKey in ActiveDBObj.TableForeignKeys do begin + i := ForeignKey.Columns.IndexOf(FocusedColumnName); + if i > -1 then begin + ForeignColumnName := ForeignKey.ForeignColumns[i]; + ReferenceTable := ForeignKey.ReferenceTable; + break; + end; + end; + if ForeignColumnName = '' then begin + LogSQL(f_('Foreign key not found for column "%s"', [FocusedColumnName]), lcInfo); + exit; + end; + // jump to ReferenceTable + Node := GetNextNode(ListTables, nil); + while Assigned(Node) do begin + PDBObj := ListTables.GetNodeData(Node); + DBObj := PDBObj^; + if DBObj.Database + '.' + DBObj.Name = ReferenceTable then begin + ActiveDBObj := DBObj; + break; + end; + Node := GetNextNode(ListTables, Node); + end; + Datatype := Results.DataType(Grid.FocusedColumn); + FocusedValue := Results.Col(Grid.FocusedColumn); + // filter to show only rows linked by the foreign key + SynMemoFilter.UndoList.AddGroupBreak; + SynMemoFilter.Text := Results.Connection.QuoteIdent(ForeignColumnName, False) + '=' + Results.Connection.EscapeString(FocusedValue, Datatype); + ToggleFilterPanel(True); + actApplyFilter.Execute; + // SynMemoFilter will be cleared and set value of asFilter (in HandleDataGridAttributes from DataGridBeforePaint) + AppSettings.SessionPath := GetRegKeyTable; + AppSettings.WriteString(asFilter, SynMemoFilter.Text); +end; + + procedure TMainForm.actCopyOrCutExecute(Sender: TObject); var CurrentControl: TWinControl;