From a7eedd3823280288151e7cfd53ef553fe91dd007 Mon Sep 17 00:00:00 2001 From: Ansgar Becker Date: Sat, 5 Sep 2009 09:30:49 +0000 Subject: [PATCH] Table editor, "Add column" action: Pointer to added TColumn object was mixed up with an existing column. ALTER code also needs to follow the order of tree nodes. Fixes issue #1340 . --- source/helpers.pas | 13 ++++- source/table_editor.pas | 126 +++++++++++++++++++--------------------- 2 files changed, 72 insertions(+), 67 deletions(-) diff --git a/source/helpers.pas b/source/helpers.pas index 2ba1d04c..13d21d14 100644 --- a/source/helpers.pas +++ b/source/helpers.pas @@ -192,7 +192,8 @@ type function CompareNumbers(List: TStringList; Index1, Index2: Integer): Integer; function ListIndexByRegExpr(List: TWideStrings; Expression: WideString): Integer; procedure RestoreSyneditStyles(Highlighter: TSynCustomHighlighter); - procedure SelectNode(VT: TVirtualStringTree; idx: Cardinal; ParentNode: PVirtualNode=nil); + procedure SelectNode(VT: TVirtualStringTree; idx: Cardinal; ParentNode: PVirtualNode=nil); overload; + procedure SelectNode(VT: TVirtualStringTree; Node: PVirtualNode); overload; function DateBackFriendlyCaption(d: TDateTime): String; procedure InheritFont(AFont: TFont); var @@ -2990,7 +2991,7 @@ begin end; -procedure SelectNode(VT: TVirtualStringTree; idx: Cardinal; ParentNode: PVirtualNode=nil); +procedure SelectNode(VT: TVirtualStringTree; idx: Cardinal; ParentNode: PVirtualNode=nil); overload; var Node: PVirtualNode; begin @@ -3010,6 +3011,14 @@ begin end; +procedure SelectNode(VT: TVirtualStringTree; Node: PVirtualNode); overload; +begin + VT.ClearSelection; + VT.FocusedNode := Node; + VT.Selected[Node] := True; +end; + + function DateBackFriendlyCaption(d: TDateTime): String; var MonthsAgo, DaysAgo, HoursAgo, MinutesAgo: Int64; diff --git a/source/table_editor.pas b/source/table_editor.pas index 8aecdd58..e8ab117d 100644 --- a/source/table_editor.pas +++ b/source/table_editor.pas @@ -642,8 +642,9 @@ var DropIt: Boolean; ds: TDataset; Key: TForeignKey; - Col: TColumn; - Node, PreviousNode: PVirtualNode; + Col, PreviousCol: PColumn; + ColObj: TColumn; + Node: PVirtualNode; begin // Compose ALTER query, called by buttons and for SQL code tab Mainform.showstatus('Composing ALTER statement ...'); @@ -684,66 +685,61 @@ begin // Update columns EnableProgressBar(FColumns.Count + OldIndexes.Count + Indexes.Count); - for i:=0 to FColumns.Count - 1 do begin + Node := listColumns.GetFirst; + PreviousCol := nil; + while Assigned(Node) do begin Mainform.ProgressBarStatus.StepIt; - Col := FColumns[i] as TColumn; - case Col.Status of - esUntouched, esAddedDeleted: Continue; - esDeleted: begin - // Delete columns + Col := listColumns.GetNodeData(Node); + if Col.Status <> esUntouched then begin + ColSpec := Mainform.mask(Col.Name); + ColSpec := ColSpec + ' ' + Col.DataType.Name; + if Col.LengthSet <> '' then + ColSpec := ColSpec + '(' + Col.LengthSet + ')'; + if Col.DataType.HasUnsigned and Col.Unsigned then + ColSpec := ColSpec + ' UNSIGNED'; + if not Col.AllowNull then + ColSpec := ColSpec + ' NOT'; + ColSpec := ColSpec + ' NULL'; + if Col.DefaultType <> cdtNothing then begin + ColSpec := ColSpec + ' ' + GetColumnDefaultClause(Col.DefaultType, Col.DefaultText); + ColSpec := TrimRight(ColSpec); // Remove whitespace for columns without default value + end; + if Col.Comment <> '' then + ColSpec := ColSpec + ' COMMENT '+esc(Col.Comment); + if Col.Collation <> '' then begin + ColSpec := ColSpec + ' COLLATE '; + if chkCharsetConvert.Checked then + ColSpec := ColSpec + comboCollation.Text + else + ColSpec := ColSpec + Col.Collation; + end; + // Server version requirement, see http://dev.mysql.com/doc/refman/4.1/en/alter-table.html + if Mainform.mysql_version >= 40001 then begin + if PreviousCol = nil then + ColSpec := ColSpec + ' FIRST' + else + ColSpec := ColSpec + ' AFTER '+Mainform.mask(PreviousCol.Name); + end; + if Col.Status = esModified then begin OldColName := Col.OldName; if OldColName = '' then OldColName := Col.Name; - Specs.Add('DROP COLUMN '+Mainform.mask(OldColName)); - Continue; - end; - else begin - ColSpec := Mainform.mask(Col.Name); - ColSpec := ColSpec + ' ' + Col.DataType.Name; - if Col.LengthSet <> '' then - ColSpec := ColSpec + '(' + Col.LengthSet + ')'; - if Col.DataType.HasUnsigned and Col.Unsigned then - ColSpec := ColSpec + ' UNSIGNED'; - if not Col.AllowNull then - ColSpec := ColSpec + ' NOT'; - ColSpec := ColSpec + ' NULL'; - if Col.DefaultType <> cdtNothing then begin - ColSpec := ColSpec + ' ' + GetColumnDefaultClause(Col.DefaultType, Col.DefaultText); - ColSpec := TrimRight(ColSpec); // Remove whitespace for columns without default value - end; - if Col.Comment <> '' then - ColSpec := ColSpec + ' COMMENT '+esc(Col.Comment); - if Col.Collation <> '' then begin - ColSpec := ColSpec + ' COLLATE '; - if chkCharsetConvert.Checked then - ColSpec := ColSpec + comboCollation.Text - else - ColSpec := ColSpec + Col.Collation; - end; - // Server version requirement, see http://dev.mysql.com/doc/refman/4.1/en/alter-table.html - if Mainform.mysql_version >= 40001 then begin - // Find position in list - Node := listColumns.GetFirst; - PreviousNode := nil; - while Assigned(Node) do begin - if listColumns.Text[Node, 1] = Col.Name then - break; - PreviousNode := Node; - Node := listColumns.GetNextSibling(Node); - end; - if not Assigned(PreviousNode) then - ColSpec := ColSpec + ' FIRST' - else - ColSpec := ColSpec + ' AFTER '+Mainform.mask(listColumns.Text[PreviousNode, 1]); - end; - if Col.Status = esModified then begin - OldColName := Col.OldName; - if OldColName = '' then - OldColName := Col.Name; - Specs.Add('CHANGE COLUMN '+Mainform.mask(OldColName) + ' ' + ColSpec); - end else if Col.Status in [esAddedUntouched, esAddedModified] then - Specs.Add('ADD COLUMN ' + ColSpec); - end; + Specs.Add('CHANGE COLUMN '+Mainform.mask(OldColName) + ' ' + ColSpec); + end else if Col.Status in [esAddedUntouched, esAddedModified] then + Specs.Add('ADD COLUMN ' + ColSpec); + end; + PreviousCol := Col; + Node := listColumns.GetNextSibling(Node); + end; + + // Deleted columns, not available as Node in above loop + for i:=0 to FColumns.Count-1 do begin + ColObj := FColumns[i] as TColumn; + if ColObj.Status = esDeleted then begin + OldColName := ColObj.OldName; + if OldColName = '' then + OldColName := ColObj.Name; + Specs.Add('DROP COLUMN '+Mainform.mask(OldColName)); end; end; @@ -958,7 +954,7 @@ procedure TfrmTableEditor.btnAddColumnClick(Sender: TObject); var NewCol: TColumn; FocusedCol: PColumn; - fn: PVirtualNode; + fn, NewNode: PVirtualNode; idx: Integer; begin // Add new column after selected one @@ -977,7 +973,7 @@ begin NewCol.Comment := FocusedCol.Comment; NewCol.Collation := FocusedCol.Collation; end else begin - idx := FColumns.Count; + idx := listColumns.RootNodeCount; NewCol.DataType := GetDatatypeByName('INT'); NewCol.LengthSet := '10'; NewCol.Unsigned := False; @@ -988,12 +984,12 @@ begin NewCol.Collation := ''; end; NewCol.Name := 'Column '+IntToStr(idx+1); - FColumns.Add(NewCol); + FColumns.Insert(idx, NewCol); + NewNode := listColumns.InsertNode(fn, amInsertAfter, @NewCol); NewCol.Status := esAddedUntouched; - listColumns.InsertNode(fn, amInsertAfter, @NewCol); - SelectNode(listColumns, idx); + SelectNode(listColumns, NewNode); ValidateColumnControls; - listColumns.EditNode(listColumns.FocusedNode, 1); + listColumns.EditNode(NewNode, 1); end; @@ -2261,7 +2257,7 @@ end; procedure TColumn.SetStatus(Value: TEditingStatus); begin // Set editing flag and enable "Save" button - if (FStatus = esAddedUntouched) and (Value = esModified) then + if (FStatus in [esAddedUntouched, esAddedModified]) and (Value = esModified) then Value := esAddedModified else if (FStatus in [esAddedUntouched, esAddedModified]) and (Value = esDeleted) then Value := esAddedDeleted;