00001 {*********************************************************}
00002 { }
00003 { Zeos Database Objects }
00004 { Abstract Read/Write Dataset component }
00005 { }
00006 { Originally written by Sergey Seroukhov }
00007 { }
00008 {*********************************************************}
00009
00010 {@********************************************************}
00011 { Copyright (c) 1999-2006 Zeos Development Group }
00012 { }
00013 { License Agreement: }
00014 { }
00015 { This library is distributed in the hope that it will be }
00016 { useful, but WITHOUT ANY WARRANTY; without even the }
00017 { implied warranty of MERCHANTABILITY or FITNESS FOR }
00018 { A PARTICULAR PURPOSE. See the GNU Lesser General }
00019 { Public License for more details. }
00020 { }
00021 { The source code of the ZEOS Libraries and packages are }
00022 { distributed under the Library GNU General Public }
00023 { License (see the file COPYING / COPYING.ZEOS) }
00024 { with the following modification: }
00025 { As a special exception, the copyright holders of this }
00026 { library give you permission to link this library with }
00027 { independent modules to produce an executable, }
00028 { regardless of the license terms of these independent }
00029 { modules, and to copy and distribute the resulting }
00030 { executable under terms of your choice, provided that }
00031 { you also meet, for each linked independent module, }
00032 { the terms and conditions of the license of that module. }
00033 { An independent module is a module which is not derived }
00034 { from or based on this library. If you modify this }
00035 { library, you may extend this exception to your version }
00036 { of the library, but you are not obligated to do so. }
00037 { If you do not wish to do so, delete this exception }
00038 { statement from your version. }
00039 { }
00040 { }
00041 { The project web site is located on: }
00042 { http:
00043 { http:
00044 { svn:
00045 { }
00046 { http:
00047 { http:
00048 { }
00049 { }
00050 { }
00051 { Zeos Development Group. }
00052 {********************************************************@}
00053
00054 unit ZAbstractDataset;
00055
00056 interface
00057
00058 {$I ZComponent.inc}
00059
00060 uses
00061 {$IFNDEF VER130BELOW}
00062 Types,
00063 Variants,
00064 {$ENDIF}
00065 SysUtils, DB, Classes, ZSqlUpdate, ZDbcIntfs, ZVariant,
00066 ZDbcCache, ZDbcCachedResultSet, ZAbstractRODataset,
00067 ZCompatibility, ZSequence;
00068
00069 type
00070 {$IFDEF FPC}
00071 TUpdateAction = (uaFail, uaAbort, uaSkip, uaRetry, uaApplied);
00072 {$ENDIF}
00073
00074 {** Update Event type. }
00075 TUpdateRecordEvent = procedure(DataSet: TDataSet; UpdateKind: TUpdateKind;
00076 var UpdateAction: TUpdateAction) of object;
00077
00078 {** Defines update modes for the resultsets. }
00079 TZUpdateMode = (umUpdateChanged, umUpdateAll);
00080
00081 {** Defines where form types for resultsets. }
00082 TZWhereMode = (wmWhereKeyOnly, wmWhereAll);
00083
00084 {**
00085 Abstract dataset component which supports read/write access and
00086 cached updates.
00087 }
00088 TZAbstractDataset = class(TZAbstractRODataset)
00089 private
00090 FCachedUpdates: Boolean;
00091 FUpdateObject: TZUpdateSQL;
00092 FCachedResultSet: IZCachedResultSet;
00093 FCachedResolver: IZCachedResolver;
00094 FOnApplyUpdateError: TDataSetErrorEvent;
00095 FOnUpdateRecord: TUpdateRecordEvent;
00096 FUpdateMode: TZUpdateMode;
00097 FWhereMode: TZWhereMode;
00098 FSequence: TZSequence;
00099 FSequenceField: string;
00100
00101 FBeforeApplyUpdates: TNotifyEvent; {bangfauzan addition}
00102 FAfterApplyUpdates: TNotifyEvent; {bangfauzan addition}
00103
00104 private
00105 function GetUpdatesPending: Boolean;
00106 procedure SetUpdateObject(Value: TZUpdateSQL);
00107 procedure SetCachedUpdates(Value: Boolean);
00108 procedure SetWhereMode(Value: TZWhereMode);
00109 procedure SetUpdateMode(Value: TZUpdateMode);
00110
00111 protected
00112 property CachedResultSet: IZCachedResultSet read FCachedResultSet
00113 write FCachedResultSet;
00114 property CachedResolver: IZCachedResolver read FCachedResolver
00115 write FCachedResolver;
00116 property UpdateMode: TZUpdateMode read FUpdateMode write SetUpdateMode
00117 default umUpdateChanged;
00118 property WhereMode: TZWhereMode read FWhereMode write SetWhereMode
00119 default wmWhereKeyOnly;
00120
00121 procedure InternalClose; override;
00122 procedure InternalEdit; override;
00123 procedure InternalAddRecord(Buffer: Pointer; Append: Boolean); override;
00124 procedure InternalPost; override;
00125 procedure InternalDelete; override;
00126 procedure InternalUpdate;
00127 procedure InternalCancel; override;
00128
00129 procedure DOBeforeApplyUpdates; {bangfauzan addition}
00130 procedure DOAfterApplyUpdates; {bangfauzan addition}
00131
00132
00133 function CreateStatement(const SQL: string; Properties: TStrings):
00134 IZPreparedStatement; override;
00135 function CreateResultSet(const SQL: string; MaxRows: Integer):
00136 IZResultSet; override;
00137 procedure Notification(AComponent: TComponent; Operation: TOperation);
00138 override;
00139
00140 {$IFDEF WITH_IPROVIDER}
00141 function PSUpdateRecord(UpdateKind: TUpdateKind;
00142 Delta: TDataSet): Boolean; override;
00143 {$ENDIF}
00144
00145 public
00146 constructor Create(AOwner: TComponent); override;
00147 destructor Destroy; override;
00148
00149 procedure ApplyUpdates;
00150 procedure CommitUpdates;
00151 procedure CancelUpdates;
00152 procedure RevertRecord;
00153
00154 procedure EmptyDataSet; {bangfauzan addition}
00155
00156 public
00157 property UpdatesPending: Boolean read GetUpdatesPending;
00158 property Sequence: TZSequence read FSequence write FSequence;
00159 property SequenceField: string read FSequenceField write FSequenceField;
00160
00161 published
00162 property UpdateObject: TZUpdateSQL read FUpdateObject write SetUpdateObject;
00163 property CachedUpdates: Boolean read FCachedUpdates write SetCachedUpdates
00164 default False;
00165
00166 property OnApplyUpdateError: TDataSetErrorEvent read FOnApplyUpdateError
00167 write FOnApplyUpdateError;
00168 property OnUpdateRecord: TUpdateRecordEvent read FOnUpdateRecord
00169 write FOnUpdateRecord;
00170
00171 property BeforeApplyUpdates: TNotifyEvent read FBeforeApplyUpdates
00172 write FBeforeApplyUpdates; {bangfauzan addition}
00173 property AfterApplyUpdates: TNotifyEvent read FAfterApplyUpdates
00174 write FAfterApplyUpdates; {bangfauzan addition}
00175
00176
00177 published
00178
00179 property BeforeInsert;
00180 property AfterInsert;
00181 property BeforeEdit;
00182 property AfterEdit;
00183 property BeforePost;
00184 property AfterPost;
00185 property BeforeCancel;
00186 property AfterCancel;
00187 property BeforeDelete;
00188 property AfterDelete;
00189 property OnDeleteError;
00190 property OnEditError;
00191 property OnPostError;
00192 property OnNewRecord;
00193 end;
00194
00195 implementation
00196
00197 uses Math, ZMessages, ZDatasetUtils;
00198
00199 { TZAbstractDataset }
00200
00201 {**
00202 Constructs this object and assignes the mail properties.
00203 @param AOwner a component owner.
00204 }
00205 constructor TZAbstractDataset.Create(AOwner: TComponent);
00206 begin
00207 inherited Create(AOwner);
00208
00209 FWhereMode := wmWhereKeyOnly;
00210 FUpdateMode := umUpdateChanged;
00211 RequestLive := True;
00212 end;
00213
00214 {**
00215 Destroys this object and cleanups the memory.
00216 }
00217 destructor TZAbstractDataset.Destroy;
00218 begin
00219 inherited Destroy;
00220 end;
00221
00222 {**
00223 Sets a new UpdateSQL object.
00224 @param Value a new UpdateSQL object.
00225 }
00226 procedure TZAbstractDataset.SetUpdateObject(Value: TZUpdateSQL);
00227 begin
00228 if FUpdateObject <> Value then
00229 begin
00230 if Assigned(FUpdateObject) then
00231 FUpdateObject.RemoveFreeNotification(Self);
00232 FUpdateObject := Value;
00233 if Assigned(FUpdateObject) then
00234 FUpdateObject.FreeNotification(Self);
00235 if Assigned(FUpdateObject) then
00236 FUpdateObject.DataSet := Self;
00237 if Active and (CachedResultSet <> nil) then
00238 begin
00239 if FUpdateObject <> nil then
00240 CachedResultSet.SetResolver(FUpdateObject)
00241 else
00242 CachedResultSet.SetResolver(CachedResolver);
00243 end;
00244 end;
00245 end;
00246
00247 {**
00248 Sets a new CachedUpdates property value.
00249 @param Value a new CachedUpdates value.
00250 }
00251 procedure TZAbstractDataset.SetCachedUpdates(Value: Boolean);
00252 begin
00253 if FCachedUpdates <> Value then
00254 begin
00255 FCachedUpdates := Value;
00256 if Active and (CachedResultSet <> nil) then
00257 CachedResultSet.SetCachedUpdates(Value);
00258 end;
00259 end;
00260
00261 {**
00262 Sets a new UpdateMode property value.
00263 @param Value a new UpdateMode value.
00264 }
00265 procedure TZAbstractDataset.SetUpdateMode(Value: TZUpdateMode);
00266 begin
00267 if FUpdateMode <> Value then
00268 begin
00269 FUpdateMode := Value;
00270 if Active then Close;
00271 end;
00272 end;
00273
00274 {**
00275 Sets a new WhereMode property value.
00276 @param Value a new WhereMode value.
00277 }
00278 procedure TZAbstractDataset.SetWhereMode(Value: TZWhereMode);
00279 begin
00280 if FWhereMode <> Value then
00281 begin
00282 FWhereMode := Value;
00283 if Active then Close;
00284 end;
00285 end;
00286
00287 {**
00288 Creates a DBC statement for the query.
00289 @param SQL an SQL query.
00290 @param Properties a statement specific properties.
00291 @returns a created DBC statement.
00292 }
00293 function TZAbstractDataset.CreateStatement(
00294 const SQL: string; Properties: TStrings): IZPreparedStatement;
00295 var
00296 Temp: TStrings;
00297 begin
00298 Temp := TStringList.Create;
00299 try
00300 Temp.AddStrings(Properties);
00301
00302 { Sets update mode property.}
00303 case FUpdateMode of
00304 umUpdateAll: Temp.Values['update'] := 'all';
00305 umUpdateChanged: Temp.Values['update'] := 'changed';
00306 end;
00307 { Sets where mode property. }
00308 case FWhereMode of
00309 wmWhereAll: Temp.Values['where'] := 'all';
00310 wmWhereKeyOnly: Temp.Values['where'] := 'keyonly';
00311 end;
00312
00313 Result := inherited CreateStatement(SQL, Temp);
00314 finally
00315 Temp.Free;
00316 end;
00317 end;
00318
00319 {**
00320 Creates a DBC resultset for the query.
00321 @param SQL an SQL query.
00322 @param MaxRows a maximum rows number (-1 for all).
00323 @returns a created DBC resultset.
00324 }
00325 function TZAbstractDataset.CreateResultSet(const SQL: string; MaxRows: Integer):
00326 IZResultSet;
00327 begin
00328 Result := inherited CreateResultSet(SQL, MaxRows);
00329
00330 if not Assigned(Result) then
00331 Exit;
00332
00333 if Result.QueryInterface(IZCachedResultSet, FCachedResultSet) = 0 then
00334 begin
00335 CachedResultSet := Result as IZCachedResultSet;
00336 CachedResolver := CachedResultSet.GetResolver;
00337 CachedResultSet.SetCachedUpdates(CachedUpdates);
00338 if FUpdateObject <> nil then
00339 CachedResultSet.SetResolver(FUpdateObject);
00340 end;
00341 end;
00342
00343 {**
00344 Performs internal query closing.
00345 }
00346 procedure TZAbstractDataset.InternalClose;
00347 begin
00348 inherited InternalClose;
00349
00350 if Assigned(CachedResultSet) then
00351 CachedResultSet.Close;
00352 CachedResultSet := nil;
00353 CachedResolver := nil;
00354 end;
00355
00356 {**
00357 Performs an internal action before switch into edit mode.
00358 }
00359 procedure TZAbstractDataset.InternalEdit;
00360 begin
00361 end;
00362
00363 {**
00364 Performs an internal record updates.
00365 }
00366 procedure TZAbstractDataset.InternalUpdate;
00367 var
00368 RowNo: Integer;
00369 RowBuffer: PZRowBuffer;
00370 begin
00371 if (CachedResultSet <> nil) and GetActiveBuffer(RowBuffer) then
00372 begin
00373 RowNo := Integer(CurrentRows[CurrentRow - 1]);
00374 CachedResultSet.MoveAbsolute(RowNo);
00375 RowAccessor.RowBuffer := RowBuffer;
00376 PostToResultSet(CachedResultSet, FieldsLookupTable, Fields, RowAccessor);
00377 try
00378 CachedResultSet.UpdateRow;
00379 except on E: EZSQLThrowable do
00380 raise EZDatabaseError.CreateFromException(E);
00381 end;
00382
00383 { Filters the row }
00384 if not FilterRow(RowNo) then
00385 begin
00386 CurrentRows.Delete(CurrentRow - 1);
00387 CurrentRow := Min(CurrentRows.Count, CurrentRow);
00388 end;
00389 end;
00390 end;
00391
00392 {**
00393 Performs an internal adding a new record.
00394 @param Buffer a buffer of the new adding record.
00395 @param Append <code>True</code> if record should be added to the end
00396 of the result set.
00397 }
00398 procedure TZAbstractDataset.InternalAddRecord(Buffer: Pointer; Append: Boolean);
00399 var
00400 RowNo: Integer;
00401 RowBuffer: PZRowBuffer;
00402 begin
00403 if not GetActiveBuffer(RowBuffer) or (RowBuffer <> Buffer) then
00404 raise EZDatabaseError.Create(SInternalError);
00405
00406 if Append then FetchRows(0);
00407
00408 if CachedResultSet <> nil then
00409 begin
00410 CachedResultSet.MoveToInsertRow;
00411 RowAccessor.RowBuffer := RowBuffer;
00412 PostToResultSet(CachedResultSet, FieldsLookupTable, Fields, RowAccessor);
00413 try
00414 CachedResultSet.InsertRow;
00415 except on E: EZSQLThrowable do
00416 raise EZDatabaseError.CreateFromException(E);
00417 end;
00418 RowNo := CachedResultSet.GetRow;
00419 FetchCount := FetchCount + 1;
00420
00421 { Filters the row }
00422 if FilterRow(RowNo) then
00423 begin
00424 if Append then
00425 begin
00426 CurrentRows.Add(Pointer(RowNo));
00427 CurrentRow := CurrentRows.Count;
00428 end
00429 else
00430 begin
00431 CurrentRow := Max(CurrentRow, 1);
00432 CurrentRows.Insert(CurrentRow - 1, Pointer(RowNo));
00433 end;
00434 end;
00435 end;
00436 end;
00437
00438 {**
00439 Performs an internal post updates.
00440 }
00441 procedure TZAbstractDataset.InternalPost;
00442 var
00443 RowBuffer: PZRowBuffer;
00444 BM:TBookMarkStr;
00445 begin
00446 if (FSequenceField <> '') and Assigned(FSequence) then
00447 begin
00448 if FieldByName(FSequenceField).IsNull then
00449 {$IFDEF VER130}
00450 FieldByName(FSequenceField).AsString := IntToStr(FSequence.GetNextValue);
00451 {$ELSE}
00452 FieldByName(FSequenceField).Value := FSequence.GetNextValue;
00453 {$ENDIF}
00454 end;
00455
00456 inherited;
00457
00458 if not GetActiveBuffer(RowBuffer) then
00459 raise EZDatabaseError.Create(SInternalError);
00460
00461 Connection.ShowSqlHourGlass;
00462 try
00463 if State = dsInsert then
00464 InternalAddRecord(RowBuffer, False)
00465 else InternalUpdate;
00466
00467 {BUG-FIX: bangfauzan addition}
00468 if (SortedFields<>'') then begin
00469 FreeFieldBuffers;
00470 SetState(dsBrowse);
00471 Resync([]);
00472 BM:=Bookmark;
00473 DisableControls;
00474 InternalSort;
00475 BookMark:=BM;
00476 UpdateCursorPos;
00477 EnableControls;
00478 end;
00479 {end of bangfauzan addition}
00480 finally
00481 Connection.HideSqlHourGlass;
00482 end;
00483 end;
00484
00485 {**
00486 Performs an internal record removing.
00487 }
00488 procedure TZAbstractDataset.InternalDelete;
00489 var
00490 RowNo: Integer;
00491 RowBuffer: PZRowBuffer;
00492 begin
00493 if (CachedResultSet <> nil) and GetActiveBuffer(RowBuffer) then
00494 begin
00495 Connection.ShowSqlHourGlass;
00496 try
00497 RowNo := Integer(CurrentRows[CurrentRow - 1]);
00498 CachedResultSet.MoveAbsolute(RowNo);
00499 try
00500 CachedResultSet.DeleteRow;
00501 except on E: EZSQLThrowable do
00502 raise EZDatabaseError.CreateFromException(E);
00503 end;
00504
00505 { Filters the row }
00506 if not FilterRow(RowNo) then
00507 begin
00508 CurrentRows.Delete(CurrentRow - 1);
00509 if not FetchRows(CurrentRow) then
00510 CurrentRow := Min(CurrentRows.Count, CurrentRow);
00511 end;
00512 finally
00513 Connection.HideSQLHourGlass;
00514 end;
00515 end;
00516 end;
00517
00518 {**
00519 Performs an internal cancel updates.
00520 }
00521 procedure TZAbstractDataset.InternalCancel;
00522 var
00523 RowNo: Integer;
00524 RowBuffer: PZRowBuffer;
00525 begin
00526 if (CachedResultSet <> nil) and GetActiveBuffer(RowBuffer)
00527 and (CurrentRow > 0) and (State = dsEdit) then
00528 begin
00529 RowNo := Integer(CurrentRows[CurrentRow - 1]);
00530 CachedResultSet.MoveAbsolute(RowNo);
00531 RowAccessor.RowBuffer := RowBuffer;
00532 FetchFromResultSet(CachedResultSet, FieldsLookupTable, Fields, RowAccessor);
00533 end;
00534 end;
00535
00536 {**
00537 Processes component notifications.
00538 @param AComponent a changed component object.
00539 @param Operation a component operation code.
00540 }
00541 procedure TZAbstractDataset.Notification(AComponent: TComponent;
00542 Operation: TOperation);
00543 begin
00544 inherited Notification(AComponent, Operation);
00545
00546 if (Operation = opRemove) then
00547 begin
00548 if (AComponent = FUpdateObject) then
00549 begin
00550 Close;
00551 FUpdateObject := nil;
00552 end;
00553 if (AComponent = FSequence) then
00554 begin
00555 FSequence := nil;
00556 end;
00557 end;
00558 end;
00559
00560 {**
00561 Applies all cached updates stored in the resultset.
00562 }
00563 procedure TZAbstractDataset.ApplyUpdates;
00564 begin
00565 if not Active then Exit;
00566
00567 Connection.ShowSQLHourGlass;
00568 try
00569 if State in [dsEdit, dsInsert] then Post;
00570
00571 DoBeforeApplyUpdates; {bangfauzan addition}
00572
00573 if CachedResultSet <> nil then
00574 CachedResultSet.PostUpdates;
00575
00576 if not (State in [dsInactive]) then
00577 Resync([]);
00578
00579 DOAfterApplyUpdates; {bangfauzan addition}
00580
00581 finally
00582 Connection.HideSqlHourGlass;
00583 end;
00584 end;
00585
00586 {**
00587 Clears cached updates buffer.
00588 }
00589 procedure TZAbstractDataset.CommitUpdates;
00590 begin
00591 CheckBrowseMode;
00592
00593 if CachedResultSet <> nil then
00594 CachedResultSet.CancelUpdates;
00595 end;
00596
00597 {**
00598 Cancels all cached updates and clears the buffer.
00599 }
00600 procedure TZAbstractDataset.CancelUpdates;
00601 begin
00602 if State in [dsEdit, dsInsert] then Cancel;
00603
00604 if CachedResultSet <> nil then
00605 CachedResultSet.CancelUpdates;
00606
00607 if not (State in [dsInactive]) then
00608 RereadRows;
00609 end;
00610
00611 {**
00612 Reverts the previous status for the current row.
00613 }
00614 procedure TZAbstractDataset.RevertRecord;
00615 begin
00616 if State in [dsInsert] then
00617 begin
00618 Cancel;
00619 Exit;
00620 end;
00621 if State in [dsEdit] then Cancel;
00622
00623 if CachedResultSet <> nil then
00624 CachedResultSet.RevertRecord;
00625
00626 if not (State in [dsInactive]) then Resync([]);
00627 end;
00628
00629 {**
00630 Checks is there cached updates pending in the buffer.
00631 @return <code>True</code> if there some pending cached updates.
00632 }
00633 function TZAbstractDataset.GetUpdatesPending: Boolean;
00634 begin
00635 if State = dsInactive then
00636 Result := False
00637 else if (CachedResultSet <> nil) and CachedResultSet.IsPendingUpdates then
00638 Result := True
00639 else if (State in [dsInsert, dsEdit]) then
00640 Result := Modified
00641 else Result := False;
00642 end;
00643
00644 {$IFDEF WITH_IPROVIDER}
00645
00646 {**
00647 Applies a single update to the underlying database table or tables.
00648 @param UpdateKind an update type.
00649 @param Delta a dataset where the current position shows the row to update.
00650 @returns <code>True</code> if updates were successfully applied.
00651 }
00652 function TZAbstractDataset.PSUpdateRecord(UpdateKind: TUpdateKind;
00653 Delta: TDataSet): Boolean;
00654
00655 var
00656 Bookmark: TBookmark;
00657 ActiveMode: Boolean;
00658 UpdateMode: Boolean;
00659
00660 function LocateRecord: Boolean;
00661 var
00662 I: Integer;
00663 KeyFields: string;
00664 Temp: Variant;
00665 SrcField: TField;
00666 KeyValues: Variant;
00667 FieldRefs: TObjectDynArray;
00668 OnlyDataFields: Boolean;
00669 begin
00670 if Properties.Values['KeyFields'] <> '' then
00671 KeyFields := Properties.Values['KeyFields']
00672 else
00673 KeyFields := DefineKeyFields(Fields);
00674 FieldRefs := DefineFields(Self, KeyFields, OnlyDataFields);
00675 Temp := VarArrayCreate([0, Length(FieldRefs) - 1], varVariant);
00676
00677 for I := 0 to Length(FieldRefs) - 1 do
00678 begin
00679 SrcField := Delta.FieldByName(TField(FieldRefs[I]).FieldName);
00680 if SrcField <> nil then
00681 begin
00682 if (SrcField.DataType = ftLargeInt)
00683 and not VarIsNull(SrcField.OldValue) then
00684 Temp[I] := Integer(SrcField.OldValue)
00685 else Temp[I] := SrcField.OldValue;
00686 end else
00687 Temp[I] := Null;
00688 end;
00689
00690 if Length(FieldRefs) = 1 then
00691 KeyValues := Temp[0]
00692 else KeyValues := Temp;
00693
00694 if KeyFields <> '' then
00695 Result := Locate(KeyFields, KeyValues, [])
00696 else Result := False;
00697 end;
00698
00699 procedure CopyRecord(SrcDataset: TDataset; DestDataset: TDataset);
00700 var
00701 I: Integer;
00702 SrcField: TField;
00703 DestField: TField;
00704 SrcStream: TStream;
00705 DestStream: TStream;
00706 begin
00707 for I := 0 to DestDataset.FieldCount - 1 do
00708 begin
00709 DestField := DestDataset.Fields[I];
00710 SrcField := SrcDataset.FieldByName(DestField.FieldName);
00711 if (SrcField = nil) or VarIsEmpty(SrcField.NewValue) then
00712 Continue;
00713
00714 if SrcField.IsNull then
00715 begin
00716 DestField.Clear;
00717 Continue;
00718 end;
00719
00720 case DestField.DataType of
00721 ftLargeInt:
00722 begin
00723 if SrcField.DataType = ftLargeInt then
00724 begin
00725 TLargeIntField(DestField).AsLargeInt :=
00726 TLargeIntField(SrcField).AsLargeInt;
00727 end else
00728 DestField.AsInteger := SrcField.AsInteger;
00729 end;
00730 ftBlob, ftMemo:
00731 begin
00732 if SrcField.DataType in [ftBlob, ftMemo] then
00733 begin
00734 SrcStream := SrcDataset.CreateBlobStream(SrcField, bmRead);
00735 try
00736 DestStream := DestDataset.CreateBlobStream(DestField, bmWrite);
00737 try
00738 DestStream.CopyFrom(SrcStream, 0);
00739 finally
00740 DestStream.Free;
00741 end;
00742 finally
00743 SrcStream.Free;
00744 end;
00745 end else
00746 DestField.AsVariant := SrcField.AsVariant;
00747 end;
00748 else
00749 DestField.AsVariant := SrcField.AsVariant;
00750 end;
00751 end;
00752 end;
00753
00754 begin
00755 Result := False;
00756 ActiveMode := Self.Active;
00757 UpdateMode := Self.RequestLive;
00758
00759 if Self.RequestLive = False then
00760 Self.RequestLive := True;
00761 if Self.Active = False then
00762 Self.Open;
00763
00764 CheckBrowseMode;
00765 try
00766 Self.DisableControls;
00767
00768 { Saves the current position. }
00769 Bookmark := Self.GetBookmark;
00770
00771 { Applies updates. }
00772 try
00773 case UpdateKind of
00774 ukModify:
00775 begin
00776 if LocateRecord then
00777 begin
00778 Self.Edit;
00779 CopyRecord(Delta, Self);
00780 Self.Post;
00781 Result := True;
00782 end;
00783 end;
00784 ukInsert:
00785 begin
00786 Self.Append;
00787 CopyRecord(Delta, Self);
00788 Self.Post;
00789 Result := True;
00790 end;
00791 ukDelete:
00792 begin
00793 if LocateRecord then
00794 begin
00795 Self.Delete;
00796 Result := True;
00797 end;
00798 end;
00799 end;
00800 except
00801 Result := False;
00802 end;
00803
00804 { Restores the previous position. }
00805 try
00806 Self.GotoBookmark(Bookmark);
00807 except
00808 Self.First;
00809 end;
00810 Self.FreeBookmark(Bookmark);
00811 finally
00812 EnableControls;
00813 Self.RequestLive := UpdateMode;
00814 Self.Active := ActiveMode;
00815 end;
00816 end;
00817
00818 {$ENDIF}
00819
00820 {============================bangfauzan addition===================}
00821
00822 procedure TZAbstractDataset.DOBeforeApplyUpdates;
00823 begin
00824 if assigned(BeforeApplyUpdates) then
00825 FBeforeApplyUpdates(Self);
00826 end;
00827
00828 procedure TZAbstractDataset.DOAfterApplyUpdates;
00829 begin
00830 if assigned(AfterApplyUpdates) then
00831 FAfterApplyUpdates(Self);
00832 end;
00833
00834 procedure TZAbstractDataset.EmptyDataSet;
00835 begin
00836 if Active then
00837 begin
00838 Self.CancelUpdates;
00839 Self.CurrentRows.Clear;
00840 Self.CurrentRow:=0;
00841 Resync([]);
00842 InitRecord(ActiveBuffer);
00843 end;
00844 end;
00845
00846 {========================end of bangfauzan addition================}
00847
00848
00849 end.