unit event_editor; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, SynEdit, SynMemo, SynRegExpr, ComCtrls, ExtCtrls, WideStrUtils, helpers, dbconnection; 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; 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); private { Private declarations } AlterCodeValid, CreateCodeValid: Boolean; function ComposeCreateStatement: String; function ComposeAlterStatement: String; function ComposeBaseStatement: String; procedure UpdateSQLcode; public { Public declarations } constructor Create(AOwner: TComponent); override; destructor Destroy; 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'); end; destructor TfrmEventEditor.Destroy; begin // Store GUI setup? Nothing yet. inherited; end; procedure TfrmEventEditor.Init(Obj: TDBObject); var CreateCode, DateExpr: String; rx: TRegExpr; d: TDateTime; i: Integer; begin inherited; editName.Clear; editComment.Clear; 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 DBObject.Name <> '' then begin // Edit mode tabALTERcode.TabVisible := True; editName.Text := DBObject.Name; // CREATE 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 := '\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; end; radioScheduleClick(Self); Modified := False; btnSave.Enabled := Modified; btnDiscard.Enabled := Modified; Mainform.ShowStatusMsg; 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 DBObject.Name = '' then sql := ComposeCreateStatement else sql := ComposeAlterStatement; try MainForm.ActiveConnection.Query(sql); DBObject.Name := editName.Text; DBObject.CreateCode := ''; tabALTERcode.TabVisible := DBObject.Name <> ''; Mainform.UpdateEditorTab; Mainform.RefreshTree(DBObject); Modified := False; btnSave.Enabled := Modified; btnDiscard.Enabled := Modified; AlterCodeValid := False; CreateCodeValid := False; UpdateSQLcode; except on E:EDatabaseError do begin ErrorDialog(E.Message); Result := mrAbort; end; end; end; function TfrmEventEditor.ComposeCreateStatement: String; begin Result := 'CREATE EVENT ' + DBObject.Connection.QuoteIdent(editName.Text) + ' ' + ComposeBaseStatement; end; function TfrmEventEditor.ComposeAlterStatement: String; begin Result := 'ALTER EVENT ' + DBObject.Connection.QuoteIdent(DBObject.Name) + ' ' + ComposeBaseStatement; end; function TfrmEventEditor.ComposeBaseStatement: String; var d: TDateTime; Quantity: String; begin // Return CREATE EVENT statement Result := 'ON SCHEDULE' + CRLF + #9#9; if radioOnce.Checked then begin d := dateOnce.DateTime; ReplaceTime(d, timeOnce.DateTime); Result := Result + 'AT ' + esc(DateTimeToStr(d)) + CRLF; end else begin if udEveryQuantity.Enabled then Quantity := IntToStr(udEveryQuantity.Position) else Quantity := esc(editEveryQuantity.Text); Result := Result + 'EVERY ' + Quantity + ' ' + comboEveryInterval.Text; if chkStarts.Checked then begin d := dateStarts.DateTime; ReplaceTime(d, timeStarts.DateTime); Result := Result + ' STARTS ' + esc(DateTimeToStr(d)); end; if chkEnds.Checked then begin d := dateEnds.DateTime; ReplaceTime(d, timeEnds.DateTime); Result := Result + ' ENDS ' + esc(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 (DBObject.Name <> '') 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 ' + esc(editComment.Text); Result := Result + CRLF + #9 + 'DO ' + SynMemoBody.Text; end; procedure TfrmEventEditor.PageControlMainChange(Sender: TObject); begin UpdateSQLcode; 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.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); var keyword: String; begin if DBObject.Name = '' then keyword := 'CREATE EVENT' else keyword := 'ALTER EVENT'; Mainform.CallSQLHelpWithKeyword(keyword); end; end.