mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-05 16:11:44 +02:00
* QueryOptions for disconnected mode and autoapplyupdates
git-svn-id: trunk@29088 -
This commit is contained in:
parent
475a9e1617
commit
a53fca1b67
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user