* QueryOptions for disconnected mode and autoapplyupdates

git-svn-id: trunk@29088 -
This commit is contained in:
michael 2014-11-17 12:24:46 +00:00
parent 475a9e1617
commit a53fca1b67
6 changed files with 295 additions and 38 deletions

View File

@ -504,7 +504,6 @@ type
procedure SetIndexFieldNames(const AValue: String);
procedure SetIndexName(AValue: String);
procedure SetMaxIndexesCount(const AValue: Integer);
procedure SetPacketRecords(aValue : integer);
procedure SetBufUniDirectional(const AValue: boolean);
// indexes handling
procedure InitDefaultIndexes;
@ -513,6 +512,7 @@ type
procedure RemoveRecordFromIndexes(const ABookmark : TBufBookmark);
protected
// abstract & virtual methods of TDataset
procedure SetPacketRecords(aValue : integer); virtual;
procedure UpdateIndexDefs; override;
procedure SetRecNo(Value: Longint); override;
function GetRecNo: Longint; override;

View File

@ -379,15 +379,27 @@ begin
DatabaseError(SErrNoDatabaseAvailable,Self)
end;
Function TDBTransaction.AllowClose(DS : TDBDataset) : Boolean;
begin
Result:=Assigned(DS);
end;
procedure TDBTransaction.CloseDataSets;
Var I : longint;
Var
I : longint;
DS : TDBDataset;
begin
If Assigned(FDatasets) then
begin
For I:=FDatasets.Count-1 downto 0 do
TDBDataset(FDatasets[i]).Close;
begin
DS:=TDBDataset(FDatasets[i]);
If AllowClose(DS) then
DS.Close;
end;
end;
end;

View File

@ -1607,7 +1607,7 @@ type
function CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream; virtual;
procedure CursorPosChanged;
procedure DataConvert(aField: TField; aSource, aDest: Pointer; aToNative: Boolean); virtual;
procedure Delete;
procedure Delete; virtual;
procedure DisableControls;
procedure Edit;
procedure EnableControls;
@ -1878,6 +1878,7 @@ type
procedure RemoveDataSets;
procedure SetActive(Value : boolean);
Protected
Function AllowClose(DS: TDBDataset): Boolean; virtual;
Procedure SetDatabase (Value : TDatabase); virtual;
procedure CloseTrans;
procedure openTrans;

View File

@ -112,6 +112,7 @@ Resourcestring
SErrNoFieldsDefined = 'Can not create a dataset when there are no fielddefinitions or fields defined';
SErrApplyUpdBeforeRefresh= 'Must apply updates before refreshing data';
SErrNoDataset = 'Missing (compatible) underlying dataset, can not open';
SErrDisconnectedPacketRecords = 'For disconnected TSQLQuery instances, packetrecords must be -1';
Implementation

View File

@ -24,8 +24,9 @@ uses SysUtils, Classes, DB, bufdataset, sqlscript;
type
TSchemaType = (stNoSchema, stTables, stSysTables, stProcedures, stColumns, stProcedureParams, stIndexes, stPackages, stSchemata);
TConnOption = (sqSupportParams, sqSupportEmptyDatabaseName, sqEscapeSlash, sqEscapeRepeat);
TConnOption = (sqSupportParams, sqSupportEmptyDatabaseName, sqEscapeSlash, sqEscapeRepeat, sqImplicitTransaction);
TConnOptions= set of TConnOption;
TConnInfoType=(citAll=-1, citServerType, citServerVersion, citServerVersionString, citClientName, citClientVersion);
TStatementType = (stUnknown, stSelect, stInsert, stUpdate, stDelete,
stDDL, stGetSegment, stPutSegment, stExecProcedure,
@ -56,6 +57,9 @@ type
TDBEventTypes = set of TDBEventType;
TDBLogNotifyEvent = Procedure (Sender : TSQLConnection; EventType : TDBEventType; Const Msg : String) of object;
TSQLQueryOption = (sqoDisconnected, sqoAutoApplyUpdates);
TSQLQueryOptions = Set of TSQLQueryOption;
TSQLHandle = Class(TObject)
end;
@ -153,11 +157,13 @@ type
FStatements : TFPList;
FLogEvents: TDBEventTypes;
FOnLog: TDBLogNotifyEvent;
FInternalTransaction : TSQLTransaction;
function GetPort: cardinal;
procedure SetPort(const AValue: cardinal);
protected
FConnOptions : TConnOptions;
FSQLFormatSettings : TFormatSettings;
// Updating of DB records is moved out of TSQLQuery.
// It is done here, so descendents can override it and implement DB-specific.
// One day, this may be factored out to a TSQLResolver class.
@ -170,7 +176,6 @@ type
procedure ApplyFieldUpdate(C : TSQLCursor; P: TSQLDBParam; F: TField; UseOldValue: Boolean); virtual;
// This is the call that updates a record, it used to be in TSQLQuery.
procedure ApplyRecUpdate(Query : TCustomSQLQuery; UpdateKind : TUpdateKind); virtual;
//
procedure GetDBInfo(const ASchemaType : TSchemaType; const ASchemaObjectName, AReturnField : string; AList: TStrings);
procedure SetTransaction(Value : TSQLTransaction); virtual;
procedure DoInternalConnect; override;
@ -182,7 +187,6 @@ type
Procedure Log(EventType : TDBEventType; Const Msg : String); virtual;
Procedure RegisterStatement(S : TCustomSQLStatement);
Procedure UnRegisterStatement(S : TCustomSQLStatement);
Function AllocateCursorHandle : TSQLCursor; virtual; abstract;
Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); virtual; abstract;
function StrToStatementType(s : string) : TStatementType; virtual;
@ -258,6 +262,7 @@ type
procedure SetParams(const AValue: TStringList);
procedure SetSQLConnection(AValue: TSQLConnection);
protected
Function AllowClose(DS: TDBDataset): Boolean; override;
function GetHandle : Pointer; virtual;
Procedure SetDatabase (Value : TDatabase); override;
Function LogEvent(EventType : TDBEventType) : Boolean;
@ -279,6 +284,8 @@ type
property Params : TStringList read FParams write SetParams;
end;
{ TCustomSQLStatement }
TCustomSQLStatement = Class(TComponent)
@ -352,6 +359,7 @@ type
TCustomSQLQuery = class (TCustomBufDataset)
private
FQueryOptions: TSQLQueryOptions;
FSchemaType : TSchemaType;
FUpdateable : boolean;
FTableName : string;
@ -387,6 +395,7 @@ type
function GetSQLTransaction: TSQLTransaction;
function GetStatementType : TStatementType;
procedure SetParamCheck(AValue: Boolean);
procedure SetQueryOptions(AValue: TSQLQueryOptions);
procedure SetSQLConnection(AValue: TSQLConnection);
procedure SetSQLTransaction(AValue: TSQLTransaction);
procedure SetUpdateSQL(const AValue: TStringlist);
@ -402,6 +411,7 @@ type
procedure ApplyFilter;
Function AddFilter(SQLstr : string) : string;
protected
procedure SetPacketRecords(aValue : integer); override;
Function Cursor : TSQLCursor;
Function LogEvent(EventType : TDBEventType) : Boolean;
Procedure Log(EventType : TDBEventType; Const Msg : String); virtual;
@ -439,6 +449,8 @@ type
procedure Prepare; virtual;
procedure UnPrepare; virtual;
procedure ExecSQL; virtual;
Procedure Post; override;
Procedure Delete; override;
procedure SetSchemaInfo( ASchemaType : TSchemaType; ASchemaObjectName, ASchemaPattern : string); virtual;
function RowsAffected: TRowsCount; virtual;
function ParamByName(Const AParamName : String) : TParam;
@ -475,6 +487,7 @@ type
property AutoCalcFields;
property Database;
// protected
Property QueryOptions : TSQLQueryOptions Read FQueryOptions Write SetQueryOptions;
property SchemaType : TSchemaType read FSchemaType default stNoSchema;
property Transaction;
property SQL : TStringlist read GetSQL write SetSQL;
@ -530,6 +543,7 @@ type
Property OnPostError;
// property SchemaInfo default stNoSchema;
Property QueryOptions;
property Database;
property Transaction;
property ReadOnly;
@ -729,6 +743,9 @@ begin
SQLState := ASQLState;
end;
Type
TInternalTransaction = Class(TSQLTransaction);
{ TCustomSQLStatement }
procedure TCustomSQLStatement.OnChangeSQL(Sender: TObject);
@ -784,7 +801,7 @@ begin
FDataLink.DataSource:=AValue;
end;
procedure TCustomSQLStatement.CopyParamsFromMaster(CopyBound : Boolean);
Procedure TCustomSQLStatement.CopyParamsFromMaster(CopyBound: Boolean);
begin
if Assigned(DataSource) and Assigned(DataSource.Dataset) then
FParams.CopyParamValuesFromDataset(DataSource.Dataset,CopyBound);
@ -817,7 +834,7 @@ begin
end;
end;
procedure TCustomSQLStatement.DoExecute;
Procedure TCustomSQLStatement.DoExecute;
begin
If (FParams.Count>0) and Assigned(DataSource) then
CopyParamsFromMaster(False);
@ -826,27 +843,27 @@ begin
Database.Execute(FCursor,Transaction, FParams);
end;
function TCustomSQLStatement.GetPrepared: Boolean;
Function TCustomSQLStatement.GetPrepared: Boolean;
begin
Result := Assigned(FCursor) and FCursor.FPrepared;
end;
function TCustomSQLStatement.CreateDataLink: TDataLink;
Function TCustomSQLStatement.CreateDataLink: TDataLink;
begin
Result:=TDataLink.Create;
end;
function TCustomSQLStatement.CreateParams: TSQLDBParams;
Function TCustomSQLStatement.CreateParams: TSQLDBParams;
begin
Result:=TSQLDBParams.Create(Nil);
end;
function TCustomSQLStatement.LogEvent(EventType: TDBEventType): Boolean;
Function TCustomSQLStatement.LogEvent(EventType: TDBEventType): Boolean;
begin
Result:=Assigned(Database) and Database.LogEvent(EventType);
end;
procedure TCustomSQLStatement.Log(EventType: TDBEventType; const Msg: String);
Procedure TCustomSQLStatement.Log(EventType: TDBEventType; Const Msg: String);
Var
M : String;
@ -897,28 +914,29 @@ begin
inherited Destroy;
end;
function TCustomSQLStatement.GetSchemaType: TSchemaType;
Function TCustomSQLStatement.GetSchemaType: TSchemaType;
begin
Result:=stNoSchema
end;
function TCustomSQLStatement.GetSchemaObjectName: String;
Function TCustomSQLStatement.GetSchemaObjectName: String;
begin
Result:='';
end;
function TCustomSQLStatement.GetSchemaPattern: String;
Function TCustomSQLStatement.GetSchemaPattern: String;
begin
Result:='';
end;
function TCustomSQLStatement.IsSelectable: Boolean;
Function TCustomSQLStatement.IsSelectable: Boolean;
begin
Result:=False;
end;
procedure TCustomSQLStatement.GetStatementInfo(var ASQL: String; out Info: TSQLStatementInfo);
begin
@ -961,7 +979,7 @@ begin
Database.PrepareStatement(FCursor,Transaction,FServerSQL,FParams);
end;
procedure TCustomSQLStatement.Prepare;
Procedure TCustomSQLStatement.Prepare;
begin
if Prepared then exit;
@ -981,7 +999,7 @@ begin
end;
end;
procedure TCustomSQLStatement.Execute;
Procedure TCustomSQLStatement.Execute;
begin
Prepare;
DoExecute;
@ -1008,7 +1026,7 @@ begin
Result:=Nil;
end;
procedure TCustomSQLStatement.Unprepare;
Procedure TCustomSQLStatement.Unprepare;
begin
// Some SQLConnections does not support statement [un]preparation, but they have allocated local cursor(s)
// so let them do cleanup f.e. cancel pending queries and/or free resultset
@ -1017,7 +1035,7 @@ begin
DoUnprepare;
end;
function TCustomSQLStatement.ParamByName(const AParamName: String): TParam;
function TCustomSQLStatement.ParamByName(Const AParamName: String): TParam;
begin
Result:=FParams.ParamByName(AParamName);
end;
@ -1072,6 +1090,7 @@ begin
end;
end;
procedure TSQLConnection.UpdateIndexDefs(IndexDefs : TIndexDefs; TableName : string);
begin
// Empty abstract
@ -1152,6 +1171,7 @@ begin
result := StrToIntDef(Params.Values['Port'],0);
end;
procedure TSQLConnection.SetPort(const AValue: cardinal);
begin
if AValue<>0 then
@ -1440,12 +1460,12 @@ begin
Result := nil;
end;
function TSQLConnection.LogEvent(EventType: TDBEventType): Boolean;
Function TSQLConnection.LogEvent(EventType: TDBEventType): Boolean;
begin
Result:=(Assigned(FOnLog) or Assigned(GlobalDBLogHook)) and (EventType in LogEvents);
end;
procedure TSQLConnection.Log(EventType: TDBEventType; const Msg: String);
Procedure TSQLConnection.Log(EventType: TDBEventType; Const Msg: String);
Var
M : String;
@ -1466,18 +1486,19 @@ begin
end;
end;
procedure TSQLConnection.RegisterStatement(S: TCustomSQLStatement);
Procedure TSQLConnection.RegisterStatement(S: TCustomSQLStatement);
begin
if FStatements.IndexOf(S)=-1 then
FStatements.Add(S);
end;
procedure TSQLConnection.UnRegisterStatement(S: TCustomSQLStatement);
Procedure TSQLConnection.UnRegisterStatement(S: TCustomSQLStatement);
begin
if Assigned(FStatements) then // Can be nil, when we are destroying and datasets are uncoupled.
FStatements.Remove(S);
end;
function TSQLConnection.InitialiseUpdateStatement(Query : TCustomSQLQuery; var qry : TCustomSQLStatement): TCustomSQLStatement;
begin
@ -1692,6 +1713,14 @@ begin
Result := SQLConnection.GetTransactionHandle(FTrans);
end;
Function TSQLTransaction.AllowClose(DS: TDBDataset): Boolean;
begin
if (DS is TSQLQuery) then
Result:=not (sqoDisconnected in TSQLQuery(DS).QueryOptions)
else
Result:=Inherited AllowClose(DS);
end;
procedure TSQLTransaction.Commit;
begin
if Active then
@ -1943,7 +1972,7 @@ begin
inherited Destroy;
end;
function TCustomSQLQuery.ParamByName(const AParamName: String): TParam;
function TCustomSQLQuery.ParamByName(Const AParamName: String): TParam;
begin
Result:=Params.ParamByName(AParamName);
@ -1955,7 +1984,7 @@ begin
CheckInactive;
end;
procedure TCustomSQLQuery.SetTransaction(Value: TDBTransaction);
Procedure TCustomSQLQuery.SetTransaction(Value: TDBTransaction);
begin
UnPrepare;
@ -1985,7 +2014,7 @@ begin
end;
end;
function TCustomSQLQuery.IsPrepared: Boolean;
Function TCustomSQLQuery.IsPrepared: Boolean;
begin
if Assigned(Fstatement) then
@ -1994,7 +2023,7 @@ begin
Result := False;
end;
function TCustomSQLQuery.AddFilter(SQLstr: string): string;
Function TCustomSQLQuery.AddFilter(SQLstr: string): string;
begin
if (FWhereStartPos > 0) and (FWhereStopPos > 0) then
@ -2025,7 +2054,7 @@ begin
First;
end;
procedure TCustomSQLQuery.SetActive(Value: Boolean);
Procedure TCustomSQLQuery.SetActive(Value: Boolean);
begin
inherited SetActive(Value);
@ -2056,6 +2085,7 @@ begin
end;
end;
procedure TCustomSQLQuery.Prepare;
begin
@ -2114,7 +2144,15 @@ begin
Result:=Transaction as TSQLTransaction;
end;
function TCustomSQLQuery.Cursor: TSQLCursor;
procedure TCustomSQLQuery.SetPacketRecords(aValue: integer);
begin
if (AValue=PacketRecords) then exit;
if (AValue<>-1) and (sqoDisconnected in QueryOptions) then
DatabaseError(SErrDisconnectedPacketRecords);
Inherited SetPacketRecords(aValue);
end;
Function TCustomSQLQuery.Cursor: TSQLCursor;
begin
Result:=FStatement.Cursor;
end;
@ -2276,6 +2314,20 @@ begin
end;
end;
Procedure TCustomSQLQuery.Post;
begin
inherited Post;
If (sqoAutoApplyUpdates in QueryOptions) then
ApplyUpdates;
end;
Procedure TCustomSQLQuery.Delete;
begin
inherited Delete;
If (sqoAutoApplyUpdates in QueryOptions) then
ApplyUpdates;
end;
procedure TCustomSQLQuery.SetReadOnly(AValue : Boolean);
begin
@ -2364,12 +2416,12 @@ begin
UnPrepareStatement(Cursor);
end;
function TCustomSQLQuery.LogEvent(EventType: TDBEventType): Boolean;
Function TCustomSQLQuery.LogEvent(EventType: TDBEventType): Boolean;
begin
Result:=Assigned(Database) and SQLConnection.LogEvent(EventType);
end;
procedure TCustomSQLQuery.Log(EventType: TDBEventType; const Msg: String);
Procedure TCustomSQLQuery.Log(EventType: TDBEventType; Const Msg: String);
Var
M : String;
@ -2403,6 +2455,15 @@ begin
FStatement.ParamCheck:=AValue;
end;
procedure TCustomSQLQuery.SetQueryOptions(AValue: TSQLQueryOptions);
begin
if FQueryOptions=AValue then Exit;
CheckInactive;
FQueryOptions:=AValue;
if sqoDisconnected in FQueryOptions then
PacketRecords:=-1;
end;
procedure TCustomSQLQuery.SetSQLConnection(AValue: TSQLConnection);
begin
Database:=AValue;
@ -2428,7 +2489,7 @@ begin
FStatement.Params.Assign(AValue);
end;
procedure TCustomSQLQuery.SetDataSource(AValue: TDataSource);
Procedure TCustomSQLQuery.SetDataSource(AValue: TDataSource);
Var
DS : TDataSource;
@ -2445,7 +2506,7 @@ begin
end;
end;
function TCustomSQLQuery.GetDataSource: TDataSource;
Function TCustomSQLQuery.GetDataSource: TDataSource;
begin
If Assigned(FStatement) then

View File

@ -9,7 +9,7 @@ unit TestSQLDB;
interface
uses
Classes, SysUtils, fpcunit, testregistry,
Classes, sqldb, SysUtils, fpcunit, testregistry,
db;
type
@ -25,10 +25,20 @@ type
{ TTestTSQLQuery }
TTestTSQLQuery = class(TSQLDBTestCase)
procedure DoAfterPost(DataSet: TDataSet);
private
FMyQ: TSQLQuery;
Procedure Allow;
Procedure SetQueryOPtions;
Procedure TrySetPacketRecords;
published
procedure TestMasterDetail;
procedure TestUpdateServerIndexDefs;
Procedure TestDisconnected;
Procedure TestDisconnectedPacketRecords;
Procedure TestCheckSettingsOnlyWhenInactive;
Procedure TestAutoApplyUpdatesPost;
Procedure TestAutoApplyUpdatesDelete;
end;
{ TTestTSQLConnection }
@ -50,11 +60,21 @@ type
implementation
uses sqldbtoolsunit, toolsunit, sqldb;
uses sqldbtoolsunit, toolsunit;
{ TTestTSQLQuery }
procedure TTestTSQLQuery.DoAfterPost(DataSet: TDataSet);
begin
AssertTrue('Have modifications in after post',FMyq.UpdateStatus=usModified)
end;
Procedure TTestTSQLQuery.Allow;
begin
end;
procedure TTestTSQLQuery.TestMasterDetail;
var MasterQuery, DetailQuery: TSQLQuery;
MasterSource: TDataSource;
@ -141,6 +161,168 @@ begin
end;
end;
Procedure TTestTSQLQuery.TestDisconnected;
var Q: TSQLQuery;
I, J : Integer;
begin
// Test that for a disconnected SQL query, calling commit does not close the dataset.
// Test also that an edit still works.
with TSQLDBConnector(DBConnector) do
begin
try
ExecuteDirect('DROP table testdiscon');
except
// Ignore
end;
ExecuteDirect('create table testdiscon (id integer not null, a varchar(10), constraint pk_testdiscon primary key(id))');
Transaction.COmmit;
for I:=1 to 20 do
ExecuteDirect(Format('INSERT INTO testdiscon values (%d,''%.6d'')',[i,i]));
Transaction.COmmit;
Q := TSQLDBConnector(DBConnector).Query;
Q.SQL.Text:='select * from testdiscon';
Q.QueryOptions:=[sqoDisconnected];
AssertEquals('PacketRecords forced to -1',-1,Q.PacketRecords);
Q.Open;
AssertEquals('Got all records',20,Q.RecordCount);
Q.SQLTransaction.Commit;
AssertTrue('Still open after transaction',Q.Active);
// Now check editing
Q.Locate('id',20,[]);
Q.Edit;
Q.FieldByName('a').AsString:='abc';
Q.Post;
AssertTrue('Have updates pending',Q.UpdateStatus=usModified);
Q.ApplyUpdates;
AssertTrue('Have no more updates pending',Q.UpdateStatus=usUnmodified);
Q.Close;
Q.SQL.Text:='select * from testdiscon where (id=20) and (a=''abc'')';
Q.Open;
AssertTrue('Have modified data record in database',not (Q.EOF AND Q.BOF));
end;
end;
Procedure TTestTSQLQuery.TrySetPacketRecords;
begin
FMyQ.PacketRecords:=10;
end;
Procedure TTestTSQLQuery.TestDisconnectedPacketRecords;
begin
with TSQLDBConnector(DBConnector) do
begin
FMyQ := TSQLDBConnector(DBConnector).Query;
FMyQ.QueryOptions:=[sqoDisconnected];
AssertException('Cannot set packetrecords when sqoDisconnected is active',EDatabaseError,@TrySetPacketRecords);
end;
end;
Procedure TTestTSQLQuery.SetQueryOPtions;
begin
FMyQ.QueryOptions:=[sqoDisconnected];
end;
Procedure TTestTSQLQuery.TestCheckSettingsOnlyWhenInactive;
begin
// Check that we can only set QueryOptions when the query is inactive.
with TSQLDBConnector(DBConnector) do
begin
try
ExecuteDirect('DROP table testdiscon');
except
// Ignore
end;
ExecuteDirect('create table testdiscon (id integer not null, a varchar(10), constraint pk_testdiscon primary key(id))');
Transaction.COmmit;
ExecuteDirect(Format('INSERT INTO testdiscon values (%d,''%.6d'')',[1,1]));
Transaction.COmmit;
FMyQ := TSQLDBConnector(DBConnector).Query;
FMyQ.SQL.Text:='select * from testdiscon';
FMyQ := TSQLDBConnector(DBConnector).Query;
FMyQ.OPen;
AssertException('Cannot set packetrecords when sqoDisconnected is active',EDatabaseError,@SetQueryOptions);
end;
end;
Procedure TTestTSQLQuery.TestAutoApplyUpdatesPost;
var Q: TSQLQuery;
I, J : Integer;
begin
// Test that if sqoAutoApplyUpdates is in QueryOptions, then POST automatically does an ApplyUpdates
// Test also that POST afterpost event is backwards compatible.
with TSQLDBConnector(DBConnector) do
begin
try
ExecuteDirect('DROP table testdiscon');
except
// Ignore
end;
ExecuteDirect('create table testdiscon (id integer not null, a varchar(10), constraint pk_testdiscon primary key(id))');
Transaction.COmmit;
for I:=1 to 2 do
ExecuteDirect(Format('INSERT INTO testdiscon values (%d,''%.6d'')',[i,i]));
Transaction.COmmit;
Q := TSQLDBConnector(DBConnector).Query;
FMyQ:=Q; // so th event handler can reach it.
Q.SQL.Text:='select * from testdiscon';
Q.QueryOptions:=[ sqoAutoApplyUpdates];
// We must test that in AfterPost, the modification is still there, for backwards compatibilty
Q.AfterPost:=@DoAfterPost;
Q.Open;
AssertEquals('Got all records',2,Q.RecordCount);
// Now check editing
Q.Locate('id',2,[]);
Q.Edit;
Q.FieldByName('a').AsString:='abc';
Q.Post;
AssertTrue('Have no more updates pending',Q.UpdateStatus=usUnmodified);
Q.Close;
Q.SQL.Text:='select * from testdiscon where (id=2) and (a=''abc'')';
Q.Open;
AssertTrue('Have modified data record in database',not (Q.EOF AND Q.BOF));
end;
end;
Procedure TTestTSQLQuery.TestAutoApplyUpdatesDelete;
var Q: TSQLQuery;
I, J : Integer;
begin
// Test that if sqoAutoApplyUpdates is in QueryOptions, then Delete automatically does an ApplyUpdates
with TSQLDBConnector(DBConnector) do
begin
try
ExecuteDirect('DROP table testdiscon');
except
// Ignore
end;
ExecuteDirect('create table testdiscon (id integer not null, a varchar(10), constraint pk_testdiscon primary key(id))');
Transaction.COmmit;
for I:=1 to 2 do
ExecuteDirect(Format('INSERT INTO testdiscon values (%d,''%.6d'')',[i,i]));
Transaction.COmmit;
Q := TSQLDBConnector(DBConnector).Query;
FMyQ:=Q; // so th event handler can reach it.
Q.SQL.Text:='select * from testdiscon';
Q.QueryOptions:=[ sqoAutoApplyUpdates];
// We must test that in AfterPost, the modification is still there, for backwards compatibilty
Q.AfterPost:=@DoAfterPost;
Q.Open;
AssertEquals('Got all records',2,Q.RecordCount);
// Now check editing
Q.Locate('id',2,[]);
Q.Delete;
AssertTrue('Have no more updates pending',Q.UpdateStatus=usUnmodified);
Q.Close;
Q.SQL.Text:='select * from testdiscon where (id=2)';
Q.Open;
AssertTrue('Data record is deleted in database', (Q.EOF AND Q.BOF));
end;
end;
{ TTestTSQLConnection }
procedure TTestTSQLConnection.ReplaceMe;