-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathudatamodule.pas
242 lines (212 loc) · 5.94 KB
/
udatamodule.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
unit uDataModule;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, DB, PQConnection, SQLDB;
type
{ TdmPgEngine }
TdmPgEngine = class(TDataModule)
dsTasks: TDataSource;
dsChains: TDataSource;
connMain: TPQConnection;
qryChains: TSQLQuery;
qryTasks: TSQLQuery;
transChains: TSQLTransaction;
procedure connMainLog(Sender: TSQLConnection; EventType: TDBEventType;
const Msg: String);
procedure connMainLogin(Sender: TObject; Username, Password: string);
procedure qryChainsAfterClose(DataSet: TDataSet);
procedure qryChainsAfterDelete(DataSet: TDataSet);
procedure qryChainsAfterInsert(DataSet: TDataSet);
procedure qryAfterPost(DataSet: TDataSet);
procedure qryChainsBeforeDelete(DataSet: TDataSet);
procedure qryTasksAfterInsert(DataSet: TDataSet);
procedure qryTasksAfterOpen(DataSet: TDataSet);
procedure qryTasksBeforePost(DataSet: TDataSet);
private
const
DEFAULT_ORDER_DELTA: double = 10.0;
var
FLastTaskOrder: double;
public
procedure Connect;
procedure Disconnect;
function IsCronValueValid(const S: string): boolean;
function IsConnected: boolean;
function SelectSQL(const sql: string; params: array of string; out Output: string): boolean;
procedure MoveTaskUp(const ATaskID: integer);
procedure MoveTaskDown(const ATaskID: integer);
function IsTaskDeleteAllowed: boolean;
end;
var
dmPgEngine: TdmPgEngine;
implementation
uses uObjects, fmMain, fmConnect, Dialogs, System.UITypes;
{$R *.lfm}
{ TdmPgEngine }
procedure TdmPgEngine.connMainLog(Sender: TSQLConnection;
EventType: TDBEventType; const Msg: String);
const et: array[TDBEventType] of string = ('detCustom', 'detPrepare', 'detExecute',
'detFetch', 'detCommit', 'detRollBack', 'detParamValue', 'detActualSQL');
begin
with MainForm.mmLog.Lines do
begin
Append(Format('[%s:] %s' + LineEnding, [et[EventType], Msg]))
end;
end;
procedure TdmPgEngine.connMainLogin(Sender: TObject; Username, Password: string);
begin
if not fmConnect.EditDatabase(Sender as TPQConnection) then Abort();
end;
procedure TdmPgEngine.qryChainsAfterClose(DataSet: TDataSet);
begin
with DataSet as TSQLQuery do
IndexName := '';
end;
procedure TdmPgEngine.qryChainsAfterDelete(DataSet: TDataSet);
begin
(DataSet as TSQLQuery).ApplyUpdates;
end;
procedure TdmPgEngine.qryChainsAfterInsert(DataSet: TDataSet);
begin
with DataSet do
begin
FieldByName('live').AsBoolean := True;
FieldByName('self_destruct').AsBoolean := False;
FieldByName('exclusive_execution').AsBoolean := False;
FieldByName('run_at').AsString := '* * * * *';
FieldByName('timeout').AsInteger := 0;
end;
end;
procedure TdmPgEngine.qryAfterPost(DataSet: TDataSet);
var
B: TBookmark;
Q: TSQLQuery;
begin
Q := DataSet as TSQLQuery;
Q.IndexName := '';
B := DataSet.GetBookmark;
try
Q.ApplyUpdates;
DataSet.Refresh;
except
on E: EDatabaseError do
begin
MessageDlg('Database Error', E.Message, mtError, [mbOK], 0);
Q.CancelUpdates;
end;
end;
DataSet.GotoBookmark(B);
if Q = qryChains then
fmMain.MainForm.UpdateSortIndication(nil);
end;
procedure TdmPgEngine.qryChainsBeforeDelete(DataSet: TDataSet);
begin
if MessageDlg('Delete confirmation',
'Are you sure you want delete current chain?', mtWarning, [mbOK, mbCancel], 0) = mrCancel then
Abort();
end;
procedure TdmPgEngine.qryTasksAfterInsert(DataSet: TDataSet);
begin
with DataSet do
begin
FieldByName('chain_id').AsLargeInt := qryChains.FieldByName('chain_id').AsLargeInt;
FieldByName('task_order').AsFloat := FLastTaskOrder + DEFAULT_ORDER_DELTA;
FieldByName('kind').AsString := 'SQL';
FieldByName('ignore_error').AsBoolean := False;
FieldByName('autonomous').AsBoolean := False;
end;
end;
procedure TdmPgEngine.qryTasksAfterOpen(DataSet: TDataSet);
begin
DataSet.Last();
FLastTaskOrder := DataSet.FieldByName('task_order').AsInteger;
end;
procedure TdmPgEngine.qryTasksBeforePost(DataSet: TDataSet);
begin
if DataSet.FieldByName('command').IsNull then Abort();
end;
procedure TdmPgEngine.Connect;
begin
qryChains.Open;
qryTasks.Open;
qryChains.First;
end;
procedure TdmPgEngine.Disconnect;
begin
connMain.Close(True);
end;
function TdmPgEngine.IsCronValueValid(const S: string): boolean;
var
Q: TSQLQuery;
begin
Result := True;
Q := TSQLQuery.Create(nil);
try
Q.DataBase := connMain;
Q.Transaction := connMain.Transaction;
Q.SQL.Text := 'SELECT CAST(:cron AS timetable.cron)';
Q.ParamByName('cron').AsString := S;
try
Q.Open;
except
Exit(False);
end;
Q.Close;
finally
FreeAndNil(Q);
end;
end;
function TdmPgEngine.IsConnected: boolean;
begin
Result := qryChains.Active and qryTasks.Active;
end;
function TdmPgEngine.SelectSQL(const sql: string; params: array of string; out Output: string): boolean;
var
Q: TSQLQuery;
i: Integer;
begin
Result := True;
Output := '';
Q := TSQLQuery.Create(nil);
try
Q.DataBase := connMain;
Q.Transaction := connMain.Transaction;
Q.SQL.Text := sql;
for i := Low(params) to High(params) do
Q.Params[i].AsString := params[i];
try
Q.Open;
while not Q.EOF do
begin
Output := Output + Q.Fields[0].AsString + LineEnding;
Q.Next;
end;
except
on E: Exception do
begin
Result := False;
if E is EPQDatabaseError then
Output := EPQDatabaseError(E).MESSAGE_PRIMARY
else
Output := E.Message;
end;
end;
Q.Close;
finally
FreeAndNil(Q);
end;
end;
procedure TdmPgEngine.MoveTaskUp(const ATaskID: integer);
begin
connMain.ExecuteDirect(Format('SELECT timetable.move_task_up(%d)', [ATaskID]));
end;
procedure TdmPgEngine.MoveTaskDown(const ATaskID: integer);
begin
connMain.ExecuteDirect(Format('SELECT timetable.move_task_down(%d)', [ATaskID]));
end;
function TdmPgEngine.IsTaskDeleteAllowed: boolean;
begin
Result := not qryTasks.BOF and not qryTasks.EOF;
end;
end.