* fcl-db: clarified Dataset.txt

* fcl-db/dbase tests: fix for failing memo, string test
  improvement in naming saved dbf files (if enabled)

git-svn-id: trunk@24525 -
This commit is contained in:
reiniero 2013-05-18 08:56:16 +00:00
parent 2fe7dbfc6c
commit 773ee3d21c
3 changed files with 71 additions and 17 deletions

View File

@ -4,7 +4,7 @@ Contents
+ Fields system
+ The buffers
+ Dataset implementation
+ Scalable Datasets
+ Switchable datasets
===============
General remarks
@ -231,10 +231,10 @@ procedure SetFieldData(Field: TField; Buffer: Pointer); virtual; abstract;
--------------------------------------------------------------------------
Move the data in associated with Field from Buffer to the active buffer.
=================
Scalable datasets
=================
In order to have Scalable database access, the concept of TDatabase and
===================
Switchable datasets
===================
In order to have flexible database access, the concept of TDatabase and
TDBDataset is introduced. The idea is that, in a visual IDE, the change
from one database to another is achieved by simply removing one TDatabase
descendent (Say, TMySqlDatabase) with another (Say, TPostGreSQLDatabase)

View File

@ -2,14 +2,13 @@ unit DBFToolsUnit;
{ Sets up dbf datasets for testing
Tests expect Get*Dataset to return a dataset with structure and test data, but closed.
Because of this, we use file-backed dbfs instead of memory backed dbfs
}
{$IFDEF FPC}
{$mode objfpc}{$H+}
{$ENDIF}
// If defined, do not delete the dbf files when done but print out location to stdout:
// If defined, save the dbf files when done and print out location to stdout:
{.$DEFINE KEEPDBFFILES}
interface
@ -42,6 +41,8 @@ type
TDBFAutoClean = class(TDBF)
private
FBackingStream: TMemoryStream;
FIndexBackingStream: TMemoryStream;
FMemoBackingStream: TMemoryStream;
FCreatedBy: string;
public
// Keeps track of which function created the dataset, useful for troubleshooting
@ -68,6 +69,41 @@ implementation
uses
FmtBCD;
function GetNewTempDBFName: string;
// Scans temp directory for dbf names and adds
var
Res: TSearchRec;
Path, Name: string;
FileAttr: LongInt;
Attr,NextFileNo: Integer;
begin
NextFileNo:=0;
Attr := faAnyFile;
if FindFirst(IncludeTrailingPathDelimiter(GetTempDir)+'*.dbf', Attr, Res) = 0 then
begin
Path := GetTempDir;
repeat
Name := ConcatPaths([Path, Res.Name]);
FileAttr := FileGetAttr(Name);
if FileAttr and faDirectory = 0 then
begin
// Capture alphabetically latest name
try
//... only if it is numeric
if strtoint(ChangeFileExt(Res.Name,''))>NextFileNo then
NextFileNo:=strtoint(ChangeFileExt(Res.Name,''));
except
// apparently not numeric
end;
end
until FindNext(Res) <> 0;
end;
FindClose(Res);
// now we now the latest file, add 1, and paste the temp directory in front of it
NextFileNo:=NextFileNo+1;
Result:=IncludeTrailingPathDelimiter(GetTempDir)+IntToStr(NextFileNo)+'.DBF';
end;
{ TDBFAutoClean }
function TDBFAutoClean.UserRequestedTableLevel: integer;
@ -90,13 +126,18 @@ end;
constructor TDBFAutoClean.Create;
begin
// Create storage for data:
FBackingStream:=TMemoryStream.Create;
// Create a unique name:
TableName := FormatDateTime('hhnnssz',Now())+'/'+inttostr(random(32767));
FIndexBackingStream:=TMemoryStream.Create;
FMemoBackingStream:=TMemoryStream.Create;
// Create a unique name (within the 10 character DBIII limit):
TableName := FormatDateTime('hhnnssz',Now())+'_'+inttostr(random(99));
TableLevel := UserRequestedTableLevel;
Storage:=stoMemory;
UserStream:=FBackingStream;
CreateTable; //write out header to disk
UserIndexStream:=FIndexBackingStream;
UserMemoStream:=FMemoBackingStream;
CreateTable; //this will also write out the dbf header to disk/stream
end;
constructor TDBFAutoClean.Create(AOwner: TComponent);
@ -113,12 +154,18 @@ var
begin
{$IFDEF KEEPDBFFILES}
Close;
FileName := GetTempFileName;
FileName := GetNewTempDBFName;
FBackingStream.SaveToFile(FileName);
FIndexBackingStream.SaveToFile(ChangeFileExt(FileName, '.mdx'));
if Self.TableLevel in [TDBF_TABLELEVEL_FOXPRO, TDBF_TABLELEVEL_VISUALFOXPRO] then
FMemoBackingStream.SaveToFile(ChangeFileExt(FileName, '.fpt'))
else
FMemoBackingStream.SaveToFile(ChangeFileExt(FileName, '.dbt'));
writeln('TDBFAutoClean: file created by ',CreatedBy,' left file: ',FileName);
{$ENDIF}
inherited Destroy;
FBackingStream.Free;
FIndexBackingStream.Free;
end;
@ -162,10 +209,10 @@ begin
FieldDefs.Add('FWORD', ftWord);
FieldDefs.Add('FBOOLEAN', ftBoolean);
FieldDefs.Add('FFLOAT', ftFloat);
// Field types only available in newer versions
if (Result as TDBF).TableLevel >= 25 then
// Field types only available in (Visual) FoxPro
if (Result as TDBF).TableLevel >= TDBF_TABLELEVEL_FOXPRO then
FieldDefs.Add('FCURRENCY', ftCurrency);
if (Result as TDBF).TableLevel >= 25 then
if (Result as TDBF).TableLevel >= TDBF_TABLELEVEL_FOXPRO then
FieldDefs.Add('FBCD', ftBCD);
FieldDefs.Add('FDATE', ftDate);
FieldDefs.Add('FDATETIME', ftDateTime);
@ -182,13 +229,15 @@ begin
FieldByName('FINTEGER').AsInteger := testIntValues[i];
FieldByName('FBOOLEAN').AsBoolean := testBooleanValues[i];
FieldByName('FFLOAT').AsFloat := testFloatValues[i];
if (Result as TDBF).TableLevel >= 25 then
if (Result as TDBF).TableLevel >= TDBF_TABLELEVEL_FOXPRO then
FieldByName('FCURRENCY').AsCurrency := testCurrencyValues[i];
// work around missing TBCDField.AsBCD:
if (Result as TDBF).TableLevel >= 25 then
if (Result as TDBF).TableLevel >= TDBF_TABLELEVEL_FOXPRO then
FieldByName('FBCD').AsBCD := StrToBCD(testFmtBCDValues[i],Self.FormatSettings);
FieldByName('FDATE').AsDateTime := StrToDate(testDateValues[i], 'yyyy/mm/dd', '-');
FieldByName('FDATETIME').AsDateTime := StrToDateTime(testValues[ftDateTime,i], Self.FormatSettings);
FieldByName('FLARGEINT').AsLargeInt := testLargeIntValues[i];
FieldByName('FMEMO').AsString := testStringValues[i];
Post;
end;
Close;

View File

@ -2316,6 +2316,8 @@ var i : byte;
Fld : TField;
begin
if (uppercase(dbconnectorname)='DBF') then
Ignore('TDBF Smallint support only from -999 to 9999');
TestfieldDefinition(ftSmallint,2,ds,Fld);
for i := 0 to testValuesCount-1 do
@ -2338,7 +2340,10 @@ begin
for i := 0 to testValuesCount-1 do
begin
CheckEquals(testStringValues[i],Fld.AsString);
if (uppercase(dbconnectorname)<>'DBF') then
CheckEquals(testStringValues[i],Fld.AsString)
else {DBF right-trims spaces in string fields }
CheckEquals(TrimRight(testStringValues[i]),Fld.AsString);
ds.Next;
end;
ds.close;