mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-06 18:24:26 +08:00
404 lines
13 KiB
ObjectPascal
404 lines
13 KiB
ObjectPascal
unit event_editor;
|
|
|
|
interface
|
|
|
|
uses
|
|
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms,
|
|
Vcl.Dialogs, Vcl.StdCtrls, Vcl.Menus, SynEdit, SynMemo, SynRegExpr, Vcl.ComCtrls, Vcl.ExtCtrls, System.WideStrUtils,
|
|
apphelpers, dbconnection, dbstructures, gnugettext, extra_controls;
|
|
|
|
type
|
|
TFrame = TDBObjectEditor;
|
|
TfrmEventEditor = class(TFrame)
|
|
SynMemoBody: TSynMemo;
|
|
btnHelp: TButton;
|
|
btnDiscard: TButton;
|
|
btnSave: TButton;
|
|
lblBody: TLabel;
|
|
PageControlMain: TPageControl;
|
|
tabSettings: TTabSheet;
|
|
tabScheduling: TTabSheet;
|
|
tabCREATEcode: TTabSheet;
|
|
tabALTERcode: TTabSheet;
|
|
lblName: TLabel;
|
|
editName: TEdit;
|
|
lblComment: TLabel;
|
|
chkDropAfterExpiration: TCheckBox;
|
|
editComment: TEdit;
|
|
grpState: TRadioGroup;
|
|
radioOnce: TRadioButton;
|
|
radioEvery: TRadioButton;
|
|
dateOnce: TDateTimePicker;
|
|
timeOnce: TDateTimePicker;
|
|
editEveryQuantity: TEdit;
|
|
udEveryQuantity: TUpDown;
|
|
comboEveryInterval: TComboBox;
|
|
chkStarts: TCheckBox;
|
|
chkEnds: TCheckBox;
|
|
dateStarts: TDateTimePicker;
|
|
timeStarts: TDateTimePicker;
|
|
timeEnds: TDateTimePicker;
|
|
dateEnds: TDateTimePicker;
|
|
SynMemoCREATEcode: TSynMemo;
|
|
SynMemoALTERcode: TSynMemo;
|
|
comboDefiner: TComboBox;
|
|
lblDefiner: TLabel;
|
|
procedure Modification(Sender: TObject);
|
|
procedure radioScheduleClick(Sender: TObject);
|
|
procedure btnSaveClick(Sender: TObject);
|
|
procedure btnHelpClick(Sender: TObject);
|
|
procedure btnDiscardClick(Sender: TObject);
|
|
procedure PageControlMainChange(Sender: TObject);
|
|
procedure chkStartsEndsClick(Sender: TObject);
|
|
procedure comboEveryIntervalChange(Sender: TObject);
|
|
procedure comboDefinerDropDown(Sender: TObject);
|
|
private
|
|
{ Private declarations }
|
|
AlterCodeValid, CreateCodeValid: Boolean;
|
|
function ComposeCreateStatement: String;
|
|
function ComposeAlterStatement: String;
|
|
function ComposeStatement(CreateOrAlter, ObjName: String): String;
|
|
procedure UpdateSQLcode;
|
|
public
|
|
{ Public declarations }
|
|
constructor Create(AOwner: TComponent); override;
|
|
procedure Init(Obj: TDBObject); override;
|
|
function ApplyModifications: TModalResult; override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses main;
|
|
|
|
{$R *.dfm}
|
|
|
|
|
|
constructor TfrmEventEditor.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
Mainform.SynCompletionProposal.AddEditor(SynMemoBody);
|
|
comboEveryInterval.Items := Explode('|', 'YEAR|QUARTER|MONTH|DAY|HOUR|MINUTE|WEEK|SECOND|YEAR_MONTH|'+
|
|
'DAY_HOUR|DAY_MINUTE|DAY_SECOND|HOUR_MINUTE|HOUR_SECOND|MINUTE_SECOND');
|
|
grpState.Items := Explode('|', 'Enable|Disable|Disable on slave');
|
|
FMainSynMemo := SynMemoBody;
|
|
btnSave.Hint := ShortCutToText(MainForm.actSaveSQL.ShortCut);
|
|
end;
|
|
|
|
|
|
procedure TfrmEventEditor.Init(Obj: TDBObject);
|
|
var
|
|
CreateCode, DateExpr: String;
|
|
rx: TRegExpr;
|
|
d: TDateTime;
|
|
i: Integer;
|
|
begin
|
|
inherited;
|
|
editName.Clear;
|
|
editComment.Clear;
|
|
comboDefiner.Text := '';
|
|
comboDefiner.TextHint := f_('Current user (%s)', [Obj.Connection.CurrentUserHostCombination]);
|
|
comboDefiner.Hint := f_('Leave empty for current user (%s)', [Obj.Connection.CurrentUserHostCombination]);
|
|
chkDropAfterExpiration.Checked := True;
|
|
radioEvery.Checked := True;
|
|
grpState.ItemIndex := 0;
|
|
SynMemoBody.Text := 'BEGIN'+CRLF+CRLF+'END';
|
|
dateOnce.Date := Now;
|
|
timeOnce.Time := Now;
|
|
dateStarts.Date := Now;
|
|
timeStarts.Time := Now;
|
|
dateEnds.Date := Now;
|
|
timeEnds.Time := Now;
|
|
udEveryQuantity.Position := 1;
|
|
comboEveryInterval.ItemIndex := comboEveryInterval.Items.IndexOf('DAY');
|
|
tabALTERcode.TabVisible := False;
|
|
if ObjectExists then begin
|
|
// Edit mode
|
|
tabALTERcode.TabVisible := True;
|
|
editName.Text := DBObject.Name;
|
|
// CREATE DEFINER=`root`@`127.0.0.1` EVENT `eventb`
|
|
// ON SCHEDULE EVERY 1 DAY STARTS '2010-04-08 08:05:04' ENDS '2010-04-30 01:01:28'
|
|
// ON COMPLETION NOT PRESERVE
|
|
// ENABLE
|
|
// DO BEGIN END
|
|
CreateCode := DBObject.CreateCode;
|
|
DateExpr := '[''"]([^''"]+)[''"]';
|
|
rx := TRegExpr.Create;
|
|
rx.ModifierI := True;
|
|
|
|
rx.Expression := '\bDEFINER\s*=\s*(\S+)\s';
|
|
if rx.Exec(CreateCode) then
|
|
comboDefiner.Text := Obj.Connection.DequoteIdent(rx.Match[1], '@')
|
|
else
|
|
comboDefiner.Text := '';
|
|
|
|
rx.Expression := '\bON\s+SCHEDULE\s+(EVERY|AT)\s+((\d+|''[^'']+'')\s+(\S+)(\s+STARTS\s+'+DateExpr+')?(\s+ENDS\s+'+DateExpr+')?|'+DateExpr+')';
|
|
if rx.Exec(CreateCode) then begin
|
|
if UpperCase(rx.Match[1]) = 'AT' then begin
|
|
radioOnce.Checked := True;
|
|
d := MainForm.ActiveConnection.ParseDateTime(WideDequotedStr(rx.Match[3], ''''));
|
|
dateOnce.DateTime := d;
|
|
timeOnce.DateTime := d;
|
|
end else begin
|
|
radioEvery.Checked := True;
|
|
comboEveryInterval.ItemIndex := comboEveryInterval.Items.IndexOf(rx.Match[4]);
|
|
comboEveryIntervalChange(Self);
|
|
if udEveryQuantity.Enabled then
|
|
udEveryQuantity.Position := MakeInt(rx.Match[3])
|
|
else
|
|
editEveryQuantity.Text := WideDequotedStr(rx.Match[3], '''');
|
|
chkStarts.Checked := rx.MatchLen[5] > 0;
|
|
if chkStarts.Checked then begin
|
|
d := MainForm.ActiveConnection.ParseDateTime(rx.Match[6]);
|
|
dateStarts.DateTime := d;
|
|
timeStarts.DateTime := d;
|
|
end;
|
|
chkEnds.Checked := rx.MatchLen[7] > 0;
|
|
if chkEnds.Checked then begin
|
|
d := MainForm.ActiveConnection.ParseDateTime(rx.Match[8]);
|
|
dateEnds.DateTime := d;
|
|
timeEnds.DateTime := d;
|
|
end;
|
|
end;
|
|
Delete(CreateCode, 1, rx.MatchPos[0]+rx.MatchLen[0]);
|
|
end;
|
|
|
|
rx.Expression := '^ON\s+COMPLETION(\s+NOT)?\s+PRESERVE\b';
|
|
if rx.Exec(CreateCode) then begin
|
|
chkDropAfterExpiration.Checked := rx.MatchLen[1] > 0;
|
|
Delete(CreateCode, 1, rx.MatchPos[0]+rx.MatchLen[0]);
|
|
end;
|
|
|
|
for i:=grpState.Items.Count-1 downto 0 do begin
|
|
if Pos(UpperCase(grpState.Items[i]), UpperCase(CreateCode)) = 1 then begin
|
|
grpState.ItemIndex := i;
|
|
Delete(CreateCode, 1, Length(grpState.Items[i]));
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
rx.ModifierG := False;
|
|
rx.Expression := '\bCOMMENT\s+''((.+)[^''])''';
|
|
if rx.Exec(CreateCode) then begin
|
|
editComment.Text := StringReplace(rx.Match[1], '''''', '''', [rfReplaceAll]);
|
|
Delete(CreateCode, rx.MatchPos[0], rx.MatchLen[0]);
|
|
end;
|
|
|
|
rx.ModifierG := True;
|
|
rx.Expression := '\bDO\s+(.*)';
|
|
if rx.Exec(CreateCode) then
|
|
SynMemoBody.Text := rx.Match[1];
|
|
|
|
rx.Free;
|
|
SynMemoBody.TopLine := FMainSynMemoPreviousTopLine;
|
|
|
|
end;
|
|
radioScheduleClick(Self);
|
|
Modified := False;
|
|
btnSave.Enabled := Modified;
|
|
btnDiscard.Enabled := Modified;
|
|
Mainform.ShowStatusMsg;
|
|
TExtForm.PageControlTabHighlight(PageControlMain);
|
|
Screen.Cursor := crDefault;
|
|
end;
|
|
|
|
|
|
procedure TfrmEventEditor.Modification(Sender: TObject);
|
|
begin
|
|
Modified := True;
|
|
btnSave.Enabled := Modified and (editName.Text <> '');
|
|
btnDiscard.Enabled := Modified;
|
|
CreateCodeValid := False;
|
|
AlterCodeValid := False;
|
|
UpdateSQLcode;
|
|
end;
|
|
|
|
|
|
procedure TfrmEventEditor.btnSaveClick(Sender: TObject);
|
|
begin
|
|
ApplyModifications;
|
|
end;
|
|
|
|
|
|
function TfrmEventEditor.ApplyModifications: TModalResult;
|
|
var
|
|
sql: String;
|
|
begin
|
|
// Create or alter table
|
|
Result := mrOk;
|
|
if not ObjectExists then
|
|
sql := ComposeCreateStatement
|
|
else
|
|
sql := ComposeAlterStatement;
|
|
try
|
|
MainForm.ActiveConnection.Query(sql);
|
|
DBObject.Name := editName.Text;
|
|
DBObject.UnloadDetails;
|
|
tabALTERcode.TabVisible := ObjectExists;
|
|
Mainform.UpdateEditorTab;
|
|
Mainform.RefreshTree(DBObject);
|
|
Modified := False;
|
|
btnSave.Enabled := Modified;
|
|
btnDiscard.Enabled := Modified;
|
|
AlterCodeValid := False;
|
|
CreateCodeValid := False;
|
|
UpdateSQLcode;
|
|
except
|
|
on E:EDbError do begin
|
|
ErrorDialog(E.Message);
|
|
Result := mrAbort;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
function TfrmEventEditor.ComposeCreateStatement: String;
|
|
begin
|
|
Result := ComposeStatement('CREATE', editName.Text);
|
|
end;
|
|
|
|
|
|
function TfrmEventEditor.ComposeAlterStatement: String;
|
|
begin
|
|
Result := ComposeStatement('ALTER', DBObject.Name);
|
|
end;
|
|
|
|
|
|
function TfrmEventEditor.ComposeStatement(CreateOrAlter, ObjName: String): String;
|
|
var
|
|
d: TDateTime;
|
|
Quantity: String;
|
|
begin
|
|
// Return CREATE EVENT statement
|
|
Result := CreateOrAlter + ' ';
|
|
if comboDefiner.Text <> '' then
|
|
Result := Result + 'DEFINER='+DBObject.Connection.QuoteIdent(comboDefiner.Text, True, '@')+' ';
|
|
Result := Result + 'EVENT ' + DBObject.Connection.QuoteIdent(ObjName) + CRLF + #9 + 'ON SCHEDULE' + CRLF + #9#9;
|
|
if radioOnce.Checked then begin
|
|
d := dateOnce.DateTime;
|
|
ReplaceTime(d, timeOnce.DateTime);
|
|
Result := Result + 'AT ' + DBObject.Connection.EscapeString(DateTimeToStr(d)) + CRLF;
|
|
end else begin
|
|
if udEveryQuantity.Enabled then
|
|
Quantity := IntToStr(udEveryQuantity.Position)
|
|
else
|
|
Quantity := DBObject.Connection.EscapeString(editEveryQuantity.Text);
|
|
Result := Result + 'EVERY ' + Quantity + ' ' + comboEveryInterval.Text;
|
|
if chkStarts.Checked then begin
|
|
d := dateStarts.DateTime;
|
|
ReplaceTime(d, timeStarts.DateTime);
|
|
Result := Result + ' STARTS ' + DBObject.Connection.EscapeString(DateTimeToStr(d));
|
|
end;
|
|
if chkEnds.Checked then begin
|
|
d := dateEnds.DateTime;
|
|
ReplaceTime(d, timeEnds.DateTime);
|
|
Result := Result + ' ENDS ' + DBObject.Connection.EscapeString(DateTimeToStr(d));
|
|
end;
|
|
Result := Result + CRLF;
|
|
end;
|
|
|
|
if chkDropAfterExpiration.Checked then
|
|
Result := Result + #9 + 'ON COMPLETION NOT PRESERVE'
|
|
else
|
|
Result := Result + #9 + 'ON COMPLETION PRESERVE';
|
|
if ObjectExists and (DBObject.Name <> editName.Text) then
|
|
Result := Result + CRLF + #9 + 'RENAME TO ' + DBObject.Connection.QuoteIdent(editName.Text);
|
|
Result := Result + CRLF + #9 + UpperCase(grpState.Items[grpState.ItemIndex]);
|
|
Result := Result + CRLF + #9 + 'COMMENT ' + DBObject.Connection.EscapeString(editComment.Text);
|
|
Result := Result + CRLF + #9 + 'DO ' + SynMemoBody.Text;
|
|
end;
|
|
|
|
|
|
procedure TfrmEventEditor.PageControlMainChange(Sender: TObject);
|
|
begin
|
|
UpdateSQLcode;
|
|
TExtForm.PageControlTabHighlight(PageControlMain);
|
|
end;
|
|
|
|
|
|
procedure TfrmEventEditor.UpdateSQLcode;
|
|
var
|
|
OldTopLine: Integer;
|
|
begin
|
|
if (PageControlMain.ActivePage = tabALTERCode) and (not AlterCodeValid) then begin
|
|
SynMemoALTERcode.BeginUpdate;
|
|
OldTopLine := SynMemoALTERcode.TopLine;
|
|
SynMemoALTERcode.Text := ComposeAlterStatement;
|
|
SynMemoALTERcode.TopLine := OldTopLine;
|
|
SynMemoALTERcode.EndUpdate;
|
|
AlterCodeValid := True;
|
|
end else if (PageControlMain.ActivePage = tabCREATECode) and (not CreateCodeValid) then begin
|
|
SynMemoCREATEcode.BeginUpdate;
|
|
OldTopLine := SynMemoCREATEcode.TopLine;
|
|
SynMemoCREATEcode.Text := ComposeCreateStatement;
|
|
SynMemoCREATEcode.TopLine := OldTopLine;
|
|
SynMemoCREATEcode.EndUpdate;
|
|
CreateCodeValid := True;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TfrmEventEditor.radioScheduleClick(Sender: TObject);
|
|
var
|
|
IsOnce: Boolean;
|
|
begin
|
|
IsOnce := radioOnce.Checked;
|
|
dateOnce.Enabled := IsOnce;
|
|
timeOnce.Enabled := IsOnce;
|
|
editEveryQuantity.Enabled := not IsOnce;
|
|
udEveryQuantity.Enabled := not IsOnce;
|
|
comboEveryInterval.Enabled := not IsOnce;
|
|
comboEveryIntervalChange(Sender);
|
|
chkStarts.Enabled := not IsOnce;
|
|
chkEnds.Enabled := not IsOnce;
|
|
chkStartsEndsClick(Sender);
|
|
Modification(Sender);
|
|
end;
|
|
|
|
|
|
procedure TfrmEventEditor.chkStartsEndsClick(Sender: TObject);
|
|
begin
|
|
// Enable/disable start+end controls
|
|
dateStarts.Enabled := chkStarts.Checked and chkStarts.Enabled;
|
|
timeStarts.Enabled := chkStarts.Checked and chkStarts.Enabled;
|
|
dateEnds.Enabled := chkEnds.Checked and chkEnds.Enabled;
|
|
timeEnds.Enabled := chkEnds.Checked and chkEnds.Enabled;
|
|
Modification(Sender);
|
|
end;
|
|
|
|
|
|
procedure TfrmEventEditor.comboDefinerDropDown(Sender: TObject);
|
|
begin
|
|
// Populate definers from mysql.user
|
|
(Sender as TComboBox).Items.Assign(DBObject.Connection.AllUserHostCombinations);
|
|
end;
|
|
|
|
|
|
procedure TfrmEventEditor.comboEveryIntervalChange(Sender: TObject);
|
|
begin
|
|
// To enter DAY_HOUR values editor has to accept "1-2"
|
|
if Pos('_', comboEveryInterval.Text) > 0 then begin
|
|
udEveryQuantity.Associate := nil;
|
|
udEveryQuantity.Enabled := False;
|
|
end else begin
|
|
udEveryQuantity.Associate := editEveryQuantity;
|
|
udEveryQuantity.Enabled := True;
|
|
end;
|
|
Modification(Sender);
|
|
end;
|
|
|
|
procedure TfrmEventEditor.btnDiscardClick(Sender: TObject);
|
|
begin
|
|
// Reinit editor, discarding changes
|
|
Modified := False;
|
|
Init(DBObject);
|
|
end;
|
|
|
|
|
|
procedure TfrmEventEditor.btnHelpClick(Sender: TObject);
|
|
begin
|
|
Help(Self, 'createevent');
|
|
end;
|
|
|
|
|
|
end.
|