* restructured the test-suite

+ added several tests
 + added a connector for TMemDataset

git-svn-id: trunk@5745 -
This commit is contained in:
joost 2006-12-29 21:33:20 +00:00
parent 4264f5d041
commit 0cab61a2e0
9 changed files with 1158 additions and 337 deletions

2
.gitattributes vendored
View File

@ -778,7 +778,7 @@ fcl/dbtests/Makefile.fpc -text
fcl/dbtests/database.ini -text
fcl/dbtests/dbftoolsunit.pas -text
fcl/dbtests/dbtestframework.pas -text
fcl/dbtests/settings.inc -text
fcl/dbtests/memdstoolsunit.pas svneol=native#text/plain
fcl/dbtests/sqldbtoolsunit.pas -text
fcl/dbtests/testbasics.pas svneol=native#text/plain
fcl/dbtests/testdbbasics.pas -text

View File

@ -1,31 +1,40 @@
[Database]
type=oracle
type=interbase
[postgresql]
connector=sql
connectorparams=postgresql
name=testdb
user=
password=
hostname=
[mysql40]
name=test
connector=sql
connectorparams=mysql40
name=cnoc02
user=root
password=
password=rosivrepus
hostname=192.168.3.1
[oracle]
connector=sql
connectorparams=oracle
name=xe
user=system
password=
password=rosivrepus
hostname=192.168.3.1
[interbase]
connector=sql
connectorparams=interbase
name=/opt/firebird/examples/employee.fdb
user=sysdba
password=masterkey
password=rosivrepus
[dbf]
connector=dbf
name=/tmp
user=
password=
hostname=
[memds]
connector=memds

View File

@ -8,53 +8,104 @@ interface
uses
Classes, SysUtils, toolsunit,
db,
Dbf, dbf_fields;
db, Dbf;
type
{ TDBFDBConnector }
{ TDBFDBConnector }
TDBFDBConnector = class(TDBConnector)
private
protected
Function CreateNDataset(n : integer) : TDataset; override;
Procedure FreeNDataset(var ds : TDataset); override;
public
destructor Destroy; override;
end;
TDBFDBConnector = class(TDBConnector)
protected
procedure CreateNDatasets; override;
procedure CreateFieldDataset; override;
procedure DropNDatasets; override;
procedure DropFieldDataset; override;
Function InternalGetNDataset(n : integer) : TDataset; override;
Function InternalGetFieldDataset : TDataSet; override;
end;
implementation
destructor TDBFDBConnector.Destroy;
procedure TDBFDBConnector.CreateNDatasets;
var countID,n : integer;
begin
inherited Destroy;
for n := 0 to MaxDataSet do
begin
with TDbf.Create(nil) do
begin
FilePath := dbname;
TableName := 'fpdev_'+inttostr(n)+'.db';
FieldDefs.Add('ID',ftInteger);
FieldDefs.Add('NAME',ftString,50);
CreateTable;
Open;
if n > 0 then for countId := 1 to n do
begin
Append;
FieldByName('ID').AsInteger := countID;
FieldByName('NAME').AsString := 'TestName'+inttostr(countID);
end;
if state = dsinsert then
Post;
Close;
Free;
end;
end;
end;
function TDBFDBConnector.CreateNDataset(n: integer): TDataset;
var countID : integer;
procedure TDBFDBConnector.CreateFieldDataset;
var i : integer;
begin
with TDbf.Create(nil) do
begin
FilePath := dbname;
TableName := 'fpdev_'+inttostr(n)+'.db';
TableName := 'fpdev_field.db';
FieldDefs.Add('ID',ftInteger);
FieldDefs.Add('NAME',ftString,50);
FieldDefs.Add('FSTRING',ftString,10);
FieldDefs.Add('FSMALLINT',ftSmallint);
FieldDefs.Add('FINTEGER',ftInteger);
// FieldDefs.Add('FWORD',ftWord);
FieldDefs.Add('FBOOLEAN',ftBoolean);
FieldDefs.Add('FFLOAT',ftFloat);
// FieldDefs.Add('FCURRENCY',ftCurrency);
// FieldDefs.Add('FBCD',ftBCD);
FieldDefs.Add('FDATE',ftDate);
// FieldDefs.Add('FTIME',ftTime);
FieldDefs.Add('FDATETIME',ftDateTime);
FieldDefs.Add('FLARGEINT',ftLargeint);
CreateTable;
Open;
for countId := 1 to n do
for i := 0 to testValuesCount-1 do
begin
Append;
FieldByName('ID').AsInteger := countID;
FieldByName('NAME').AsString := 'TestName'+inttostr(countID);
end;
if state = dsinsert then
FieldByName('ID').AsInteger := i;
FieldByName('FSTRING').AsString := testStringValues[i];
FieldByName('FSMALLINT').AsInteger := testSmallIntValues[i];
FieldByName('FINTEGER').AsInteger := testIntValues[i];
FieldByName('FBOOLEAN').AsBoolean := testBooleanValues[i];
FieldByName('FFLOAT').AsFloat := testFloatValues[i];
ShortDateFormat := 'yyyy-mm-dd';
FieldByName('FDATE').AsDateTime := StrToDate(testDateValues[i]);
FieldByName('FLARGEINT').AsLargeInt := testLargeIntValues[i];
Post;
end;
Close;
Free;
end;
// A dataset that has been opened and closed can't be used. Or else the tests
// for a newly generated dataset can't work properly.
end;
procedure TDBFDBConnector.DropNDatasets;
var n : integer;
begin
for n := 0 to MaxDataSet do
DeleteFile(ExtractFilePath(dbname)+PathDelim+'fpdev_'+inttostr(n)+'.db');
end;
procedure TDBFDBConnector.DropFieldDataset;
begin
DeleteFile(ExtractFilePath(dbname)+PathDelim+'fpdev_field.db');
end;
function TDBFDBConnector.InternalGetNDataset(n: integer): TDataset;
begin
Result := TDbf.Create(nil);
with (result as TDbf) do
begin
@ -63,11 +114,17 @@ begin
end;
end;
procedure TDBFDBConnector.FreeNDataset(var ds: TDataset);
function TDBFDBConnector.InternalGetFieldDataset: TDataSet;
begin
if ds.Active then ds.close;
FreeAndNil(ds);
Result := TDbf.Create(nil);
with (result as TDbf) do
begin
FilePath := dbname;
TableName := 'fpdev_field.db';
end;
end;
initialization
RegisterClass(TDBFDBConnector);
end.

View File

@ -0,0 +1,116 @@
unit MemDSToolsUnit;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, toolsunit,
db,
Memds;
type
{ TMemDSConnector }
TMemDSDBConnector = class(TDBConnector)
protected
procedure CreateNDatasets; override;
procedure CreateFieldDataset; override;
procedure DropNDatasets; override;
procedure DropFieldDataset; override;
Function InternalGetNDataset(n : integer) : TDataset; override;
Function InternalGetFieldDataset : TDataSet; override;
end;
implementation
{ TMemDSDBConnector }
procedure TMemDSDBConnector.CreateNDatasets;
begin
// All datasets only exist in memory, so nothing has to be done
end;
procedure TMemDSDBConnector.CreateFieldDataset;
begin
// All datasets only exist in memory, so nothing has to be done
end;
procedure TMemDSDBConnector.DropNDatasets;
begin
// All datasets only exist in memory, so nothing has to be done
end;
procedure TMemDSDBConnector.DropFieldDataset;
begin
// All datasets only exist in memory, so nothing has to be done
end;
function TMemDSDBConnector.InternalGetNDataset(n: integer): TDataset;
var MemDS : TMemDataset;
i : integer;
begin
MemDs := TMemDataset.Create(nil);
MemDS.FieldDefs.Add('ID',ftInteger);
MemDS.FieldDefs.Add('NAME',ftString,50);
MemDS.CreateTable;
MemDS.Open;
for i := 1 to n do
begin
memds.Append;
memds.FieldByName('ID').AsInteger := i;
memds.FieldByName('NAME').AsString := 'TestName' + inttostr(i);
MemDS.Post;
end;
MemDS.Close;
Result := MemDS;
end;
function TMemDSDBConnector.InternalGetFieldDataset : TDataSet;
var MemDS : TMemDataset;
i : integer;
begin
MemDs := TMemDataset.Create(nil);
with MemDS do
begin
FieldDefs.Add('ID',ftInteger);
FieldDefs.Add('FSTRING',ftString,10);
FieldDefs.Add('FSMALLINT',ftSmallint);
FieldDefs.Add('FINTEGER',ftInteger);
// FieldDefs.Add('FWORD',ftWord);
FieldDefs.Add('FBOOLEAN',ftBoolean);
FieldDefs.Add('FFLOAT',ftFloat);
// FieldDefs.Add('FCURRENCY',ftCurrency);
// FieldDefs.Add('FBCD',ftBCD);
FieldDefs.Add('FDATE',ftDate);
FieldDefs.Add('FTIME',ftTime);
FieldDefs.Add('FDATETIME',ftDateTime);
FieldDefs.Add('FLARGEINT',ftLargeint);
CreateTable;
Open;
for i := 0 to testValuesCount-1 do
begin
Append;
FieldByName('ID').AsInteger := i;
FieldByName('FSTRING').AsString := testStringValues[i];
FieldByName('FSMALLINT').AsInteger := testSmallIntValues[i];
FieldByName('FINTEGER').AsInteger := testIntValues[i];
FieldByName('FBOOLEAN').AsBoolean := testBooleanValues[i];
FieldByName('FFLOAT').AsFloat := testFloatValues[i];
ShortDateFormat := 'yyyy-mm-dd';
FieldByName('FDATE').AsDateTime := StrToDate(testDateValues[i]);
FieldByName('FLARGEINT').AsLargeInt := testLargeIntValues[i];
Post;
end;
Close;
end;
Result := MemDS;
end;
initialization
RegisterClass(TMemDSDBConnector);
end.

View File

@ -1,6 +0,0 @@
{$IFDEF fpc}
{$define SQLDB_AVAILABLE}
{$define DBF_AVAILABLE}
{$ELSE}
{$DEFINE DBF_AVAILABLE}
{$ENDIF}

View File

@ -9,44 +9,56 @@ uses
db,
sqldb, ibconnection, mysql40conn, mysql41conn, mysql50conn, pqconnection,odbcconn,oracleconnection;
const SQLDBdbTypes = [mysql40,mysql41,mysql50,postgresql,interbase,odbc,oracle];
MySQLdbTypes = [mysql40,mysql41,mysql50];
type TSQLDBTypes = (mysql40,mysql41,mysql50,postgresql,interbase,odbc,oracle);
const MySQLdbTypes = [mysql40,mysql41,mysql50];
DBTypesNames : Array [TSQLDBTypes] of String[19] =
('MYSQL40','MYSQL41','MYSQL50','POSTGRESQL','INTERBASE','ODBC','ORACLE');
type
{ TSQLDBConnector }
TSQLDBConnector = class(TDBConnector)
FConnection : TSQLConnection;
FTransaction : TSQLTransaction;
FQuery : TSQLQuery;
private
procedure CreateFConnection;
procedure CreateFTransaction;
Function CreateQuery : TSQLQuery;
protected
procedure CreateNDatasets; override;
procedure CreateFieldDataset; override;
procedure DropNDatasets; override;
procedure DropFieldDataset; override;
Function InternalGetNDataset(n : integer) : TDataset; override;
Function InternalGetFieldDataset : TDataSet; override;
public
destructor Destroy; override;
constructor Create; override;
property Connection : TSQLConnection read FConnection;
property Transaction : TSQLTransaction read FTransaction;
property Query : TSQLQuery read FQuery;
end;
TSQLDBConnector = class(TDBConnector)
FConnection : TSQLConnection;
FTransaction : TSQLTransaction;
FQuery : TSQLQuery;
private
procedure CreateFConnection;
procedure CreateFTransaction;
Function CreateQuery : TSQLQuery;
protected
Procedure FreeNDataset(var ds : TDataset); override;
Function CreateNDataset(n : integer) : TDataset; override;
public
destructor Destroy; override;
constructor Create;
property Connection : TSQLConnection read FConnection;
property Transaction : TSQLTransaction read FTransaction;
property Query : TSQLQuery read FQuery;
end;
var SQLDbType : TSQLDBTypes;
implementation
procedure TSQLDBConnector.CreateFConnection;
{ TSQLDBConnector }
procedure TSQLDBConnector.CreateFConnection;
var i : TSQLDBTypes;
begin
if dbtype = mysql40 then Fconnection := tMySQL40Connection.Create(nil);
if dbtype = mysql41 then Fconnection := tMySQL41Connection.Create(nil);
if dbtype = mysql50 then Fconnection := tMySQL50Connection.Create(nil);
if dbtype = postgresql then Fconnection := tpqConnection.Create(nil);
if dbtype = interbase then Fconnection := tIBConnection.Create(nil);
if dbtype = odbc then Fconnection := tODBCConnection.Create(nil);
if dbtype = oracle then Fconnection := TOracleConnection.Create(nil);
for i := low(DBTypesNames) to high(DBTypesNames) do
if UpperCase(dbconnectorparams) = DBTypesNames[i] then sqldbtype := i;
if SQLDbType = MYSQL40 then Fconnection := tMySQL40Connection.Create(nil);
if SQLDbType = MYSQL41 then Fconnection := tMySQL41Connection.Create(nil);
if SQLDbType = MYSQL50 then Fconnection := tMySQL50Connection.Create(nil);
if SQLDbType = POSTGRESQL then Fconnection := tpqConnection.Create(nil);
if SQLDbType = INTERBASE then Fconnection := tIBConnection.Create(nil);
if SQLDbType = ODBC then Fconnection := tODBCConnection.Create(nil);
if SQLDbType = ORACLE then Fconnection := TOracleConnection.Create(nil);
if not assigned(Fconnection) then writeln('Invalid database-type, check if a valid database-type was provided in the file ''database.ini''');
@ -60,8 +72,6 @@ begin
end;
end;
{ TSQLDBConnector }
procedure TSQLDBConnector.CreateFTransaction;
begin
@ -81,51 +91,20 @@ begin
end;
end;
destructor TSQLDBConnector.Destroy;
procedure TSQLDBConnector.CreateNDatasets;
var CountID : Integer;
begin
try
if Ftransaction.Active then Ftransaction.Rollback;
Ftransaction.StartTransaction;
Fconnection.ExecuteDirect('DROP TABLE FPDEV');
Ftransaction.Commit;
Except
if Ftransaction.Active then Ftransaction.Rollback
end;
try
if Ftransaction.Active then Ftransaction.Rollback;
Ftransaction.StartTransaction;
Fconnection.ExecuteDirect('DROP TABLE FPDEV2');
Ftransaction.Commit;
Except
if Ftransaction.Active then Ftransaction.Rollback
end;
FreeAndNil(FQuery);
FreeAndNil(FTransaction);
FreeAndNil(FConnection);
inherited Destroy;
end;
constructor TSQLDBConnector.Create;
var countID : integer;
begin
CreateFConnection;
CreateFTransaction;
FQuery := CreateQuery;
FConnection.Transaction := FTransaction;
try
Ftransaction.StartTransaction;
Fconnection.ExecuteDirect('create table FPDEV ( ' +
' ID INT NOT NULL, ' +
' NAME VARCHAR(50) ' +
' NAME VARCHAR(50), ' +
' PRIMARY KEY (ID) ' +
') ');
FTransaction.CommitRetaining;
for countID := 1 to 35 do
for countID := 1 to MaxDataSet do
Fconnection.ExecuteDirect('insert into FPDEV (ID,NAME)' +
'values ('+inttostr(countID)+',''TestName'+inttostr(countID)+''')');
@ -135,21 +114,104 @@ begin
end;
end;
function TSQLDBConnector.CreateNDataset(n: integer): TDataset;
procedure TSQLDBConnector.CreateFieldDataset;
var CountID : Integer;
begin
result := CreateQuery;
with result as TSQLQuery do
try
Ftransaction.StartTransaction;
Fconnection.ExecuteDirect('create table FPDEV_FIELD ( ' +
' ID INT NOT NULL, ' +
' FSTRING VARCHAR(10), ' +
' FINTEGER INT, ' +
' FDATE DATE, ' +
' FDATETIME TIMESTAMP, ' +
' PRIMARY KEY (ID) ' +
') ');
FTransaction.CommitRetaining;
for countID := 0 to testValuesCount-1 do
Fconnection.ExecuteDirect('insert into FPDEV_FIELD (ID,FSTRING,FINTEGER,FDATE,FDATETIME)' +
'values ('+inttostr(countID)+','''+testStringValues[CountID]+''','''+inttostr(testIntValues[CountID])+''','''+testDateValues[CountID]+''','''+testDateValues[CountID]+''')');
Ftransaction.Commit;
except
if Ftransaction.Active then Ftransaction.Rollback
end;
end;
procedure TSQLDBConnector.DropNDatasets;
begin
try
if Ftransaction.Active then Ftransaction.Rollback;
Ftransaction.StartTransaction;
Fconnection.ExecuteDirect('DROP TABLE FPDEV');
Ftransaction.Commit;
Except
if Ftransaction.Active then Ftransaction.Rollback
end;
end;
procedure TSQLDBConnector.DropFieldDataset;
begin
try
if Ftransaction.Active then Ftransaction.Rollback;
Ftransaction.StartTransaction;
Fconnection.ExecuteDirect('DROP TABLE FPDEV_FIELD');
Ftransaction.Commit;
Except
if Ftransaction.Active then Ftransaction.Rollback
end;
end;
function TSQLDBConnector.InternalGetNDataset(n: integer): TDataset;
begin
Result := CreateQuery;
with (Result as TSQLQuery) do
begin
sql.clear;
sql.add('SELECT ID,NAME FROM FPDEV WHERE ID<'+inttostr(n+1));
sql.add('SELECT * FROM FPDEV WHERE ID < '+inttostr(n+1));
end;
end;
procedure TSQLDBConnector.FreeNDataset(var ds: TDataset);
function TSQLDBConnector.InternalGetFieldDataset: TDataSet;
begin
if ds.active then ds.Close;
FreeAndNil(ds);
Result := CreateQuery;
with (Result as TSQLQuery) do
begin
sql.clear;
sql.add('SELECT * FROM FPDEV_FIELD');
end;
end;
destructor TSQLDBConnector.Destroy;
begin
try
if Ftransaction.Active then Ftransaction.Rollback;
Ftransaction.StartTransaction;
Fconnection.ExecuteDirect('DROP TABLE FPDEV2');
Ftransaction.Commit;
Except
if Ftransaction.Active then Ftransaction.Rollback
end;
inherited Destroy;
FreeAndNil(FQuery);
FreeAndNil(FTransaction);
FreeAndNil(FConnection);
end;
constructor TSQLDBConnector.Create;
begin
FConnection := nil;
CreateFConnection;
CreateFTransaction;
FQuery := CreateQuery;
FConnection.Transaction := FTransaction;
Inherited;
end;
initialization
RegisterClass(TSQLDBConnector);
end.

View File

@ -1,28 +1,40 @@
unit TestDBBasics;
{$IFDEF FPC}
{$mode objfpc}{$H+}
{$mode Delphi}{$H+}
{$ENDIF}
interface
uses
fpcunit, testutils, testregistry, testdecorator,
Classes, SysUtils;
Classes, SysUtils, db;
type
{ TTestSQLMechanism }
{ TTestDBBasics }
TTestDBBasics = class(TTestCase)
private
procedure TestfieldDefinition(AFieldType : TFieldType;ADatasize : integer;var ADS : TDataset; var AFld: TField);
protected
procedure SetUp; override;
procedure TearDown; override;
published
procedure TestSupportIntegerFields;
procedure TestSupportSmallIntFields;
procedure TestSupportStringFields;
procedure TestSupportBooleanFields;
procedure TestSupportFloatFields;
procedure TestSupportLargeIntFields;
procedure TestSupportDateFields;
procedure TestIsEmpty;
procedure TestAppendOnEmptyDataset;
procedure TestInsertOnEmptyDataset;
procedure TestBufDatasetCancelUpdates; //bug 6938
procedure TestEofAfterFirst; //bug 7211
procedure TestBufDatasetCancelUpdates1;
procedure TestDoubleClose;
procedure TestAssignFieldftString;
@ -44,14 +56,65 @@ type
TDBBasicsTestSetup = class(TTestSetup)
protected
procedure OneTimeSetup; override;
procedure OneTimeTearDown; override;
end;
implementation
uses db, toolsunit;
uses toolsunit, bufdataset;
procedure TTestDBBasics.TestIsEmpty;
begin
if not (DBConnector.GetNDataset(5) is TBufDataset) then
Ignore('This test only applies to TBufDataset and descendents.');
with tbufdataset(DBConnector.GetNDataset(True,1)) do
begin
open;
delete;
refresh;
applyupdates;
AssertTrue(IsEmpty);
end;
end;
procedure TTestDBBasics.TestAppendOnEmptyDataset;
begin
with DBConnector.GetNDataset(0) do
begin
open;
AssertTrue(CanModify);
AssertTrue(eof);
AssertTrue(bof);
append;
AssertFalse(Bof);
AssertTrue(Eof);
post;
AssertFalse(eof);
AssertFalse(bof);
end;
end;
procedure TTestDBBasics.TestInsertOnEmptyDataset;
begin
with DBConnector.GetNDataset(0) do
begin
open;
AssertTrue(CanModify);
AssertTrue(eof);
AssertTrue(bof);
AssertTrue(IsEmpty);
insert;
AssertTrue(Bof);
AssertTrue(Eof);
AssertFalse(IsEmpty);
post;
AssertFalse(IsEmpty);
AssertFalse(eof);
AssertFalse(bof);
end;
end;
procedure TTestDBBasics.TestSelectQueryBasics;
var b : TFieldType;
@ -66,11 +129,11 @@ begin
AssertEquals(2,FieldCount);
AssertTrue(CompareText('ID',fields[0].FieldName)=0);
AssertTrue(CompareText('ID',fields[0].DisplayName)=0); // uitzoeken verschil displaylabel
AssertTrue(CompareText('ID',fields[0].DisplayName)=0);
AssertTrue('The datatype of the field ''ID'' is incorrect, it should be ftInteger',ftInteger=fields[0].DataType);
AssertTrue(CompareText('NAME',fields[1].FieldName)=0);
AssertTrue(CompareText('NAME',fields[1].DisplayName)=0); // uitzoeken verschil displaylabel
AssertTrue(CompareText('NAME',fields[1].DisplayName)=0);
AssertTrue(ftString=fields[1].DataType);
AssertEquals(1,fields[0].Value);
@ -85,11 +148,7 @@ begin
with DBConnector.GetNDataset(1) do
begin
open;
{$IFDEF FPC}
AssertException('Post was called in a non-edit state',EDatabaseError,@Post);
{$ELSE}
AssertException('Post was called in a non-edit state',EDatabaseError,Post);
{$ENDIF}
end;
end;
@ -106,30 +165,33 @@ begin
ABufferCount := 11;
aDatalink.BufferCount := ABufferCount;
DataEvents := '';
for count := 0 to 32 do with DBConnector.GetNDataset(count) do
for count := 0 to 32 do
begin
aDatasource.DataSet := DBConnector.GetNDataset(count);
i := 1;
Open;
AssertEquals('deUpdateState:0;',DataEvents);
DataEvents := '';
while not EOF do
with aDatasource.Dataset do
begin
AssertEquals(i,fields[0].AsInteger);
AssertEquals('TestName'+inttostr(i),fields[1].AsString);
inc(i);
i := 1;
Open;
AssertEquals('deUpdateState:0;',DataEvents);
DataEvents := '';
while not EOF do
begin
AssertEquals(i,fields[0].AsInteger);
AssertEquals('TestName'+inttostr(i),fields[1].AsString);
inc(i);
Next;
if (i > ABufferCount) and not EOF then
AssertEquals('deCheckBrowseMode:0;deDataSetScroll:-1;',DataEvents)
else
AssertEquals('deCheckBrowseMode:0;deDataSetScroll:0;',DataEvents);
Next;
if (i > ABufferCount) and not EOF then
AssertEquals('deCheckBrowseMode:0;deDataSetScroll:-1;',DataEvents)
else
AssertEquals('deCheckBrowseMode:0;deDataSetScroll:0;',DataEvents);
DataEvents := '';
end;
AssertEquals(count,i-1);
close;
AssertEquals('deUpdateState:0;',DataEvents);
DataEvents := '';
end;
AssertEquals(count,i-1);
close;
AssertEquals('deUpdateState:0;',DataEvents);
DataEvents := '';
end;
end;
@ -138,14 +200,16 @@ procedure TTestDBBasics.TestdeFieldListChange;
var i,count : integer;
aDatasource : TDataSource;
aDatalink : TDataLink;
ds : TDataset;
begin
aDatasource := TDataSource.Create(nil);
aDatalink := TTestDataLink.Create;
aDatalink.DataSource := aDatasource;
with DBConnector.GetNDataset(1) do
ds := DBConnector.GetNDataset(1);
with ds do
begin
aDatasource.DataSet := DBConnector.GetNDataset(1);
aDatasource.DataSet := ds;
DataEvents := '';
open;
Fields.add(tfield.Create(DBConnector.GetNDataset(1)));
@ -163,9 +227,7 @@ procedure TTestDBBasics.TestActiveBufferWhenClosed;
begin
with DBConnector.GetNDataset(0) do
begin
{$IFDEF fpc}
AssertNull(ActiveBuffer);
{$ENDIF}
open;
AssertFalse('Activebuffer of an empty dataset shouldn''t be nil',ActiveBuffer = nil);
end;
@ -195,12 +257,11 @@ begin
aDatalink := TTestDataLink.Create;
aDatalink.DataSource := aDatasource;
ds := DBConnector.GetNDataset(6);
ds.BeforeScroll := @DBConnector.DataEvent;
ds.BeforeScroll := DBConnector.DataEvent;
with ds do
begin
aDatasource.DataSet := ds;
open;
// first;
DataEvents := '';
Resync([rmExact]);
AssertEquals('deDataSetChange:0;',DataEvents);
@ -213,8 +274,6 @@ begin
aDatalink.Free;
end;
procedure TTestDBBasics.TestLastAppendCancel;
var count : integer;
@ -234,15 +293,39 @@ begin
Close;
end;
end;
procedure TTestDBBasics.TestRecNo;
var i : longint;
passed : boolean;
begin
with DBConnector.GetNDataset(0) do
begin
AssertEquals('Failed to get the RecNo from a closed dataset',0,RecNo);
AssertEquals(0,RecordCount);
// Accessing RecNo on a closed dataset should raise an EDatabaseError or should
// return 0
passed := false;
try
i := recno;
except on E: Exception do
begin
passed := E.classname = EDatabaseError.className
end;
end;
if not passed then
AssertEquals('Failed to get the RecNo from a closed dataset',0,RecNo);
// Accessing Recordcount on a closed dataset should raise an EDatabaseError or should
// return 0
passed := false;
try
i := recordcount;
except on E: Exception do
begin
passed := E.classname = EDatabaseError.className
end;
end;
if not passed then
AssertEquals('Failed to get the Recordcount from a closed dataset',0,RecNo);
Open;
@ -332,13 +415,160 @@ end;
procedure TTestDBBasics.SetUp;
begin
DBConnector.InitialiseDatasets;
DBConnector.StartTest;
end;
procedure TTestDBBasics.TearDown;
var count : integer;
begin
DBConnector.FreeDatasets;
DBConnector.StopTest;
end;
procedure TTestDBBasics.TestEofAfterFirst;
begin
with DBConnector.GetNDataset(0) do
begin
open;
AssertTrue(eof);
AssertTrue(BOF);
first;
AssertTrue(eof);
AssertTrue(BOF);
end;
end;
procedure TTestDBBasics.TestfieldDefinition(AFieldType : TFieldType;ADatasize : integer;var ADS : TDataset; var AFld: TField);
var i : byte;
begin
ADS := DBConnector.GetFieldDataset;
ADS.Open;
AFld := ADS.FindField('F'+FieldTypeNames[AfieldType]);
AssertNotNull('Fields of the type ' + FieldTypeNames[AfieldType] + ' are not supported by this type of dataset',AFld);
AssertTrue(Afld.DataType = AFieldType);
AssertEquals(ADatasize,Afld.DataSize );
end;
procedure TTestDBBasics.TestSupportIntegerFields;
var i : byte;
ds : TDataset;
Fld : TField;
begin
TestfieldDefinition(ftInteger,4,ds,Fld);
for i := 0 to testValuesCount-1 do
begin
AssertEquals(testIntValues[i],Fld.AsInteger);
ds.Next;
end;
ds.close;
end;
procedure TTestDBBasics.TestSupportSmallIntFields;
var i : byte;
ds : TDataset;
Fld : TField;
begin
TestfieldDefinition(ftSmallint,2,ds,Fld);
for i := 0 to testValuesCount-1 do
begin
AssertEquals(testSmallIntValues[i],Fld.AsInteger);
ds.Next;
end;
ds.close;
end;
procedure TTestDBBasics.TestSupportStringFields;
var i : byte;
ds : TDataset;
Fld : TField;
begin
TestfieldDefinition(ftString,11,ds,Fld);
for i := 0 to testValuesCount-1 do
begin
AssertEquals(testStringValues[i],Fld.AsString);
ds.Next;
end;
ds.close;
end;
procedure TTestDBBasics.TestSupportBooleanFields;
var i : byte;
ds : TDataset;
Fld : TField;
begin
TestfieldDefinition(ftBoolean,2,ds,Fld);
for i := 0 to testValuesCount-1 do
begin
AssertEquals(testBooleanValues[i],Fld.AsBoolean);
ds.Next;
end;
ds.close;
end;
procedure TTestDBBasics.TestSupportFloatFields;
var i : byte;
ds : TDataset;
Fld : TField;
begin
TestfieldDefinition(ftFloat,8,ds,Fld);
for i := 0 to testValuesCount-1 do
begin
AssertEquals(testFloatValues[i],Fld.AsFloat);
ds.Next;
end;
ds.close;
end;
procedure TTestDBBasics.TestSupportLargeIntFields;
var i : byte;
ds : TDataset;
Fld : TField;
begin
TestfieldDefinition(ftLargeint,8,ds,Fld);
for i := 0 to testValuesCount-1 do
begin
AssertEquals(testLargeIntValues[i],Fld.AsLargeInt);
ds.Next;
end;
ds.close;
end;
procedure TTestDBBasics.TestSupportDateFields;
var i : byte;
ds : TDataset;
Fld : TField;
begin
TestfieldDefinition(ftDate,8,ds,Fld);
for i := 0 to testValuesCount-1 do
begin
AssertEquals(testDateValues[i],FormatDateTime('yyyy/mm/dd',Fld.AsDateTime));
ds.Next;
end;
ds.close;
end;
procedure TTestDBBasics.TestDoubleClose;
@ -363,9 +593,8 @@ begin
begin
open;
AField := fieldbyname('name');
(AField as tstringfield).FixedChar := true;
AParam.AssignField(AField);
AssertTrue(ftFixedChar=AParam.DataType);
AssertTrue(ftString=AParam.DataType);
close;
end;
AParam.Free;
@ -391,7 +620,8 @@ end;
procedure TTestDBBasics.TestBufDatasetCancelUpdates;
var i : byte;
begin
AssertTrue(SIgnoreAssertion,DBConnector.GetNDataset(5) is TBufDataset);
if not (DBConnector.GetNDataset(5) is TBufDataset) then
Ignore('This test only applies to TBufDataset and descendents.');
with DBConnector.GetNDataset(5) as TBufDataset do
begin
open;
@ -420,54 +650,54 @@ end;
procedure TTestDBBasics.Testbug7007;
var
datalink1: tdatalink;
datasource1: tdatasource;
query1: TDataSet;
datalink1: tdatalink;
datasource1: tdatasource;
query1: TDataSet;
begin
query1:= DBConnector.GetNDataset(6);
datalink1:= TTestDataLink.create;
datasource1:= tdatasource.create(nil);
try
datalink1.datasource:= datasource1;
datasource1.dataset:= query1;
datalink1.datasource:= datasource1;
query1:= DBConnector.GetNDataset(6);
datalink1:= TTestDataLink.create;
datasource1:= tdatasource.create(nil);
try
datalink1.datasource:= datasource1;
datasource1.dataset:= query1;
datalink1.datasource:= datasource1;
DataEvents := '';
query1.open;
datalink1.buffercount:= query1.recordcount;
AssertEquals('deUpdateState:0;',DataEvents);
AssertEquals(0, datalink1.ActiveRecord);
AssertEquals(6, datalink1.RecordCount);
AssertEquals(6, query1.RecordCount);
AssertEquals(1, query1.RecNo);
DataEvents := '';
query1.open;
datalink1.buffercount:= query1.recordcount;
AssertEquals('deUpdateState:0;',DataEvents);
AssertEquals(0, datalink1.ActiveRecord);
AssertEquals(6, datalink1.RecordCount);
AssertEquals(6, query1.RecordCount);
AssertEquals(1, query1.RecNo);
DataEvents := '';
query1.append;
AssertEquals('deCheckBrowseMode:0;deUpdateState:0;deDataSetChange:0;',DataEvents);
AssertEquals(5, datalink1.ActiveRecord);
AssertEquals(6, datalink1.RecordCount);
AssertEquals(6, query1.RecordCount);
AssertEquals(0, query1.RecNo);
DataEvents := '';
query1.append;
AssertEquals('deCheckBrowseMode:0;deUpdateState:0;deDataSetChange:0;',DataEvents);
AssertEquals(5, datalink1.ActiveRecord);
AssertEquals(6, datalink1.RecordCount);
AssertEquals(6, query1.RecordCount);
AssertTrue(query1.RecNo in [0,7]);
DataEvents := '';
query1.cancel;
AssertEquals('deCheckBrowseMode:0;deUpdateState:0;deDataSetChange:0;',DataEvents);
AssertEquals(5, datalink1.ActiveRecord);
AssertEquals(6, datalink1.RecordCount);
AssertEquals(6, query1.RecordCount);
AssertEquals(6, query1.RecNo);
DataEvents := '';
query1.cancel;
AssertEquals('deCheckBrowseMode:0;deUpdateState:0;deDataSetChange:0;',DataEvents);
AssertEquals(5, datalink1.ActiveRecord);
AssertEquals(6, datalink1.RecordCount);
AssertEquals(6, query1.RecordCount);
AssertEquals(6, query1.RecNo);
finally
datalink1.free;
datasource1.free;
end;
datalink1.free;
datasource1.free;
end;
end;
procedure TTestDBBasics.TestBufDatasetCancelUpdates1;
var i : byte;
begin
AssertTrue(SIgnoreAssertion,DBConnector.GetNDataset(5) is TBufDataset);
if not (DBConnector.GetNDataset(5) is TBufDataset) then
Ignore('This test only applies to TBufDataset and descendents.');
with DBConnector.GetNDataset(5) as TBufDataset do
begin
open;

View File

@ -1,4 +1,4 @@
unit TestSQLFieldTypes;
unit TestSQLFieldTypes;
{$mode objfpc}{$H+}
@ -10,21 +10,38 @@ uses
type
TParamProc = procedure(AParam:TParam; i : integer);
TFieldProc = procedure(AField:TField; i : integer);
{ TTestFieldTypes }
TTestFieldTypes= class(TTestCase)
private
procedure CreateTableWithFieldType(ADatatype : TFieldType; ASQLTypeDecl : string);
procedure TestFieldDeclaration(ADatatype: TFieldType; ADataSize: integer);
procedure TestXXParamQuery(ADatatype : TFieldType; ASQLTypeDecl : string; testValuescount : integer);
protected
procedure SetUp; override;
procedure TearDown; override;
procedure RunTest; override;
published
procedure TestInt;
procedure TestScript;
procedure TestParametersAndDates;
procedure TestExceptionOnsecondClose;
procedure TestBlob;
procedure TestChangeBlob;
procedure TestLargeRecordSize;
procedure TestNumeric;
procedure TestFloat;
procedure TestDateTime; // bug 6925
procedure TestNumeric;
procedure TestString;
procedure TestUnlVarChar;
procedure TestDate;
@ -32,18 +49,89 @@ type
procedure TestNullValues;
procedure TestParamQuery;
procedure TestStringParamQuery;
procedure TestDateParamQuery;
procedure TestIntParamQuery;
procedure TestFloatParamQuery;
published
procedure TestAggregates;
end;
implementation
uses sqldbtoolsunit,toolsunit, variants;
procedure TTestFieldTypes.TestInt;
uses sqldbtoolsunit,toolsunit, variants, sqldb;
const
testValuesCount = 17;
testValues : Array[0..testValuesCount-1] of integer = (-maxInt,-maxSmallint-1,-maxSmallint,-256,-255,-128,-127,-1,0,1,127,128,255,256,maxSmallint,maxSmallint+1,MaxInt);
testFloatValuesCount = 21;
testFloatValues : Array[0..testFloatValuesCount-1] of double = (-maxSmallint-1,-maxSmallint,-256,-255,-128,-127,-1,0,1,127,128,255,256,maxSmallint,maxSmallint+1,0.123456,-0.123456,4.35,12.434E7,9.876e-5,123.45678);
testIntValuesCount = 17;
testIntValues : Array[0..testIntValuesCount-1] of integer = (-maxInt,-maxSmallint-1,-maxSmallint,-256,-255,-128,-127,-1,0,1,127,128,255,256,maxSmallint,maxSmallint+1,MaxInt);
testStringValuesCount = 20;
testStringValues : Array[0..testStringValuesCount-1] of string = (
'',
'a',
'ab',
'abc',
'abcd',
'abcde',
'abcdef',
'abcdefg',
'abcdefgh',
'abcdefghi',
'abcdefghij',
'lMnOpQrStU',
'1234567890',
'_!@#$%^&*(',
' ''quotes'' ',
')-;:/?.<>',
'~`|{}- =', // note that there's no \ (backslash) since some db's uses that as escape-character
' WRaP ',
'wRaP ',
' wRAP'
);
testDateValuesCount = 18;
testDateValues : Array[0..testDateValuesCount-1] of string = (
'2000-01-01',
'1999-12-31',
'2004-02-29',
'2004-03-01',
'1991-02-28',
'1991-03-01',
'2040-10-16',
'1977-09-29',
'1800-03-30',
'1650-05-10',
'1754-06-04',
'0904-04-12',
'0199-07-09',
'0001-01-01',
'1899-12-29',
'1899-12-30',
'1899-12-31',
'1900-01-01'
);
procedure TTestFieldTypes.TestScript;
var Ascript : TSQLScript;
begin
Ascript := tsqlscript.create(nil);
with Ascript do
begin
DataBase := TSQLDBConnector(DBConnector).Connection;
transaction := TSQLDBConnector(DBConnector).Transaction;
script.clear;
script.append('create table a (id int);');
script.append('create table b (id int);');
ExecuteScript;
end;
end;
procedure TTestFieldTypes.TestInt;
var
i : byte;
@ -52,21 +140,48 @@ begin
CreateTableWithFieldType(ftInteger,'INT');
TestFieldDeclaration(ftInteger,4);
for i := 0 to testValuesCount-1 do
TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (' + inttostr(testValues[i]) + ')');
for i := 0 to testIntValuesCount-1 do
TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (' + inttostr(testIntValues[i]) + ')');
with TSQLDBConnector(DBConnector).Query do
begin
Open;
for i := 0 to testValuesCount-1 do
for i := 0 to testIntValuesCount-1 do
begin
AssertEquals(testValues[i],fields[0].AsInteger);
AssertEquals(testIntValues[i],fields[0].AsInteger);
Next;
end;
close;
end;
end;
procedure TTestFieldTypes.TestLargeRecordSize;
var
i : byte;
begin
TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (plant varchar(8192),sampling_type varchar(8192),area varchar(8192), area_description varchar(8192), batch varchar(8192), sampling_datetime timestamp, status varchar(8192), batch_commentary varchar(8192))');
// Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
if UpperCase(dbconnectorparams)='INTERBASE' then TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
with TSQLDBConnector(DBConnector).Query do
begin
sql.clear;
sql.append('insert into FPDEV2 (plant,sampling_type,batch,sampling_datetime,status,batch_commentary) values (''ZUBNE PASTE'',''OTISCI POVR￿INA'',''000037756'',''2005-07-01'',''NE ODGOVARA'',''Ovdje se upisuje komentar o kontrolnom broju..............'')');
ExecSQL;
sql.clear;
sql.append('select * from FPDEV2');
open;
AssertEquals('ZUBNE PASTE',FieldByName('plant').AsString);
AssertEquals(EncodeDate(2005,07,01),FieldByName('sampling_datetime').AsDateTime);
close;
end;
end;
procedure TTestFieldTypes.TestNumeric;
const
@ -137,7 +252,7 @@ begin
Open;
for i := 0 to testValuesCount-1 do
begin
if (dbtype in MySQLdbTypes) then
if (SQLDbType in MySQLdbTypes) then
AssertEquals(TrimRight(testValues[i]),fields[0].AsString) // MySQL automatically trims strings
else
AssertEquals(testValues[i],fields[0].AsString);
@ -180,7 +295,7 @@ var
i : byte;
begin
AssertTrue(SIgnoreAssertion,dbtype = postgresql); // Only postgres accept this type-definition
// AssertTrue(SIgnoreAssertion,SQLDbType = postgresql); // Only postgres accept this type-definition
CreateTableWithFieldType(ftString,'VARCHAR');
TestFieldDeclaration(ftString,dsMaxStringSize+1);
@ -201,29 +316,6 @@ end;
procedure TTestFieldTypes.TestDate;
const
testValuesCount = 18;
testValues : Array[0..testValuesCount-1] of string = (
'2000-01-01',
'1999-12-31',
'2004-02-29',
'2004-03-01',
'1991-02-28',
'1991-03-01',
'2040-10-16',
'1977-09-29',
'1800-03-30',
'1650-05-10',
'1754-06-04',
'0904-04-12',
'0199-07-09',
'0001-01-01',
'1899-12-29',
'1899-12-30',
'1899-12-31',
'1900-01-01'
);
var
i : byte;
@ -231,20 +323,20 @@ begin
CreateTableWithFieldType(ftDate,'DATE');
TestFieldDeclaration(ftDate,8);
for i := 0 to testValuesCount-1 do
if dbtype=oracle then
TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (to_date (''' + testValues[i] + ''',''YYYY-MM-DD''))')
for i := 0 to testDateValuesCount-1 do
if SQLDbType=oracle then
TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (to_date (''' + testDateValues[i] + ''',''YYYY-MM-DD''))')
else
TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (''' + testValues[i] + ''')');
TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (''' + testDateValues[i] + ''')');
// TSQLDBConnector(DBConnector).Transaction.CommitRetaining; // For debug-purposes
with TSQLDBConnector(DBConnector).Query do
begin
Open;
for i := 0 to testValuesCount-1 do
for i := 0 to testDateValuesCount-1 do
begin
AssertEquals(testValues[i],FormatDateTime('yyyy/mm/dd',fields[0].AsDateTime));
AssertEquals(testDateValues[i],FormatDateTime('yyyy/mm/dd',fields[0].AsDateTime));
Next;
end;
close;
@ -252,6 +344,74 @@ begin
end;
procedure TTestFieldTypes.TestChangeBlob;
var s : string;
begin
TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (ID int,FT blob)');
TSQLDBConnector(DBConnector).Transaction.CommitRetaining; // For interbase
TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (ID,FT) values (1,''Test deze blob'')');
with TSQLDBConnector(DBConnector).Query do
begin
sql.clear;
sql.add('select * from FPDEV2');
Open;
fields[1].ProviderFlags := [pfInUpdate]; // blob niet in de where
UpdateMode := upWhereAll;
AssertEquals('Test deze blob',fields[1].AsString);
edit;
// Dat werkt niet lekker, omdat de stream vernield wordt...
// fields[0].asstring := 'Deze blob is gewijzigd!';
With Createblobstream(fields[1],bmwrite) do
begin
s := 'Deze blob is gewijzigd!';
WriteBuffer(Pointer(s)^,Length(s));
post;
free;
end;
AssertEquals('Deze blob is gewijzigd!',fields[1].AsString);
ApplyUpdates(0);
TSQLDBConnector(DBConnector).Transaction.CommitRetaining; // For debug-purposes
close;
open;
AssertEquals('Deze blob is gewijzigd!',fields[1].AsString);
close;
end;
end;
procedure TTestFieldTypes.TestBlob;
var
i : byte;
begin
// CreateTableWithFieldType(ftBlob,'BLOB');
CreateTableWithFieldType(ftBlob,'TEXT');
TestFieldDeclaration(ftBlob,0);
TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (''Test deze blob'')');
// TSQLDBConnector(DBConnector).Transaction.CommitRetaining; // For debug-purposes
with TSQLDBConnector(DBConnector).Query do
begin
Open;
AssertEquals('Test deze blob',fields[0].AsString);
close;
end;
end;
procedure TTestFieldTypes.TestDateTime;
const
@ -297,11 +457,11 @@ begin
CreateTableWithFieldType(ftDateTime,'TIMESTAMP');
TestFieldDeclaration(ftDateTime,8);
if dbtype=mysql40 then corrTestValueCount := testValuesCount-21
if SQLDbType=mysql40 then corrTestValueCount := testValuesCount-21
else corrTestValueCount := testValuesCount;
for i := 0 to corrTestValueCount-1 do
if dbtype=oracle then
if SQLDbType=oracle then
TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (to_date (''' + testValues[i] + ''',''YYYY-MM-DD HH24:MI:SS''))')
else
TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (''' + testValues[i] + ''')');
@ -444,50 +604,59 @@ begin
end;
procedure TTestFieldTypes.TestIntParamQuery;
begin
TestXXParamQuery(ftInteger,'INT',testIntValuesCount);
end;
procedure TTestFieldTypes.TestFloatParamQuery;
begin
TestXXParamQuery(ftFloat,'FLOAT',testFloatValuesCount);
end;
procedure TTestFieldTypes.TestStringParamQuery;
const
testValuesCount = 20;
testValues : Array[0..testValuesCount-1] of string = (
'',
'a',
'ab',
'abc',
'abcd',
'abcde',
'abcdef',
'abcdefg',
'abcdefgh',
'abcdefghi',
'abcdefghij',
'lMnOpQrStU',
'1234567890',
'_!@#$%^&*(',
' ''quotes'' ',
')-;:/?.<>',
'~`|{}- =', // note that there's no \ (backslash) since some db's uses that as escape-character
' WRaP ',
'wRaP ',
' wRAP'
);
begin
TestXXParamQuery(ftString,'VARCHAR(10)',testStringValuesCount);
end;
procedure TTestFieldTypes.TestDateParamQuery;
begin
TestXXParamQuery(ftDate,'DATE',testDateValuesCount);
end;
procedure TTestFieldTypes.TestXXParamQuery(ADatatype : TFieldType; ASQLTypeDecl : string; testValuescount : integer);
var i : integer;
begin
TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (ID INT, FIELD1 VARCHAR(10))');
TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (ID INT, FIELD1 '+ASQLTypeDecl+')');
// Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
if SQLDbType=interbase then TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
with TSQLDBConnector(DBConnector).Query do
begin
sql.clear;
sql.append('insert into FPDEV2 (ID,FIELD1) values (:id,:field1)');
ShortDateFormat := 'yyyy-mm-dd';
for i := 0 to testValuesCount -1 do
begin
Params.ParamByName('id').AsInteger := i;
Params.ParamByName('field1').AsString := testValues[i];
case ADataType of
ftInteger: Params.ParamByName('field1').asinteger := testIntValues[i];
ftFloat : Params.ParamByName('field1').AsFloat := testFloatValues[i];
ftString : Params.ParamByName('field1').AsString := testStringValues[i];
ftDate : Params.ParamByName('field1').AsDateTime:= StrToDate(testDateValues[i]);
else
AssertTrue('no test for paramtype available',False);
end;
ExecSQL;
end;
TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
@ -499,7 +668,14 @@ begin
for i := 0 to testValuesCount -1 do
begin
AssertEquals(i,FieldByName('ID').AsInteger);
AssertEquals(testValues[i],FieldByName('FIELD1').AsString);
case ADataType of
ftInteger: AssertEquals(testIntValues[i],FieldByName('FIELD1').AsInteger);
ftFloat : AssertEquals(testFloatValues[i],FieldByName('FIELD1').AsFloat);
ftString : AssertEquals(testStringValues[i],FieldByName('FIELD1').AsString);
ftdate : AssertEquals(testDateValues[i],FormatDateTime('yyyy/mm/dd',FieldByName('FIELD1').AsDateTime));
else
AssertTrue('no test for paramtype available',False);
end;
Next;
end;
close;
@ -584,11 +760,57 @@ end;
procedure TTestFieldTypes.RunTest;
begin
if (dbtype in SQLDBdbTypes) then
// if (SQLDbType in TSQLDBTypes) then
inherited RunTest;
end;
procedure TTestFieldTypes.TestParametersAndDates;
begin
with TSQLDBConnector(DBConnector).Query do
begin
SQL.Clear;
sql.add('select now()::date as current_date where 1=1');
open;
first;
writeln(fields[0].asstring); // return the correct date
close;
sql.clear;
sql.add('select now()::date as current_date where cast(1 as integer) = :PARAM1');
params.parambyname('PARAM1').asinteger:= 1;
open;
first;
writeln(fields[0].asstring); // return invalid date
close;
end
end;
procedure TTestFieldTypes.TestExceptionOnsecondClose;
begin
with TSQLDBConnector(DBConnector).Query do
begin
SQL.Clear;
SQL.Add('select * from FPDEV');
Open;
close;
SQL.Clear;
SQL.Add('select blaise from FPDEV');
{$IFDEF FPC}
// AssertException(EIBDatabaseError,@Open);
{$ELSE}
// AssertException(EIBDatabaseError,Open);
{$ENDIF}
Open;
Close;
end;
end;
initialization
if dbtype in SQLDBdbTypes then RegisterTest(TTestFieldTypes);
if uppercase(dbconnectorname)='SQL' then RegisterTest(TTestFieldTypes);
end.

View File

@ -4,8 +4,6 @@ unit ToolsUnit;
{$mode objfpc}{$H+}
{$ENDIF}
{$I settings.inc}
interface
uses
@ -16,18 +14,47 @@ Const MaxDataSet = 35;
type
{ TDBConnector }
TDBConnector = class(TObject)
TDBConnectorClass = class of TDBConnector;
TDBConnector = class(TPersistent)
private
FDatasets : array[0..MaxDataset] of TDataset;
FChangedDatasets : array[0..MaxDataSet] of boolean;
FUsedDatasets : TFPList;
FChangedFieldDataset : boolean;
protected
Procedure FreeNDataset(var ds : TDataset); virtual; abstract;
Function CreateNDataset(n : integer) : TDataset; virtual; abstract;
// These methods should be implemented by any descendents
// They are called eacht time a test need a TDataset descendent
Function InternalGetNDataset(n : integer) : TDataset; virtual; abstract;
Function InternalGetFieldDataset : TDataSet; virtual; abstract;
// These methods should be implemented by any descendents
// They are called only once in the constructor. They can be used
// to create the tables on disk, or on a DB-Server
procedure CreateNDatasets; virtual; abstract;
procedure CreateFieldDataset; virtual; abstract;
// These methods are called after each test in which a dataset is used
// by calling GetXXXDataset with Achange=true
// They should reset all data to their right/initial values.
procedure ResetNDatasets; virtual;
procedure ResetFieldDataset; virtual;
// These methods are called only once in the destructor.
// They should clean up all mess, like tables on disk or on a DB-server
procedure DropNDatasets; virtual; abstract;
procedure DropFieldDataset; virtual; abstract;
public
constructor create; virtual;
destructor destroy; override;
procedure DataEvent(dataset :TDataset);
Function GetNDataset(n : integer) : TDataset; virtual;
procedure InitialiseDatasets; virtual;
procedure FreeDatasets; virtual;
Function GetNDataset(n : integer) : TDataset; overload;
Function GetNDataset(AChange : Boolean; n : integer) : TDataset; overload;
Function GetFieldDataset : TDataSet; overload;
Function GetFieldDataset(AChange : Boolean) : TDataSet; overload;
procedure StartTest;
procedure StopTest;
end;
@ -42,81 +69,160 @@ type
{$ENDIF}
end;
type TDBTypes=(mysql40,mysql41,mysql50,interbase,postgresql,odbc,oracle,dbf);
const
DBTypesNames : Array [TDBTypes] of String[19] =
('mysql40','mysql41','mysql50','interbase','postgresql','odbc','oracle','dbf');
DataEventnames : Array [TDataEvent] of String[19] =
('deFieldChange', 'deRecordChange', 'deDataSetChange', 'deDataSetScroll',
'deLayoutChange', 'deUpdateRecord', 'deUpdateState', 'deCheckBrowseMode',
'dePropertyChange', 'deFieldListChange', 'deFocusControl' ,'deParentScroll'
{$IFNDEF VER2_0_2}, 'deConnectChange','deReconcileError','deDisabledStateChange'{$ENDIF}
);
'dePropertyChange', 'deFieldListChange', 'deFocusControl' ,'deParentScroll',
'deConnectChange', 'deReconcileError', 'deDisabledStateChange');
var dbtype : TDBTypes;
const
testValuesCount = 25;
testFloatValues : Array[0..testValuesCount-1] of double = (-maxSmallint-1,-maxSmallint,-256,-255,-128,-127,-1,0,1,127,128,255,256,maxSmallint,maxSmallint+1,0.123456,-0.123456,4.35,12.434E7,9.876e-5,123.45678,2.4,3.2,0.4,23);
testIntValues : Array[0..testValuesCount-1] of integer = (-maxInt,-maxInt+1,-maxSmallint-1,-maxSmallint,-256,-255,-128,-127,-1,0,1,127,128,255,256,maxSmallint,maxSmallint+1,MaxInt-1,MaxInt,100,130,150,-150,-132,234);
testSmallIntValues : Array[0..testValuesCount-1] of smallint = (-maxSmallint,-maxSmallint+1,-256,-255,-128,-127,-1,0,1,127,128,255,256,maxSmallint,maxSmallint-1,100,110,120,130,150,-150,-132,234,231,42);
testLargeIntValues : Array[0..testValuesCount-1] of smallint = (-MaxSIntValue,MaxSIntValue+1,-maxInt-1,-maxInt+1,-maxSmallint,-maxSmallint+1,-256,-255,-128,-127,-1,0,1,127,128,255,256,maxSmallint,maxSmallint-1,maxSmallint+1,MaxInt-1,MaxInt,MaxSIntValue-1,MaxSIntValue,235253244);
testBooleanValues : Array[0..testValuesCount-1] of boolean = (true,false,false,true,true,false,false,true,false,true,true,true,false,false,false,false,true,true,true,true,false,true,true,false,false);
testStringValues : Array[0..testValuesCount-1] of string = (
'',
'a',
'ab',
'abc',
'abcd',
'abcde',
'abcdef',
'abcdefg',
'abcdefgh',
'abcdefghi',
'abcdefghij',
'lMnOpQrStU',
'1234567890',
'_!@#$%^&*(',
'_!@#$%^&*(',
// ' ''quotes'' ',
')-;:/?.<>',
'~`|{}- =', // note that there's no \ (backslash) since some db's uses that as escape-character
' WRaP ',
'wRaP ',
' wRAP',
'this',
'is',
'fun',
'VB7^',
'vdfbst'
);
testDateValues : Array[0..testValuesCount-1] of string = (
'2000-01-01',
'1999-12-31',
'2004-02-29',
'2004-03-01',
'1991-02-28',
'1991-03-01',
'2040-10-16',
'1977-09-29',
'1800-03-30',
'1650-05-10',
'1754-06-04',
'0904-04-12',
'0199-07-09',
'0001-01-01',
'0031-11-02',
'1899-12-29',
'1899-12-30',
'1899-12-31',
'1977-09-29',
'1917-12-29',
'0079-11-29',
'1997-11-29',
'0001-01-01',
'1997-11-29',
'1900-01-01'
);
var dbtype,
dbconnectorname,
dbconnectorparams,
dbname,
dbuser,
dbhostname,
dbpassword : string;
DBConnector : TDBConnector;
dbpassword : string;
DataEvents : string;
DBConnector : TDBConnector;
DataEvents : string;
procedure InitialiseDBConnector;
resourcestring
SIgnoreAssertion = 'You can safely ignore this failure. This function is just not supported by the selected database';
implementation
uses
{$IFDEF SQLDB_AVAILABLE}
sqldbtoolsunit,
{$ENDIF}
{$IFDEF DBF_AVAILABLE}
dbftoolsunit,
{$ENDIF}
memdstoolsunit,
inifiles;
constructor TDBConnector.create;
begin
CreateFieldDataset;
CreateNDatasets;
FUsedDatasets := TFPList.Create;
end;
destructor TDBConnector.destroy;
begin
FUsedDatasets.Destroy;
DropNDatasets;
DropFieldDataset;
end;
procedure TDBConnector.ResetNDatasets;
begin
DropNDatasets;
CreateNDatasets;
end;
procedure TDBConnector.ResetFieldDataset;
begin
DropFieldDataset;
CreateFieldDataset;
end;
procedure TDBConnector.DataEvent(dataset : tdataset);
begin
DataEvents := DataEvents + 'DataEvent' + ';';
end;
function TDBConnector.GetNDataset(n: integer): TDataset;
begin
Result := GetNDataset(False,n);
end;
procedure ReadIniFile;
var IniFile : TIniFile;
s : string;
i : TDBTypes;
begin
IniFile := TIniFile.Create(getcurrentdir + PathDelim + 'database.ini');
s := IniFile.ReadString('Database','Type','');
for i := low(DBTypesNames) to high(DBTypesNames) do
if s = DBTypesNames[i] then dbtype := i;
dbtype := IniFile.ReadString('Database','Type','');
dbconnectorname := IniFile.ReadString(dbtype,'Connector','');
dbname := IniFile.ReadString(dbtype,'Name','');
dbuser := IniFile.ReadString(dbtype,'User','');
dbhostname := IniFile.ReadString(dbtype,'Hostname','');
dbpassword := IniFile.ReadString(dbtype,'Password','');
dbconnectorparams := IniFile.ReadString(dbtype,'ConnectorParams','');
dbname := IniFile.ReadString(s,'Name','');
dbuser := IniFile.ReadString(s,'User','');
dbhostname := IniFile.ReadString(s,'Hostname','');
dbpassword := IniFile.ReadString(s,'Password','');
IniFile.Free;
end;
procedure InitialiseDBConnector;
var DBConnectorClass : TPersistentClass;
begin
// ReadIniFile;
if (1 <> 1) then begin end
{$IFDEF SQLDB_AVAILABLE}
else if (dbtype in SQLDBdbTypes) then DBConnector := TSQLDBConnector.Create
{$ENDIF}
{$IFDEF DBF_AVAILABLE}
else if dbtype = dbf then DBConnector := TDBFDBConnector.Create
{$ENDIF}
else Raise Exception.Create('Invalid database-type specified');
if dbconnectorname = '' then raise Exception.Create('There is no db-connector specified');
DBConnectorClass := GetClass('T'+dbconnectorname+'DBConnector');
if assigned(DBConnectorClass) then
DBConnector := TDBConnectorClass(DBConnectorClass).create
else Raise Exception.Create('Unknown db-connector specified');
end;
{ TTestDataLink }
@ -133,23 +239,48 @@ end;
{ TDBConnector }
function TDBConnector.GetNDataset(n: integer): TDataset;
function TDBConnector.GetNDataset(AChange : Boolean; n: integer): TDataset;
begin
Result := FDatasets[n];
if AChange then FChangedDatasets[n] := True;
Result := InternalGetNDataset(n);
FUsedDatasets.Add(Result);
end;
procedure TDBConnector.InitialiseDatasets;
var count : integer;
function TDBConnector.GetFieldDataset: TDataSet;
begin
for count := 0 to MaxDataSet do
FDatasets[count] := CreateNDataset(count);
Result := GetFieldDataset(False);
end;
procedure TDBConnector.FreeDatasets;
var count : integer;
function TDBConnector.GetFieldDataset(AChange: Boolean): TDataSet;
begin
for count := 0 to MaxDataSet do if assigned(FDatasets[count]) then
FreeNDataset(FDatasets[count]);
if AChange then FChangedFieldDataset := True;
Result := InternalGetFieldDataset;
FUsedDatasets.Add(Result);
end;
procedure TDBConnector.StartTest;
begin
// Do nothing?
end;
procedure TDBConnector.StopTest;
var i : integer;
ds : TDataset;
begin
for i := 0 to FUsedDatasets.Count -1 do
begin
ds := tdataset(FUsedDatasets[i]);
if ds.active then ds.Close;
ds.Free;
end;
FUsedDatasets.Clear;
if FChangedFieldDataset then ResetFieldDataset;
for i := 0 to MaxDataSet do if FChangedDatasets[i] then
begin
ResetNDatasets;
fillchar(FChangedDatasets,sizeof(FChangedDatasets),ord(False));
break;
end;
end;
initialization