* Factor more code out of each database object editors into parent TDBObjectEditor.

* Use this chance to add a confirmation dialog when leaving the editors, to ask the user if he wants to save modifications. Fixes issue #1524.
* Also, enhance Mainform.RefreshTreeDB in a way that it does not trigger the OnFocusChange event. Important for the editors when saving changes.
This commit is contained in:
Ansgar Becker
2009-12-14 23:55:36 +00:00
parent cbedf0d163
commit dd398bb101
7 changed files with 213 additions and 147 deletions

View File

@ -147,9 +147,15 @@ type
private
FModified: Boolean;
procedure SetModified(Value: Boolean);
protected
FEditObjectName: WideString;
public
procedure Init(ObjectName: WideString=''; ObjectType: TListNodeType=lntNone); Virtual; Abstract;
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Init(ObjectName: WideString=''; ObjectType: TListNodeType=lntNone); virtual;
procedure DeInit;
property Modified: Boolean read FModified write SetModified;
procedure ApplyModifications; virtual; abstract;
end;
@ -245,7 +251,7 @@ var
implementation
uses main, uVistaFuncs;
uses main, uVistaFuncs, table_editor, view, routine_editor, trigger_editor;
type
CharacterSet = record
@ -3236,11 +3242,56 @@ end;
{ *** TDBObjectEditor }
constructor TDBObjectEditor.Create(AOwner: TComponent);
begin
inherited;
// Do not set alClient via DFM! In conjunction with ExplicitXXX properties that
// repeatedly breaks the GUI layout when you reload the project
Align := alClient;
InheritFont(Font);
end;
destructor TDBObjectEditor.Destroy;
begin
DeInit;
inherited;
end;
procedure TDBObjectEditor.SetModified(Value: Boolean);
begin
FModified := Value;
end;
procedure TDBObjectEditor.Init(ObjectName: WideString=''; ObjectType: TListNodeType=lntNone);
begin
DeInit;
Mainform.showstatus('Initializing editor ...');
FEditObjectName := ObjectName;
Mainform.SetEditorTabCaption(Self, FEditObjectName);
Screen.Cursor := crHourglass;
MainForm.SetupSynEditors;
end;
procedure TDBObjectEditor.DeInit;
var
Msg, ObjType: WideString;
begin
// Ask for saving modifications
if Modified then begin
if Self is TfrmTableEditor then ObjType := 'table'
else if Self is TfrmView then ObjType := 'view'
else if Self is TfrmRoutineEditor then ObjType := 'routine'
else if Self is TfrmTriggerEditor then ObjType := 'trigger'
else ObjType := '<Unknown Type - should never appear>';
if FEditObjectName <> '' then
Msg := 'Save modified '+ObjType+' "'+FEditObjectName+'"?'
else
Msg := 'Save new '+ObjType+'?';
if MessageDlg(Msg, mtConfirmation, [mbYes, mbNo], 0) = mrYes then
ApplyModifications;
end;
end;
end.

View File

@ -1056,6 +1056,20 @@ procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
var
filename : String;
begin
// Destroy editors and dialogs. Must be done before connection gets closed, as some destructors do SQL stuff.
FreeAndNil(RoutineEditor);
FreeAndNil(TableToolsDialog);
FreeAndNil(UserManagerForm);
FreeAndNil(ViewEditor);
FreeAndNil(SelectDBObjectForm);
FreeAndNil(SQLHelpForm);
FreeAndNil(OptionsForm);
FreeAndNil(SessionManager);
FreeAndNil(TableEditor);
FreeAndNil(TriggerEditor);
FreeAndNil(CreateDatabaseForm);
// Close database connection
DoDisconnect;
OpenRegistry;
@ -1086,18 +1100,6 @@ begin
SaveListSetup(ListCommandStats);
SaveListSetup(ListTables);
FreeAndNil(RoutineEditor);
FreeAndNil(TableToolsDialog);
FreeAndNil(UserManagerForm);
FreeAndNil(ViewEditor);
FreeAndNil(SelectDBObjectForm);
FreeAndNil(SQLHelpForm);
FreeAndNil(OptionsForm);
FreeAndNil(SessionManager);
FreeAndNil(TableEditor);
FreeAndNil(TriggerEditor);
FreeAndNil(CreateDatabaseForm);
debug('mem: clearing query and browse data.');
SetLength(DataGridResult.Rows, 0);
SetLength(DataGridResult.Columns, 0);
@ -6286,15 +6288,39 @@ end;
procedure TMainForm.RefreshTreeDB(db: WideString);
var
oldActiveDatabase: WideString;
dbnode: PVirtualNode;
DBNode, FNode: PVirtualNode;
oldSelectedTable: TListNode;
TableHereHadFocus: Boolean;
Results: TMySQLQuery;
FocusChangeEvent: procedure(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex) of object;
begin
oldActiveDatabase := ActiveDatabase;
DBtree.ClearSelection;
oldSelectedTable := SelectedTable;
DBNode := FindDBNode(db);
FNode := DBtree.FocusedNode;
TableHereHadFocus := FNode.Parent = DBNode;
// Suspend focus changing event, to avoid tab jumping
FocusChangeEvent := DBtree.OnFocusChanged;
DBtree.OnFocusChanged := nil;
// Refresh db node
RefreshDbTableList(db);
DBTree.ReinitNode(dbnode, true);
DBtree.InvalidateChildren(dbnode, false);
ActiveDatabase := oldActiveDatabase;
DBTree.ReinitNode(DBNode, true);
DBtree.InvalidateChildren(DBNode, false);
// Set focus on previously focused table node
if TableHereHadFocus then begin
Results := FetchDbTableList(db);
while not Results.Eof do begin
// Need to check if table was renamed, in which case oldSelectedTable is no longer available
if (Results.Col(DBO_NAME) = oldSelectedTable.Text)
and (GetDBObjectType(Results) = oldSelectedTable.NodeType) then begin
SelectDBObject(oldSelectedTable.Text, oldSelectedTable.NodeType);
break;
end;
Results.Next;
end;
end;
// Reactivate focus changing event
DBtree.OnFocusChanged := FocusChangeEvent;
end;

View File

@ -85,7 +85,7 @@ object frmRoutineEditor: TfrmRoutineEditor
Caption = 'Save'
Default = True
TabOrder = 12
OnClick = PostChanges
OnClick = btnSaveClick
end
object btnDiscard: TButton
Left = 84

View File

@ -36,7 +36,7 @@ type
lblSQLcode: TLabel;
SynMemoBody: TSynMemo;
procedure comboTypeSelect(Sender: TObject);
procedure PostChanges(Sender: TObject);
procedure btnSaveClick(Sender: TObject);
procedure btnHelpClick(Sender: TObject);
procedure editNameChange(Sender: TObject);
procedure btnAddParamClick(Sender: TObject);
@ -69,12 +69,12 @@ type
private
{ Private declarations }
Parameters: TWideStringList;
FAlterRoutineName: WideString;
FAlterRoutineType: String;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
procedure Init(ObjectName: WideString=''; ObjectType: TListNodeType=lntNone); override;
procedure ApplyModifications; override;
end;
@ -92,8 +92,7 @@ constructor TfrmRoutineEditor.Create(AOwner: TComponent);
var
i: Integer;
begin
inherited Create(AOwner);
Align := alClient;
inherited;
// Combo items in a .dfm are sporadically lost after an IDE restart,
// so we set them here to avoid developer annoyance
comboType.Items.Add('Procedure (doesn''t return a result)');
@ -106,8 +105,6 @@ begin
comboSecurity.Items.Add('Invoker');
for i := Low(Datatypes) to High(Datatypes) do
comboReturns.Items.Add(Datatypes[i].Name);
SetWindowSizeGrip(Handle, True);
InheritFont(Font);
Mainform.SynCompletionProposal.AddEditor(SynMemoBody);
FixVT(listParameters);
Parameters := TWideStringList.Create;
@ -124,11 +121,10 @@ var
rx: TRegExpr;
i: Integer;
begin
MainForm.SetupSynEditors;
FAlterRoutineName := ObjectName;
inherited;
if ObjectType = lntProcedure then FAlterRoutineType := 'PROCEDURE'
else FAlterRoutineType := 'FUNCTION';
editName.Text := FAlterRoutineName;
editName.Text := FEditObjectName;
comboType.ItemIndex := 0;
comboReturns.Text := '';
listParameters.Clear;
@ -137,16 +133,15 @@ begin
comboSecurity.ItemIndex := 0;
editComment.Clear;
SynMemoBody.Text := 'BEGIN'+CRLF+CRLF+'END';
if FAlterRoutineName <> '' then begin
if FEditObjectName <> '' then begin
// Editing existing routine
Mainform.SetEditorTabCaption(Self, FAlterRoutineName);
Results := Mainform.Connection.GetResults('SELECT * FROM '+DBNAME_INFORMATION_SCHEMA+'.ROUTINES'+
' WHERE ROUTINE_SCHEMA='+esc(Mainform.ActiveDatabase)+
' AND ROUTINE_NAME='+esc(FAlterRoutineName)+
' AND ROUTINE_NAME='+esc(FEditObjectName)+
' AND ROUTINE_TYPE='+esc(FAlterRoutineType)
);
if Results.RecordCount <> 1 then
Exception.Create('Cannot find properties of stored routine '+FAlterRoutineName);
Exception.Create('Cannot find properties of stored routine '+FEditObjectName);
comboType.ItemIndex := ListIndexByRegExpr(comboType.Items, '^'+FAlterRoutineType+'\b');
chkDeterministic.Checked := Results.Col('IS_DETERMINISTIC') = 'YES';
comboReturns.Text := Results.Col('DTD_IDENTIFIER');
@ -185,7 +180,6 @@ begin
FreeAndNil(Results);
end else begin
editName.Text := 'Enter routine name';
Mainform.SetEditorTabCaption(Self, '');
end;
editNameChange(Self);
comboTypeSelect(comboType);
@ -403,7 +397,14 @@ begin
end;
procedure TfrmRoutineEditor.PostChanges(Sender: TObject);
procedure TfrmRoutineEditor.btnSaveClick(Sender: TObject);
begin
// Apply or OK button clicked
ApplyModifications;
end;
procedure TfrmRoutineEditor.ApplyModifications;
var
BaseSQL, TempSQL, FinalSQL, TempName: WideString;
i: Integer;
@ -411,18 +412,8 @@ var
ProcOrFunc: String;
TargetExists: Boolean;
begin
// Apply or OK button clicked
// Save changes
ProcOrFunc := UpperCase(GetFirstWord(comboType.Text));
if editName.Text = '' then begin
MessageDlg('Please specify the routine''s name.', mtError, [mbOK], 0);
editName.SetFocus;
Exit;
end else if (ProcOrFunc = 'FUNCTION') and (comboReturns.Text = '') then begin
MessageDlg('Please specify the function''s returning datatype.', mtError, [mbOK], 0);
comboReturns.SetFocus;
Exit;
end;
BaseSQL := '';
for i := 0 to Parameters.Count - 1 do begin
par := explode(DELIM, Parameters[i]);
@ -448,18 +439,18 @@ begin
// Create a temp routine, check for syntax errors, then drop the old routine and create it.
// See also: http://dev.mysql.com/doc/refman/5.0/en/alter-procedure.html
try
if FAlterRoutineName <> '' then begin
if FEditObjectName <> '' then begin
// Create temp name
i := 0;
allRoutineNames := Mainform.Connection.GetCol('SELECT ROUTINE_NAME FROM '+Mainform.mask(DBNAME_INFORMATION_SCHEMA)+'.'+Mainform.mask('ROUTINES')+
' WHERE ROUTINE_SCHEMA = '+esc(Mainform.ActiveDatabase)+
' AND ROUTINE_TYPE = '+esc(ProcOrFunc)
);
TargetExists := ((editName.Text <> FAlterRoutineName) or (ProcOrFunc <> FAlterRoutineType)) and
TargetExists := ((editName.Text <> FEditObjectName) or (ProcOrFunc <> FAlterRoutineType)) and
(allRoutineNames.IndexOf(editName.Text) > -1);
if TargetExists then begin
if MessageDlg('Routine "'+editName.Text+'" already exists. Overwrite it?',
mtConfirmation, [mbOk, mbCancel], 0) = mrCancel then begin
mtConfirmation, [mbYes, mbNo], 0) = mrNo then begin
Exit;
end;
end;
@ -474,7 +465,7 @@ begin
// Drop temporary routine, used for syntax checking
Mainform.Connection.Query('DROP '+ProcOrFunc+' IF EXISTS '+Mainform.mask(TempName));
// Drop edited routine
Mainform.Connection.Query('DROP '+FAlterRoutineType+' IF EXISTS '+Mainform.mask(FAlterRoutineName));
Mainform.Connection.Query('DROP '+FAlterRoutineType+' IF EXISTS '+Mainform.mask(FEditObjectName));
if TargetExists then begin
// Drop target routine - overwriting has been confirmed, see above
Mainform.Connection.Query('DROP '+ProcOrFunc+' IF EXISTS '+Mainform.mask(editName.Text));
@ -483,10 +474,10 @@ begin
FinalSQL := 'CREATE '+ProcOrFunc+' '+Mainform.mask(editName.Text)+'(' + BaseSQL;
Mainform.Connection.Query(FinalSQL);
// Set editing name if create/alter query was successful
FAlterRoutineName := editName.Text;
FAlterRoutineType := ProcOrFunc;
Mainform.SetEditorTabCaption(Self, FAlterRoutineName);
Mainform.actRefresh.Execute;
FEditObjectName := editName.Text;
FAlterRoutineType := UpperCase(GetFirstWord(comboType.Text));
Mainform.SetEditorTabCaption(Self, FEditObjectName);
Mainform.RefreshTreeDB(Mainform.ActiveDatabase);
Modified := False;
btnSave.Enabled := Modified;
btnDiscard.Enabled := Modified;
@ -501,9 +492,10 @@ procedure TfrmRoutineEditor.btnDiscardClick(Sender: TObject);
var
t: TListNodeType;
begin
Modified := False;
if FAlterRoutineType = 'PROCEDURE' then t := lntProcedure
else t := lntFunction;
Init(FAlterRoutineName, t);
Init(FEditObjectName, t);
end;

View File

@ -170,7 +170,6 @@ type
private
{ Private declarations }
FLoaded: Boolean;
FAlterTableName: WideString;
CreateCodeValid, AlterCodeValid: Boolean;
FColumns, FKeys, FForeignKeys: TObjectList;
DeletedKeys, DeletedForeignKeys: TWideStringList;
@ -190,6 +189,7 @@ type
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Init(ObjectName: WideString=''; ObjectType: TListNodeType=lntNone); override;
procedure ApplyModifications; override;
end;
@ -207,12 +207,8 @@ const
constructor TfrmTableEditor.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
// Do not set alClient via DFM! In conjunction with ExplicitXXX properties that
// repeatedly breaks the GUI layout when you reload the project
Align := alClient;
inherited;
PageControlMain.Height := GetRegValue(REGNAME_TABLEEDITOR_TABSHEIGHT, PageControlMain.Height);
InheritFont(Font);
FixVT(listColumns);
FixVT(treeIndexes);
FixVT(listForeignKeys);
@ -243,7 +239,7 @@ begin
Mainform.SaveListSetup(listColumns);
Mainform.SaveListSetup(treeIndexes);
Mainform.SaveListSetup(listForeignKeys);
Inherited;
inherited;
end;
@ -252,22 +248,16 @@ var
CreateTable, AttrName, AttrValue: WideString;
rx: TRegExpr;
begin
Mainform.showstatus('Initializing editor ...');
Screen.Cursor := crHourglass;
inherited;
FLoaded := False;
// Start with "basic" tab activated when just called
if FAlterTableName <> ObjectName then
PageControlMain.ActivePage := tabBasic;
comboEngine.Items := Mainform.Connection.TableEngines;
comboEngine.ItemIndex := comboEngine.Items.IndexOf(Mainform.Connection.TableEngineDefault);
comboCollation.Items := Mainform.Connection.CollationList;
FAlterTableName := ObjectName;
listColumns.BeginUpdate;
FColumns.Clear;
btnClearIndexesClick(Self);
btnClearForeignKeysClick(Self);
tabALTERcode.TabVisible := FAlterTableName <> '';
MainForm.SetupSynEditors;
tabALTERcode.TabVisible := FEditObjectName <> '';
// Clear value editors
memoComment.Text := '';
editAutoInc.Text := '';
@ -279,16 +269,14 @@ begin
memoUnionTables.Clear;
comboInsertMethod.ItemIndex := -1;
if FAlterTableName = '' then begin
if FEditObjectName = '' then begin
// Creating new table
editName.Text := 'Enter table name';
Mainform.SetEditorTabCaption(Self, '');
comboCollation.ItemIndex := comboCollation.Items.IndexOf(Mainform.Connection.GetVar('SHOW VARIABLES LIKE ''collation_database''', 1));
PageControlMain.ActivePage := tabBasic;
end else begin
// Editing existing table
editName.Text := FAlterTableName;
Mainform.SetEditorTabCaption(Self, FAlterTableName);
editName.Text := FEditObjectName;
CreateTable := Mainform.SelectedTableCreateStatement;
rx := TRegExpr.Create;
rx.ModifierI := True;
@ -347,22 +335,28 @@ end;
procedure TfrmTableEditor.btnDiscardClick(Sender: TObject);
begin
// Reinit GUI, discarding changes
Init(FAlterTableName);
Modified := False;
Init(FEditObjectName);
end;
procedure TfrmTableEditor.btnSaveClick(Sender: TObject);
begin
ApplyModifications;
end;
procedure TfrmTableEditor.ApplyModifications;
var
sql: WideString;
i: Integer;
Specs: TWideStringlist;
Key: TForeignKey;
Col: TTableColumn;
FocusChangeEvent: procedure(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex) of object;
begin
// Create or alter table
try
if FAlterTableName = '' then
Specs := TWideStringList.Create;
if FEditObjectName = '' then
sql := ComposeCreateStatement
else begin
sql := ComposeAlterStatement;
@ -371,19 +365,17 @@ begin
// See also http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html :
// "You cannot add a foreign key and drop a foreign key in separate clauses of a single
// ALTER TABLE statement. Separate statements are required."
Specs := TWideStringList.Create;
for i:=0 to FForeignKeys.Count-1 do begin
Key := FForeignKeys[i] as TForeignKey;
if Key.Modified and (not Key.Added) then
Specs.Add('DROP FOREIGN KEY '+Mainform.mask(Key.KeyName));
end;
if Specs.Count > 0 then
Mainform.Connection.Query('ALTER TABLE '+Mainform.mask(FAlterTableName)+' '+ImplodeStr(', ', Specs));
end;
try
if Specs.Count > 0 then
Mainform.Connection.Query('ALTER TABLE '+Mainform.mask(FEditObjectName)+' '+ImplodeStr(', ', Specs));
Mainform.Connection.Query(sql);
// Set table name for altering if Apply was clicked
FAlterTableName := editName.Text;
tabALTERcode.TabVisible := FAlterTableName <> '';
tabALTERcode.TabVisible := FEditObjectName <> '';
if chkCharsetConvert.Checked then begin
// Autoadjust column collations
for i:=0 to FColumns.Count-1 do begin
@ -392,15 +384,12 @@ begin
Col.Collation := comboCollation.Text;
end;
end;
ResetModificationFlags;
// Refresh db tree and reselect edited table node.
// Supress tab jumping, implicitely invoked by RefreshTreeDB.
FocusChangeEvent := Mainform.DBtree.OnFocusChanged;
Mainform.DBtree.OnFocusChanged := nil;
// Set table name for altering if Apply was clicked
FEditObjectName := editName.Text;
tabALTERcode.TabVisible := FEditObjectName <> '';
Mainform.SetEditorTabCaption(Self, FEditObjectName);
Mainform.RefreshTreeDB(Mainform.ActiveDatabase);
Mainform.DBtree.OnFocusChanged := FocusChangeEvent;
Mainform.SelectDBObject(FAlterTableName, lntTable);
ResetModificationFlags;
except
on E:Exception do
MessageDlg(E.Message, mtError, [mbOk], 0);
@ -466,7 +455,7 @@ begin
Mainform.showstatus('Composing ALTER statement ...');
Screen.Cursor := crHourglass;
Specs := TWideStringlist.Create;
if editName.Text <> FAlterTableName then
if editName.Text <> FEditObjectName then
Specs.Add('RENAME TO ' + Mainform.mask(editName.Text));
if memoComment.Tag = ModifiedFlag then
Specs.Add('COMMENT=' + esc(memoComment.Text));
@ -595,7 +584,7 @@ begin
Specs.Add('ADD '+GetForeignKeySQL(i));
end;
Result := 'ALTER TABLE '+Mainform.mask(FAlterTableName) + CRLF + #9 + ImplodeStr(',' + CRLF + #9, Specs);
Result := 'ALTER TABLE '+Mainform.mask(FEditObjectName) + CRLF + #9 + ImplodeStr(',' + CRLF + #9, Specs);
Result := Trim(Result);
FreeAndNil(Specs);
Mainform.showstatus;
@ -1731,7 +1720,7 @@ end;
procedure TfrmTableEditor.chkCharsetConvertClick(Sender: TObject);
begin
chkCharsetConvert.Enabled := (FAlterTablename <> '') and (comboCollation.ItemIndex > -1);
chkCharsetConvert.Enabled := (FEditObjectName <> '') and (comboCollation.ItemIndex > -1);
listColumns.Repaint;
Modification(Sender);
end;

View File

@ -31,11 +31,11 @@ type
var CurrentInput: WideString; var x, y: Integer; var CanExecute: Boolean);
private
{ Private declarations }
FEditTriggerName: WideString;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
procedure Init(ObjectName: WideString=''; ObjectType: TListNodeType=lntNone); override;
procedure ApplyModifications; override;
end;
implementation
@ -53,10 +53,8 @@ var
col: TProposalColumn;
i: Integer;
begin
inherited Create(AOwner);
Align := alClient;
inherited;
SynMemoStatement.Highlighter := Mainform.SynSQLSyn1;
InheritFont(Font);
editName.MaxLength := NAME_LEN;
comboTiming.Items.Text := 'BEFORE'+CRLF+'AFTER';
comboEvent.Items.Text := 'INSERT'+CRLF+'UPDATE'+CRLF+'DELETE';
@ -78,8 +76,7 @@ procedure TfrmTriggerEditor.Init(ObjectName: WideString=''; ObjectType: TListNod
var
Definition, TableList: TMySQLQuery;
begin
Mainform.SetupSynEditors;
FEditTriggerName := ObjectName;
inherited;
editName.Text := '';
SynMemoStatement.Text := '';
comboEvent.ItemIndex := 0;
@ -93,20 +90,18 @@ begin
end;
if comboTable.Items.Count > 0 then
comboTable.ItemIndex := 0;
if FEditTriggerName <> '' then begin
if FEditObjectName <> '' then begin
// Edit mode
Mainform.SetEditorTabCaption(Self, FEditTriggerName);
editName.Text := FEditTriggerName;
editName.Text := FEditObjectName;
Definition := Mainform.Connection.GetResults('SELECT '+
'EVENT_MANIPULATION, EVENT_OBJECT_TABLE, ACTION_STATEMENT, ACTION_TIMING '+
'FROM information_schema.TRIGGERS '+
'WHERE TRIGGER_SCHEMA='+esc(Mainform.ActiveDatabase)+' AND TRIGGER_NAME='+esc(FEditTriggerName));
'WHERE TRIGGER_SCHEMA='+esc(Mainform.ActiveDatabase)+' AND TRIGGER_NAME='+esc(FEditObjectName));
comboTable.ItemIndex := comboTable.Items.IndexOf(Definition.Col('EVENT_OBJECT_TABLE'));
comboTiming.ItemIndex := comboTiming.Items.IndexOf(UpperCase(Definition.Col('ACTION_TIMING')));
comboEvent.ItemIndex := comboEvent.Items.IndexOf(UpperCase(Definition.Col('EVENT_MANIPULATION')));
SynMemoStatement.Text := Definition.Col('ACTION_STATEMENT');
end else begin
Mainform.SetEditorTabCaption(Self, '');
editName.Text := 'Enter trigger name';
end;
Modified := False;
@ -129,19 +124,25 @@ end;
procedure TfrmTriggerEditor.btnDiscardClick(Sender: TObject);
begin
// Reinit editor, discarding changes
Init(FEditTriggerName);
Modified := False;
Init(FEditObjectName);
end;
procedure TfrmTriggerEditor.btnSaveClick(Sender: TObject);
begin
ApplyModifications;
end;
procedure TfrmTriggerEditor.ApplyModifications;
var
sql: WideString;
FocusChangeEvent: procedure(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex) of object;
begin
// Edit mode means we drop the trigger and recreate it, as there is no ALTER TRIGGER.
try
if FEditTriggerName <> '' then
Mainform.Connection.Query('DROP TRIGGER '+Mainform.mask(FEditTriggerName));
if FEditObjectName <> '' then
Mainform.Connection.Query('DROP TRIGGER '+Mainform.mask(FEditObjectName));
// CREATE
// [DEFINER = { user | CURRENT_USER }]
// TRIGGER trigger_name trigger_time trigger_event
@ -151,12 +152,12 @@ begin
' ON '+Mainform.mask(comboTable.Text)+
' FOR EACH ROW '+SynMemoStatement.Text;
Mainform.Connection.Query(sql);
FocusChangeEvent := Mainform.DBtree.OnFocusChanged;
Mainform.DBtree.OnFocusChanged := nil;
FEditObjectName := editName.Text;
Mainform.SetEditorTabCaption(Self, FEditObjectName);
Mainform.RefreshTreeDB(Mainform.ActiveDatabase);
Mainform.DBtree.OnFocusChanged := FocusChangeEvent;
Mainform.SelectDBObject(editName.Text, lntTrigger);
Init(editName.Text);
Modified := False;
btnSave.Enabled := Modified;
btnDiscard.Enabled := Modified;
except on E:Exception do
MessageDlg(E.Message, mtError, [mbOK], 0);
end;

View File

@ -26,11 +26,11 @@ type
procedure Modification(Sender: TObject);
private
{ Private declarations }
FEditViewName: WideString;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
procedure Init(ObjectName: WideString=''; ObjectType: TListNodeType=lntNone); override;
procedure ApplyModifications; override;
end;
@ -46,11 +46,9 @@ uses main;
}
constructor TfrmView.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Align := alClient;
inherited;
SynMemoSelect.Highlighter := Mainform.SynSQLSyn1;
Mainform.SynCompletionProposal.AddEditor(SynMemoSelect);
InheritFont(Font);
editName.MaxLength := NAME_LEN;
end;
@ -64,16 +62,15 @@ var
db: WideString;
rx: TRegExpr;
begin
FEditViewName := ObjectName;
if FEditViewName <> '' then begin
inherited;
if FEditObjectName <> '' then begin
// Edit mode
editName.Text := FEditViewName;
Mainform.SetEditorTabCaption(Self, FEditViewName);
editName.Text := FEditObjectName;
db := Mainform.ActiveDatabase;
Results := Mainform.Connection.GetResults('SELECT * FROM '+Mainform.mask(DBNAME_INFORMATION_SCHEMA)+'.VIEWS ' +
'WHERE TABLE_SCHEMA = '+esc(db)+' AND TABLE_NAME = '+esc(FEditViewName));
'WHERE TABLE_SCHEMA = '+esc(db)+' AND TABLE_NAME = '+esc(FEditObjectName));
if Results.RecordCount = 0 then
raise Exception.Create('Can''t find view definition for "'+FEditViewName+'" in '+DBNAME_INFORMATION_SCHEMA);
raise Exception.Create('Can''t find view definition for "'+FEditObjectName+'" in '+DBNAME_INFORMATION_SCHEMA);
// Algorithm is not changeable as we cannot look up its current state!
rgAlgorithm.Enabled := False;
rgAlgorithm.ItemIndex := 0;
@ -88,7 +85,6 @@ begin
rx.Free;
end else begin
// Create mode
Mainform.SetEditorTabCaption(Self, '');
editName.Text := 'Enter view name';
rgAlgorithm.Enabled := True;
rgAlgorithm.ItemIndex := 0;
@ -98,7 +94,6 @@ begin
end;
// Ensure name is validated
editNameChange(Self);
MainForm.SetupSynEditors;
Modified := False;
btnSave.Enabled := Modified;
btnDiscard.Enabled := Modified;
@ -129,7 +124,7 @@ procedure TfrmView.btnHelpClick(Sender: TObject);
var
keyword: String;
begin
if FEditViewName = '' then
if FEditObjectName = '' then
keyword := 'CREATE VIEW'
else
keyword := 'ALTER VIEW';
@ -140,24 +135,31 @@ end;
procedure TfrmView.btnDiscardClick(Sender: TObject);
begin
// Reinit editor, discarding changes
Init(FEditViewName);
Modified := False;
Init(FEditObjectName);
end;
{**
Apply changes: Compose and execute SQL
Apply changes
}
procedure TfrmView.btnSaveClick(Sender: TObject);
begin
ApplyModifications;
end;
procedure TfrmView.ApplyModifications;
var
sql, viewname, renamed: String;
begin
// Compose CREATE or ALTER statement
if FEditViewName = '' then begin
// Save changes
if FEditObjectName = '' then begin
sql := 'CREATE ';
viewname := editName.Text;
end else begin
sql := 'ALTER ';
viewname := FEditViewName;
viewname := FEditObjectName;
end;
viewname := Mainform.mask(viewname);
if rgAlgorithm.Enabled and (rgAlgorithm.ItemIndex > -1) then
@ -169,11 +171,16 @@ begin
try
Mainform.Connection.Query(sql);
// Probably rename view
if (FEditViewName <> '') and (FEditViewName <> editName.Text) then begin
if (FEditObjectName <> '') and (FEditObjectName <> editName.Text) then begin
renamed := Mainform.mask(editName.Text);
Mainform.Connection.Query('RENAME TABLE '+viewname + ' TO '+renamed);
end;
FEditObjectName := editName.Text;
Mainform.SetEditorTabCaption(Self, FEditObjectName);
Mainform.RefreshTreeDB(Mainform.ActiveDatabase);
Modified := False;
btnSave.Enabled := Modified;
btnDiscard.Enabled := Modified;
except
on E:Exception do
MessageDlg(E.Message, mtError, [mbOk], 0);