* Implemented CSVDataset

git-svn-id: trunk@30417 -
This commit is contained in:
michael 2015-04-04 09:46:43 +00:00
parent c37720d12d
commit 6b130438eb
7 changed files with 810 additions and 30 deletions

2
.gitattributes vendored
View File

@ -2101,6 +2101,7 @@ packages/fcl-db/src/base/Makefile svneol=native#text/plain
packages/fcl-db/src/base/Makefile.fpc svneol=native#text/plain
packages/fcl-db/src/base/bufdataset.pas svneol=native#text/plain
packages/fcl-db/src/base/bufdataset_parser.pp svneol=native#text/plain
packages/fcl-db/src/base/csvdataset.pp svneol=native#text/plain
packages/fcl-db/src/base/database.inc svneol=native#text/plain
packages/fcl-db/src/base/dataset.inc svneol=native#text/plain
packages/fcl-db/src/base/datasource.inc svneol=native#text/plain
@ -2314,6 +2315,7 @@ packages/fcl-db/tests/memdstoolsunit.pas svneol=native#text/plain
packages/fcl-db/tests/reruntest.sh svneol=native#text/plain
packages/fcl-db/tests/sdfdstoolsunit.pas svneol=native#text/plain
packages/fcl-db/tests/sqldbtoolsunit.pas svneol=native#text/plain
packages/fcl-db/tests/tccsvdataset.pp svneol=native#text/plain
packages/fcl-db/tests/tcgensql.pas svneol=native#text/plain
packages/fcl-db/tests/tcparser.pas svneol=native#text/plain
packages/fcl-db/tests/tcsdfdata.pp svneol=native#text/plain

View File

@ -92,6 +92,13 @@ begin
AddUnit('dbconst');
end;
T:=P.Targets.AddUnit('csvdataset.pp');
with T.Dependencies do
begin
AddUnit('db');
AddUnit('bufdataset');
end;
T:=P.Targets.AddUnit('bufdataset_parser.pp');
with T.Dependencies do
begin

View File

@ -0,0 +1,389 @@
{
This file is part of the Free Pascal run time library.
Copyright (c) 1999-2014 by Michael Van Canneyt, member of the
Free Pascal development team
CSV Dataset implementation.
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
unit csvdataset;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, bufdataset, csvreadwrite, db, sqldb;
Type
{ TCSVOptions }
TCSVOptions = Class(TCSVHandler)
private
FDefaultFieldLength: Word;
FFirstLineAsFieldNames: Boolean;
Public
Constructor Create; override;
Procedure Assign(Source : TPersistent); override;
Published
// Does first line of the file contain the field names to use ?
property FirstLineAsFieldNames : Boolean Read FFirstLineAsFieldNames Write FFirstLineAsFieldNames;
// Default is to create all fields as strings with the same length. Default string field length.
// If the CSV dataset has field defs prior to loading, this is ignored.
property DefaultFieldLength : Word Read FDefaultFieldLength Write FDefaultFieldLength;
// Field delimiter
property Delimiter;
// Character used to quote "problematic" data
// (e.g. with delimiters or spaces in them)
// A common quotechar is "
property QuoteChar;
// String at the end of the line of data (e.g. CRLF)
property LineEnding;
// Ignore whitespace between delimiters and field data
property IgnoreOuterWhitespace;
// Use quotes when outer whitespace is found
property QuoteOuterWhitespace;
end;
{ TCSVDataPacketReader }
TCSVDataPacketReader = class(TDataPacketReader)
private
FOptions: TCSVOptions;
FOwnsOptions: Boolean;
FParser : TCSVParser;
FBuilder : TCSVBuilder;
FLine : TStringList;
FCurrentRow : Integer;
FEOF : Boolean;
FCreateFieldDefs : TFieldDefs;
// Read next row in Fline
Protected
Procedure ReadNextRow;virtual;
procedure SetCreateFieldDefs(AValue: TFieldDefs);virtual;
public
constructor Create(ADataSet: TCustomBufDataset; AStream : TStream); override;
constructor Create(ADataSet: TCustomBufDataset; AStream : TStream; AOptions : TCSVOptions);
Destructor Destroy; override;
procedure LoadFieldDefs(var AnAutoIncValue : integer); override;
procedure StoreFieldDefs(AnAutoIncValue : integer); override;
function GetRecordRowState(out AUpdOrder : Integer) : TRowState; override;
procedure FinalizeStoreRecords; override;
function GetCurrentRecord : boolean; override;
procedure GotoNextRecord; override;
procedure InitLoadRecords; override;
procedure RestoreRecord override;
procedure StoreRecord(ARowState : TRowState; AUpdOrder : integer = 0); override;
class function RecognizeStream(AStream : TStream) : boolean; override;
Property Options : TCSVOptions Read FOptions;
Property CreateFieldDefs : TFieldDefs read FCreateFieldDefs Write SetCreateFieldDefs;
end;
{ TCustomCSVDataset }
TCustomCSVDataset = Class(TBufDataset)
private
FCSVOptions: TCSVOptions;
procedure SetCSVOptions(AValue: TCSVOptions);
Protected
procedure LoadBlobIntoBuffer(FieldDef: TFieldDef;ABlobBuf: PBufBlobField); override;
procedure InternalInitFieldDefs; override;
Public
Constructor Create(AOwner : TComponent); override;
Destructor Destroy; override;
{ If FieldDefs is filled prior to calling one of the load functions,
the fielddefs definitions will be checked against file contents
as far as possible: count and names if names are on first line}
procedure LoadFromCSVStream(AStream : TStream);
procedure LoadFromCSVFile(Const AFileName: string);
procedure SaveToCSVStream(AStream : TStream);
procedure SaveToCSVFile(AFileName: string = '');
Protected
Property CSVOptions : TCSVOptions Read FCSVOptions Write SetCSVOptions;
end;
TCSVDataset = Class(TCustomCSVDataset)
Published
Property CSVOptions;
end;
implementation
{ TCSVDataPacketReader }
Procedure TCSVDataPacketReader.ReadNextRow;
begin
FLine.Clear;
if not FEOF then
begin
if (FCurrentRow>0) then
FLine.Add(FParser.CurrentCellText);
Repeat
FEOF:=Not FParser.ParseNextCell;
if (not FEOF) and (FParser.CurrentRow=FCurrentRow) then
FLine.Add(FParser.CurrentCellText);
until FEOF or (FParser.CurrentRow>FCurrentRow);
end;
FCurrentRow:=FParser.CurrentRow;
end;
procedure TCSVDataPacketReader.SetCreateFieldDefs(AValue: TFieldDefs);
begin
if FCreateFieldDefs=AValue then Exit;
if (FCreateFieldDefs=Nil) then
begin
FCreateFieldDefs:=TFieldDefs.Create(AValue.Dataset);
FCreateFieldDefs.Assign(AValue);
end;
end;
constructor TCSVDataPacketReader.Create(ADataSet: TCustomBufDataset; AStream: TStream);
begin
inherited Create(ADataSet,AStream);
if FOptions=Nil then
begin
FOptions:=TCSVOptions.Create;
FOptions.FFirstLineAsFieldNames:=True;
FOwnsOptions:=True;
end;
FLine:=TStringList.Create;
end;
constructor TCSVDataPacketReader.Create(ADataSet: TCustomBufDataset; AStream: TStream; AOptions: TCSVOptions);
begin
FOptions:=AOptions;
Create(ADataset,AStream);
FOwnsOptions:=AOptions=Nil;
end;
Destructor TCSVDataPacketReader.Destroy;
begin
If FOwnsOptions then
FreeAndNil(FOPtions);
FreeAndNil(Fline);
inherited Destroy;
end;
procedure TCSVDataPacketReader.LoadFieldDefs(var AnAutoIncValue: integer);
Var
FN : String;
I : Integer;
begin
FParser:=TCSVParser.Create;
FParser.SetSource(Stream);
FCurrentRow:=0;
ReadNextRow;
If Assigned(CreateFieldDefs) then
begin
if (CreateFieldDefs.Count<>Fline.Count) then
DatabaseErrorFmt('CSV File Field count (%d) does not match dataset field count (%d).',[Fline.Count,CreateFieldDefs.Count],Dataset.FieldDefs.Dataset);
If FOptions.FirstLineAsFieldNames then
For I:=0 to FLine.Count-1 do
If (CompareText(FLine[i],CreateFieldDefs[i].Name)<>0) then
DatabaseErrorFmt('CSV File field %d: name "%s" does not match dataset field name "%s".',[I,FLine[i],CreateFieldDefs[i].Name],Dataset.FieldDefs.Dataset);
Dataset.FieldDefs.Assign(CreateFieldDefs);
end
else if (FLine.Count>0) then
For I:=0 to FLine.Count-1 do
begin
If FOptions.FirstLineAsFieldNames then
FN:=FLine[i]
else
FN:=Format('Column%d',[i+1]);
Dataset.FieldDefs.Add(FN,ftString,Foptions.DefaultFieldLength);
end;
if FOptions.FirstLineAsFieldNames then
ReadNextRow;
end;
procedure TCSVDataPacketReader.StoreFieldDefs(AnAutoIncValue: integer);
Var
I : Integer;
begin
FBuilder:=TCSVBuilder.Create;
FBuilder.SetOutput(Stream);
if FOptions.FirstLineAsFieldNames then
begin
For I:=0 to Dataset.FieldDefs.Count-1 do
FBuilder.AppendCell(Dataset.FieldDefs[i].Name);
FBuilder.AppendRow;
end;
end;
function TCSVDataPacketReader.GetRecordRowState(out AUpdOrder: Integer
): TRowState;
begin
AUpdOrder:=0;
Result:=[];
end;
procedure TCSVDataPacketReader.FinalizeStoreRecords;
begin
end;
function TCSVDataPacketReader.GetCurrentRecord: boolean;
begin
Result:=Fline.Count>0;
end;
procedure TCSVDataPacketReader.GotoNextRecord;
begin
ReadNextRow;
end;
procedure TCSVDataPacketReader.InitLoadRecords;
begin
// Do nothing
end;
procedure TCSVDataPacketReader.RestoreRecord;
Var
I : integer;
begin
For I:=0 to Fline.Count-1 do
Dataset.Fields[i].AsString:=Copy(FLine[i],1,Dataset.Fields[i].Size)
end;
procedure TCSVDataPacketReader.StoreRecord(ARowState: TRowState; AUpdOrder: integer);
Var
I : integer;
begin
For I:=0 to Dataset.Fields.Count-1 do
FBuilder.AppendCell(Dataset.Fields[i].AsString);
FBuilder.AppendRow;
end;
class function TCSVDataPacketReader.RecognizeStream(AStream: TStream): boolean;
begin
Result:=False;
end;
{ TCSVOptions }
Constructor TCSVOptions.Create;
begin
inherited Create;
DefaultFieldLength:=255;
end;
Procedure TCSVOptions.Assign(Source: TPersistent);
begin
if (Source is TCSVOptions) then
begin
FFirstLineAsFieldNames:=TCSVOptions(Source).FirstLineAsFieldNames;
FDefaultFieldLength:=TCSVOptions(Source).FDefaultFieldLength
end;
inherited Assign(Source);
end;
{ TCustomCSVDataset }
procedure TCustomCSVDataset.SetCSVOptions(AValue: TCSVOptions);
begin
if (FCSVOptions=AValue) then Exit;
FCSVOptions.Assign(AValue);
end;
procedure TCustomCSVDataset.LoadBlobIntoBuffer(FieldDef: TFieldDef;
ABlobBuf: PBufBlobField);
begin
// Do nothing
end;
procedure TCustomCSVDataset.InternalInitFieldDefs;
begin
// Do nothing
end;
Constructor TCustomCSVDataset.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCSVOptions:=TCSVOptions.Create;
end;
Destructor TCustomCSVDataset.Destroy;
begin
FreeAndNil(FCSVOptions);
inherited Destroy;
end;
procedure TCustomCSVDataset.LoadFromCSVStream(AStream: TStream);
Var
P : TCSVDataPacketReader;
begin
CheckInactive;
P:=TCSVDataPacketReader.Create(Self,AStream,FCSVOptions);
try
if FieldDefs.Count>0 then
P.CreateFieldDefs:=FieldDefs;
SetDatasetPacket(P);
finally
P.Free;
end;
end;
procedure TCustomCSVDataset.LoadFromCSVFile(Const AFileName: string);
Var
F : TFileStream;
begin
F:=TFileStream.Create(AFileName,fmOpenRead or fmShareDenyWrite);
try
LoadFromCSVStream(F);
finally
F.Free;
end;
end;
procedure TCustomCSVDataset.SaveToCSVStream(AStream: TStream);
Var
P : TCSVDataPacketReader;
begin
First;
MergeChangeLog;
P:=TCSVDataPacketReader.Create(Self,AStream,FCSVOPtions);
try
GetDatasetPacket(P);
finally
P.Free;
end;
end;
procedure TCustomCSVDataset.SaveToCSVFile(AFileName: string);
Var
F : TFileStream;
begin
F:=TFileStream.Create(AFileName,fmOpenRead or fmShareDenyWrite);
try
SaveToCSVStream(F);
finally
F.Free;
end;
end;
end.

View File

@ -28,7 +28,7 @@ uses
TestSpecificTBufDataset,
TestSpecificTDBF,
TestSpecificTMemDataset,
TestDBExport,
TestDBExport, tccsvdataset,
consoletestrunner;
Procedure LegacyOutput;

View File

@ -27,12 +27,6 @@
<IncludeFiles Value="$(ProjOutDir)"/>
<OtherUnitFiles Value="../src/base;../src/sqldb/odbc;../src/sqldb/mssql;../src/sqldb/sqlite;../src/sqldb/postgres;../src/sqldb/oracle;../src/memds;../src/sqldb;../src/sqldb/interbase;../src/sqldb/mysql;../src/dbase;../src/sdf"/>
</SearchPaths>
<Other>
<CompilerMessages>
<UseMsgFile Value="True"/>
</CompilerMessages>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
</Item2>
<Item3 Name="Default_no_local_ppus">
@ -46,12 +40,6 @@
<GenerateDebugInfo Value="False"/>
</Debugging>
</Linking>
<Other>
<CompilerMessages>
<UseMsgFile Value="True"/>
</CompilerMessages>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
</Item3>
<Item4 Name="Default_no_local_ppus_debug">
@ -65,12 +53,6 @@
<OptimizationLevel Value="0"/>
</Optimizations>
</CodeGeneration>
<Other>
<CompilerMessages>
<UseMsgFile Value="True"/>
</CompilerMessages>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
</Item4>
</BuildModes>
@ -82,7 +64,6 @@
<RunParams>
<local>
<FormatVersion Value="1"/>
<LaunchingApplication PathPlusParams="/usr/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
</local>
</RunParams>
<RequiredPackages Count="4">
@ -99,17 +80,20 @@
<PackageName Value="FCL"/>
</Item4>
</RequiredPackages>
<Units Count="2">
<Units Count="3">
<Unit0>
<Filename Value="dbtestframework_gui.lpr"/>
<IsPartOfProject Value="True"/>
<UnitName Value="dbtestframework_gui"/>
</Unit0>
<Unit1>
<Filename Value="dbguitestrunner.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="DBGuiTestRunner"/>
</Unit1>
<Unit2>
<Filename Value="tccsvdataset.pp"/>
<IsPartOfProject Value="True"/>
<UnitName Value="tccsvdataset"/>
</Unit2>
</Units>
</ProjectOptions>
<CompilerOptions>
@ -123,12 +107,6 @@
<GenerateDebugInfo Value="False"/>
</Debugging>
</Linking>
<Other>
<CompilerMessages>
<UseMsgFile Value="True"/>
</CompilerMessages>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
<Debugging>
<Exceptions Count="7">

View File

@ -35,7 +35,7 @@ uses
TestSpecificTBufDataset,
TestSpecificTDBF,
TestSpecificTMemDataset,
TestDBExport;
TestDBExport, tccsvdataset;
{$R *.res}

View File

@ -0,0 +1,404 @@
unit tccsvdataset;
{$mode objfpc}{$H+}
interface
uses
Classes, db, SysUtils, fpcunit, testutils, testregistry, csvdataset;
type
{ TTestCSVDataset }
TTestCSVDataset= class(TTestCase)
private
FCSVDataset: TCSVDataset;
// Load CSVDataset from CSV stream containing lines
Procedure LoadFromLines(Const Lines: Array of string);
// Save CSVDataset to CSV stream, transform to lines
Procedure SaveToLines(Const Lines: TStrings);
// Save CSVDataset to CSV stream, transform to lines, compare with given lines
Procedure AssertLines(Const Lines: Array of string);
protected
procedure SetUp; override;
procedure TearDown; override;
Property CSVDataset : TCSVDataset Read FCSVDataset;
published
procedure TestEmpty;
procedure TestDefaults;
Procedure TestLoadEmptyDefault;
Procedure TestLoadEmptyFirstLineAsNames;
Procedure TestLoad2fieldsFirstLineAsNames;
Procedure TestLoad2fields;
Procedure TestLoad2Records2fields;
Procedure TestSaveEmptyDefault;
Procedure TestSaveEmptyFirstLineAsNames;
Procedure TestSaveOneRecordDefault;
Procedure TestSaveOneRecordFirstLineAsNames;
Procedure TestSaveTwoRecordsDefault;
Procedure TestSaveTwoRecordsFirstLineAsNames;
Procedure TestSaveOneRecord2FieldsDefault;
Procedure TestSaveOneRecord2FieldsFirstLineAsNames;
Procedure TestLoadPriorFieldDefs;
Procedure TestLoadPriorFieldDefsNoFieldNames;
Procedure TestLoadPriorFieldDefsNoFieldNamesWrongCount;
Procedure TestLoadPriorFieldDefsFieldNamesWrongCount;
Procedure TestLoadPriorFieldDefsFieldNamesWrongNames;
end;
implementation
procedure TTestCSVDataset.TestEmpty;
begin
AssertNotNull('Have CSV dataset',CSVDataset);
AssertFalse('Not open',CSVDataset.Active);
AssertEquals('No fielddefs',0,CSVDataset.FieldDefs.Count);
AssertEquals('Name','DS',CSVDataset.Name);
end;
procedure TTestCSVDataset.TestDefaults;
begin
With CSVDataset.CSVOptions do
begin
AssertEquals('DefaultFieldLength',255,DefaultFieldLength);
AssertEquals('FirstLineAsFieldNames',False,FirstLineAsFieldNames);
AssertEquals('Delimiter',',',Delimiter);
AssertEquals('QuoteChar','"',QuoteChar);
AssertEquals('LineEnding',sLineBreak,LineEnding);
AssertEquals('IgnoreOuterWhitespace',False,IgnoreOuterWhitespace);
AssertEquals('QuoteOuterWhitespace',True,QuoteOuterWhitespace);
AssertEquals('EqualColCountPerRow',True,EqualColCountPerRow);
end;
end;
Procedure TTestCSVDataset.LoadFromLines(Const Lines : Array of string);
Var
L : TStringList;
s : TStream;
begin
S:=Nil;
L:=TStringList.Create;
try
L.AddStrings(Lines);
S:=TStringStream.Create(L.Text);
CSVDataset.LoadFromCSVStream(S);
finally
S.Free;
L.Free;
end;
end;
Procedure TTestCSVDataset.SaveToLines(Const Lines: TStrings);
Var
S : TStringStream;
begin
S:=TStringStream.Create('');
try
CSVDataset.SaveToCSVStream(S);
Lines.Text:=S.DataString;
{
Writeln('----');
Writeln(S.DataString);
Writeln('----');
}
finally
S.Free;
end;
end;
Procedure TTestCSVDataset.AssertLines(Const Lines: Array of string);
Var
L : TStrings;
I : Integer;
begin
L:=TStringList.Create;
try
SaveToLines(L);
AssertEquals('Number of lines',Length(Lines),L.Count);
For I:=0 to L.Count-1 do
AssertEquals('Correct line '+IntToStr(0),Lines[I],L[i]);
finally
L.Free;
end;
end;
Procedure TTestCSVDataset.TestLoadEmptyDefault;
begin
LoadFromLines(['a']);
AssertEquals('Active',True,CSVDataset.Active);
AssertEquals('field count',1,CSVDataset.FieldDefs.Count);
AssertEquals('field name','Column1',CSVDataset.FieldDefs[0].Name);
AssertEquals('field size',CSVDataset.CSVOptions.DefaultFieldLength,CSVDataset.FieldDefs[0].Size);
AssertEquals('Not Empty',False,CSVDataset.EOF and CSVDataset.BOF);
AssertEquals('field contents','a',CSVDataset.Fields[0].AsString);
end;
Procedure TTestCSVDataset.TestLoadEmptyFirstLineAsNames;
begin
CSVDataset.CSVOptions.FirstLineAsFieldNames:=True;
CSVDataset.CSVOptions.DefaultFieldLength:=128;
LoadFromLines(['a']);
AssertEquals('Active',True,CSVDataset.Active);
AssertEquals('field count',1,CSVDataset.FieldDefs.Count);
AssertEquals('field name','a',CSVDataset.FieldDefs[0].Name);
AssertEquals('field size',CSVDataset.CSVOptions.DefaultFieldLength,CSVDataset.FieldDefs[0].Size);
AssertEquals('Empty',True,CSVDataset.EOF and CSVDataset.BOF);
end;
Procedure TTestCSVDataset.TestLoad2fieldsFirstLineAsNames;
begin
CSVDataset.CSVOptions.FirstLineAsFieldNames:=True;
CSVDataset.CSVOptions.DefaultFieldLength:=128;
LoadFromLines(['a,b']);
AssertEquals('Active',True,CSVDataset.Active);
AssertEquals('field count',2,CSVDataset.FieldDefs.Count);
AssertEquals('field 0 name','a',CSVDataset.FieldDefs[0].Name);
AssertEquals('field 0 size',CSVDataset.CSVOptions.DefaultFieldLength,CSVDataset.FieldDefs[0].Size);
AssertEquals('field 1 name','b',CSVDataset.FieldDefs[1].Name);
AssertEquals('field 1 size',CSVDataset.CSVOptions.DefaultFieldLength,CSVDataset.FieldDefs[1].Size);
AssertEquals('Empty',True,CSVDataset.EOF and CSVDataset.BOF);
end;
Procedure TTestCSVDataset.TestLoad2fields;
begin
CSVDataset.CSVOptions.DefaultFieldLength:=128;
LoadFromLines(['a,b']);
AssertEquals('Active',True,CSVDataset.Active);
AssertEquals('field count',2,CSVDataset.FieldDefs.Count);
AssertEquals('field 0 name','Column1',CSVDataset.FieldDefs[0].Name);
AssertEquals('field 0 size',CSVDataset.CSVOptions.DefaultFieldLength,CSVDataset.FieldDefs[0].Size);
AssertEquals('field 1 name','Column2',CSVDataset.FieldDefs[1].Name);
AssertEquals('field 1 size',CSVDataset.CSVOptions.DefaultFieldLength,CSVDataset.FieldDefs[1].Size);
AssertEquals('Empty',False,CSVDataset.EOF and CSVDataset.BOF);
AssertEquals('Not Empty',False,CSVDataset.EOF and CSVDataset.BOF);
AssertEquals('field 0 contents','a',CSVDataset.Fields[0].AsString);
AssertEquals('field 1 contents','b',CSVDataset.Fields[1].AsString);
end;
Procedure TTestCSVDataset.TestLoad2Records2fields;
begin
CSVDataset.CSVOptions.DefaultFieldLength:=128;
LoadFromLines(['a,b','c,d']);
AssertEquals('Active',True,CSVDataset.Active);
AssertEquals('field count',2,CSVDataset.FieldDefs.Count);
AssertEquals('field 0 name','Column1',CSVDataset.FieldDefs[0].Name);
AssertEquals('field 0 size',CSVDataset.CSVOptions.DefaultFieldLength,CSVDataset.FieldDefs[0].Size);
AssertEquals('field 1 name','Column2',CSVDataset.FieldDefs[1].Name);
AssertEquals('field 1 size',CSVDataset.CSVOptions.DefaultFieldLength,CSVDataset.FieldDefs[1].Size);
AssertEquals('Empty',False,CSVDataset.EOF and CSVDataset.BOF);
AssertEquals('Not Empty',False,CSVDataset.EOF and CSVDataset.BOF);
AssertEquals('field 0 contents','a',CSVDataset.Fields[0].AsString);
AssertEquals('field 1 contents','b',CSVDataset.Fields[1].AsString);
CSVDataset.Next;
AssertEquals('not At EOF',False,CSVDataset.EOF);
AssertEquals('field 0 contents','c',CSVDataset.Fields[0].AsString);
AssertEquals('field 1 contents','d',CSVDataset.Fields[1].AsString);
CSVDataset.Next;
AssertEquals('At EOF',True,CSVDataset.EOF);
end;
Procedure TTestCSVDataset.TestSaveEmptyDefault;
begin
CSVDataset.FieldDefs.Add('a',ftString);
CSVDataset.CreateDataset;
AssertLines([]);
end;
Procedure TTestCSVDataset.TestSaveEmptyFirstLineAsNames;
begin
CSVDataset.CSVOptions.FirstLineAsFieldNames:=True;
CSVDataset.FieldDefs.Add('a',ftString);
CSVDataset.CreateDataset;
AssertLines(['a']);
end;
Procedure TTestCSVDataset.TestSaveOneRecordDefault;
begin
// CSVDataset.CSVOptions.FirstLineAsFieldNames:=True;
CSVDataset.FieldDefs.Add('a',ftString,20);
CSVDataset.CreateDataset;
CSVDataset.Append;
CSVDataset.Fields[0].AsString:='b';
CSVDataset.Post;
AssertLines(['b']);
end;
Procedure TTestCSVDataset.TestSaveOneRecordFirstLineAsNames;
begin
CSVDataset.CSVOptions.FirstLineAsFieldNames:=True;
CSVDataset.FieldDefs.Add('a',ftString,20);
CSVDataset.CreateDataset;
CSVDataset.Append;
CSVDataset.Fields[0].AsString:='b';
CSVDataset.Post;
AssertLines(['a','b']);
end;
Procedure TTestCSVDataset.TestSaveTwoRecordsDefault;
begin
CSVDataset.FieldDefs.Add('a',ftString,20);
CSVDataset.CreateDataset;
CSVDataset.Append;
CSVDataset.Fields[0].AsString:='b';
CSVDataset.Post;
CSVDataset.Append;
CSVDataset.Fields[0].AsString:='c';
CSVDataset.Post;
AssertLines(['b','c']);
end;
Procedure TTestCSVDataset.TestSaveTwoRecordsFirstLineAsNames;
begin
CSVDataset.CSVOptions.FirstLineAsFieldNames:=True;
CSVDataset.FieldDefs.Add('a',ftString,20);
CSVDataset.CreateDataset;
CSVDataset.Append;
CSVDataset.Fields[0].AsString:='b';
CSVDataset.Post;
CSVDataset.Append;
CSVDataset.Fields[0].AsString:='c';
CSVDataset.Post;
AssertLines(['a','b','c']);
end;
Procedure TTestCSVDataset.TestSaveOneRecord2FieldsDefault;
begin
CSVDataset.FieldDefs.Add('a',ftString,20);
CSVDataset.FieldDefs.Add('b',ftString,20);
CSVDataset.CreateDataset;
CSVDataset.Append;
CSVDataset.Fields[0].AsString:='c';
CSVDataset.Fields[1].AsString:='d';
CSVDataset.Post;
AssertLines(['c,d']);
end;
Procedure TTestCSVDataset.TestSaveOneRecord2FieldsFirstLineAsNames;
begin
CSVDataset.CSVOptions.FirstLineAsFieldNames:=True;
CSVDataset.FieldDefs.Add('a',ftString,20);
CSVDataset.FieldDefs.Add('b',ftString,20);
CSVDataset.CreateDataset;
CSVDataset.Append;
CSVDataset.Fields[0].AsString:='c';
CSVDataset.Fields[1].AsString:='d';
CSVDataset.Post;
AssertLines(['a,b','c,d']);
end;
Procedure TTestCSVDataset.TestLoadPriorFieldDefs;
begin
CSVDataset.CSVOptions.FirstLineAsFieldNames:=True;
CSVDataset.FieldDefs.Add('a',ftString,20);
CSVDataset.FieldDefs.Add('b',ftInteger,4);
LoadFromLines(['a,b','1,2']);
AssertEquals('field count',2,CSVDataset.FieldDefs.Count);
AssertEquals('field 0 name','a',CSVDataset.FieldDefs[0].Name);
AssertEquals('field 0 size',20,CSVDataset.FieldDefs[0].Size);
AssertEquals('field 1 name','b',CSVDataset.FieldDefs[1].Name);
AssertEquals('field 1 size',4,CSVDataset.FieldDefs[1].Size);
AssertEquals('field 1 typee',Ord(ftInteger),Ord(CSVDataset.FieldDefs[1].DataType));
AssertEquals('Not Empty',False,CSVDataset.EOF and CSVDataset.BOF);
AssertEquals('field 0 contents','1',CSVDataset.Fields[0].AsString);
AssertEquals('field 1 contents',2,CSVDataset.Fields[1].AsInteger);
end;
Procedure TTestCSVDataset.TestLoadPriorFieldDefsNoFieldNames;
begin
CSVDataset.FieldDefs.Add('a',ftString,20);
CSVDataset.FieldDefs.Add('b',ftInteger,4);
LoadFromLines(['1,2']);
AssertEquals('field count',2,CSVDataset.FieldDefs.Count);
AssertEquals('field 0 name','a',CSVDataset.FieldDefs[0].Name);
AssertEquals('field 0 size',20,CSVDataset.FieldDefs[0].Size);
AssertEquals('field 1 name','b',CSVDataset.FieldDefs[1].Name);
AssertEquals('field 1 size',4,CSVDataset.FieldDefs[1].Size);
AssertEquals('field 1 typee',Ord(ftInteger),Ord(CSVDataset.FieldDefs[1].DataType));
AssertEquals('Not Empty',False,CSVDataset.EOF and CSVDataset.BOF);
AssertEquals('field 0 contents','1',CSVDataset.Fields[0].AsString);
AssertEquals('field 1 contents',2,CSVDataset.Fields[1].AsInteger);
end;
Procedure TTestCSVDataset.TestLoadPriorFieldDefsNoFieldNamesWrongCount;
Var
OK : Boolean;
begin
CSVDataset.FieldDefs.Add('a',ftString,20);
CSVDataset.FieldDefs.Add('b',ftInteger,4);
try
LoadFromLines(['1']);
OK:=False;
except
OK:=true;
end;
if not OK then
Fail('Expected exception, but none raised');
end;
Procedure TTestCSVDataset.TestLoadPriorFieldDefsFieldNamesWrongCount;
const
EM = 'DS : CSV File Field count (1) does not match dataset field count (2).';
Var
OK : String;
begin
CSVDataset.CSVOptions.FirstLineAsFieldNames:=True;
CSVDataset.FieldDefs.Add('a',ftString,20);
CSVDataset.FieldDefs.Add('b',ftInteger,4);
try
LoadFromLines(['A']);
OK:='Expected exception, but none raised';
except
on E : Exception do
if (E.Message<>EM) then
OK:=ComparisonMsg(EM,E.Message);
end;
if (OK<>'') then
Fail(OK);
end;
Procedure TTestCSVDataset.TestLoadPriorFieldDefsFieldNamesWrongNames;
const
EM = 'DS : CSV File field 1: name "c" does not match dataset field name "b".';
Var
OK : String;
begin
CSVDataset.CSVOptions.FirstLineAsFieldNames:=True;
CSVDataset.FieldDefs.Add('a',ftString,20);
CSVDataset.FieldDefs.Add('b',ftInteger,4);
try
LoadFromLines(['a,c']);
OK:='No exception raised';
except
on E : Exception do
if (E.Message<>EM) then
OK:=ComparisonMsg(EM,E.Message)
end;
if (OK<>'') then
Fail(OK);
end;
procedure TTestCSVDataset.SetUp;
begin
FCSVDataset:=TCSVDataset.Create(Nil);
FCSVDataset.Name:='DS';
end;
procedure TTestCSVDataset.TearDown;
begin
FreeAndNil(FCSVDataset);
end;
Initialization
RegisterTest(TTestCSVDataset);
end.