From b1ab76e0ba67fe6acad8c233c9fc475f4d4c3612 Mon Sep 17 00:00:00 2001 From: Ansgar Becker Date: Wed, 14 Apr 2010 22:45:12 +0000 Subject: [PATCH] Display first available text column value when editing InnoDB contents. Fixes issue #1849. --- source/grideditlinks.pas | 24 ++++++++++++++---- source/main.pas | 55 +++++++++++++++++++++++++++++++--------- 2 files changed, 62 insertions(+), 17 deletions(-) diff --git a/source/grideditlinks.pas b/source/grideditlinks.pas index ae361dc5..f9c525bc 100644 --- a/source/grideditlinks.pas +++ b/source/grideditlinks.pas @@ -93,7 +93,7 @@ type private FCombo: TComboBox; public - ValueList: TStringList; + ValueList, DisplayList: TStringList; AllowCustomText: Boolean; constructor Create(Tree: TVirtualStringTree); override; destructor Destroy; override; @@ -707,6 +707,7 @@ begin FCombo.OnKeyDown := DoKeyDown; FCombo.OnExit := DoEndEdit; ValueList := TStringList.Create; + DisplayList := TStringList.Create; FMainControl := FCombo; end; @@ -729,26 +730,39 @@ end; function TEnumEditorLink.EndEdit: Boolean; stdcall; +var + NewText: String; begin - Result := EndEditHelper(FCombo.Text); + if AllowCustomText then + NewText := FCombo.Text + else if ValueList.Count > 0 then + NewText := ValueList[FCombo.ItemIndex] + else + NewText := ''; + Result := EndEditHelper(NewText); end; function TEnumEditorLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; stdcall; var i: Integer; + Items: TStringList; begin Result := inherited PrepareEdit(Tree, Node, Column); if Result then begin - for i := 0 to ValueList.Count - 1 do - FCombo.Items.Add(ValueList[i]); + if DisplayList.Count = ValueList.Count then + Items := DisplayList + else + Items := ValueList; + for i:=0 to Items.Count - 1 do + FCombo.Items.Add(Items[i]); if AllowCustomText then begin FCombo.Style := csDropDown; FCombo.Text := FCellText; end else begin // Set style to OwnerDraw, otherwise we wouldn't be able to adjust the combo's height FCombo.Style := csOwnerDrawFixed; - FCombo.ItemIndex := FCombo.Items.IndexOf(FCellText); + FCombo.ItemIndex := ValueList.IndexOf(FCellText); end; end; end; diff --git a/source/main.pas b/source/main.pas index 629941c2..3dbf29ab 100644 --- a/source/main.pas +++ b/source/main.pas @@ -7375,31 +7375,62 @@ var InplaceEditor: TInplaceEditorLink; TypeCat: TDatatypeCategoryIndex; ForeignKey: TForeignKey; + TblColumn: TTableColumn; idx: Integer; - Col: String; - ForeignValues: TStringList; + KeyCol, TextCol, SQL, CreateTable: String; + Columns: TTableColumnList; + Keys: TTableKeyList; + ForeignKeys: TForeignKeyList; + ForeignResults: TMySQLQuery; begin VT := Sender as TVirtualStringTree; // Find foreign key values on InnoDB table cells - ForeignValues := nil; for ForeignKey in SelectedTableForeignKeys do begin idx := ForeignKey.Columns.IndexOf(DataGrid.Header.Columns[Column].Text); if idx > -1 then begin - Col := Mask(ForeignKey.ForeignColumns[idx]); - ForeignValues := Connection.GetCol('SELECT '+Col+' FROM '+MaskMulti(ForeignKey.ReferenceTable)+' GROUP BY '+Col+' ORDER BY '+Col); + // Find the first text column if available and use that for displaying in the pulldown instead of using meaningless id numbers + CreateTable := Connection.GetVar('SHOW CREATE TABLE '+MaskMulti(ForeignKey.ReferenceTable), 1); + Columns := TTableColumnList.Create; + Keys := nil; + ForeignKeys := nil; + ParseTableStructure(CreateTable, Columns, Keys, ForeignKeys); + TextCol := ''; + for TblColumn in Columns do begin + if (TblColumn.DataType.Category = dtcText) and (TblColumn.Name <> ForeignKey.ForeignColumns[idx]) then begin + TextCol := TblColumn.Name; + break; + end; + end; + + KeyCol := Mask(ForeignKey.ForeignColumns[idx]); + SQL := 'SELECT '+KeyCol; + if TextCol <> '' then SQL := SQL + ', LEFT(' + Mask(TextCol) + ', 256)'; + SQL := SQL + ' FROM '+MaskMulti(ForeignKey.ReferenceTable)+' GROUP BY '+KeyCol+' ORDER BY '; + if TextCol <> '' then SQL := SQL + Mask(TextCol) else SQL := SQL + KeyCol; + SQL := SQL + ' LIMIT 1000'; + + EnumEditor := TEnumEditorLink.Create(VT); + EnumEditor.DataType := DataGridResult.Columns[Column].Datatype; + EditLink := EnumEditor; + if TextCol = '' then + EnumEditor.ValueList := Connection.GetCol(SQL) + else begin + ForeignResults := Connection.GetResults(SQL); + while not ForeignResults.Eof do begin + EnumEditor.ValueList.Add(ForeignResults.Col(0)); + EnumEditor.DisplayList.Add(ForeignResults.Col(0)+': '+ForeignResults.Col(1)); + ForeignResults.Next; + end; + end; break; end; end; TypeCat := DataGridResult.Columns[Column].DatatypeCat; - if Assigned(ForeignValues) then begin - EnumEditor := TEnumEditorLink.Create(VT); - EnumEditor.AllowCustomText := True; - EnumEditor.DataType := DataGridResult.Columns[Column].Datatype; - EnumEditor.ValueList := ForeignValues; - EditLink := EnumEditor; - end else if (TypeCat = dtcText) or ((TypeCat in [dtcBinary, dtcSpatial]) and actBlobAsText.Checked) then begin + if Assigned(EditLink) then + // Editor was created above, do nothing now + else if (TypeCat = dtcText) or ((TypeCat in [dtcBinary, dtcSpatial]) and actBlobAsText.Checked) then begin InplaceEditor := TInplaceEditorLink.Create(VT); InplaceEditor.DataType := DataGridResult.Columns[Column].Datatype; InplaceEditor.MaxLength := DataGridResult.Columns[Column].MaxLength;