Browse Source

--- Merging r18214 into '.':
U packages/fcl-db/src/export/fpxmlxsdexport.pp
U packages/fcl-db/src/export/XMLXSDExportReadme.TXT
--- Merging r18215 into '.':
U packages/fcl-db/tests/xmlxsdexporttestcase1.pas
--- Merging r18944 into '.':
U packages/fcl-db/src/export/fpdbfexport.pp
--- Merging r18945 into '.':
U packages/fcl-db/src/export/fpdbexport.pp
--- Merging r18985 into '.':
G packages/fcl-db/src/export/fpdbfexport.pp
--- Merging r18986 into '.':
A packages/fcl-db/tests/dbfexporttest.lpi
A packages/fcl-db/tests/dbfexporttest.lpr
A packages/fcl-db/tests/dbfexporttestcase1.pas
--- Merging r19237 into '.':
U packages/fcl-db/tests/dbfexporttestcase1.pas

# revisions: 18214,18215,18944,18945,18985,18986,19237
------------------------------------------------------------------------
r18214 | michael | 2011-08-15 12:25:22 +0200 (Mon, 15 Aug 2011) | 16 lines
Changed paths:
M /trunk/packages/fcl-db/src/export/XMLXSDExportReadme.TXT
M /trunk/packages/fcl-db/src/export/fpxmlxsdexport.pp

* Patch by Reinier Olislagers (bug ID 19987):
1. Code cleanup to make it more modular and maintainable: split out code per export format and moved class-level variables there.
2. Delphi Clientdataset export now works thanks to FPC XML fixes by Sergei Gorelkin and tests/improvements by Ludo Brands.
3. Extended test coverage with all field types in a BufDataset so tests cover more.
4. Fixes for invalid data: Access, ADO.Net, Excel date limits respected (generate NULL or text fields respectively)
5. Decimalseparator setting in Access export should now work.
6. Variants are saved as blobs, not strings, because of their variable nature.
7. Fix for proper export of null values to Access NULL values (instead of empty/default values).
8. Changed description of class from "Unicode XML file with XSD" to "Unicode XML file" to better match unit function.
9. Compiled on Windows x86, Linux x64 without warnings using fpc -vweh fpxmlxsdexport.pp. Compared output.
- ftVarBytes gave different output on Windows & Linux. Disregarded as I don't fill these fields in the test because of bug #19930
10. Added option KeepFilesAfterTest = true in xmlxsdexporttestcase1; can be switched to false to delete export test files after use.
11. Lower-cased source code file names.
12. Fixes for Linux invalid date export to Excel by using clocale and specifying dateformat (restored at end of export).
13 .Datasize instead of .Size for string/widestring Delphi fields.

------------------------------------------------------------------------
------------------------------------------------------------------------
r18215 | michael | 2011-08-15 12:29:06 +0200 (Mon, 15 Aug 2011) | 1 line
Changed paths:
M /trunk/packages/fcl-db/tests/xmlxsdexporttestcase1.pas

* Better test case from Reinier, Bug ID #19987
------------------------------------------------------------------------
------------------------------------------------------------------------
r18944 | michael | 2011-09-02 15:06:21 +0200 (Fri, 02 Sep 2011) | 1 line
Changed paths:
M /trunk/packages/fcl-db/src/export/fpdbfexport.pp

* Patch from Reinier Olislagers to fix max fieldlength (bug 20134)
------------------------------------------------------------------------
------------------------------------------------------------------------
r18945 | michael | 2011-09-02 15:09:29 +0200 (Fri, 02 Sep 2011) | 1 line
Changed paths:
M /trunk/packages/fcl-db/src/export/fpdbexport.pp

* Patch from Reinier Olislagers to fix bug #20069
------------------------------------------------------------------------
------------------------------------------------------------------------
r18985 | michael | 2011-09-05 23:16:36 +0200 (Mon, 05 Sep 2011) | 1 line
Changed paths:
M /trunk/packages/fcl-db/src/export/fpdbfexport.pp

* Patch from Reinier Olislagers to fix bug #20160
------------------------------------------------------------------------
------------------------------------------------------------------------
r18986 | michael | 2011-09-06 12:16:56 +0200 (Tue, 06 Sep 2011) | 1 line
Changed paths:
A /trunk/packages/fcl-db/tests/dbfexporttest.lpi
A /trunk/packages/fcl-db/tests/dbfexporttest.lpr
A /trunk/packages/fcl-db/tests/dbfexporttestcase1.pas

* Testcase for DBF export
------------------------------------------------------------------------
------------------------------------------------------------------------
r19237 | marco | 2011-09-25 21:52:10 +0200 (Sun, 25 Sep 2011) | 3 lines
Changed paths:
M /trunk/packages/fcl-db/tests/dbfexporttestcase1.pas

* patch from BigChimp, fixing dbf related testing of output, from
reopened Mantis #20163

------------------------------------------------------------------------

git-svn-id: branches/fixes_2_6@20026 -

marco 13 years ago
parent
commit
6b5c954a94

+ 3 - 0
.gitattributes

@@ -1977,6 +1977,9 @@ packages/fcl-db/tests/XMLXSDExportTest.lpi svneol=native#text/plain
 packages/fcl-db/tests/XMLXSDExportTest.lpr svneol=native#text/plain
 packages/fcl-db/tests/bufdatasettoolsunit.pas svneol=native#text/plain
 packages/fcl-db/tests/database.ini.txt svneol=native#text/plain
+packages/fcl-db/tests/dbfexporttest.lpi svneol=native#text/plain
+packages/fcl-db/tests/dbfexporttest.lpr svneol=native#text/plain
+packages/fcl-db/tests/dbfexporttestcase1.pas svneol=native#text/plain
 packages/fcl-db/tests/dbftoolsunit.pas svneol=native#text/plain
 packages/fcl-db/tests/dbtestframework.pas svneol=native#text/plain
 packages/fcl-db/tests/memdstoolsunit.pas svneol=native#text/plain

+ 52 - 36
packages/fcl-db/src/export/XMLXSDExportReadme.TXT

@@ -1,51 +1,67 @@
-fpXMLXSDExport
-==============
-This export module provides export to various forms of XML, selectable by the ExportFormat setting:
+1. fpXMLXSDExport
+=================
+This export module provides export to various forms of XML, selectable by the ExportFormat setting.
+Note that not exporting indexes appears as a limitation in most formats below, but indexes probably will probably need to be changed anyway in an new environment/database.
 
-1. AccessCompatible
-Microsoft Access XP/2002-2010 and SQL Server compatible XML
+1.1 AccessCompatible
+====================
+This format generates Microsoft Access XP/2002-2010 (and presumably SQL Server) compatible XML.
 You can specify to include or exclude inline XSD data definition with the CreateXSD setting. Recommended to leave it to true so Access can build up the table structure. If you have an existing compatible table, you wouldn't need the XSD.
 Index definitions are exported in this format.
-The Access format as emitted by Access XP at least uses the decimal separator of the computer the export is running on. E.g. a US locale will emit 42.42, while a Dutch locale will emit 42,42. If you want to override the decimal separator to a value regardless of locale (recommended if exchanging data across multiple locales), please set the DecimalSeparator.
-Import of BLOB/binary type data is problematic as Access has no binary datatype, only an OLE datatype. Access stores OLE metadata, after that the binary object.
-This entire packet is exported as base64 data.
-We cannot replicate this functionality, so we just base64 encode the BLOB, and lose the OLE metadata. If you want to, in Access, you can probably programmatically read the data as blob data and copy it to a "real" OLE field.
+The Access format as emitted by Access XP at least uses the decimal separator of the computer the export is running on. E.g. a US locale will emit 42.42, while a Dutch locale will emit 42,42. If you want to override the decimal separator to a value regardless of locale (recommended if exchanging data across multiple locales), please set the DecimalSeparator (e.g. to '.').
+Limitations:
+* Import of BLOB/binary type data in Access is problematic as Access has no binary datatype, only an OLE datatype. Access stores OLE metadata, after that the binary object. This entire packet is exported as base64 data.
+We cannot replicate this functionality, so we just base64 encode the BLOB, and lose the OLE metadata. If you want to, in Access, you can probably programmatically read the data as blob data and copy it to a "real" OLE field. See e.g. http://support.microsoft.com/?kbid=103257 for hints on how to save the contents of the export BLOB to a file.
+* Date/time field data outside of Access limits are discarded (a NULL is inserted).
+* GUIDs are exported as text as Access has no equivalent field.
+* Large numeric values may overflow Access import capabilities. Patches welcome.
 
-2. ADONETCompatible
-XML compatible with the .Net framework (specifically the ADO.NET data access libraries), versions 2 to 4
+1.2 ADONETCompatible
+====================
+This format generates XML compatible with the .Net framework (specifically the ADO.NET data access libraries). It should work for versions 2 to 4; version 1/1.1 has not been tested.
 In this format you can also specify XSD or no XSD using the CreateXSD setting.
 This output format is fairly generic and could be usable for import in other applications, as well.
-Index definitions are not exported in this format.
+Limitations:
+* Index definitions are not exported in this format.
 
-3. ExcelCompatible
-Microsoft Excel XP/2002-2010 compatible XML
+1.3 ExcelCompatible
+===================
+This format generates Microsoft Excel XP/2002-2010 compatible XML.
 This format recreates the data as Excel worksheet data. It does not include formatting and formulas, just plain data.
-Index definitions are not exported in this format.
-The CreateXSD setting has no effect in this format.
-The Boolean (true/false) data format is not supported in Excel.
+The CreateXSD setting has no effect in this format - the Excel XML format doesn't seem to support compatible metadata.
+Limitations:
+* Index definitions are not exported in this format.
+* Binary data is not supported in the Excel XML format.
+* The Boolean (true/false) data format is not supported in Excel; instead 0/1 integers are exported.
+* Line endings within text cells/fields (generated in Excel by pressing Alt-Enter) are not supported as we'd need to output 
 in the XML which is not possible using current FCL XML libraries.
+An alternative to using this format could be the fpSpreadsheet components.
 
-3. DelphiClientDataset
-Delphi ClientDataset compatible XML
+1.4 DelphiClientDataset
+=======================
+This format generates Delphi ClientDataset compatible XML.
 This format allows Delphi applications to use the ClientDataset.LoadFromFile method to read the data.
-It has been written based on TurboDelphi (Delphi 2006) behaviour.
-Index definitions are not exported in this format.
-The CreateXSD setting has no effect in this format.
-Apparently, ClientDatasets have insert new data and update data modes; as of now, only the insert new data mode is supported.
+It has been written based on TurboDelphi (Delphi 2006) behaviour and exports UTF-8 encoded XML.
+The CreateXSD setting has no effect in this format - Clientdataset metadata is always exported.
+Limitations:
+* Index definitions are not exported in this format.
+* Variants are exported as binary data; patches for conversion are welcome.
+* Apparently, ClientDatasets have insert new data and update data modes; as of now, only the insert new data mode is supported.
 
-Other settings:
-As the XML formats used above defines how date/time formats, boolean formats etc are used, thes general export settings have no effect:
-BooleanFalse
-BooleanTrue
-DateFormat
-DateTimeFormat
-DecimalSeparator (only has effects in Access compatible export mode, no effect in other modes)
-CurrencyDigits
-CurrencySymbol
-IntegerFormat
-TimeFormat
+2. Other settings
+=================
+As the XML formats used above defines how date/time formats, boolean formats etc are used, these general export settings have no effect:
+- BooleanFalse
+- BooleanTrue
+- DateFormat
+- DateTimeFormat
+- DecimalSeparator (only has effects in Access compatible export mode, no effect in other modes)
+- CurrencyDigits
+- CurrencySymbol
+- IntegerFormat
+- TimeFormat
 
-License
-=======
+3. License
+==========
 The fpXMLXSDExport module is freeware, licensed under the MIT license: all use free, but no liability accepted.
 It is also licensed under the FreePascal license, so take your pick, but don't blame me for things that go wrong.
 

+ 2 - 2
packages/fcl-db/src/export/fpdbexport.pp

@@ -293,11 +293,11 @@ Procedure UnRegisterExportFormat(Const AName : String);
 
 Const
   StringFieldTypes = [ftString,ftFixedChar,ftWidestring,ftFixedWideChar];
-  IntFieldTypes    = [ftInteger,ftWord,ftsmallint,ftautoinc];
+  IntFieldTypes    = [ftInteger,ftWord,ftSmallint,ftAutoinc];
   OrdFieldTypes    = IntFieldTypes +[ftBoolean,ftLargeInt];
   DateFieldTypes   = [ftDate,ftTime,ftDateTime,ftTimeStamp];
   MemoFieldTypes   = [ftMemo,ftFmtMemo,ftWideMemo];
-  BlobFieldTypes   =  [ftBlob,ftGraphic,ftOraBlob,ftOraClob];
+  BlobFieldTypes   =  [ftBlob,ftDBaseOLE,ftGraphic,ftOraBlob,ftOraClob,ftParadoxOLE];
   
 
 implementation

+ 40 - 25
packages/fcl-db/src/export/fpdbfexport.pp

@@ -42,7 +42,7 @@ Type
     function GetSettings: TDBFExportFormatSettings;
     procedure SetSettings(const AValue: TDBFExportFormatSettings);
   Protected
-    Procedure CheckExportFieldNames; virtual;
+    Procedure CheckExportFieldNames(const MaxFieldNameLength: integer); virtual;
     Function BindFields : Boolean; override;
     Function CreateFormatSettings : TCustomExportFormatSettings; override;
 
@@ -97,28 +97,30 @@ begin
   Inherited FormatSettings.Assign(AValue);
 end;
 
-procedure TFPCustomDBFExport.CheckExportFieldNames;
+procedure TFPCustomDBFExport.CheckExportFieldNames(const MaxFieldNameLength: integer);
 
 Var
-  I,J : Integer;
+  i,NameCounter : Integer;
   EF : TExportFieldItem;
-  FN : String;
+  NewFieldName : String;
   
 begin
-  For I:=0 to ExportFields.Count-1 do
+  For i:=0 to ExportFields.Count-1 do
     begin
     EF:=ExportFields[i];
-    If (Length(EF.ExportedName)>10) then
+    { Cut off field name at max length, and
+      rename if it already exists:}
+    If (Length(EF.ExportedName)>MaxFieldNameLength) then
       begin
-      FN:=Copy(EF.ExportedName,1,10);
-      If ExportFIelds.IndexOfExportedName(FN)<>-1 then
+      NewFieldName:=Copy(EF.ExportedName,1,MaxFieldNameLength);
+      If ExportFields.IndexOfExportedName(NewFieldName)<>-1 then
         begin
-        J:=1;
+        NameCounter:=1;
         Repeat
-          FN:=Copy(EF.ExportedName,1,8)+Format('%.2d',[J]);
-        Until (ExportFIelds.IndexOfExportedName(FN)=-1);
+          NewFieldName:=Copy(EF.ExportedName,1,8)+Format('%.2d',[NameCounter]);
+        Until (ExportFIelds.IndexOfExportedName(NewFieldName)=-1);
         end;
-      EF.ExportedName:=FN;
+      EF.ExportedName:=NewFieldName;
       end;
     end;
 end;
@@ -130,28 +132,32 @@ Const
   
 Var
   EF : TDBFExportFieldItem;
-  I : Integer;
+  i : Integer;
   
 begin
-  If FormatSettings.AutoRenameFields and (FormatSettings.TableFormat=tfDbaseIII) then
-    CheckExportFieldNames;
+  // DBase III,IV, and FoxPro have a 10 character field length limit.
+  If FormatSettings.AutoRenameFields and (FormatSettings.TableFormat in [tfDbaseIII,tfDbaseIV,tfFoxPro]) then
+    CheckExportFieldNames(10);
+  // DBase VII has a 32 character field length limit.
+  If FormatSettings.AutoRenameFields and (FormatSettings.TableFormat=tfDbaseVII) then
+    CheckExportFieldNames(32);
   Result:=Inherited;
   try
     with FDBF.FieldDefs do
       begin
       Clear;
-      For I:=0 to ExportFields.Count-1 do
+      For i:=0 to ExportFields.Count-1 do
         begin
-        EF:=ExportFIelds[i] as TDBFExportFieldItem;
-        If EF.ENabled and Assigned(EF.Field) then
-          Add(EF.ExportedName,EF.FIeld.DataType,EF.Field.Size);
+        EF:=ExportFields[i] as TDBFExportFieldItem;
+        If EF.Enabled and Assigned(EF.Field) then
+          Add(EF.ExportedName,EF.Field.DataType,EF.Field.Size);
         end;
       FDBF.TableLevel:=Levels[FormatSettings.TableFormat];
       FDBF.CreateTable;
       FDBF.Exclusive := true;
       FDBF.Open;
       end;
-    For I:=0 to ExportFields.Count-1 do
+    For i:=0 to ExportFields.Count-1 do
       begin
       EF:=ExportFIelds[i] as TDBFExportFieldItem;
       If EF.Enabled then
@@ -222,20 +228,29 @@ Var
 begin
   F:=EF as TDBFExportFieldItem;
   With F do
+    // Export depending on field datatype;
+    // convert to dbf data types where necessary.
+    // Fall back to string if unknown datatype
     If FIeld.IsNull then
       DestField.Clear
-    else If Field.Datatype in IntFieldTypes then
+    else if Field.Datatype in (IntFieldTypes+[ftAutoInc,ftLargeInt]) then
       DestField.AsInteger:=Field.AsInteger
-    else if Field.dataType in [ftString,ftFixedChar] then
+    else if Field.Datatype in [ftBCD,ftCurrency,ftFloat,ftFMTBcd] then
+      DestField.AsFloat:=Field.AsFloat
+    else if Field.DataType in [ftString,ftFixedChar] then
+      DestField.AsString:=Field.AsString
+    else if (Field.DataType in ([ftWideMemo,ftWideString,ftFixedWideChar]+BlobFieldTypes)) then
+      DestField.AsWideString:=Field.AsWideString
+      { Note: we test for the wide text fields before the MemoFieldTypes, in order to
+      let ftWideMemo end up at the right place }
+    else if Field.DataType in MemoFieldTypes then
       DestField.AsString:=Field.AsString
     else if Field.DataType=ftBoolean then
       DestField.AsBoolean:=Field.AsBoolean
-    else if (Field.DataType in ([ftWidestring,ftFixedWideChar]+BlobFieldTypes)) then
-      DestField.AsWideString:=Field.AsWideString
     else if field.DataType in DateFieldTypes then
       DestField.AsDatetime:=Field.AsDateTime
     else
-      DestField.AsDatetime:=Field.AsDateTime
+      DestField.AsString:=Field.AsString
 end;
 
 Procedure RegisterDBFExportFormat;

File diff suppressed because it is too large
+ 519 - 170
packages/fcl-db/src/export/fpxmlxsdexport.pp


+ 113 - 0
packages/fcl-db/tests/dbfexporttest.lpi

@@ -0,0 +1,113 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <PathDelim Value="\"/>
+    <General>
+      <Flags>
+        <SaveOnlyProjectUnits Value="True"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="dbfexporttest"/>
+      <ResourceType Value="res"/>
+    </General>
+    <i18n>
+      <EnableI18N LFM="False"/>
+    </i18n>
+    <VersionInfo>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="2">
+      <Item1 Name="Default" Default="True"/>
+      <Item2 Name="Debug">
+        <CompilerOptions>
+          <Version Value="10"/>
+          <PathDelim Value="\"/>
+          <SearchPaths>
+            <IncludeFiles Value="$(ProjOutDir)"/>
+          </SearchPaths>
+          <CodeGeneration>
+            <Checks>
+              <IOChecks Value="True"/>
+              <RangeChecks Value="True"/>
+              <OverflowChecks Value="True"/>
+              <StackChecks Value="True"/>
+            </Checks>
+          </CodeGeneration>
+          <Linking>
+            <Debugging>
+              <GenerateDebugInfo Value="True"/>
+              <GenerateDwarf Value="True"/>
+              <UseHeaptrc Value="True"/>
+            </Debugging>
+          </Linking>
+          <Other>
+            <CompilerMessages>
+              <UseMsgFile Value="True"/>
+            </CompilerMessages>
+            <CompilerPath Value="$(CompPath)"/>
+          </Other>
+        </CompilerOptions>
+      </Item2>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <CommandLineParams Value="-a --format=plain"/>
+        <LaunchingApplication PathPlusParams="\usr\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <RequiredPackages Count="2">
+      <Item1>
+        <PackageName Value="FPCUnitConsoleRunner"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="FCL"/>
+      </Item2>
+    </RequiredPackages>
+    <Units Count="2">
+      <Unit0>
+        <Filename Value="dbfexporttest.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="dbfexporttest"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="dbfexporttestcase1.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="dbfexporttestcase1"/>
+      </Unit1>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="10"/>
+    <PathDelim Value="\"/>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+    </SearchPaths>
+    <Other>
+      <CompilerMessages>
+        <UseMsgFile Value="True"/>
+      </CompilerMessages>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 28 - 0
packages/fcl-db/tests/dbfexporttest.lpr

@@ -0,0 +1,28 @@
+program dbfexporttest;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes,
+  consoletestrunner,
+  dbfexporttestcase1;
+
+type
+
+  { TLazTestRunner }
+
+  TMyTestRunner = class(TTestRunner)
+  protected
+    // override the protected methods of TTestRunner to customize its behavior
+  end;
+
+var
+  Application: TMyTestRunner;
+
+begin
+  Application := TMyTestRunner.Create(nil);
+  Application.Initialize;
+  Application.Run;
+  Application.Free;
+end.
+

+ 495 - 0
packages/fcl-db/tests/dbfexporttestcase1.pas

@@ -0,0 +1,495 @@
+unit dbfexporttestcase1;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, Fpcunit, Testutils, Testregistry, DB, fpdbfexport,
+  BufDataset, dateutils;
+
+type
+
+  { TTestDBFExport1 }
+
+  TTestDBFExport1 = class(Ttestcase)
+  const
+    KeepFilesAfterTest = false;
+    //Change if you want to keep export files for further testing
+  private
+    procedure FillTestData;
+  protected
+    FTestDataset: TBufDataset;
+    FExportTempDir: string; //where we store exported files in these tests
+    procedure FillRecord(const RowNumber: integer; const Teststring: string;
+      const TestGUID: string; const TestInteger: integer;
+      const TestExtended: extended; const TestDatetime: Tdatetime;
+      const TestBoolean: boolean);
+    procedure Setup; override;
+    procedure Teardown; override;
+  published
+    procedure TestDBExportRuns;
+  end;
+
+implementation
+
+function FileSize(FileName: string): integer;
+  // LCL has similar function, but we don't want to depend on that.
+var
+  SearchResult: TSearchRec;
+begin
+  Result := 0;
+  if FindFirst(FileName, faAnyFile, SearchResult) = 0 then
+  begin
+    try
+      Result := SearchResult.Size;
+    finally
+      FindClose(SearchResult);
+    end;
+  end;
+end;
+
+procedure TTestDBFExport1.TestDBExportRuns;
+
+var
+  Export: TFPDBFExport;
+  ExportSettings: TDBFExportFormatSettings;
+  NumberExported: integer;
+begin
+  Export := TFPDBFExport.Create(nil);
+  ExportSettings:=TDBFExportFormatSettings.Create(true);
+  try
+    //Don't override decimal separator
+    ExportSettings.TableFormat:=tfDBaseVII; //dbase IV seems to have a 10 character field name limit
+    Export.FormatSettings:=ExportSettings;
+    Export.Dataset := FTestDataset;
+    Export.FileName := FExportTempDir + 'dbfexporttest.dbf';
+    NumberExported := Export.Execute;
+    FTestDataset.Close;
+    AssertEquals('Number of records exported', NumberExported, FTestDataset.RecordCount);
+    AssertTrue('Output file created', FileExists(Export.FileName));
+    AssertTrue('Output file has contents', (FileSize(Export.FileName) > 0));
+  finally
+    if (KeepFilesAfterTest = False) then
+    begin
+      DeleteFile(Export.FileName);
+    end;
+    ExportSettings.Free;
+    Export.Free;
+  end;
+end;
+
+
+procedure TTestDBFExport1.FillTestData;
+var
+  RowNumber: integer; //Keep track of how many rows we inserted
+  TestBoolean: boolean;
+  TestDateTime: TDateTime;
+  TestExtended: extended;
+  //yes, a lot of precision; we can convert to single/double if required
+  TestInteger: integer;
+  TestGuid: string;
+  TestString: string;
+begin
+  FTestDataset.Close;
+  RowNumber := 0;
+  //for memds:
+  //FTestDataset.Clear(False); //memds: clear out any data
+  //FTestDataset.Fields.Clear; //bufds: clear out any data, but also FIELDDEFS: don't use
+  FTestDataset.Open;
+
+  // Fill some test data
+  // First row: positive numerical values, late dates/times, strings with special chars (tab, linefeed, ; > <)
+  FTestDataset.Append;
+  TestBoolean := True;
+  TestDateTime := EncodeDate(9999, 12, 31) + EncodeTime(23, 59, 59, 999);
+  TestExtended := 42.424242424242424242424242424242;
+  TestInteger := Round(TestExtended);
+  TestGuid := '{21EC2020-3AEA-1069-A2DD-08002B30309D}';
+  TestString := 'Douglas Adams less than: < greater than > tab:' +
+    #9 + 'crlf:' + #13 + #10 +
+    '國缺界广欠廣界界东缺. Haddock drinks rosé (ros, e accent aigu), водка (wodka cyrillic) and ούζο (ouzo Greek) but prefers Loch Lomond whiskey.';
+  RowNumber := RowNumber + 1;
+  FillRecord(RowNumber, Teststring, TestGUID, Testinteger, Testextended,
+    Testdatetime, Testboolean);
+  FTestDataset.Post;
+
+  // Second row: negative numerical values, early dates/times, strings with maximum field width and Greek, east asian (multibyte) characters
+  FTestDataset.Append;
+  TestBoolean := False;
+  TestDateTime := EncodeDate(1, 1, 1) + EncodeTime(0, 0, 0, 1);
+  TestExtended := -42.424242424242424242424242424242;
+  TestInteger := Round(TestExtended);
+  TestGuid := '{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}';
+  TestString := 'ARMA virumque cano, Troiae qui primus ab oris' +
+    #13 + #10 + 'Italiam, fato profugus, Laviniaque venit' + #13 +
+    #10 + 'litora, multum ille et terris iactatus et alto' + #13 +
+    #10 + 'vi superum saevae memorem Iunonis ob iram;' + #13 + #10 +
+    'multa quoque et bello passus, dum conderet urbem,' + #13 + #10 +
+    'inferretque deos Latio, genus unde Latinum,' + #13 + #10 +
+    'Albanique patres, atque altae moenia Romae.' + #13 + #10 + #13 +
+    #10 + 'Musa, mihi causas memora, quo numine laeso,' + #13 + #10 +
+    'quidve dolens, regina deum tot volvere casus' + #13 + #10 +
+    'insignem pietate virum, tot adire labores' + #13 + #10 +
+    'impulerit.  Tantaene animis caelestibus irae?' + #13 + #10 +
+    #13 + #10 + 'Urbs antiqua fuit, Tyrii tenuere coloni,' + #13 +
+    #10 + 'Karthago, Italiam contra Tiberinaque longe' + #13 + #10 +
+    'ostia, dives opum studiisque asperrima belli;' + #13 + #10 +
+    'quam Iuno fertur terris magis omnibus unam' + #13 + #10 +
+    'posthabita coluisse Samo; hic illius arma,' + #13 + #10 +
+    'hic currus fuit; hoc regnum dea gentibus esse,' + #13 + #10 +
+    'si qua fata sinant, iam tum tenditque fovetque.' + #13 + #10 +
+    'Progeniem sed enim Troiano a sanguine duci' + #13 + #10 +
+    'audierat, Tyrias olim quae verteret arces;' + #13 + #10 +
+    'hinc populum late regem belloque superbum' + #13 + #10 +
+    'venturum excidio Libyae:  sic volvere Parcas.' + #13 + #10 +
+    'Id metuens, veterisque memor Saturnia belli,' + #13 + #10 +
+    'prima quod ad Troiam pro caris gesserat Argis---' + #13 + #10 +
+    'necdum etiam causae irarum saevique dolores' + #13 + #10 +
+    'exciderant animo:  manet alta mente repostum' + #13 + #10 +
+    'iudicium Paridis spretaeque iniuria formae,' + #13 + #10 +
+    'et genus invisum, et rapti Ganymedis honores.' + #13 + #10 +
+    'His accensa super, iactatos aequore toto' + #13 + #10 +
+    'Troas, reliquias Danaum atque immitis Achilli,' + #13 + #10 +
+    'arcebat longe Latio, multosque per annos' + #13 + #10 +
+    'errabant, acti fatis, maria omnia circum.' + #13 + #10 +
+    'Tantae molis erat Romanam condere gentem!';
+  RowNumber := RowNumber + 1;
+  FillRecord(RowNumber, Teststring, TestGUID, Testinteger, Testextended,
+    Testdatetime, Testboolean);
+  FTestDataset.Post;
+
+  // Third row: empty/zero numerical values, dates/times, strings
+  FTestDataset.Append;
+  TestBoolean := False;
+  TestDateTime := EncodeDate(1, 1, 1) + EncodeTime(0, 0, 0, 0);
+  TestExtended := 0;
+  TestInteger := Round(TestExtended);
+  TestGuid := '{3F2504E0-4F89-11D3-9A0C-0305E82C3301}';
+  TestString := '';
+  RowNumber := RowNumber + 1;
+  FillRecord(RowNumber, Teststring, TestGUID, Testinteger, Testextended,
+    Testdatetime, Testboolean);
+  FTestDataset.Post;
+
+  // Fourth row: plausible data
+  FTestDataset.Append;
+  TestBoolean := True;
+  TestDateTime := EncodeDate(2005, 9, 10) + EncodeTime(13, 52, 18, 0);
+  TestExtended := 42;
+  TestInteger := Round(TestExtended);
+  TestString := 'The answer to life, the universe, and everything';
+  RowNumber := RowNumber + 1;
+  FillRecord(RowNumber, Teststring, TestGUID, Testinteger, Testextended,
+    Testdatetime, Testboolean);
+  FTestDataset.Post;
+
+  // Make sure recordcount is correct:
+  FTestDataset.Last;
+  FTestDataset.First;
+  AssertEquals('Number of records in test dataset', RowNumber, FTestDataset.RecordCount);
+end;
+
+procedure TTestDBFExport1.Setup;
+const
+  NumberOfDecimals = 2;
+  NumberOfBytes = 10;
+var
+  FieldDef: TFieldDef;
+begin
+  FExportTempDir := GetTempDir(False);
+  FTestDataset := TBufDataset.Create(nil);
+  {Tweaked for dbf export}
+  {We should cover all data types defined in FPC:
+
+  FPC maps "external" types such as ftOracleBlob to
+  internal types, but that can be overridden, which is done
+  by e.g. IBX and mseide.
+  So it makes sense to keep as many datatypes in the exporter code as possible: it documents the mappings and allows other people to use these types without the exporter breaking.
+  }
+  {Sorted by datatype; commented out what doesn't work at the moment in bufdataset
+  See http://docwiki.embarcadero.com/VCL/en/DB.TField.Size for overview of field sizes in the competition product ;)
+  Apparently ftGuid also needs size...
+  }
+
+  {
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftADT';
+  FieldDef.DataType := ftADT;
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
+  }
+
+  {
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftArray';
+  FieldDef.DataType := ftArray;
+  FieldDef.Size := 10;//the number of elements in the array
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftAutoInc';
+  FieldDef.DataType := ftAutoInc;
+  }
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftBCD';
+  FieldDef.DataType := ftBCD;
+  FieldDef.Size := NumberOfDecimals;
+  //Size is the number of digits after the decimal place
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  //Note dbf 3 has a 10 character field length limit
+  FieldDef.Name := 'ftBlob_4096';
+  FieldDef.DataType := ftBlob;
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftBoolean';
+  FieldDef.DataType := ftBoolean;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftBytes';
+  FieldDef.DataType := ftBytes;
+  FieldDef.Size := NumberOfBytes;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftCurrency';
+  FieldDef.DataType := ftCurrency;
+
+  {
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftCursor';
+  FieldDef.DataType := ftCursor;
+  }
+
+  {
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftDataSet';
+  FieldDef.DataType := ftDataSet;
+  }
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftDate';
+  FieldDef.DataType := ftDate;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftDateTime';
+  FieldDef.DataType := ftDateTime;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftDBaseOle';
+  FieldDef.DataType := ftDBaseOle;
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftFixedChar_2';
+  FieldDef.DataType := ftFixedChar;
+  FieldDef.Size := NumberOfDecimals;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftFixedWideChar_2';
+  FieldDef.DataType := ftFixedWideChar;
+  FieldDef.Size := NumberOfBytes;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftFloat';
+  FieldDef.DataType := ftFloat;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftFMTBcd';
+  FieldDef.DataType := ftFMTBcd;
+  FieldDef.Size := NumberOfDecimals; //the number of digits after the decimal place.
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftFmtMemo';
+  FieldDef.DataType := ftFmtMemo;
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftGraphic';
+  FieldDef.DataType := ftGraphic;
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftGuid';
+  FieldDef.DataType := ftGuid;
+  FieldDef.Size := 38;
+  //Apparently right answer is not 42; had to look up 38 in source code.
+
+  {
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftIDispatch';
+  FieldDef.DataType := ftIDispatch;
+  }
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftInteger';
+  FieldDef.DataType := ftInteger;
+
+  {
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftInterface';
+  FieldDef.DataType := ftInterface;
+  }
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftLargeint';
+  FieldDef.DataType := ftLargeint;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftMemo';
+  FieldDef.DataType := ftMemo;
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftOraBlob';
+  FieldDef.DataType := ftOraBlob;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftOraClob';
+  FieldDef.DataType := ftOraClob;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftParadoxOle';
+  FieldDef.DataType := ftParadoxOle;
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
+
+  {
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftReference';
+  FieldDef.DataType := ftReference;
+  }
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftSmallInt';
+  FieldDef.DataType := ftInteger;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftString_1';
+  FieldDef.DataType := ftString;
+  FieldDef.Size := 1;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftString_256'; //1 character more than many db string types support
+  FieldDef.DataType := ftString;
+  FieldDef.Size := 256;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftTime';
+  FieldDef.DataType := ftTime;
+
+  {
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftTimeStamp';
+  FieldDef.DataType := ftTimeStamp;
+  }
+
+  {
+  //Bufdataset probably doesn't support this
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  // DBF 10 character limit comes into play here:
+  FieldDef.Name := 'ftTypedBin';
+  FieldDef.DataType := ftTypedBinary;
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
+  }
+
+  FieldDef.Name := 'ftVariant';
+  FieldDef.DataType := ftVariant;
+  FieldDef.Size := NumberOfBytes;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftVarBytes';
+  FieldDef.DataType := ftVarBytes;
+  FieldDef.Size := NumberOfBytes;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftWideMemo';
+  FieldDef.DataType := ftWideMemo;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftWideString256';
+  FieldDef.DataType := ftWideString;
+  FieldDef.Size := 256;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftWord';
+  FieldDef.DataType := ftWord;
+  
+  //Finally, a long field name that should trigger
+  //field renaming code in dbf export
+  //(dbase VII supports up to 32 characters, others up to 10)
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'AVeryLongFieldDataTypeDoesNotMatter';
+  FieldDef.DataType := ftString;
+  FieldDef.Size := 256;
+
+  //Createtable is needed if you use a memds
+  //FTestDataset.CreateTable;
+  //CreateDataset is needed if you use a bufdataset
+  FTestDataset.CreateDataSet;
+
+  // Fill dataset with test data
+  FillTestData;
+end;
+
+procedure TTestDBFExport1.FillRecord(const RowNumber: integer;
+  const TestString: string; const TestGUID: string; const TestInteger: integer;
+  const TestExtended: extended; const TestDatetime: Tdatetime;
+  const TestBoolean: boolean);
+var
+  FieldCounter: integer;
+begin
+  {As our bufdataset doesn't support these datatypes, don't use them:
+ftAutoInc -> exists but doesn't seem to return any data.
+ftCursor
+ftDataSet
+ftInterface
+ftReference
+ftTimeStamp}
+
+  FTestDataset.FieldByName('ftBCD').AsFloat := Testextended;
+  FTestDataset.FieldByName('ftBlob_4096').AsString := Teststring;
+  FTestDataset.FieldByName('ftBoolean').AsBoolean := Testboolean;
+  FTestDataset.FieldByName('ftBytes').AsString := Teststring;
+  FTestDataset.FieldByName('ftCurrency').Ascurrency := Testextended;
+  FTestDataset.FieldByName('ftDate').AsDateTime := Testdatetime;
+  FTestDataset.FieldByName('ftDateTime').AsDateTime := Testdatetime;
+  FTestDataset.FieldByName('ftDBaseOle').AsString := Teststring;
+  FTestDataset.FieldByName('ftFixedChar_2').AsString := Teststring;
+  FTestDataset.FieldByName('ftFixedWideChar_2').AsString := Teststring;
+  FTestDataset.FieldByName('ftFloat').AsFloat := Testextended;
+  FTestDataset.FieldByName('ftFMTBcd').AsFloat := Testextended;
+  FTestDataset.FieldByName('ftFmtMemo').AsString := Teststring;
+  FTestDataset.FieldByName('ftGraphic').AsString := Teststring;
+  FTestDataset.FieldByName('ftGuid').AsString := TestGUID;
+  FTestDataset.FieldByName('ftInteger').AsInteger := Testinteger;
+  FTestDataset.FieldByName('ftLargeint').AsInteger := Testinteger;
+  FTestDataset.FieldByName('ftMemo').AsString := Teststring;
+  FTestDataset.FieldByName('ftOraBlob').AsString := Teststring;
+  {
+  FTestDataset.FieldByName('ftOraClob').AsString := Teststring;
+  }
+  FTestDataset.FieldByName('ftParadoxOle').AsString := Teststring;
+  FTestDataset.FieldByName('ftSmallInt').AsInteger := Testinteger;
+  FTestDataset.FieldByName('ftString_1').AsString := Teststring;
+  FTestDataset.FieldByName('ftString_256').AsString := Teststring;
+  FTestDataset.FieldByName('ftTime').AsDateTime := Testdatetime;
+  {
+  FTestDataset.FieldByName('ftTypedBin').AsString := Teststring;
+  }
+  FTestDataSet.FieldByName('ftVarBytes').AsString := TestString;
+  FTestDataSet.FieldByName('ftVariant').AsString := TestString;
+  FTestDataset.FieldByName('ftWideMemo').AsString := Teststring;
+  FTestDataset.FieldByName('ftWideString256').AsString := Teststring;
+  FTestDataset.FieldByName('ftWord').AsInteger := Abs(Testinteger);
+  FTestDataset.FieldByName('AVeryLongFieldDataTypeDoesNotMatter').AsString := Teststring;
+end;
+
+procedure TTestDBFExport1.Teardown;
+begin
+  FTestDataset.Free;
+end;
+
+initialization
+  Registertest(TTestDBFExport1);
+end.
+

+ 416 - 77
packages/fcl-db/tests/xmlxsdexporttestcase1.pas

@@ -10,19 +10,28 @@ uses
 
 type
 
+  { Ttestxmlxsdexport1 }
+
   Ttestxmlxsdexport1 = class(Ttestcase)
+  const
+    KeepFilesAfterTest = true;
+    //Change if you want to keep export files for further testing
   private
     procedure FillTestData;
   protected
     FTestDataset: TBufDataset;
     FExportTempDir: string; //where we store exported files in these tests
+    procedure FillRecord(const RowNumber: integer; const Teststring: string;
+      const TestGUID: string; const TestInteger: integer;
+      const TestExtended: extended; const TestDatetime: Tdatetime;
+      const TestBoolean: boolean);
     procedure Setup; override;
     procedure Teardown; override;
   published
-    procedure TestXSDExport_Access_NoXSD_Decimal;
-    procedure TestXSDExport_Access_NoXSD_NoDecimal;
-    procedure TestXSDExport_Access_XSD_Decimal;
-    procedure TestXSDExport_Access_XSD_NoDecimal;
+    procedure TestXSDExport_Access_NoXSD_DecimalOverride;
+    procedure TestXSDExport_Access_NoXSD_NoDecimalOverride;
+    procedure TestXSDExport_Access_XSD_DecimalOverride;
+    procedure TestXSDExport_Access_XSD_NoDecimalOverride;
     procedure TestXSDExport_ADONET_NoXSD;
     procedure TestXSDExport_ADONET_XSD;
     procedure TestXSDExport_DelphiClientDataset;
@@ -31,7 +40,7 @@ type
 
 implementation
 
-procedure Ttestxmlxsdexport1.TestXSDExport_Access_NoXSD_NoDecimal;
+procedure Ttestxmlxsdexport1.TestXSDExport_Access_NoXSD_NoDecimalOverride;
 
 var
   Export: TXMLXSDExporter;
@@ -44,24 +53,25 @@ begin
   try
     //Don't override decimal separator
     Settings.CreateXSD := False;
-    Settings.DecimalSeparator := Char(''); //Don't override decimalseparator
+    Settings.DecimalSeparator := char(''); //Don't override decimalseparator
     Settings.ExportFormat := AccessCompatible;
     Export.Dataset := FTestDataset;
     Export.FormatSettings := Settings;
-    Export.FileName := FExportTempDir + 'Access_NoXSD_NoDecimal.xml';
+    Export.FileName := FExportTempDir + 'Access_NoXSD_NoDecimalOverride.xml';
     NumberExported := Export.Execute;
     FTestDataset.Close;
     AssertEquals('Number of records exported', NumberExported, FTestDataset.RecordCount);
-    //we should have exported 2 records.
   finally
     Settings.Free;
-    { TODO 9 -oAnyone -cNice to have : When initial testing is complete, delete export files. }
-    //DeleteFile(Export.FileName); //todo: fix this for release
+    if (KeepFilesAfterTest = False) then
+    begin
+      DeleteFile(Export.FileName);
+    end;
     Export.Free;
   end;
 end;
 
-procedure Ttestxmlxsdexport1.TestXSDExport_Access_NoXSD_Decimal;
+procedure Ttestxmlxsdexport1.TestXSDExport_Access_NoXSD_DecimalOverride;
 var
   Export: TXMLXSDExporter;
   Settings: TXMLXSDFormatSettings;
@@ -77,19 +87,21 @@ begin
     Settings.ExportFormat := AccessCompatible;
     Export.Dataset := FTestDataset;
     Export.FormatSettings := Settings;
-    Export.FileName := FExportTempDir + 'Access_NoXSD_Decimal.xml';
+    Export.FileName := FExportTempDir + 'Access_NoXSD_DecimalOverride.xml';
     NumberExported := Export.Execute;
     FTestDataset.Close;
     AssertEquals('Number of records exported', NumberExported, FTestDataset.RecordCount);
-    //we should have exported 2 records.
   finally
     Settings.Free;
-    //DeleteFile(Export.FileName); //todo: fix this for release
+    if (KeepFilesAfterTest = False) then
+    begin
+      DeleteFile(Export.FileName);
+    end;
     Export.Free;
   end;
 end;
 
-procedure Ttestxmlxsdexport1.TestXSDExport_Access_XSD_NoDecimal;
+procedure Ttestxmlxsdexport1.TestXSDExport_Access_XSD_NoDecimalOverride;
 var
   Export: TXMLXSDExporter;
   Settings: TXMLXSDFormatSettings;
@@ -104,19 +116,21 @@ begin
     Settings.ExportFormat := AccessCompatible;
     Export.Dataset := FTestDataset;
     Export.FormatSettings := Settings;
-    Export.FileName := FExportTempDir + 'Access_XSD_NoDecimal.xml';
+    Export.FileName := FExportTempDir + 'Access_XSD_NoDecimalOverride.xml';
     NumberExported := Export.Execute;
     FTestDataset.Close;
     AssertEquals('Number of records exported', NumberExported, FTestDataset.RecordCount);
-    //we should have exported 2 records.
   finally
     Settings.Free;
-    //DeleteFile(Export.FileName); //todo: fix this for release
+    if (KeepFilesAfterTest = False) then
+    begin
+      DeleteFile(Export.FileName);
+    end;
     Export.Free;
   end;
 end;
 
-procedure Ttestxmlxsdexport1.TestXSDExport_Access_XSD_Decimal;
+procedure Ttestxmlxsdexport1.TestXSDExport_Access_XSD_DecimalOverride;
 var
   Export: TXMLXSDExporter;
   Settings: TXMLXSDFormatSettings;
@@ -131,14 +145,16 @@ begin
     Settings.ExportFormat := AccessCompatible;
     Export.Dataset := FTestDataset;
     Export.FormatSettings := Settings;
-    Export.FileName := FExportTempDir + 'Access_XSD_Decimal.xml';
+    Export.FileName := FExportTempDir + 'Access_XSD_DecimalOverride.xml';
     NumberExported := Export.Execute;
     FTestDataset.Close;
     AssertEquals('Number of records exported', NumberExported, FTestDataset.RecordCount);
-    //we should have exported 2 records.
   finally
     Settings.Free;
-    //DeleteFile(Export.FileName); //todo: fix this for release
+    if (KeepFilesAfterTest = False) then
+    begin
+      DeleteFile(Export.FileName);
+    end;
     Export.Free;
   end;
 end;
@@ -161,10 +177,12 @@ begin
     NumberExported := Export.Execute;
     FTestDataset.Close;
     AssertEquals('Number of records exported', NumberExported, FTestDataset.RecordCount);
-    //we should have exported 2 records.
   finally
     Settings.Free;
-    //DeleteFile(Export.FileName); //todo: fix this for release
+    if (KeepFilesAfterTest = False) then
+    begin
+      DeleteFile(Export.FileName);
+    end;
     Export.Free;
   end;
 end;
@@ -187,10 +205,12 @@ begin
     NumberExported := Export.Execute;
     FTestDataset.Close;
     AssertEquals('Number of records exported', NumberExported, FTestDataset.RecordCount);
-    //we should have exported 2 records.
   finally
     Settings.Free;
-    //DeleteFile(Export.FileName); //todo: fix this for release
+    if (KeepFilesAfterTest = False) then
+    begin
+      DeleteFile(Export.FileName);
+    end;
     Export.Free;
   end;
 end;
@@ -215,7 +235,10 @@ begin
     //we should have exported 2 records.
   finally
     Settings.Free;
-    //DeleteFile(Export.FileName); //todo: fix this for release
+    if (KeepFilesAfterTest = False) then
+    begin
+      DeleteFile(Export.FileName);
+    end;
     Export.Free;
   end;
 end;
@@ -240,7 +263,10 @@ begin
     //we should have exported 2 records.
   finally
     Settings.Free;
-    //DeleteFile(Export.FileName); //todo: fix this for release
+    if (KeepFilesAfterTest = False) then
+    begin
+      DeleteFile(Export.FileName);
+    end;
     Export.Free;
   end;
 end;
@@ -248,94 +274,336 @@ end;
 
 procedure Ttestxmlxsdexport1.FillTestData;
 var
-  Utf8teststring: string;
+  RowNumber: integer; //Keep track of how many rows we inserted
+  TestBoolean: boolean;
+  TestDateTime: TDateTime;
+  TestExtended: extended;
+  //yes, a lot of precision; we can convert to single/double if required
+  TestInteger: integer;
+  TestGuid: string;
+  TestString: string;
 begin
   FTestDataset.Close;
+  RowNumber := 0;
   //for memds:
   //FTestDataset.Clear(False); //memds: clear out any data
   //FTestDataset.Fields.Clear; //bufds: clear out any data, but also FIELDDEFS: don't use
   FTestDataset.Open;
 
   // Fill some test data
-  // First row
+  // First row: positive numerical values, late dates/times, strings with special chars (tab, linefeed, ; > <)
   FTestDataset.Append;
-  FTestDataset.FieldByName('IDINTEGER').AsInteger := 42;
-  FTestDataset.FieldByName('NAMESTRING').AsString := 'Douglas Adams';
-  FTestDataset.FieldByName('REMARKSMEMO').AsString :=
-    'So long, and thanks for all the fish.';
-  FTestDataset.FieldByName('BIRTHDAYDATE').AsDateTime :=
-    ScanDateTime('yyyymmdd', '19520311', 1);
-  FTestDataset.FieldByName('CVBLOB').AsString :=
-    'A very succesful and funny writer. He died some years ago.';
-  FTestDataset.FieldByName('POCKETMONEYCURRENCY').AsCurrency := 42.42;
-  FTestDataset.FieldByName('NAUGHTYBOOLEAN').AsBoolean := False;
+  TestBoolean := True;
+  TestDateTime := EncodeDate(9999, 12, 31) + EncodeTime(23, 59, 59, 999);
+  TestExtended := 42.424242424242424242424242424242;
+  TestInteger := Round(TestExtended);
+  TestGuid := '{21EC2020-3AEA-1069-A2DD-08002B30309D}';
+  TestString := 'Douglas Adams less than: < greater than > tab:' +
+    #9 + 'crlf:' + #13 + #10 +
+    '國缺界广欠廣界界东缺. Haddock drinks rosé (ros, e accent aigu), водка (wodka cyrillic) and ούζο (ouzo Greek) but prefers Loch Lomond whiskey.';
+  RowNumber := RowNumber + 1;
+  FillRecord(RowNumber, Teststring, TestGUID, Testinteger, Testextended,
+    Testdatetime, Testboolean);
   FTestDataset.Post;
 
-  // Second row
+  // Second row: negative numerical values, early dates/times, strings with maximum field width and Greek, east asian (multibyte) characters
   FTestDataset.Append;
-  FTestDataset.FieldByName('IDINTEGER').AsInteger := 444;
-  FTestDataset.FieldByName('NAMESTRING').AsString := 'Captain Haddock';
-  UTF8TestString :=
-    'Drinks rosé (ros, e accent aigu), водка (wodka cyrillic) and ούζο (ouzo Greek) but prefers Loch Lomond whiskey.';
-  FTestDataset.FieldByName('REMARKSMEMO').AsString := (UTF8TestString);
-  //examples of UTF8 code
-  FTestDataset.FieldByName('BIRTHDAYDATE').AsDateTime :=
-    ScanDateTime('yyyymmdd', '19401017', 1);
-  FTestDataset.FieldByName('CVBLOB').AsString := '';
-  FTestDataset.FieldByName('POCKETMONEYCURRENCY').AsCurrency := 12.4866666;
-  FTestDataset.FieldByName('NAUGHTYBOOLEAN').AsBoolean := True;
+  TestBoolean := False;
+  TestDateTime := EncodeDate(1, 1, 1) + EncodeTime(0, 0, 0, 1);
+  TestExtended := -42.424242424242424242424242424242;
+  TestInteger := Round(TestExtended);
+  TestGuid := '{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}';
+  TestString := 'ARMA virumque cano, Troiae qui primus ab oris' +
+    #13 + #10 + 'Italiam, fato profugus, Laviniaque venit' + #13 +
+    #10 + 'litora, multum ille et terris iactatus et alto' + #13 +
+    #10 + 'vi superum saevae memorem Iunonis ob iram;' + #13 + #10 +
+    'multa quoque et bello passus, dum conderet urbem,' + #13 + #10 +
+    'inferretque deos Latio, genus unde Latinum,' + #13 + #10 +
+    'Albanique patres, atque altae moenia Romae.' + #13 + #10 + #13 +
+    #10 + 'Musa, mihi causas memora, quo numine laeso,' + #13 + #10 +
+    'quidve dolens, regina deum tot volvere casus' + #13 + #10 +
+    'insignem pietate virum, tot adire labores' + #13 + #10 +
+    'impulerit.  Tantaene animis caelestibus irae?' + #13 + #10 +
+    #13 + #10 + 'Urbs antiqua fuit, Tyrii tenuere coloni,' + #13 +
+    #10 + 'Karthago, Italiam contra Tiberinaque longe' + #13 + #10 +
+    'ostia, dives opum studiisque asperrima belli;' + #13 + #10 +
+    'quam Iuno fertur terris magis omnibus unam' + #13 + #10 +
+    'posthabita coluisse Samo; hic illius arma,' + #13 + #10 +
+    'hic currus fuit; hoc regnum dea gentibus esse,' + #13 + #10 +
+    'si qua fata sinant, iam tum tenditque fovetque.' + #13 + #10 +
+    'Progeniem sed enim Troiano a sanguine duci' + #13 + #10 +
+    'audierat, Tyrias olim quae verteret arces;' + #13 + #10 +
+    'hinc populum late regem belloque superbum' + #13 + #10 +
+    'venturum excidio Libyae:  sic volvere Parcas.' + #13 + #10 +
+    'Id metuens, veterisque memor Saturnia belli,' + #13 + #10 +
+    'prima quod ad Troiam pro caris gesserat Argis---' + #13 + #10 +
+    'necdum etiam causae irarum saevique dolores' + #13 + #10 +
+    'exciderant animo:  manet alta mente repostum' + #13 + #10 +
+    'iudicium Paridis spretaeque iniuria formae,' + #13 + #10 +
+    'et genus invisum, et rapti Ganymedis honores.' + #13 + #10 +
+    'His accensa super, iactatos aequore toto' + #13 + #10 +
+    'Troas, reliquias Danaum atque immitis Achilli,' + #13 + #10 +
+    'arcebat longe Latio, multosque per annos' + #13 + #10 +
+    'errabant, acti fatis, maria omnia circum.' + #13 + #10 +
+    'Tantae molis erat Romanam condere gentem!';
+  RowNumber := RowNumber + 1;
+  FillRecord(RowNumber, Teststring, TestGUID, Testinteger, Testextended,
+    Testdatetime, Testboolean);
   FTestDataset.Post;
+
+  // Third row: empty/zero numerical values, dates/times, strings
+  FTestDataset.Append;
+  TestBoolean := False;
+  TestDateTime := EncodeDate(1, 1, 1) + EncodeTime(0, 0, 0, 0);
+  TestExtended := 0;
+  TestInteger := Round(TestExtended);
+  TestGuid := '{3F2504E0-4F89-11D3-9A0C-0305E82C3301}';
+  TestString := '';
+  RowNumber := RowNumber + 1;
+  FillRecord(RowNumber, Teststring, TestGUID, Testinteger, Testextended,
+    Testdatetime, Testboolean);
+  FTestDataset.Post;
+
+  // Fourth row: plausible data
+  FTestDataset.Append;
+  TestBoolean := True;
+  TestDateTime := EncodeDate(2005, 9, 10) + EncodeTime(13, 52, 18, 0);
+  TestExtended := 42;
+  TestInteger := Round(TestExtended);
+  TestString := 'The answer to life, the universe, and everything';
+  RowNumber := RowNumber + 1;
+  FillRecord(RowNumber, Teststring, TestGUID, Testinteger, Testextended,
+    Testdatetime, Testboolean);
+  FTestDataset.Post;
+
+  // Make sure recordcount is correct:
   FTestDataset.Last;
   FTestDataset.First;
-  AssertEquals('Number of records in test dataset', 2, FTestDataset.RecordCount);
+  AssertEquals('Number of records in test dataset', RowNumber, FTestDataset.RecordCount);
 end;
 
 procedure Ttestxmlxsdexport1.Setup;
+const
+  NumberOfDecimals = 2;
+  NumberOfBytes = 10;
 var
   FieldDef: TFieldDef;
 begin
   FExportTempDir := GetTempDir(False);
   FTestDataset := TBufDataset.Create(nil);
-  {for memds - or can we use the lines below, too?:
-  FTestDataset.FieldDefs.Add('IDINTEGER', ftInteger);
-  FTestDataset.FieldDefs.Add('NAMESTRING', ftString, 50);
-  //memds probably won't support memo
-  //TestDataset.FieldDefs.Add('REMARKSMEMO', ftMemo);
-  TestDataset.FieldDefs.Add('BIRTHDAYDATE', ftDate);
-  // No support for blobs in this dataset.
-  //TestDataset.FieldDefs.Add('CVBLOB', ftBlob); // A blob containing e.g. text
-  TestDataset.FieldDefs.Add('POCKETMONEYCURRENCY', ftCurrency);
+
+  {We should cover all data types defined in FPC:
+
+  FPC maps "external" types such as ftOracleBlob to
+  internal types, but that can be overridden, which is done
+  by e.g. IBX and mseide.
+  So it makes sense to keep as many datatypes in the exporter code as possible: it documents the mappings and allows other people to use these types without the exporter breaking.
   }
-  //for Bufdataset:
+  {Sorted by datatype; commented out what doesn't work at the moment in bufdataset
+  See http://docwiki.embarcadero.com/VCL/en/DB.TField.Size for overview of field sizes in the competition product ;)
+  Apparently ftGuid also needs size...
+  }
+
+  {
   FieldDef := FTestDataset.FieldDefs.AddFieldDef;
-  FieldDef.Name := 'IDINTEGER';
-  FieldDef.DataType := ftInteger;
+  FieldDef.Name := 'ftADT';
+  FieldDef.DataType := ftADT;
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
+  }
 
+  {
   FieldDef := FTestDataset.FieldDefs.AddFieldDef;
-  FieldDef.Name := 'NAMESTRING';
-  FieldDef.DataType := ftString;
-  FieldDef.Size := 50;
+  FieldDef.Name := 'ftArray';
+  FieldDef.DataType := ftArray;
+  FieldDef.Size := 10;//the number of elements in the array
 
   FieldDef := FTestDataset.FieldDefs.AddFieldDef;
-  FieldDef.Name := 'REMARKSMEMO';
-  FieldDef.DataType := ftMemo;
+  FieldDef.Name := 'ftAutoInc';
+  FieldDef.DataType := ftAutoInc;
+  }
 
   FieldDef := FTestDataset.FieldDefs.AddFieldDef;
-  FieldDef.Name := 'BIRTHDAYDATE';
-  FieldDef.DataType := ftDate;
+  FieldDef.Name := 'ftBCD';
+  FieldDef.DataType := ftBCD;
+  FieldDef.Size := NumberOfDecimals;
+  //Size is the number of digits after the decimal place
 
   FieldDef := FTestDataset.FieldDefs.AddFieldDef;
-  FieldDef.Name := 'CVBLOB';
+  FieldDef.Name := 'ftBlob_4096';
   FieldDef.DataType := ftBlob;
-  FieldDef.Size := 16384;//large but hopefully not too large for memory.
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
 
   FieldDef := FTestDataset.FieldDefs.AddFieldDef;
-  FieldDef.Name := 'POCKETMONEYCURRENCY';
+  FieldDef.Name := 'ftBoolean';
+  FieldDef.DataType := ftBoolean;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftBytes';
+  FieldDef.DataType := ftBytes;
+  FieldDef.Size := NumberOfBytes;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftCurrency';
   FieldDef.DataType := ftCurrency;
 
+  {
   FieldDef := FTestDataset.FieldDefs.AddFieldDef;
-  FieldDef.Name := 'NAUGHTYBOOLEAN';
-  FieldDef.DataType := ftBoolean;
+  FieldDef.Name := 'ftCursor';
+  FieldDef.DataType := ftCursor;
+  }
+
+  {
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftDataSet';
+  FieldDef.DataType := ftDataSet;
+  }
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftDate';
+  FieldDef.DataType := ftDate;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftDateTime';
+  FieldDef.DataType := ftDateTime;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftDBaseOle';
+  FieldDef.DataType := ftDBaseOle;
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftFixedChar_2';
+  FieldDef.DataType := ftFixedChar;
+  FieldDef.Size := NumberOfDecimals;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftFixedWideChar_2';
+  FieldDef.DataType := ftFixedWideChar;
+  FieldDef.Size := NumberOfBytes;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftFloat';
+  FieldDef.DataType := ftFloat;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftFMTBcd';
+  FieldDef.DataType := ftFMTBcd;
+  FieldDef.Size := NumberOfDecimals; //the number of digits after the decimal place.
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftFmtMemo';
+  FieldDef.DataType := ftFmtMemo;
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftGraphic';
+  FieldDef.DataType := ftGraphic;
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftGuid';
+  FieldDef.DataType := ftGuid;
+  FieldDef.Size := 38;
+  //Apparently right answer is not 42; had to look up 38 in source code.
+
+  {
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftIDispatch';
+  FieldDef.DataType := ftIDispatch;
+  }
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftInteger';
+  FieldDef.DataType := ftInteger;
+
+  {
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftInterface';
+  FieldDef.DataType := ftInterface;
+  }
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftLargeint';
+  FieldDef.DataType := ftLargeint;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftMemo';
+  FieldDef.DataType := ftMemo;
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftOraBlob';
+  FieldDef.DataType := ftOraBlob;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftOraClob';
+  FieldDef.DataType := ftOraClob;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftParadoxOle';
+  FieldDef.DataType := ftParadoxOle;
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
+
+  {
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftReference';
+  FieldDef.DataType := ftReference;
+  }
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftSmallInt';
+  FieldDef.DataType := ftInteger;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftString_1';
+  FieldDef.DataType := ftString;
+  FieldDef.Size := 1;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftString_256'; //1 character more than many db string types support
+  FieldDef.DataType := ftString;
+  FieldDef.Size := 256;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftTime';
+  FieldDef.DataType := ftTime;
+
+  {
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftTimeStamp';
+  FieldDef.DataType := ftTimeStamp;
+  }
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftTypedBinary';
+  FieldDef.DataType := ftTypedBinary;
+  FieldDef.Size := 4096;//large but hopefully not too large for memory.
+
+  { ftVariant and ftVarBytes don't work; see bug 19930
+  However, there's more wront in bufdataset; if I don't
+  include these field definitions, I get access violations later on.}
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftVariant';
+  FieldDef.DataType := ftVariant;
+  FieldDef.Size := NumberOfBytes;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftVarBytes';
+  FieldDef.DataType := ftVarBytes;
+  FieldDef.Size := NumberOfBytes;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftWideMemo';
+  FieldDef.DataType := ftWideMemo;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftWideString256';
+  FieldDef.DataType := ftWideString;
+  FieldDef.Size := 256;
+
+  FieldDef := FTestDataset.FieldDefs.AddFieldDef;
+  FieldDef.Name := 'ftWord';
+  FieldDef.DataType := ftWord;
 
   //Createtable is needed if you use a memds
   //FTestDataset.CreateTable;
@@ -346,6 +614,77 @@ begin
   FillTestData;
 end;
 
+procedure Ttestxmlxsdexport1.FillRecord(const RowNumber: integer;
+  const TestString: string; const TestGUID: string; const TestInteger: integer;
+  const TestExtended: extended; const TestDatetime: Tdatetime;
+  const TestBoolean: boolean);
+var
+  FieldCounter: integer;
+begin
+  writeln('*** Starting to fill row ' + IntToStr(RowNumber));
+  {As our bufdataset doesn't support these datatypes, don't use them:
+ftAutoInc -> exists but doesn't seem to return any data.
+ftCursor
+ftDataSet
+ftInterface
+ftReference
+ftTimeStamp}
+
+  FTestDataset.FieldByName('ftBCD').AsFloat := Testextended;
+  FTestDataset.FieldByName('ftBlob_4096').AsString := Teststring;
+  FTestDataset.FieldByName('ftBoolean').AsBoolean := Testboolean;
+  FTestDataset.FieldByName('ftBytes').AsString := Teststring;
+  FTestDataset.FieldByName('ftCurrency').Ascurrency := Testextended;
+  FTestDataset.FieldByName('ftDate').AsDateTime := Testdatetime;
+  FTestDataset.FieldByName('ftDateTime').AsDateTime := Testdatetime;
+  FTestDataset.FieldByName('ftDBaseOle').AsString := Teststring;
+  FTestDataset.FieldByName('ftFixedChar_2').AsString := Teststring;
+  FTestDataset.FieldByName('ftFixedWideChar_2').AsString := Teststring;
+  FTestDataset.FieldByName('ftFloat').AsFloat := Testextended;
+  FTestDataset.FieldByName('ftFMTBcd').AsFloat := Testextended;
+  FTestDataset.FieldByName('ftFmtMemo').AsString := Teststring;
+  FTestDataset.FieldByName('ftGraphic').AsString := Teststring;
+  FTestDataset.FieldByName('ftGuid').AsString := TestGUID;
+  FTestDataset.FieldByName('ftInteger').AsInteger := Testinteger;
+  FTestDataset.FieldByName('ftLargeint').AsInteger := Testinteger;
+  FTestDataset.FieldByName('ftMemo').AsString := Teststring;
+  FTestDataset.FieldByName('ftOraBlob').AsString := Teststring;
+  FTestDataset.FieldByName('ftOraClob').AsString := Teststring;
+  FTestDataset.FieldByName('ftParadoxOle').AsString := Teststring;
+  FTestDataset.FieldByName('ftSmallInt').AsInteger := Testinteger;
+  FTestDataset.FieldByName('ftString_1').AsString := Teststring;
+  FTestDataset.FieldByName('ftString_256').AsString := Teststring;
+  FTestDataset.FieldByName('ftTime').AsDateTime := Testdatetime;
+  FTestDataset.FieldByName('ftTypedBinary').AsString := Teststring;
+  { ftVarBytes and ftVariant don't work; see bug 19930}
+  {
+  FTestDataSet.FieldByName('ftVarBytes').AsString := TestString;
+  FTestDataSet.FieldByName('ftVariant').AsString := TestString;
+  }
+  FTestDataset.FieldByName('ftWideMemo').AsString := Teststring;
+  FTestDataset.FieldByName('ftWideString256').AsString := Teststring;
+  FTestDataset.FieldByName('ftWord').AsInteger := Abs(Testinteger);
+  //If I keep the output code below on Win32, I don't get an access violation.
+  //If I remove it, I do. Probably bug 19930 again?
+  for Fieldcounter := 0 to FTestDataset.Fields.Count - 1 do
+  begin
+    try
+      writeln('Field: ' + FTestDataset.Fields[FieldCounter].FieldName +
+        ' has value ' + FTestDataset.Fields[FieldCounter].AsString);
+      {writeln('Field: ' + FTestDataset.Fields[FieldCounter].FieldName +
+        ' has displaytext ' + FTestDataset.Fields[FieldCounter].DisplayText);}
+    except
+      on E: Exception do
+      begin
+        writeln('Field: ' + FTestDataset.Fields[FieldCounter].FieldName +
+          ': error retrieving value: ');
+        writeln(E.ClassName, '; detailed error message: ', E.message);
+      end;
+    end;
+  end;
+  writeln('*** Finished filling row ' + IntToStr(RowNumber));
+end;
+
 procedure Ttestxmlxsdexport1.Teardown;
 begin
   FTestDataset.Free;

Some files were not shown because too many files changed in this diff