ADOUpdateSQL源码

  1 {***************************************************************
  2  *
  3  * Unit Name: ADOUpdateSQL
  4  * Purpose  :
  5  * Author   : Fred Schetterer
  6  * History  : 12-Mar-2000 - Created
  7  *
  8  * Copyright ?1994-2000 by FreDsterWare ComputerTools Ltd.
  9  *
 10  ****************************************************************}
 11 
 12 unit ADOUpdateSQL;
 13 
 14 interface
 15 
 16 uses
 17    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 18    Db, ADOInt, ADODB;
 19 
 20 type
 21    TUpdateErrorEvent = procedure(DataSet: TDataSet; E: EDatabaseError; UpdateKind: TUpdateKind; var UpdateAction: TUpdateAction) of object;
 22    TADOUpdateSQL = class;
 23 
 24    TADOUpdDataSet = class(TADODataSet)
 25    private
 26       { Private declarations }
 27       FUpdateObject: TADOUpdateSQL;
 28       FOnUpdateRecord: TUpdateRecordEvent;
 29       fOnUpdateError: TUpdateErrorEvent;
 30       procedure SetUpdateObject(Value: TADOUpdateSQL);
 31       function UpdatePending(var UpdateKind: TUpdateKind): boolean;
 32    protected
 33       { Protected declarations }
 34       procedure ApplyUpdates(AffectRecords: TAffectRecords);
 35    public
 36       { Public declarations }
 37       procedure UpdateBatch(AffectRecords: TAffectRecords = arAll); reintroduce;
 38    published
 39       { Published declarations }
 40       property UpdateObject: TADOUpdateSQL read FUpdateObject write SetUpdateObject;
 41       { Events }
 42       //property OnUpdateRecord: TUpdateRecordEvent read FOnUpdateRecord write FOnUpdateRecord;
 43       property OnUpdateError: TUpdateErrorEvent read fOnUpdateError write fOnUpdateError;
 44    end;
 45 
 46    TADOUpdateSQL = class(TComponent)
 47    private
 48       { Private declarations }
 49       FDataSet: TADOUpdDataSet;
 50       FQueries: array[TUpdateKind] of TADOQuery;
 51       FSQLText: array[TUpdateKind] of TStrings;
 52       function GetQuery(UpdateKind: TUpdateKind): TADOQuery;
 53       function GetSQL(UpdateKind: TUpdateKind): TStrings;
 54       function GetSQLIndex(Index: Integer): TStrings;
 55       procedure SetSQL(UpdateKind: TUpdateKind; Value: TStrings);
 56       procedure SetSQLIndex(Index: Integer; Value: TStrings);
 57    protected
 58       { Protected declarations }
 59       function GetDataSet: TADOUpdDataSet;
 60       procedure SetDataSet(ADataSet: TADOUpdDataSet);
 61       procedure SQLChanged(Sender: TObject);
 62    public
 63       { Public declarations }
 64       constructor Create(AOwner: TComponent); override;
 65       destructor Destroy; override;
 66       property DataSet: TADOUpdDataSet read GetDataSet write SetDataSet;
 67       procedure Apply(UpdateKind: TUpdateKind);
 68       procedure ExecSQL(UpdateKind: TUpdateKind);
 69       procedure SetParams(UpdateKind: TUpdateKind);
 70       property Query[UpdateKind: TUpdateKind]: TADOQuery read GetQuery;
 71       property SQL[UpdateKind: TUpdateKind]: TStrings read GetSQL write SetSQL;
 72    published
 73       { Published declarations }
 74       property ModifySQL: TStrings index 0 read GetSQLIndex write SetSQLIndex;
 75       property InsertSQL: TStrings index 1 read GetSQLIndex write SetSQLIndex;
 76       property DeleteSQL: TStrings index 2 read GetSQLIndex write SetSQLIndex;
 77    end;
 78 
 79 procedure Register;
 80 
 81 implementation
 82 
 83 resourcestring
 84    rsUpdateFailed                       = Update failed;
 85 
 86 procedure Register;
 87 begin
 88    RegisterComponents(FreDsterWare, [TADOUpdDataSet, TADOUpdateSQL]);
 89 end;
 90 
 91 { TADOUpdDataSet }
 92 
 93 {-----------------------------------------------------
 94           TADOUpdDataSet.SetUpdateObject
 95 
 96  * Purpose  : Set the UpdateObject
 97               If another dataset already references this updateobject, then remove the reference
 98  * Author   : Fred Schetterer
 99  * History  :
100               12-Mar-2000 - Created
101 --------------------------------------------------------}
102 
103 procedure TADOUpdDataSet.SetUpdateObject(Value: TADOUpdateSQL);
104 begin
105    if Value <> FUpdateObject then
106    begin
107       if Assigned(FUpdateObject) and (FUpdateObject.DataSet = Self) then
108          FUpdateObject.DataSet := nil;
109       FUpdateObject := Value;
110       if Assigned(FUpdateObject) then
111       begin
112          if Assigned(FUpdateObject.DataSet) and
113             (FUpdateObject.DataSet <> Self) then
114             FUpdateObject.DataSet.UpdateObject := nil;
115          FUpdateObject.DataSet := Self;
116       end;
117    end;
118 end;
119 {-----------------------------------------------------
120           TADOUpdDataSet.UpdateBatch
121 
122  * Purpose  :
123  * Author   : Fred Schetterer
124  * History  :
125               12-Mar-2000 - Created
126 --------------------------------------------------------}
127 
128 procedure TADOUpdDataSet.UpdateBatch(AffectRecords: TAffectRecords);
129 begin
130    if Assigned(FUpdateObject)
131       or Assigned(FOnUpdateRecord) then
132       ApplyUpdates(AffectRecords)
133    else
134       inherited UpdateBatch(AffectRecords);
135 end;
136 {-----------------------------------------------------
137           TADOUpdDataSet.ApplyUpdates
138 
139  * Purpose  :
140  * Author   : Fred Schetterer
141  * History  :
142               12-Mar-2000 - Created
143 --------------------------------------------------------}
144 
145 procedure TADOUpdDataSet.ApplyUpdates(AffectRecords: TAffectRecords);
146 var
147    UpdateAction                         : TUpdateAction;
148    UpdateKind                           : TUpdateKind;
149    SavedFilter                          : string;
150    SavedFilterGroup                     : TFilterGroup;
151    wasFiltered                          : Boolean;
152 
153    RequeryNeeded                        : Boolean;
154 begin
155 
156    SavedFilter := Filter;
157    SavedFilterGroup := FilterGroup;
158    wasFiltered := Filtered;
159    FilterGroup := fgNone;
160    RequeryNeeded := False;
161 
162    CheckBrowseMode;
163    if not isEmpty then
164    begin
165       DisableControls;
166       try
167          UpdateCursorPos;
168          if not (RecordSet.EOF and RecordSet.BOF) then
169          begin
170             RecordSet.Filter := adFilterPendingRecords;
171             if not (RecordSet.EOF and RecordSet.BOF) then
172             begin
173                RecordSet.MoveFirst;
174                while not RecordSet.Eof do
175                begin
176                   if (Recordset.Status and adRecDeleted) = adRecDeleted then
177                   begin
178                      UpdateAction := uaFail;
179                      UpdateKind := ukDelete;
180                      try
181                         RequeryNeeded := True;
182                         Recordset.CancelBatch(adAffectCurrent);
183                         FUpdateObject.Apply(UpdateKind);
184                      except
185                         on E: EDatabaseError do
186                            if Assigned(OnUpdateError) then
187                               OnUpdateError(Self, E, UpdateKind, UpdateAction)
188                      end;
189                   end;
190                   RecordSet.MoveNext;
191                end;
192             end;
193             RecordSet.Filter := adFilterPendingRecords;
194          end;
195 
196          FilterGroup := fgPendingRecords;
197          Filtered := true;
198          if not (EOF and BOF) then
199          begin
200             First;
201             while not Eof do
202             begin
203                UpdateCursorPos;
204                if UpdatePending(UpdateKind) then
205                begin
206                   RequeryNeeded := RequeryNeeded or (UpdateKind <> ukModify);
207                   UpdateAction := uaFail;
208                   if Assigned(FOnUpdateRecord) then
209                      FOnUpdateRecord(self, UpdateKind, UpdateAction)
210                   else
211                   begin
212                      try
213                         FUpdateObject.Apply(UpdateKind);
214                      except
215                         on E: EDatabaseError do
216                            if Assigned(OnUpdateError) then
217                               OnUpdateError(Self, E, UpdateKind, UpdateAction)
218                      end;
219                      Recordset.CancelBatch(adAffectCurrent);
220                   end;
221                end;
222                Next;
223             end;
224          end;
225       finally
226          FilterGroup := fgNone;
227          FilterGroup := SavedFilterGroup;
228          Filter := SavedFilter;
229          Filtered := wasFiltered;
230 
231          if RequeryNeeded then
232             Requery
233          else
234             Refresh;
235          EnableControls;
236       end;
237    end;
238 end;
239 {-----------------------------------------------------
240           TADOUpdDataSet.UpdatePending
241 
242  * Purpose  : Map UpdateStatus to UpdateKind
243  * Author   : Fred Schetterer
244  * History  :
245               12-Mar-2000 - Created
246 --------------------------------------------------------}
247 
248 function TADOUpdDataSet.UpdatePending(var UpdateKind: TUpdateKind): boolean;
249 var
250    AUpdateStatus                        : TUpdateStatus;
251 begin
252    AUpdateStatus := UpdateStatus;
253    Result := (AUpdateStatus <> usUnmodified);
254    if Result then
255       UpdateKind := TUpdateKind(Ord(AUpdateStatus) - 1);
256 end;
257 
258 { TADOUpdateSQL }
259 
260 {-----------------------------------------------------
261           TADOUpdateSQL.Apply
262 
263  * Purpose  :
264  * Author   : Fred Schetterer
265  * History  :
266               12-Mar-2000 - Created
267 --------------------------------------------------------}
268 
269 procedure TADOUpdateSQL.Apply(UpdateKind: TUpdateKind);
270 begin
271    SetParams(UpdateKind);
272    ExecSQL(UpdateKind);
273 end;
274 {-----------------------------------------------------
275           TADOUpdateSQL.Create
276 
277  * Purpose  :
278  * Author   : Fred Schetterer
279  * History  :
280               12-Mar-2000 - Created
281 --------------------------------------------------------}
282 
283 constructor TADOUpdateSQL.Create(AOwner: TComponent);
284 var
285    UpdateKind                           : TUpdateKind;
286 begin
287    inherited Create(AOwner);
288    for UpdateKind := Low(TUpdateKind) to High(TUpdateKind) do
289    begin
290       FSQLText[UpdateKind] := TStringList.Create;
291       TStringList(FSQLText[UpdateKind]).OnChange := SQLChanged;
292    end;
293 
294 {$IFDEF UNREGISTERED}
295    if not (csDesigning in ComponentState) then              { running outside IDE}
296       if (FindWindowEx(0, 0, TAppBuilder, nil) = 0) then
297       begin                                                 { Delphi not found}
298          Application.NormalizeTopMosts;
299          ShowMessage(Self.ClassName +  is NOT a public domain product, if you find it usefull then please register it..);
300          Application.RestoreTopMosts;
301       end;
302 {$ENDIF}
303 
304 end;
305 
306 {-----------------------------------------------------
307           TADOUpdateSQL.Destroy
308 
309  * Purpose  :
310  * Author   : Fred Schetterer
311  * History  :
312               12-Mar-2000 - Created
313 --------------------------------------------------------}
314 
315 destructor TADOUpdateSQL.Destroy;
316 var
317    UpdateKind                           : TUpdateKind;
318 begin
319    if Assigned(FDataSet) and (FDataSet.UpdateObject = Self) then
320       FDataSet.UpdateObject := nil;
321    for UpdateKind := Low(TUpdateKind) to High(TUpdateKind) do
322       FSQLText[UpdateKind].Free;
323    inherited Destroy;
324 end;
325 {-----------------------------------------------------
326           TADOUpdateSQL.ExecSQL
327 
328  * Purpose  :
329  * Author   : Fred Schetterer
330  * History  :
331               12-Mar-2000 - Created
332 --------------------------------------------------------}
333 
334 procedure TADOUpdateSQL.ExecSQL(UpdateKind: TUpdateKind);
335 begin
336    with Query[UpdateKind] do
337    begin
338       Prepared := True;
339       ExecSQL;
340       if (RowsAffected = 0) then
341          DatabaseError(rsUpdateFailed);
342    end;
343 end;
344 
345 {-----------------------------------------------------
346           TADOUpdateSQL.GetQuery
347 
348  * Purpose  :
349  * Author   : Fred Schetterer
350  * History  :
351               12-Mar-2000 - Created
352 --------------------------------------------------------}
353 
354 function TADOUpdateSQL.GetQuery(UpdateKind: TUpdateKind): TADOQuery;
355 begin
356    if not Assigned(FQueries[UpdateKind]) then
357    begin
358       FQueries[UpdateKind] := TADOQuery.Create(Self);
359       FQueries[UpdateKind].SQL.Assign(FSQLText[UpdateKind]);
360       if Assigned(FDataSet.Connection) then
361          FQueries[UpdateKind].Connection := FDataSet.Connection
362       else
363          FQueries[UpdateKind].ConnectionString := FDataSet.ConnectionString;
364    end;
365    Result := FQueries[UpdateKind];
366 end;
367 
368 {-----------------------------------------------------
369           TADOUpdateSQL.GetSQL
370 
371  * Purpose  :
372  * Author   : Fred Schetterer
373  * History  :
374               12-Mar-2000 - Created
375 --------------------------------------------------------}
376 
377 function TADOUpdateSQL.GetSQL(UpdateKind: TUpdateKind): TStrings;
378 begin
379    Result := FSQLText[UpdateKind];
380 end;
381 {-----------------------------------------------------
382           TADOUpdateSQL.GetSQLIndex
383 
384  * Purpose  :
385  * Author   : Fred Schetterer
386  * History  :
387               12-Mar-2000 - Created
388 --------------------------------------------------------}
389 
390 function TADOUpdateSQL.GetSQLIndex(Index: Integer): TStrings;
391 begin
392    Result := FSQLText[TUpdateKind(Index)];
393 end;
394 {-----------------------------------------------------
395           TADOUpdateSQL.GetDataSet
396 
397  * Purpose  :
398  * Author   : Fred Schetterer
399  * History  :
400               12-Mar-2000 - Created
401 --------------------------------------------------------}
402 
403 function TADOUpdateSQL.GetDataSet: TADOUpdDataSet;
404 begin
405    Result := FDataSet;
406 end;
407 {-----------------------------------------------------
408           TADOUpdateSQL.SetDataSet
409 
410  * Purpose  :
411  * Author   : Fred Schetterer
412  * History  :
413               12-Mar-2000 - Created
414 --------------------------------------------------------}
415 
416 procedure TADOUpdateSQL.SetDataSet(ADataSet: TADOUpdDataSet);
417 begin
418    FDataSet := ADataSet;
419 end;
420 
421 {-----------------------------------------------------
422           TADOUpdateSQL.SetParams
423 
424  * Purpose  :
425  * Author   : Fred Schetterer
426  * History  :
427               12-Mar-2000 - Created
428 --------------------------------------------------------}
429 
430 procedure TADOUpdateSQL.SetParams(UpdateKind: TUpdateKind);
431 var
432    I                                    : Integer;
433    isOld                                : Boolean;
434    Parameter                            : TParameter;
435    ParameterName                        : string;
436    AValue                               : Variant;
437    ADOField                             : OleVariant;
438 begin
439    if not Assigned(FDataSet) then Exit;
440 
441    with Query[UpdateKind] do
442    begin
443       Parameters.ParseSQL(SQL.Text, True);
444       for I := 0 to Parameters.Count - 1 do
445       begin
446          Parameter := Parameters.Items[I];
447          ParameterName := Parameter.Name;
448          isOld := CompareText (Copy(ParameterName, 1, 4), OLD_) = 0;
449          if isOld then
450             System.Delete(ParameterName, 1, 4);
451          if not Assigned(FDataSet.FindField(ParameterName)) then
452             Continue;
453 
454          ADOField := FDataSet.Recordset.Fields[ParameterName];
455          if isOld then
456             AValue := ADOField.OriginalValue
457          else
458             if VarIsEmpty(ADOField.Value) or VarIsNull(ADOField.Value) then
459          begin
460             Parameter.ParameterObject.Type_ := FDataSet.Recordset.Fields[ParameterName].Type_;
461             AValue := NULL;
462          end
463          else
464             AValue := ADOField.Value;
465          Parameter.Value := AValue;
466       end;
467    end;
468 
469 end;
470 
471 {-----------------------------------------------------
472           TADOUpdateSQL.SetSQL
473 
474  * Purpose  :
475  * Author   : Fred Schetterer
476  * History  :
477               12-Mar-2000 - Created
478 --------------------------------------------------------}
479 
480 procedure TADOUpdateSQL.SetSQL(UpdateKind: TUpdateKind; Value: TStrings);
481 begin
482    FSQLText[UpdateKind].Assign(Value);
483 end;
484 {-----------------------------------------------------
485           TADOUpdateSQL.SetSQLIndex
486 
487  * Purpose  :
488  * Author   : Fred Schetterer
489  * History  :
490               12-Mar-2000 - Created
491 --------------------------------------------------------}
492 
493 procedure TADOUpdateSQL.SetSQLIndex(Index: Integer; Value: TStrings);
494 begin
495    SetSQL(TUpdateKind(Index), Value);
496 end;
497 {-----------------------------------------------------
498           TADOUpdateSQL.SQLChanged
499 
500  * Purpose  :
501  * Author   : Fred Schetterer
502  * History  :
503               12-Mar-2000 - Created
504 --------------------------------------------------------}
505 
506 procedure TADOUpdateSQL.SQLChanged(Sender: TObject);
507 var
508    UpdateKind                           : TUpdateKind;
509 begin
510    for UpdateKind := Low(TUpdateKind) to High(TUpdateKind) do
511       if Sender = FSQLText[UpdateKind] then
512       begin
513          if Assigned(FQueries[UpdateKind]) then
514          begin
515             FQueries[UpdateKind].Parameters.Clear;
516             FQueries[UpdateKind].SQL.Assign(FSQLText[UpdateKind]);
517          end;
518          Break;
519       end;
520 end;
521 
522 end.

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。