Browse Source

--- Merging r15812 into '.':
U rtl/i386/i386.inc
U rtl/linux/i386/syscall.inc
U rtl/linux/x86_64/syscall.inc
--- Merging r15832 into '.':
A packages/fcl-db/tests/tcsqlscanner.pas
U packages/fcl-db/tests/Makefile.fpc
A packages/fcl-db/tests/testsqlscanner.lpi
A packages/fcl-db/tests/tcgensql.pas
A packages/fcl-db/tests/testsqlfiles.lpi
A packages/fcl-db/tests/tcparser.pas
A packages/fcl-db/tests/testsqlscanner.lpr
C packages/fcl-db/tests/Makefile
A packages/fcl-db/tests/testsqlfiles.lpr
U packages/fcl-db/Makefile.fpc
A packages/fcl-db/src/sql
A packages/fcl-db/src/sql/fpsqltree.pp
A packages/fcl-db/src/sql/Makefile.fpc
A packages/fcl-db/src/sql/fpsqlparser.pas
A packages/fcl-db/src/sql/Makefile
A packages/fcl-db/src/sql/fpsqlscanner.pp
C packages/fcl-db/Makefile
--- Merging r15915 into '.':
U packages/fpvectorial/src/svgvectorialwriter.pas
U packages/fpvectorial/examples/fpvwritetest.pas
--- Merging r15923 into '.':
U packages/fpvectorial/src/fpvectorial.pas
G packages/fpvectorial/src/svgvectorialwriter.pas
--- Merging r15924 into '.':
G packages/fpvectorial/examples/fpvwritetest.pas
--- Merging r15926 into '.':
U packages/fcl-image/src/fpreadpng.pp
--- Merging r15928 into '.':
G packages/fpvectorial/src/fpvectorial.pas
G packages/fpvectorial/src/svgvectorialwriter.pas
U packages/fpvectorial/src/fpvectbuildunit.pas
--- Merging r15929 into '.':
G packages/fpvectorial/src/svgvectorialwriter.pas
G packages/fpvectorial/examples/fpvwritetest.pas
--- Merging r15930 into '.':
G packages/fpvectorial/src/svgvectorialwriter.pas
--- Merging r15931 into '.':
A packages/fpvectorial/examples/fpvwritetest.lpi
--- Merging r15932 into '.':
G packages/fpvectorial/src/svgvectorialwriter.pas
--- Merging r15933 into '.':
G packages/fpvectorial/examples/fpvwritetest.pas
--- Merging r15941 into '.':
U rtl/inc/variants.pp
--- Merging r15942 into '.':
U packages/fcl-db/tests/tcsqlscanner.pas
U packages/fcl-db/tests/testsqlscanner.lpi
U packages/fcl-db/tests/tcgensql.pas
U packages/fcl-db/tests/tcparser.pas
U packages/fcl-db/src/sql/fpsqltree.pp
U packages/fcl-db/src/sql/fpsqlparser.pas
U packages/fcl-db/src/sql/fpsqlscanner.pp
--- Merging r15944 into '.':
U rtl/inc/matrix.pp
--- Merging r15945 into '.':
U rtl/objpas/sysutils/sysstr.inc
--- Merging r15946 into '.':
A tests/test/tstrreal4.pp
--- Merging r15950 into '.':
U rtl/x86_64/strings.inc
C rtl/x86_64/mathu.inc
--- Merging r15955 into '.':
C packages/libxml/Makefile
--- Merging r15961 into '.':
U rtl/linux/i386/si_prc.inc
U rtl/linux/i386/si_dll.inc
--- Merging r15977 into '.':
U packages/fcl-json/src/jsonscanner.pp
U packages/fcl-json/src/jsonparser.pp
--- Merging r15978 into '.':
A packages/fcl-json/src/README.txt
--- Merging r15982 into '.':
G rtl/objpas/sysutils/sysstr.inc
--- Merging r15983 into '.':
A tests/test/tstrreal5.pp
--- Merging r15988 into '.':
U packages/openssl/src/openssl.pas
--- Merging r15999 into '.':
U tests/test/tstrreal4.pp
--- Merging r16026 into '.':
G rtl/objpas/sysutils/sysstr.inc
--- Merging r16042 into '.':
U packages/fcl-base/src/win/eventlog.inc
--- Merging r16043 into '.':
U packages/fcl-base/fpmake.pp
--- Merging r16044 into '.':
U packages/winunits-base/fpmake.pp
--- Merging r16058 into '.':
U rtl/objpas/classes/stringl.inc
U rtl/objpas/classes/classesh.inc
--- Merging r16064 into '.':
C packages/libgbafpc/Makefile.fpc
C packages/libgbafpc/Makefile
U packages/libgbafpc/examples/graphics/Makefile.fpc
C packages/libgbafpc/examples/graphics/Makefile
U packages/libgbafpc/examples/audio/Makefile.fpc
C packages/libgbafpc/examples/audio/Makefile
U packages/libgbafpc/examples/template/Makefile.fpc
C packages/libgbafpc/examples/template/Makefile
Summary of conflicts:
Text conflicts: 9

# revisions: 15812,15832,15915,15923,15924,15926,15928,15929,15930,15931,15932,15933,15941,15942,15944,15945,15946,15950,15955,15961,15977,15978,15982,15983,15988,15999,16026,16042,16043,16044,16058,16064
------------------------------------------------------------------------
r15812 | florian | 2010-08-15 11:11:06 +0200 (Sun, 15 Aug 2010) | 2 lines
Changed paths:
M /trunk/rtl/i386/i386.inc
M /trunk/rtl/linux/i386/syscall.inc
M /trunk/rtl/linux/x86_64/syscall.inc

+ adds mcount calls to syscall assembler helpers for i386 and x86-64, resolves #17140

------------------------------------------------------------------------
------------------------------------------------------------------------
r15832 | michael | 2010-08-17 01:13:24 +0200 (Tue, 17 Aug 2010) | 1 line
Changed paths:
M /trunk/packages/fcl-db/Makefile
M /trunk/packages/fcl-db/Makefile.fpc
A /trunk/packages/fcl-db/src/sql
A /trunk/packages/fcl-db/src/sql/Makefile
A /trunk/packages/fcl-db/src/sql/Makefile.fpc
A /trunk/packages/fcl-db/src/sql/fpsqlparser.pas
A /trunk/packages/fcl-db/src/sql/fpsqlscanner.pp
A /trunk/packages/fcl-db/src/sql/fpsqltree.pp
M /trunk/packages/fcl-db/tests/Makefile
M /trunk/packages/fcl-db/tests/Makefile.fpc
A /trunk/packages/fcl-db/tests/tcgensql.pas
A /trunk/packages/fcl-db/tests/tcparser.pas
A /trunk/packages/fcl-db/tests/tcsqlscanner.pas
A /trunk/packages/fcl-db/tests/testsqlfiles.lpi
A /trunk/packages/fcl-db/tests/testsqlfiles.lpr
A /trunk/packages/fcl-db/tests/testsqlscanner.lpi
A /trunk/packages/fcl-db/tests/testsqlscanner.lpr

* SQL parser
------------------------------------------------------------------------
------------------------------------------------------------------------
r15915 | sekelsenmat | 2010-08-28 13:52:03 +0200 (Sat, 28 Aug 2010) | 1 line
Changed paths:
M /trunk/packages/fpvectorial/examples/fpvwritetest.pas
M /trunk/packages/fpvectorial/src/svgvectorialwriter.pas

Fixes the svg coordinates and svg path generation
------------------------------------------------------------------------
------------------------------------------------------------------------
r15923 | sekelsenmat | 2010-08-31 11:48:27 +0200 (Tue, 31 Aug 2010) | 1 line
Changed paths:
M /trunk/packages/fpvectorial/src/fpvectorial.pas
M /trunk/packages/fpvectorial/src/svgvectorialwriter.pas

Patch from JiXian, advances the implementation of text rendering and bezier drawing for the svg writer in fpvectorial
------------------------------------------------------------------------
------------------------------------------------------------------------
r15924 | sekelsenmat | 2010-08-31 11:51:14 +0200 (Tue, 31 Aug 2010) | 1 line
Changed paths:
M /trunk/packages/fpvectorial/examples/fpvwritetest.pas

Updates the fpvectorial tests
------------------------------------------------------------------------
------------------------------------------------------------------------
r15926 | marc | 2010-08-31 23:09:40 +0200 (Tue, 31 Aug 2010) | 2 lines
Changed paths:
M /trunk/packages/fcl-image/src/fpreadpng.pp

* Fix the byte -> word expansion of the alpha channel on palette enties of a PNG image

------------------------------------------------------------------------
------------------------------------------------------------------------
r15928 | sekelsenmat | 2010-09-01 09:59:28 +0200 (Wed, 01 Sep 2010) | 1 line
Changed paths:
M /trunk/packages/fpvectorial/src/fpvectbuildunit.pas
M /trunk/packages/fpvectorial/src/fpvectorial.pas
M /trunk/packages/fpvectorial/src/svgvectorialwriter.pas

Fixes the coordinates, dpi value and text rendering of the svg output of fpvectorial
------------------------------------------------------------------------
------------------------------------------------------------------------
r15929 | sekelsenmat | 2010-09-01 10:11:36 +0200 (Wed, 01 Sep 2010) | 1 line
Changed paths:
M /trunk/packages/fpvectorial/examples/fpvwritetest.pas
M /trunk/packages/fpvectorial/src/svgvectorialwriter.pas

Fixes the font size setting in the fpvectorial svg output and adds a bigger test to the suite
------------------------------------------------------------------------
------------------------------------------------------------------------
r15930 | sekelsenmat | 2010-09-01 10:57:54 +0200 (Wed, 01 Sep 2010) | 1 line
Changed paths:
M /trunk/packages/fpvectorial/src/svgvectorialwriter.pas

Rewrites the bezier rendering of the svg output of fpvectorial
------------------------------------------------------------------------
------------------------------------------------------------------------
r15931 | sekelsenmat | 2010-09-01 11:01:08 +0200 (Wed, 01 Sep 2010) | 1 line
Changed paths:
A /trunk/packages/fpvectorial/examples/fpvwritetest.lpi

Adds a lazarus project for fpvwritetest
------------------------------------------------------------------------
------------------------------------------------------------------------
r15932 | sekelsenmat | 2010-09-01 11:13:55 +0200 (Wed, 01 Sep 2010) | 1 line
Changed paths:
M /trunk/packages/fpvectorial/src/svgvectorialwriter.pas

Fixes typo on fpvectorial svg output
------------------------------------------------------------------------
------------------------------------------------------------------------
r15933 | sekelsenmat | 2010-09-01 11:15:06 +0200 (Wed, 01 Sep 2010) | 1 line
Changed paths:
M /trunk/packages/fpvectorial/examples/fpvwritetest.pas

Makes the multi_test_1.svg file a little more beaultiful
------------------------------------------------------------------------
------------------------------------------------------------------------
r15941 | marco | 2010-09-03 18:34:04 +0200 (Fri, 03 Sep 2010) | 2 lines
Changed paths:
M /trunk/rtl/inc/variants.pp

* fix for bug #17325, an inc(i) was missing in aloop.

------------------------------------------------------------------------
------------------------------------------------------------------------
r15942 | michael | 2010-09-03 19:01:01 +0200 (Fri, 03 Sep 2010) | 1 line
Changed paths:
M /trunk/packages/fcl-db/src/sql/fpsqlparser.pas
M /trunk/packages/fcl-db/src/sql/fpsqlscanner.pp
M /trunk/packages/fcl-db/src/sql/fpsqltree.pp
M /trunk/packages/fcl-db/tests/tcgensql.pas
M /trunk/packages/fcl-db/tests/tcparser.pas
M /trunk/packages/fcl-db/tests/tcsqlscanner.pas
M /trunk/packages/fcl-db/tests/testsqlscanner.lpi

* Added tests for Grant/Revoke, fixed some bugs on the way
------------------------------------------------------------------------
------------------------------------------------------------------------
r15944 | marco | 2010-09-06 12:58:09 +0200 (Mon, 06 Sep 2010) | 2 lines
Changed paths:
M /trunk/rtl/inc/matrix.pp

* add $mode fpc to matrix unit, mants 17357

------------------------------------------------------------------------
------------------------------------------------------------------------
r15945 | michael | 2010-09-06 13:09:39 +0200 (Mon, 06 Sep 2010) | 1 line
Changed paths:
M /trunk/rtl/objpas/sysutils/sysstr.inc

* Patch from Zeljan Rikalo to fix issue #13722 (FloatToStrF negative 0)
------------------------------------------------------------------------
------------------------------------------------------------------------
r15946 | michael | 2010-09-06 13:13:46 +0200 (Mon, 06 Sep 2010) | 1 line
Changed paths:
A /trunk/tests/test/tstrreal4.pp

* Test for formatfloat negative zero
------------------------------------------------------------------------
------------------------------------------------------------------------
r15950 | jonas | 2010-09-08 16:40:38 +0200 (Wed, 08 Sep 2010) | 3 lines
Changed paths:
M /trunk/rtl/x86_64/mathu.inc
M /trunk/rtl/x86_64/strings.inc

+ added {$asmmode gas} directives to fix compiling when fpc.cfg contains
-Rintel (mantis #17354)

------------------------------------------------------------------------
------------------------------------------------------------------------
r15955 | florian | 2010-09-09 10:42:48 +0200 (Thu, 09 Sep 2010) | 1 line
Changed paths:
M /trunk/packages/libxml/Makefile

* regenerated with up-to-date fpcmake
------------------------------------------------------------------------
------------------------------------------------------------------------
r15961 | jonas | 2010-09-09 21:46:59 +0200 (Thu, 09 Sep 2010) | 2 lines
Changed paths:
M /trunk/rtl/linux/i386/si_dll.inc
M /trunk/rtl/linux/i386/si_prc.inc

* moved {$asmmode att} to top of file (mantis #17377)

------------------------------------------------------------------------
------------------------------------------------------------------------
r15977 | michael | 2010-09-13 23:09:22 +0200 (Mon, 13 Sep 2010) | 1 line
Changed paths:
M /trunk/packages/fcl-json/src/jsonparser.pp
M /trunk/packages/fcl-json/src/jsonscanner.pp

* Introduced strict property
------------------------------------------------------------------------
------------------------------------------------------------------------
r15978 | michael | 2010-09-13 23:40:17 +0200 (Mon, 13 Sep 2010) | 1 line
Changed paths:
A /trunk/packages/fcl-json/src/README.txt

* Some minimal documentation
------------------------------------------------------------------------
------------------------------------------------------------------------
r15982 | michael | 2010-09-14 13:23:41 +0200 (Tue, 14 Sep 2010) | 1 line
Changed paths:
M /trunk/rtl/objpas/sysutils/sysstr.inc

* Implementation of values 11..15 of negcurrentformat from Zeljan Rikalo
------------------------------------------------------------------------
------------------------------------------------------------------------
r15983 | michael | 2010-09-14 13:25:04 +0200 (Tue, 14 Sep 2010) | 1 line
Changed paths:
A /trunk/tests/test/tstrreal5.pp

* Test for negcurrformat values 11-15 from Zeljan Rikalo
------------------------------------------------------------------------
------------------------------------------------------------------------
r15988 | sekelsenmat | 2010-09-15 10:50:21 +0200 (Wed, 15 Sep 2010) | 1 line
Changed paths:
M /trunk/packages/openssl/src/openssl.pas

Patch from Alberto Brito, improves OpenSSL and allows only one of the 2 DLLs to be loaded. See bug #17270
------------------------------------------------------------------------
------------------------------------------------------------------------
r15999 | jonas | 2010-09-16 22:58:34 +0200 (Thu, 16 Sep 2010) | 4 lines
Changed paths:
M /trunk/tests/test/tstrreal4.pp

* patch by zeljko to make the test independent of the locale, and fix a
a problem when NegCurrFormat > 10 (from
http://lists.freepascal.org/lists/fpc-devel/2010-September/021865.html)

------------------------------------------------------------------------
------------------------------------------------------------------------
r16026 | michael | 2010-09-20 09:46:04 +0200 (Mon, 20 Sep 2010) | 1 line
Changed paths:
M /trunk/rtl/objpas/sysutils/sysstr.inc

* Fixed IntToHex in case of (0,0)
------------------------------------------------------------------------
------------------------------------------------------------------------
r16042 | joost | 2010-09-25 21:40:46 +0200 (Sat, 25 Sep 2010) | 1 line
Changed paths:
M /trunk/packages/fcl-base/src/win/eventlog.inc

* Fixed compilation
------------------------------------------------------------------------
------------------------------------------------------------------------
r16043 | joost | 2010-09-25 21:41:22 +0200 (Sat, 25 Sep 2010) | 1 line
Changed paths:
M /trunk/packages/fcl-base/fpmake.pp

* Set fpmake dependencies
------------------------------------------------------------------------
------------------------------------------------------------------------
r16044 | joost | 2010-09-25 21:45:25 +0200 (Sat, 25 Sep 2010) | 1 line
Changed paths:
M /trunk/packages/winunits-base/fpmake.pp

* Set fpmake dependencies
------------------------------------------------------------------------
------------------------------------------------------------------------
r16058 | marco | 2010-09-28 16:52:44 +0200 (Tue, 28 Sep 2010) | 2 lines
Changed paths:
M /trunk/rtl/objpas/classes/classesh.inc
M /trunk/rtl/objpas/classes/stringl.inc

* D2009 compat: TStringList.OwnsObjects

------------------------------------------------------------------------
------------------------------------------------------------------------
r16064 | jonas | 2010-09-29 23:45:02 +0200 (Wed, 29 Sep 2010) | 2 lines
Changed paths:
M /trunk/packages/libgbafpc/Makefile
M /trunk/packages/libgbafpc/Makefile.fpc
M /trunk/packages/libgbafpc/examples/audio/Makefile
M /trunk/packages/libgbafpc/examples/audio/Makefile.fpc
M /trunk/packages/libgbafpc/examples/graphics/Makefile
M /trunk/packages/libgbafpc/examples/graphics/Makefile.fpc
M /trunk/packages/libgbafpc/examples/template/Makefile
M /trunk/packages/libgbafpc/examples/template/Makefile.fpc

+ added package names so Makefile (re)generation works

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

git-svn-id: branches/fixes_2_4@16421 -

marco 15 years ago
parent
commit
b443a955d8
51 changed files with 27339 additions and 314 deletions
  1. 16 0
      .gitattributes
  2. 1 1
      packages/fcl-base/fpmake.pp
  3. 1 1
      packages/fcl-base/src/win/eventlog.inc
  4. 166 61
      packages/fcl-db/Makefile
  5. 2 1
      packages/fcl-db/Makefile.fpc
  6. 2613 0
      packages/fcl-db/src/sql/Makefile
  7. 26 0
      packages/fcl-db/src/sql/Makefile.fpc
  8. 3864 0
      packages/fcl-db/src/sql/fpsqlparser.pas
  9. 948 0
      packages/fcl-db/src/sql/fpsqlscanner.pp
  10. 4806 0
      packages/fcl-db/src/sql/fpsqltree.pp
  11. 108 63
      packages/fcl-db/tests/Makefile
  12. 1 1
      packages/fcl-db/tests/Makefile.fpc
  13. 2550 0
      packages/fcl-db/tests/tcgensql.pas
  14. 7996 0
      packages/fcl-db/tests/tcparser.pas
  15. 1626 0
      packages/fcl-db/tests/tcsqlscanner.pas
  16. 266 0
      packages/fcl-db/tests/testsqlfiles.lpi
  17. 163 0
      packages/fcl-db/tests/testsqlfiles.lpr
  18. 288 0
      packages/fcl-db/tests/testsqlscanner.lpi
  19. 28 0
      packages/fcl-db/tests/testsqlscanner.lpr
  20. 1 1
      packages/fcl-image/src/fpreadpng.pp
  21. 163 0
      packages/fcl-json/src/README.txt
  22. 15 2
      packages/fcl-json/src/jsonparser.pp
  23. 26 10
      packages/fcl-json/src/jsonscanner.pp
  24. 72 0
      packages/fpvectorial/examples/fpvwritetest.lpi
  25. 46 5
      packages/fpvectorial/examples/fpvwritetest.pas
  26. 2 1
      packages/fpvectorial/src/fpvectbuildunit.pas
  27. 35 16
      packages/fpvectorial/src/fpvectorial.pas
  28. 125 14
      packages/fpvectorial/src/svgvectorialwriter.pas
  29. 33 3
      packages/libgbafpc/Makefile
  30. 193 11
      packages/libgbafpc/examples/audio/Makefile
  31. 3 0
      packages/libgbafpc/examples/audio/Makefile.fpc
  32. 197 11
      packages/libgbafpc/examples/graphics/Makefile
  33. 3 0
      packages/libgbafpc/examples/graphics/Makefile.fpc
  34. 125 7
      packages/libgbafpc/examples/template/Makefile
  35. 3 0
      packages/libgbafpc/examples/template/Makefile.fpc
  36. 318 93
      packages/openssl/src/openssl.pas
  37. 3 0
      packages/winunits-base/fpmake.pp
  38. 81 0
      rtl/i386/i386.inc
  39. 1 0
      rtl/inc/matrix.pp
  40. 4 1
      rtl/inc/variants.pp
  41. 1 1
      rtl/linux/i386/si_dll.inc
  42. 1 1
      rtl/linux/i386/si_prc.inc
  43. 61 0
      rtl/linux/i386/syscall.inc
  44. 82 0
      rtl/linux/x86_64/syscall.inc
  45. 4 0
      rtl/objpas/classes/classesh.inc
  46. 16 6
      rtl/objpas/classes/stringl.inc
  47. 41 1
      rtl/objpas/sysutils/sysstr.inc
  48. 3 2
      rtl/x86_64/mathu.inc
  49. 2 0
      rtl/x86_64/strings.inc
  50. 154 0
      tests/test/tstrreal4.pp
  51. 56 0
      tests/test/tstrreal5.pp

+ 16 - 0
.gitattributes

@@ -1285,6 +1285,11 @@ packages/fcl-db/src/sdf/fpmake.pp svneol=native#text/plain
 packages/fcl-db/src/sdf/sdfdata.pp svneol=native#text/plain
 packages/fcl-db/src/sdf/sdfdata.pp svneol=native#text/plain
 packages/fcl-db/src/sdf/testfix.pp svneol=native#text/plain
 packages/fcl-db/src/sdf/testfix.pp svneol=native#text/plain
 packages/fcl-db/src/sdf/testsdf.pp svneol=native#text/plain
 packages/fcl-db/src/sdf/testsdf.pp svneol=native#text/plain
+packages/fcl-db/src/sql/Makefile svneol=native#text/plain
+packages/fcl-db/src/sql/Makefile.fpc svneol=native#text/plain
+packages/fcl-db/src/sql/fpsqlparser.pas svneol=native#text/plain
+packages/fcl-db/src/sql/fpsqlscanner.pp svneol=native#text/plain
+packages/fcl-db/src/sql/fpsqltree.pp svneol=native#text/plain
 packages/fcl-db/src/sqldb/Makefile svneol=native#text/plain
 packages/fcl-db/src/sqldb/Makefile svneol=native#text/plain
 packages/fcl-db/src/sqldb/Makefile.fpc svneol=native#text/plain
 packages/fcl-db/src/sqldb/Makefile.fpc svneol=native#text/plain
 packages/fcl-db/src/sqldb/examples/alisttables.pp svneol=native#text/plain
 packages/fcl-db/src/sqldb/examples/alisttables.pp svneol=native#text/plain
@@ -1349,12 +1354,19 @@ packages/fcl-db/tests/dbtestframework.pas -text
 packages/fcl-db/tests/memdstoolsunit.pas svneol=native#text/plain
 packages/fcl-db/tests/memdstoolsunit.pas svneol=native#text/plain
 packages/fcl-db/tests/sdfdstoolsunit.pas svneol=native#text/plain
 packages/fcl-db/tests/sdfdstoolsunit.pas svneol=native#text/plain
 packages/fcl-db/tests/sqldbtoolsunit.pas -text
 packages/fcl-db/tests/sqldbtoolsunit.pas -text
+packages/fcl-db/tests/tcgensql.pas svneol=native#text/plain
+packages/fcl-db/tests/tcparser.pas svneol=native#text/plain
+packages/fcl-db/tests/tcsqlscanner.pas svneol=native#text/plain
 packages/fcl-db/tests/testbasics.pas svneol=native#text/plain
 packages/fcl-db/tests/testbasics.pas svneol=native#text/plain
 packages/fcl-db/tests/testbufdatasetstreams.pas svneol=native#text/plain
 packages/fcl-db/tests/testbufdatasetstreams.pas svneol=native#text/plain
 packages/fcl-db/tests/testdatasources.pas svneol=native#text/plain
 packages/fcl-db/tests/testdatasources.pas svneol=native#text/plain
 packages/fcl-db/tests/testdbbasics.pas -text
 packages/fcl-db/tests/testdbbasics.pas -text
 packages/fcl-db/tests/testdddiff.pp svneol=native#text/plain
 packages/fcl-db/tests/testdddiff.pp svneol=native#text/plain
 packages/fcl-db/tests/testfieldtypes.pas svneol=native#text/plain
 packages/fcl-db/tests/testfieldtypes.pas svneol=native#text/plain
+packages/fcl-db/tests/testsqlfiles.lpi svneol=native#text/plain
+packages/fcl-db/tests/testsqlfiles.lpr svneol=native#text/plain
+packages/fcl-db/tests/testsqlscanner.lpi svneol=native#text/plain
+packages/fcl-db/tests/testsqlscanner.lpr svneol=native#text/plain
 packages/fcl-db/tests/testsqlscript.pas svneol=native#text/plain
 packages/fcl-db/tests/testsqlscript.pas svneol=native#text/plain
 packages/fcl-db/tests/toolsunit.pas -text
 packages/fcl-db/tests/toolsunit.pas -text
 packages/fcl-extra/Makefile svneol=native#text/plain
 packages/fcl-extra/Makefile svneol=native#text/plain
@@ -1479,6 +1491,7 @@ packages/fcl-json/examples/parsedemo.pp svneol=native#text/plain
 packages/fcl-json/examples/simpledemo.lpi svneol=native#text/plain
 packages/fcl-json/examples/simpledemo.lpi svneol=native#text/plain
 packages/fcl-json/examples/simpledemo.pp svneol=native#text/plain
 packages/fcl-json/examples/simpledemo.pp svneol=native#text/plain
 packages/fcl-json/fpmake.pp svneol=native#text/plain
 packages/fcl-json/fpmake.pp svneol=native#text/plain
+packages/fcl-json/src/README.txt svneol=native#text/plain
 packages/fcl-json/src/fpjson.pp svneol=native#text/plain
 packages/fcl-json/src/fpjson.pp svneol=native#text/plain
 packages/fcl-json/src/jsonconf.pp svneol=native#text/plain
 packages/fcl-json/src/jsonconf.pp svneol=native#text/plain
 packages/fcl-json/src/jsonparser.pp svneol=native#text/plain
 packages/fcl-json/src/jsonparser.pp svneol=native#text/plain
@@ -1870,6 +1883,7 @@ packages/fpvectorial/examples/fpvc_mainform.pas svneol=native#text/plain
 packages/fpvectorial/examples/fpvectorialconverter.ico -text
 packages/fpvectorial/examples/fpvectorialconverter.ico -text
 packages/fpvectorial/examples/fpvectorialconverter.lpi svneol=native#text/plain
 packages/fpvectorial/examples/fpvectorialconverter.lpi svneol=native#text/plain
 packages/fpvectorial/examples/fpvectorialconverter.lpr svneol=native#text/plain
 packages/fpvectorial/examples/fpvectorialconverter.lpr svneol=native#text/plain
+packages/fpvectorial/examples/fpvwritetest.lpi svneol=native#text/plain
 packages/fpvectorial/examples/fpvwritetest.pas svneol=native#text/plain
 packages/fpvectorial/examples/fpvwritetest.pas svneol=native#text/plain
 packages/fpvectorial/fpmake.pp svneol=native#text/plain
 packages/fpvectorial/fpmake.pp svneol=native#text/plain
 packages/fpvectorial/src/avisocncgcodereader.pas svneol=native#text/plain
 packages/fpvectorial/src/avisocncgcodereader.pas svneol=native#text/plain
@@ -8715,6 +8729,8 @@ tests/test/tstring9.pp svneol=native#text/plain
 tests/test/tstrreal1.pp svneol=native#text/plain
 tests/test/tstrreal1.pp svneol=native#text/plain
 tests/test/tstrreal2.pp svneol=native#text/plain
 tests/test/tstrreal2.pp svneol=native#text/plain
 tests/test/tstrreal3.pp svneol=native#text/plain
 tests/test/tstrreal3.pp svneol=native#text/plain
+tests/test/tstrreal4.pp svneol=native#text/plain
+tests/test/tstrreal5.pp svneol=native#text/plain
 tests/test/tsubdecl.pp svneol=native#text/plain
 tests/test/tsubdecl.pp svneol=native#text/plain
 tests/test/tsymlibrary1.pp svneol=native#text/pascal
 tests/test/tsymlibrary1.pp svneol=native#text/pascal
 tests/test/tunaligned1.pp svneol=native#text/plain
 tests/test/tunaligned1.pp svneol=native#text/plain

+ 1 - 1
packages/fcl-base/fpmake.pp

@@ -17,7 +17,7 @@ begin
     P.Directory:='fcl-base';
     P.Directory:='fcl-base';
 {$endif ALLPACKAGES}
 {$endif ALLPACKAGES}
     P.Version:='2.4.3';
     P.Version:='2.4.3';
-    P.Dependencies.Add('winunits-jedi',[Win32,Win64]);
+    P.Dependencies.Add('univint',[Darwin]);
 
 
     P.Author := '<various>';
     P.Author := '<various>';
     P.License := 'LGPL with modification, ';
     P.License := 'LGPL with modification, ';

+ 1 - 1
packages/fcl-base/src/win/eventlog.inc

@@ -113,7 +113,7 @@ Var
   ELKey : String;
   ELKey : String;
 begin
 begin
   ELKey:=Format(SKeyEventLog,[IDentification]);
   ELKey:=Format(SKeyEventLog,[IDentification]);
-  Result:=RegDeleteKeyA(HKEY_LOCAL_MACHINE,pchar(ELKey));
+  Result:=(RegDeleteKeyA(HKEY_LOCAL_MACHINE,pchar(ELKey))=ERROR_SUCCESS);
 end;
 end;
 
 
 function TEventLog.MapTypeToCategory(EventType: TEventType): Word;
 function TEventLog.MapTypeToCategory(EventType: TEventType): Word;

+ 166 - 61
packages/fcl-db/Makefile

@@ -1,5 +1,5 @@
 #
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2010/08/25]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2010/11/23]
 #
 #
 default: all
 default: all
 MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
 MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
@@ -267,184 +267,184 @@ PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(F
 override PACKAGE_NAME=fcl-db
 override PACKAGE_NAME=fcl-db
 override PACKAGE_VERSION=2.4.3
 override PACKAGE_VERSION=2.4.3
 ifeq ($(FULL_TARGET),i386-linux)
 ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
 ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),i386-win32)
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/paradox src/sqlite src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/paradox src/sqlite src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),i386-os2)
 ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),i386-beos)
 ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),i386-haiku)
 ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox
 endif
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
 ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite
 endif
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
 ifeq ($(FULL_TARGET),i386-qnx)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),i386-netware)
 ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox
 endif
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
 ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
 ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite
 endif
 endif
 ifeq ($(FULL_TARGET),i386-emx)
 ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
 ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),i386-wince)
 ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
 ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
 ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
 ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
 ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
 ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
 ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
 ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
 ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
 ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox
 endif
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
 ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite
 endif
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
 ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
 ifeq ($(FULL_TARGET),x86_64-solaris)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
 ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
 ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),arm-linux)
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
 ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),arm-darwin)
 ifeq ($(FULL_TARGET),arm-darwin)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite
 endif
 endif
 ifeq ($(FULL_TARGET),arm-wince)
 ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),arm-gba)
 ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),arm-nds)
 ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
 ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
 ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
 ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
 ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),avr-embedded)
 ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),armeb-linux)
 ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 endif
 endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql
 endif
 endif
 ifeq ($(FULL_TARGET),mipsel-linux)
 ifeq ($(FULL_TARGET),mipsel-linux)
-override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
+override TARGET_DIRS+=src/sdf src/memds src/sqldb src/base src/sql  src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 endif
 endif
 override INSTALL_FPCPACKAGE=y
 override INSTALL_FPCPACKAGE=y
 ifeq ($(FULL_TARGET),i386-linux)
 ifeq ($(FULL_TARGET),i386-linux)
@@ -2669,6 +2669,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -2681,12 +2682,14 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),i386-win32)
 ifeq ($(FULL_TARGET),i386-win32)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
@@ -2699,12 +2702,14 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
 ifeq ($(FULL_TARGET),i386-freebsd)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -2717,6 +2722,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -2729,6 +2735,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -2741,6 +2748,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -2750,6 +2758,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 endif
 endif
@@ -2758,18 +2767,21 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),i386-netware)
 ifeq ($(FULL_TARGET),i386-netware)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
 ifeq ($(FULL_TARGET),i386-openbsd)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -2779,12 +2791,14 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
 ifeq ($(FULL_TARGET),i386-darwin)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 endif
 endif
@@ -2793,24 +2807,28 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
 ifeq ($(FULL_TARGET),i386-watcom)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
 ifeq ($(FULL_TARGET),i386-netwlibc)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),i386-wince)
 ifeq ($(FULL_TARGET),i386-wince)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/EXPORT=1
 TARGET_DIRS_SRC/EXPORT=1
@@ -2822,18 +2840,21 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
 ifeq ($(FULL_TARGET),i386-symbian)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
 ifeq ($(FULL_TARGET),m68k-linux)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -2846,6 +2867,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -2858,6 +2880,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -2867,18 +2890,21 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
 ifeq ($(FULL_TARGET),m68k-atari)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
 ifeq ($(FULL_TARGET),m68k-openbsd)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -2888,18 +2914,21 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
 ifeq ($(FULL_TARGET),m68k-embedded)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
 ifeq ($(FULL_TARGET),powerpc-linux)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -2912,6 +2941,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -2921,18 +2951,21 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
 ifeq ($(FULL_TARGET),powerpc-macos)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
 ifeq ($(FULL_TARGET),powerpc-darwin)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 endif
 endif
@@ -2941,18 +2974,21 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
 ifeq ($(FULL_TARGET),powerpc-embedded)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
 ifeq ($(FULL_TARGET),sparc-linux)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -2965,6 +3001,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -2974,6 +3011,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 endif
 endif
@@ -2982,12 +3020,14 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
 ifeq ($(FULL_TARGET),x86_64-linux)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -3000,6 +3040,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -3012,6 +3053,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 endif
 endif
@@ -3020,6 +3062,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 endif
 endif
@@ -3028,6 +3071,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/EXPORT=1
 TARGET_DIRS_SRC/EXPORT=1
 TARGET_DIRS_SRC/DATADICT=1
 TARGET_DIRS_SRC/DATADICT=1
@@ -3038,12 +3082,14 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),arm-linux)
 ifeq ($(FULL_TARGET),arm-linux)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -3056,12 +3102,14 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),arm-darwin)
 ifeq ($(FULL_TARGET),arm-darwin)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 endif
 endif
@@ -3070,6 +3118,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/EXPORT=1
 TARGET_DIRS_SRC/EXPORT=1
@@ -3081,30 +3130,35 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),arm-nds)
 ifeq ($(FULL_TARGET),arm-nds)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
 ifeq ($(FULL_TARGET),arm-embedded)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
 ifeq ($(FULL_TARGET),arm-symbian)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
 ifeq ($(FULL_TARGET),powerpc64-linux)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -3117,6 +3171,7 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 endif
 endif
@@ -3125,18 +3180,21 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),avr-embedded)
 ifeq ($(FULL_TARGET),avr-embedded)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),armeb-linux)
 ifeq ($(FULL_TARGET),armeb-linux)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -3149,12 +3207,14 @@ TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 endif
 endif
 ifeq ($(FULL_TARGET),mipsel-linux)
 ifeq ($(FULL_TARGET),mipsel-linux)
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/SDF=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/MEMDS=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/SQLDB=1
 TARGET_DIRS_SRC/BASE=1
 TARGET_DIRS_SRC/BASE=1
+TARGET_DIRS_SRC/SQL=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/DBASE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/SQLITE=1
 TARGET_DIRS_SRC/PARADOX=1
 TARGET_DIRS_SRC/PARADOX=1
@@ -3342,6 +3402,51 @@ src/base:
 	$(MAKE) -C src/base all
 	$(MAKE) -C src/base all
 .PHONY: src/base_all src/base_debug src/base_smart src/base_release src/base_units src/base_examples src/base_shared src/base_install src/base_sourceinstall src/base_exampleinstall src/base_distinstall src/base_zipinstall src/base_zipsourceinstall src/base_zipexampleinstall src/base_zipdistinstall src/base_clean src/base_distclean src/base_cleanall src/base_info src/base_makefiles src/base
 .PHONY: src/base_all src/base_debug src/base_smart src/base_release src/base_units src/base_examples src/base_shared src/base_install src/base_sourceinstall src/base_exampleinstall src/base_distinstall src/base_zipinstall src/base_zipsourceinstall src/base_zipexampleinstall src/base_zipdistinstall src/base_clean src/base_distclean src/base_cleanall src/base_info src/base_makefiles src/base
 endif
 endif
+ifdef TARGET_DIRS_SRC/SQL
+src/sql_all:
+	$(MAKE) -C src/sql all
+src/sql_debug:
+	$(MAKE) -C src/sql debug
+src/sql_smart:
+	$(MAKE) -C src/sql smart
+src/sql_release:
+	$(MAKE) -C src/sql release
+src/sql_units:
+	$(MAKE) -C src/sql units
+src/sql_examples:
+	$(MAKE) -C src/sql examples
+src/sql_shared:
+	$(MAKE) -C src/sql shared
+src/sql_install:
+	$(MAKE) -C src/sql install
+src/sql_sourceinstall:
+	$(MAKE) -C src/sql sourceinstall
+src/sql_exampleinstall:
+	$(MAKE) -C src/sql exampleinstall
+src/sql_distinstall:
+	$(MAKE) -C src/sql distinstall
+src/sql_zipinstall:
+	$(MAKE) -C src/sql zipinstall
+src/sql_zipsourceinstall:
+	$(MAKE) -C src/sql zipsourceinstall
+src/sql_zipexampleinstall:
+	$(MAKE) -C src/sql zipexampleinstall
+src/sql_zipdistinstall:
+	$(MAKE) -C src/sql zipdistinstall
+src/sql_clean:
+	$(MAKE) -C src/sql clean
+src/sql_distclean:
+	$(MAKE) -C src/sql distclean
+src/sql_cleanall:
+	$(MAKE) -C src/sql cleanall
+src/sql_info:
+	$(MAKE) -C src/sql info
+src/sql_makefiles:
+	$(MAKE) -C src/sql makefiles
+src/sql:
+	$(MAKE) -C src/sql all
+.PHONY: src/sql_all src/sql_debug src/sql_smart src/sql_release src/sql_units src/sql_examples src/sql_shared src/sql_install src/sql_sourceinstall src/sql_exampleinstall src/sql_distinstall src/sql_zipinstall src/sql_zipsourceinstall src/sql_zipexampleinstall src/sql_zipdistinstall src/sql_clean src/sql_distclean src/sql_cleanall src/sql_info src/sql_makefiles src/sql
+endif
 ifdef TARGET_DIRS_SRC/DBASE
 ifdef TARGET_DIRS_SRC/DBASE
 src/dbase_all:
 src/dbase_all:
 	$(MAKE) -C src/dbase all
 	$(MAKE) -C src/dbase all

+ 2 - 1
packages/fcl-db/Makefile.fpc

@@ -7,7 +7,7 @@ name=fcl-db
 version=2.4.3
 version=2.4.3
 
 
 [target]
 [target]
-dirs=src/sdf src/memds src/sqldb src/base 
+dirs=src/sdf src/memds src/sqldb src/base src/sql
 dirs_beos=src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 dirs_beos=src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 dirs_haiku=src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 dirs_haiku=src/dbase src/sqlite src/paradox src/export src/datadict src/codegen
 dirs_linux=src/dbase src/sqlite src/paradox src/export src/datadict src/codegen 
 dirs_linux=src/dbase src/sqlite src/paradox src/export src/datadict src/codegen 
@@ -56,3 +56,4 @@ src/dbase_debug: src/base_debug
 src/dbase_smart: src/base_smart
 src/dbase_smart: src/base_smart
 src/dbase_release: src/base_release
 src/dbase_release: src/base_release
 src/dbase_shared: src/base_shared
 src/dbase_shared: src/base_shared
+

+ 2613 - 0
packages/fcl-db/src/sql/Makefile

@@ -0,0 +1,2613 @@
+#
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2010/07/16]
+#
+default: all
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
+BSDs = freebsd netbsd openbsd darwin
+UNIXs = linux $(BSDs) solaris qnx haiku
+LIMIT83fs = go32v2 os2 emx watcom
+OSNeedsComspecToRunBatch = go32v2 watcom
+FORCE:
+.PHONY: FORCE
+override PATH:=$(patsubst %/,%,$(subst \,/,$(PATH)))
+ifneq ($(findstring darwin,$(OSTYPE)),)
+inUnix=1 #darwin
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+ifeq ($(findstring ;,$(PATH)),)
+inUnix=1
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+SEARCHPATH:=$(subst ;, ,$(PATH))
+endif
+endif
+SEARCHPATH+=$(patsubst %/,%,$(subst \,/,$(dir $(MAKE))))
+PWD:=$(strip $(wildcard $(addsuffix /pwd.exe,$(SEARCHPATH))))
+ifeq ($(PWD),)
+PWD:=$(strip $(wildcard $(addsuffix /pwd,$(SEARCHPATH))))
+ifeq ($(PWD),)
+$(error You need the GNU utils package to use this Makefile)
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=
+endif
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=.exe
+endif
+ifndef inUnix
+ifeq ($(OS),Windows_NT)
+inWinNT=1
+else
+ifdef OS2_SHELL
+inOS2=1
+endif
+endif
+else
+ifneq ($(findstring cygdrive,$(PATH)),)
+inCygWin=1
+endif
+endif
+ifdef inUnix
+SRCBATCHEXT=.sh
+else
+ifdef inOS2
+SRCBATCHEXT=.cmd
+else
+SRCBATCHEXT=.bat
+endif
+endif
+ifdef COMSPEC
+ifneq ($(findstring $(OS_SOURCE),$(OSNeedsComspecToRunBatch)),)
+ifndef RUNBATCH
+RUNBATCH=$(COMSPEC) /C
+endif
+endif
+endif
+ifdef inUnix
+PATHSEP=/
+else
+PATHSEP:=$(subst /,\,/)
+ifdef inCygWin
+PATHSEP=/
+endif
+endif
+ifdef PWD
+BASEDIR:=$(subst \,/,$(shell $(PWD)))
+ifdef inCygWin
+ifneq ($(findstring /cygdrive/,$(BASEDIR)),)
+BASENODIR:=$(patsubst /cygdrive%,%,$(BASEDIR))
+BASEDRIVE:=$(firstword $(subst /, ,$(BASENODIR)))
+BASEDIR:=$(subst /cygdrive/$(BASEDRIVE)/,$(BASEDRIVE):/,$(BASEDIR))
+endif
+endif
+else
+BASEDIR=.
+endif
+ifdef inOS2
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO=echo
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+endif
+override DEFAULT_FPCDIR=../../../..
+ifndef FPC
+ifdef PP
+FPC=$(PP)
+endif
+endif
+ifndef FPC
+FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(FPCPROG),)
+FPCPROG:=$(firstword $(FPCPROG))
+ifneq ($(CPU_TARGET),)
+FPC:=$(shell $(FPCPROG) -P$(CPU_TARGET) -PB)
+else
+FPC:=$(shell $(FPCPROG) -PB)
+endif
+ifneq ($(findstring Error,$(FPC)),)
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+else
+ifeq ($(strip $(wildcard $(FPC))),)
+FPC:=$(firstword $(FPCPROG))
+endif
+endif
+else
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+endif
+override FPC:=$(subst $(SRCEXEEXT),,$(FPC))
+override FPC:=$(subst \,/,$(FPC))$(SRCEXEEXT)
+FOUNDFPC:=$(strip $(wildcard $(FPC)))
+ifeq ($(FOUNDFPC),)
+FOUNDFPC=$(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))
+ifeq ($(FOUNDFPC),)
+$(error Compiler $(FPC) not found)
+endif
+endif
+ifndef FPC_COMPILERINFO
+FPC_COMPILERINFO:=$(shell $(FPC) -iVSPTPSOTO)
+endif
+ifndef FPC_VERSION
+FPC_VERSION:=$(word 1,$(FPC_COMPILERINFO))
+endif
+export FPC FPC_VERSION FPC_COMPILERINFO
+unexport CHECKDEPEND ALLDEPENDENCIES
+ifndef CPU_TARGET
+ifdef CPU_TARGET_DEFAULT
+CPU_TARGET=$(CPU_TARGET_DEFAULT)
+endif
+endif
+ifndef OS_TARGET
+ifdef OS_TARGET_DEFAULT
+OS_TARGET=$(OS_TARGET_DEFAULT)
+endif
+endif
+ifneq ($(words $(FPC_COMPILERINFO)),5)
+FPC_COMPILERINFO+=$(shell $(FPC) -iSP)
+FPC_COMPILERINFO+=$(shell $(FPC) -iTP)
+FPC_COMPILERINFO+=$(shell $(FPC) -iSO)
+FPC_COMPILERINFO+=$(shell $(FPC) -iTO)
+endif
+ifndef CPU_SOURCE
+CPU_SOURCE:=$(word 2,$(FPC_COMPILERINFO))
+endif
+ifndef CPU_TARGET
+CPU_TARGET:=$(word 3,$(FPC_COMPILERINFO))
+endif
+ifndef OS_SOURCE
+OS_SOURCE:=$(word 4,$(FPC_COMPILERINFO))
+endif
+ifndef OS_TARGET
+OS_TARGET:=$(word 5,$(FPC_COMPILERINFO))
+endif
+FULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+FULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifeq ($(CPU_TARGET),armeb)
+ARCH=arm
+override FPCOPT+=-Cb
+else
+ifeq ($(CPU_TARGET),armel)
+ARCH=arm
+override FPCOPT+=-CaEABI
+else
+ARCH=$(CPU_TARGET)
+endif
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+SOURCESUFFIX=$(OS_SOURCE)
+else
+TARGETSUFFIX=$(FULL_TARGET)
+SOURCESUFFIX=$(FULL_SOURCE)
+endif
+ifneq ($(FULL_TARGET),$(FULL_SOURCE))
+CROSSCOMPILE=1
+endif
+ifeq ($(findstring makefile,$(MAKECMDGOALS)),)
+ifeq ($(findstring $(FULL_TARGET),$(MAKEFILETARGETS)),)
+$(error The Makefile doesn't support target $(FULL_TARGET), please run fpcmake first)
+endif
+endif
+ifneq ($(findstring $(OS_TARGET),$(BSDs)),)
+BSDhier=1
+endif
+ifeq ($(OS_TARGET),linux)
+linuxHier=1
+endif
+export OS_TARGET OS_SOURCE ARCH CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE
+ifdef FPCDIR
+override FPCDIR:=$(subst \,/,$(FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+else
+override FPCDIR=wrong
+endif
+ifdef DEFAULT_FPCDIR
+ifeq ($(FPCDIR),wrong)
+override FPCDIR:=$(subst \,/,$(DEFAULT_FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+endif
+endif
+ifeq ($(FPCDIR),wrong)
+ifdef inUnix
+override FPCDIR=/usr/local/lib/fpc/$(FPC_VERSION)
+ifeq ($(wildcard $(FPCDIR)/units),)
+override FPCDIR=/usr/lib/fpc/$(FPC_VERSION)
+endif
+else
+override FPCDIR:=$(subst /$(FPC),,$(firstword $(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))))
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(BASEDIR)
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=c:/pp
+endif
+endif
+endif
+endif
+endif
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(FPCDIR)/bin/$(TARGETSUFFIX))
+endif
+ifeq ($(OS_TARGET),darwin)
+ifeq ($(OS_SOURCE),darwin)
+DARWIN2DARWIN=1
+endif
+endif
+ifndef BINUTILSPREFIX
+ifndef CROSSBINDIR
+ifdef CROSSCOMPILE
+ifndef DARWIN2DARWIN
+BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)-
+endif
+endif
+endif
+endif
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX))
+ifeq ($(UNITSDIR),)
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
+endif
+PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
+override PACKAGE_NAME=fcl-db
+PACKAGEDIR_MAIN:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fcl-db/Makefile.fpc,$(PACKAGESDIR))))))
+ifeq ($(FULL_TARGET),i386-linux)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override TARGET_UNITS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override TARGET_RSTS+=fpsqltree fpsqlscanner fpsqlparser
+endif
+override INSTALL_FPCPACKAGE=y
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override COMPILER_UNITDIR+=../dbase
+endif
+ifdef REQUIRE_UNITSDIR
+override UNITSDIR+=$(REQUIRE_UNITSDIR)
+endif
+ifdef REQUIRE_PACKAGESDIR
+override PACKAGESDIR+=$(REQUIRE_PACKAGESDIR)
+endif
+ifdef ZIPINSTALL
+ifneq ($(findstring $(OS_TARGET),$(UNIXs)),)
+UNIXHier=1
+endif
+else
+ifneq ($(findstring $(OS_SOURCE),$(UNIXs)),)
+UNIXHier=1
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef PREFIX
+INSTALL_PREFIX=$(PREFIX)
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef UNIXHier
+INSTALL_PREFIX=/usr/local
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=/pp
+else
+INSTALL_BASEDIR:=/$(PACKAGE_NAME)
+endif
+endif
+endif
+export INSTALL_PREFIX
+ifdef INSTALL_FPCSUBDIR
+export INSTALL_FPCSUBDIR
+endif
+ifndef DIST_DESTDIR
+DIST_DESTDIR:=$(BASEDIR)
+endif
+export DIST_DESTDIR
+ifndef COMPILER_UNITTARGETDIR
+ifdef PACKAGEDIR_MAIN
+COMPILER_UNITTARGETDIR=$(PACKAGEDIR_MAIN)/units/$(TARGETSUFFIX)
+else
+COMPILER_UNITTARGETDIR=units/$(TARGETSUFFIX)
+endif
+endif
+ifndef COMPILER_TARGETDIR
+COMPILER_TARGETDIR=.
+endif
+ifndef INSTALL_BASEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/fpc/$(FPC_VERSION)
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/$(PACKAGE_NAME)
+endif
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)
+endif
+endif
+ifndef INSTALL_BINDIR
+ifdef UNIXHier
+INSTALL_BINDIR:=$(INSTALL_PREFIX)/bin
+else
+INSTALL_BINDIR:=$(INSTALL_BASEDIR)/bin
+ifdef INSTALL_FPCPACKAGE
+ifdef CROSSCOMPILE
+ifdef CROSSINSTALL
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(SOURCESUFFIX)
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+endif
+endif
+endif
+ifndef INSTALL_UNITDIR
+INSTALL_UNITDIR:=$(INSTALL_BASEDIR)/units/$(TARGETSUFFIX)
+ifdef INSTALL_FPCPACKAGE
+ifdef PACKAGE_NAME
+INSTALL_UNITDIR:=$(INSTALL_UNITDIR)/$(PACKAGE_NAME)
+endif
+endif
+endif
+ifndef INSTALL_LIBDIR
+ifdef UNIXHier
+INSTALL_LIBDIR:=$(INSTALL_PREFIX)/lib
+else
+INSTALL_LIBDIR:=$(INSTALL_UNITDIR)
+endif
+endif
+ifndef INSTALL_SOURCEDIR
+ifdef UNIXHier
+ifdef BSDhier
+SRCPREFIXDIR=share/src
+else
+ifdef linuxHier
+SRCPREFIXDIR=share/src
+else
+SRCPREFIXDIR=src
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source
+endif
+endif
+endif
+ifndef INSTALL_DOCDIR
+ifdef UNIXHier
+ifdef BSDhier
+DOCPREFIXDIR=share/doc
+else
+ifdef linuxHier
+DOCPREFIXDIR=share/doc
+else
+DOCPREFIXDIR=doc
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc
+endif
+endif
+endif
+ifndef INSTALL_EXAMPLEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/fpc-$(FPC_VERSION)/examples/$(PACKAGE_NAME)
+endif
+endif
+else
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+endif
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples/$(PACKAGE_NAME)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples
+endif
+endif
+endif
+ifndef INSTALL_DATADIR
+INSTALL_DATADIR=$(INSTALL_BASEDIR)
+endif
+ifndef INSTALL_SHAREDDIR
+INSTALL_SHAREDDIR=$(INSTALL_PREFIX)/lib
+endif
+ifdef CROSSCOMPILE
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(CROSSTARGETDIR)/bin/$(SOURCESUFFIX))
+ifeq ($(CROSSBINDIR),)
+CROSSBINDIR:=$(wildcard $(INSTALL_BASEDIR)/cross/$(TARGETSUFFIX)/bin/$(FULL_SOURCE))
+endif
+endif
+else
+CROSSBINDIR=
+endif
+BATCHEXT=.bat
+LOADEREXT=.as
+EXEEXT=.exe
+PPLEXT=.ppl
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.so
+SHAREDLIBPREFIX=libfp
+STATICLIBPREFIX=libp
+IMPORTLIBPREFIX=libimp
+RSTEXT=.rst
+ifeq ($(findstring 1.0.,$(FPC_VERSION)),)
+ifeq ($(OS_TARGET),go32v1)
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+OEXT=.obj
+ASMEXT=.asm
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=wat
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),emx)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=emx
+ECHO=echo
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),morphos)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=mos
+endif
+ifeq ($(OS_TARGET),atari)
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),haiku)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=hai
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nw
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),netwlibc)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nwl
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),darwin)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=dwn
+endif
+ifeq ($(OS_TARGET),gba)
+EXEEXT=.gba
+SHAREDLIBEXT=.so
+SHORTSUFFIX=gba
+endif
+ifeq ($(OS_TARGET),symbian)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=symbian
+endif
+ifeq ($(OS_TARGET),NativeNT)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=nativent
+endif
+else
+ifeq ($(OS_TARGET),go32v1)
+PPUEXT=.pp1
+OEXT=.o1
+ASMEXT=.s1
+SMARTEXT=.sl1
+STATICLIBEXT=.a1
+SHAREDLIBEXT=.so1
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+SHORTSUFFIX=wat
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+PPUEXT=.ppw
+OEXT=.ow
+ASMEXT=.sw
+SMARTEXT=.slw
+STATICLIBEXT=.aw
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+PPUEXT=.ppo
+ASMEXT=.so2
+OEXT=.oo2
+AOUTEXT=.out
+SMARTEXT=.sl2
+STATICLIBPREFIX=
+STATICLIBEXT=.ao2
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),atari)
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+STATICLIBPREFIX=
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.nlm
+EXEEXT=.nlm
+SHORTSUFFIX=nw
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),netwlibc)
+STATICLIBPREFIX=
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.nlm
+EXEEXT=.nlm
+SHORTSUFFIX=nwl
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+IMPORTLIBPREFIX=imp
+endif
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+FPCMADE=fpcmade.$(SHORTSUFFIX)
+ZIPSUFFIX=$(SHORTSUFFIX)
+ZIPCROSSPREFIX=
+ZIPSOURCESUFFIX=src
+ZIPEXAMPLESUFFIX=exm
+else
+FPCMADE=fpcmade.$(TARGETSUFFIX)
+ZIPSOURCESUFFIX=.source
+ZIPEXAMPLESUFFIX=.examples
+ifdef CROSSCOMPILE
+ZIPSUFFIX=.$(SOURCESUFFIX)
+ZIPCROSSPREFIX=$(TARGETSUFFIX)-
+else
+ZIPSUFFIX=.$(TARGETSUFFIX)
+ZIPCROSSPREFIX=
+endif
+endif
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO= __missing_command_ECHO
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+ifndef DATE
+DATE:=$(strip $(wildcard $(addsuffix /gdate$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE:=$(strip $(wildcard $(addsuffix /date$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE= __missing_command_DATE
+else
+DATE:=$(firstword $(DATE))
+endif
+else
+DATE:=$(firstword $(DATE))
+endif
+endif
+export DATE
+ifndef GINSTALL
+GINSTALL:=$(strip $(wildcard $(addsuffix /ginstall$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL:=$(strip $(wildcard $(addsuffix /install$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL= __missing_command_GINSTALL
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+endif
+export GINSTALL
+ifndef CPPROG
+CPPROG:=$(strip $(wildcard $(addsuffix /cp$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(CPPROG),)
+CPPROG= __missing_command_CPPROG
+else
+CPPROG:=$(firstword $(CPPROG))
+endif
+endif
+export CPPROG
+ifndef RMPROG
+RMPROG:=$(strip $(wildcard $(addsuffix /rm$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(RMPROG),)
+RMPROG= __missing_command_RMPROG
+else
+RMPROG:=$(firstword $(RMPROG))
+endif
+endif
+export RMPROG
+ifndef MVPROG
+MVPROG:=$(strip $(wildcard $(addsuffix /mv$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MVPROG),)
+MVPROG= __missing_command_MVPROG
+else
+MVPROG:=$(firstword $(MVPROG))
+endif
+endif
+export MVPROG
+ifndef MKDIRPROG
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /gmkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /mkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG= __missing_command_MKDIRPROG
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+endif
+export MKDIRPROG
+ifndef ECHOREDIR
+ifndef inUnix
+ECHOREDIR=echo
+else
+ECHOREDIR=$(ECHO)
+endif
+endif
+ifndef COPY
+COPY:=$(CPPROG) -fp
+endif
+ifndef COPYTREE
+COPYTREE:=$(CPPROG) -Rfp
+endif
+ifndef MKDIRTREE
+MKDIRTREE:=$(MKDIRPROG) -p
+endif
+ifndef MOVE
+MOVE:=$(MVPROG) -f
+endif
+ifndef DEL
+DEL:=$(RMPROG) -f
+endif
+ifndef DELTREE
+DELTREE:=$(RMPROG) -rf
+endif
+ifndef INSTALL
+ifdef inUnix
+INSTALL:=$(GINSTALL) -c -m 644
+else
+INSTALL:=$(COPY)
+endif
+endif
+ifndef INSTALLEXE
+ifdef inUnix
+INSTALLEXE:=$(GINSTALL) -c -m 755
+else
+INSTALLEXE:=$(COPY)
+endif
+endif
+ifndef MKDIR
+MKDIR:=$(GINSTALL) -m 755 -d
+endif
+export ECHOREDIR COPY COPYTREE MOVE DEL DELTREE INSTALL INSTALLEXE MKDIR
+ifndef PPUMOVE
+PPUMOVE:=$(strip $(wildcard $(addsuffix /ppumove$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(PPUMOVE),)
+PPUMOVE= __missing_command_PPUMOVE
+else
+PPUMOVE:=$(firstword $(PPUMOVE))
+endif
+endif
+export PPUMOVE
+ifndef FPCMAKE
+FPCMAKE:=$(strip $(wildcard $(addsuffix /fpcmake$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(FPCMAKE),)
+FPCMAKE= __missing_command_FPCMAKE
+else
+FPCMAKE:=$(firstword $(FPCMAKE))
+endif
+endif
+export FPCMAKE
+ifndef ZIPPROG
+ZIPPROG:=$(strip $(wildcard $(addsuffix /zip$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ZIPPROG),)
+ZIPPROG= __missing_command_ZIPPROG
+else
+ZIPPROG:=$(firstword $(ZIPPROG))
+endif
+endif
+export ZIPPROG
+ifndef TARPROG
+TARPROG:=$(strip $(wildcard $(addsuffix /gtar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG= __missing_command_TARPROG
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+endif
+export TARPROG
+ASNAME=$(BINUTILSPREFIX)as
+LDNAME=$(BINUTILSPREFIX)ld
+ARNAME=$(BINUTILSPREFIX)ar
+RCNAME=$(BINUTILSPREFIX)rc
+ifneq ($(findstring 1.0.,$(FPC_VERSION)),)
+ifeq ($(OS_TARGET),win32)
+ifeq ($(CROSSBINDIR),)
+ASNAME=asw
+LDNAME=ldw
+ARNAME=arw
+endif
+endif
+endif
+ifndef ASPROG
+ifdef CROSSBINDIR
+ASPROG=$(CROSSBINDIR)/$(ASNAME)$(SRCEXEEXT)
+else
+ASPROG=$(ASNAME)
+endif
+endif
+ifndef LDPROG
+ifdef CROSSBINDIR
+LDPROG=$(CROSSBINDIR)/$(LDNAME)$(SRCEXEEXT)
+else
+LDPROG=$(LDNAME)
+endif
+endif
+ifndef RCPROG
+ifdef CROSSBINDIR
+RCPROG=$(CROSSBINDIR)/$(RCNAME)$(SRCEXEEXT)
+else
+RCPROG=$(RCNAME)
+endif
+endif
+ifndef ARPROG
+ifdef CROSSBINDIR
+ARPROG=$(CROSSBINDIR)/$(ARNAME)$(SRCEXEEXT)
+else
+ARPROG=$(ARNAME)
+endif
+endif
+AS=$(ASPROG)
+LD=$(LDPROG)
+RC=$(RCPROG)
+AR=$(ARPROG)
+PPAS=ppas$(SRCBATCHEXT)
+ifdef inUnix
+LDCONFIG=ldconfig
+else
+LDCONFIG=
+endif
+ifdef DATE
+DATESTR:=$(shell $(DATE) +%Y%m%d)
+else
+DATESTR=
+endif
+ifndef UPXPROG
+ifeq ($(OS_TARGET),go32v2)
+UPXPROG:=1
+endif
+ifeq ($(OS_TARGET),win32)
+UPXPROG:=1
+endif
+ifdef UPXPROG
+UPXPROG:=$(strip $(wildcard $(addsuffix /upx$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(UPXPROG),)
+UPXPROG=
+else
+UPXPROG:=$(firstword $(UPXPROG))
+endif
+else
+UPXPROG=
+endif
+endif
+export UPXPROG
+ZIPOPT=-9
+ZIPEXT=.zip
+ifeq ($(USETAR),bz2)
+TAROPT=vj
+TAREXT=.tar.bz2
+else
+TAROPT=vz
+TAREXT=.tar.gz
+endif
+override REQUIRE_PACKAGES=rtl fcl-base
+ifeq ($(FULL_TARGET),i386-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_UNIVINT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_UNIVINT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_UNIVINT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_UNIVINT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_UNIVINT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifdef REQUIRE_PACKAGES_RTL
+PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_RTL),)
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)),)
+UNITDIR_RTL=$(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)
+else
+UNITDIR_RTL=$(PACKAGEDIR_RTL)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_RTL)/$(OS_TARGET)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_RTL)/$(OS_TARGET) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(OS_TARGET)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_RTL=
+UNITDIR_RTL:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /rtl/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_RTL),)
+UNITDIR_RTL:=$(firstword $(UNITDIR_RTL))
+else
+UNITDIR_RTL=
+endif
+endif
+ifdef UNITDIR_RTL
+override COMPILER_UNITDIR+=$(UNITDIR_RTL)
+endif
+endif
+ifdef REQUIRE_PACKAGES_FCL-BASE
+PACKAGEDIR_FCL-BASE:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fcl-base/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_FCL-BASE),)
+ifneq ($(wildcard $(PACKAGEDIR_FCL-BASE)/units/$(TARGETSUFFIX)),)
+UNITDIR_FCL-BASE=$(PACKAGEDIR_FCL-BASE)/units/$(TARGETSUFFIX)
+else
+UNITDIR_FCL-BASE=$(PACKAGEDIR_FCL-BASE)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_FCL-BASE)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_FCL-BASE) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_FCL-BASE)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_FCL-BASE=
+UNITDIR_FCL-BASE:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /fcl-base/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_FCL-BASE),)
+UNITDIR_FCL-BASE:=$(firstword $(UNITDIR_FCL-BASE))
+else
+UNITDIR_FCL-BASE=
+endif
+endif
+ifdef UNITDIR_FCL-BASE
+override COMPILER_UNITDIR+=$(UNITDIR_FCL-BASE)
+endif
+endif
+ifdef REQUIRE_PACKAGES_UNIVINT
+PACKAGEDIR_UNIVINT:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /univint/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_UNIVINT),)
+ifneq ($(wildcard $(PACKAGEDIR_UNIVINT)/units/$(TARGETSUFFIX)),)
+UNITDIR_UNIVINT=$(PACKAGEDIR_UNIVINT)/units/$(TARGETSUFFIX)
+else
+UNITDIR_UNIVINT=$(PACKAGEDIR_UNIVINT)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_UNIVINT)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_UNIVINT) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_UNIVINT)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_UNIVINT=
+UNITDIR_UNIVINT:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /univint/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_UNIVINT),)
+UNITDIR_UNIVINT:=$(firstword $(UNITDIR_UNIVINT))
+else
+UNITDIR_UNIVINT=
+endif
+endif
+ifdef UNITDIR_UNIVINT
+override COMPILER_UNITDIR+=$(UNITDIR_UNIVINT)
+endif
+endif
+ifndef NOCPUDEF
+override FPCOPTDEF=$(ARCH)
+endif
+ifneq ($(OS_TARGET),$(OS_SOURCE))
+override FPCOPT+=-T$(OS_TARGET)
+endif
+ifneq ($(CPU_TARGET),$(CPU_SOURCE))
+override FPCOPT+=-P$(ARCH)
+endif
+ifeq ($(OS_SOURCE),openbsd)
+override FPCOPT+=-FD$(NEW_BINUTILS_PATH)
+endif
+ifndef CROSSBOOTSTRAP
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-XP$(BINUTILSPREFIX)
+endif
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-Xr$(RLINKPATH)
+endif
+endif
+ifdef UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(UNITDIR))
+endif
+ifdef LIBDIR
+override FPCOPT+=$(addprefix -Fl,$(LIBDIR))
+endif
+ifdef OBJDIR
+override FPCOPT+=$(addprefix -Fo,$(OBJDIR))
+endif
+ifdef INCDIR
+override FPCOPT+=$(addprefix -Fi,$(INCDIR))
+endif
+ifdef LINKSMART
+override FPCOPT+=-XX
+endif
+ifdef CREATESMART
+override FPCOPT+=-CX
+endif
+ifdef DEBUG
+override FPCOPT+=-gl
+override FPCOPTDEF+=DEBUG
+endif
+ifdef RELEASE
+ifneq ($(findstring 2.0.,$(FPC_VERSION)),)
+ifeq ($(CPU_TARGET),i386)
+FPCCPUOPT:=-OG2p3
+endif
+ifeq ($(CPU_TARGET),powerpc)
+FPCCPUOPT:=-O1r
+endif
+else
+FPCCPUOPT:=-O2
+endif
+override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n
+override FPCOPTDEF+=RELEASE
+endif
+ifdef STRIP
+override FPCOPT+=-Xs
+endif
+ifdef OPTIMIZE
+override FPCOPT+=-O2
+endif
+ifdef VERBOSE
+override FPCOPT+=-vwni
+endif
+ifdef COMPILER_OPTIONS
+override FPCOPT+=$(COMPILER_OPTIONS)
+endif
+ifdef COMPILER_UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(COMPILER_UNITDIR))
+endif
+ifdef COMPILER_LIBRARYDIR
+override FPCOPT+=$(addprefix -Fl,$(COMPILER_LIBRARYDIR))
+endif
+ifdef COMPILER_OBJECTDIR
+override FPCOPT+=$(addprefix -Fo,$(COMPILER_OBJECTDIR))
+endif
+ifdef COMPILER_INCLUDEDIR
+override FPCOPT+=$(addprefix -Fi,$(COMPILER_INCLUDEDIR))
+endif
+ifdef CROSSBINDIR
+override FPCOPT+=-FD$(CROSSBINDIR)
+endif
+ifdef COMPILER_TARGETDIR
+override FPCOPT+=-FE$(COMPILER_TARGETDIR)
+ifeq ($(COMPILER_TARGETDIR),.)
+override TARGETDIRPREFIX=
+else
+override TARGETDIRPREFIX=$(COMPILER_TARGETDIR)/
+endif
+endif
+ifdef COMPILER_UNITTARGETDIR
+override FPCOPT+=-FU$(COMPILER_UNITTARGETDIR)
+ifeq ($(COMPILER_UNITTARGETDIR),.)
+override UNITTARGETDIRPREFIX=
+else
+override UNITTARGETDIRPREFIX=$(COMPILER_UNITTARGETDIR)/
+endif
+else
+ifdef COMPILER_TARGETDIR
+override COMPILER_UNITTARGETDIR=$(COMPILER_TARGETDIR)
+override UNITTARGETDIRPREFIX=$(TARGETDIRPREFIX)
+endif
+endif
+ifdef CREATESHARED
+override FPCOPT+=-Cg
+ifeq ($(CPU_TARGET),i386)
+override FPCOPT+=-Aas
+endif
+endif
+ifeq ($(findstring 2.0.,$(FPC_VERSION)),)
+ifeq ($(OS_TARGET),linux)
+ifeq ($(CPU_TARGET),x86_64)
+override FPCOPT+=-Cg
+endif
+endif
+endif
+ifdef LINKSHARED
+endif
+ifdef OPT
+override FPCOPT+=$(OPT)
+endif
+ifdef FPCOPTDEF
+override FPCOPT+=$(addprefix -d,$(FPCOPTDEF))
+endif
+ifdef CFGFILE
+override FPCOPT+=@$(CFGFILE)
+endif
+ifdef USEENV
+override FPCEXTCMD:=$(FPCOPT)
+override FPCOPT:=!FPCEXTCMD
+export FPCEXTCMD
+endif
+override AFULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+override AFULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifneq ($(AFULL_TARGET),$(AFULL_SOURCE))
+override ACROSSCOMPILE=1
+endif
+ifdef ACROSSCOMPILE
+override FPCOPT+=$(CROSSOPT)
+endif
+override COMPILER:=$(FPC) $(FPCOPT)
+ifeq (,$(findstring -s ,$(COMPILER)))
+EXECPPAS=
+else
+ifeq ($(FULL_SOURCE),$(FULL_TARGET))
+ifdef RUNBATCH
+EXECPPAS:=@$(RUNBATCH) $(PPAS)
+else
+EXECPPAS:=@$(PPAS)
+endif
+endif
+endif
+.PHONY: fpc_units
+ifneq ($(TARGET_UNITS)$(TARGET_IMPLICITUNITS),)
+override ALLTARGET+=fpc_units
+override UNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_UNITS))
+override IMPLICITUNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_IMPLICITUNITS))
+override INSTALLPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES)
+override CLEANPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES)
+endif
+fpc_units: $(COMPILER_UNITTARGETDIR) $(UNITPPUFILES)
+ifdef TARGET_RSTS
+override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
+override CLEANRSTFILES+=$(RSTFILES)
+endif
+.PHONY: fpc_all fpc_smart fpc_debug fpc_release fpc_shared
+$(FPCMADE): $(ALLDEPENDENCIES) $(ALLTARGET)
+	@$(ECHOREDIR) Compiled > $(FPCMADE)
+fpc_all: $(FPCMADE)
+fpc_smart:
+	$(MAKE) all LINKSMART=1 CREATESMART=1
+fpc_debug:
+	$(MAKE) all DEBUG=1
+fpc_release:
+	$(MAKE) all RELEASE=1
+.SUFFIXES: $(EXEEXT) $(PPUEXT) $(OEXT) .pas .lpr .dpr .pp .rc .res
+$(COMPILER_UNITTARGETDIR):
+	$(MKDIRTREE) $(COMPILER_UNITTARGETDIR)
+$(COMPILER_TARGETDIR):
+	$(MKDIRTREE) $(COMPILER_TARGETDIR)
+%$(PPUEXT): %.pp
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(PPUEXT): %.pas
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(EXEEXT): %.pp
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(EXEEXT): %.pas
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(EXEEXT): %.lpr
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(EXEEXT): %.dpr
+	$(COMPILER) $<
+	$(EXECPPAS)
+%.res: %.rc
+	windres -i $< -o $@
+vpath %.pp $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.pas $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.lpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.dpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.inc $(COMPILER_INCLUDEDIR)
+vpath %$(OEXT) $(COMPILER_UNITTARGETDIR)
+vpath %$(PPUEXT) $(COMPILER_UNITTARGETDIR)
+.PHONY: fpc_shared
+override INSTALLTARGET+=fpc_shared_install
+ifndef SHARED_LIBVERSION
+SHARED_LIBVERSION=$(FPC_VERSION)
+endif
+ifndef SHARED_LIBNAME
+SHARED_LIBNAME=$(PACKAGE_NAME)
+endif
+ifndef SHARED_FULLNAME
+SHARED_FULLNAME=$(SHAREDLIBPREFIX)$(SHARED_LIBNAME)-$(SHARED_LIBVERSION)$(SHAREDLIBEXT)
+endif
+ifndef SHARED_LIBUNITS
+SHARED_LIBUNITS:=$(TARGET_UNITS) $(TARGET_IMPLICITUNITS)
+override SHARED_LIBUNITS:=$(filter-out $(INSTALL_BUILDUNIT),$(SHARED_LIBUNITS))
+endif
+fpc_shared:
+ifdef HASSHAREDLIB
+	$(MAKE) all CREATESHARED=1 LINKSHARED=1 CREATESMART=1
+ifneq ($(SHARED_BUILD),n)
+	$(PPUMOVE) -q $(SHARED_LIBUNITS) -i$(COMPILER_UNITTARGETDIR) -o$(SHARED_FULLNAME) -d$(COMPILER_UNITTARGETDIR)
+endif
+else
+	@$(ECHO) Shared Libraries not supported
+endif
+fpc_shared_install:
+ifneq ($(SHARED_BUILD),n)
+ifneq ($(SHARED_LIBUNITS),)
+ifneq ($(wildcard $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME)),)
+	$(INSTALL) $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME) $(INSTALL_SHAREDDIR)
+endif
+endif
+endif
+.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall
+ifdef INSTALL_UNITS
+override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(INSTALL_UNITS))
+endif
+ifdef INSTALL_BUILDUNIT
+override INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT),$(INSTALLPPUFILES))
+endif
+ifdef INSTALLPPUFILES
+override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES)))
+ifneq ($(UNITTARGETDIRPREFIX),)
+override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPUFILES)))
+override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPULINKFILES))))
+endif
+override INSTALL_CREATEPACKAGEFPC=1
+endif
+ifdef INSTALLEXEFILES
+ifneq ($(TARGETDIRPREFIX),)
+override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(INSTALLEXEFILES)))
+endif
+endif
+fpc_install: all $(INSTALLTARGET)
+ifdef INSTALLEXEFILES
+	$(MKDIR) $(INSTALL_BINDIR)
+ifdef UPXPROG
+	-$(UPXPROG) $(INSTALLEXEFILES)
+endif
+	$(INSTALLEXE) $(INSTALLEXEFILES) $(INSTALL_BINDIR)
+endif
+ifdef INSTALL_CREATEPACKAGEFPC
+ifdef FPCMAKE
+ifdef PACKAGE_VERSION
+ifneq ($(wildcard Makefile.fpc),)
+	$(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc
+	$(MKDIR) $(INSTALL_UNITDIR)
+	$(INSTALL) Package.fpc $(INSTALL_UNITDIR)
+endif
+endif
+endif
+endif
+ifdef INSTALLPPUFILES
+	$(MKDIR) $(INSTALL_UNITDIR)
+	$(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR)
+ifneq ($(INSTALLPPULINKFILES),)
+	$(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR)
+endif
+ifneq ($(wildcard $(LIB_FULLNAME)),)
+	$(MKDIR) $(INSTALL_LIBDIR)
+	$(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR)
+ifdef inUnix
+	ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME)
+endif
+endif
+endif
+ifdef INSTALL_FILES
+	$(MKDIR) $(INSTALL_DATADIR)
+	$(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADIR)
+endif
+fpc_sourceinstall: distclean
+	$(MKDIR) $(INSTALL_SOURCEDIR)
+	$(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR)
+fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
+ifdef HASEXAMPLES
+	$(MKDIR) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef EXAMPLESOURCEFILES
+	$(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef TARGET_EXAMPLEDIRS
+	$(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR)
+endif
+.PHONY: fpc_clean fpc_cleanall fpc_distclean
+ifdef EXEFILES
+override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
+endif
+ifdef CLEAN_PROGRAMS
+override CLEANEXEFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEEXT), $(CLEAN_PROGRAMS)))
+endif
+ifdef CLEAN_UNITS
+override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
+endif
+ifdef CLEANPPUFILES
+override CLEANPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES)))
+ifdef DEBUGSYMEXT
+override CLEANPPULINKFILES+=$(subst $(PPUEXT),$(DEBUGSYMEXT),$(CLEANPPUFILES))
+endif
+override CLEANPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPUFILES))
+override CLEANPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPULINKFILES)))
+endif
+fpc_clean: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+	-$(DEL) $(CLEANEXEFILES)
+endif
+ifdef CLEANPPUFILES
+	-$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+	-$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+ifdef CLEAN_FILES
+	-$(DEL) $(CLEAN_FILES)
+endif
+ifdef LIB_NAME
+	-$(DEL) $(LIB_NAME) $(LIB_FULLNAME)
+endif
+	-$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+	-$(DEL) *$(ASMEXT) *_ppas$(BATCHEXT)
+fpc_cleanall: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+	-$(DEL) $(CLEANEXEFILES)
+endif
+ifdef COMPILER_UNITTARGETDIR
+ifdef CLEANPPUFILES
+	-$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+	-$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+endif
+ifdef CLEAN_FILES
+	-$(DEL) $(CLEAN_FILES)
+endif
+	-$(DELTREE) units
+	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+ifneq ($(PPUEXT),.ppu)
+	-$(DEL) *.o *.ppu *.a
+endif
+	-$(DELTREE) *$(SMARTEXT)
+	-$(DEL) fpcmade.* Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+	-$(DEL) *_ppas$(BATCHEXT)
+ifdef AOUTEXT
+	-$(DEL) *$(AOUTEXT)
+endif
+ifdef DEBUGSYMEXT
+	-$(DEL) *$(DEBUGSYMEXT)
+endif
+fpc_distclean: cleanall
+.PHONY: fpc_baseinfo
+override INFORULES+=fpc_baseinfo
+fpc_baseinfo:
+	@$(ECHO)
+	@$(ECHO)  == Package info ==
+	@$(ECHO)  Package Name..... $(PACKAGE_NAME)
+	@$(ECHO)  Package Version.. $(PACKAGE_VERSION)
+	@$(ECHO)
+	@$(ECHO)  == Configuration info ==
+	@$(ECHO)
+	@$(ECHO)  FPC.......... $(FPC)
+	@$(ECHO)  FPC Version.. $(FPC_VERSION)
+	@$(ECHO)  Source CPU... $(CPU_SOURCE)
+	@$(ECHO)  Target CPU... $(CPU_TARGET)
+	@$(ECHO)  Source OS.... $(OS_SOURCE)
+	@$(ECHO)  Target OS.... $(OS_TARGET)
+	@$(ECHO)  Full Source.. $(FULL_SOURCE)
+	@$(ECHO)  Full Target.. $(FULL_TARGET)
+	@$(ECHO)  SourceSuffix. $(SOURCESUFFIX)
+	@$(ECHO)  TargetSuffix. $(TARGETSUFFIX)
+	@$(ECHO)
+	@$(ECHO)  == Directory info ==
+	@$(ECHO)
+	@$(ECHO)  Required pkgs... $(REQUIRE_PACKAGES)
+	@$(ECHO)
+	@$(ECHO)  Basedir......... $(BASEDIR)
+	@$(ECHO)  FPCDir.......... $(FPCDIR)
+	@$(ECHO)  CrossBinDir..... $(CROSSBINDIR)
+	@$(ECHO)  UnitsDir........ $(UNITSDIR)
+	@$(ECHO)  PackagesDir..... $(PACKAGESDIR)
+	@$(ECHO)
+	@$(ECHO)  GCC library..... $(GCCLIBDIR)
+	@$(ECHO)  Other library... $(OTHERLIBDIR)
+	@$(ECHO)
+	@$(ECHO)  == Tools info ==
+	@$(ECHO)
+	@$(ECHO)  As........ $(AS)
+	@$(ECHO)  Ld........ $(LD)
+	@$(ECHO)  Ar........ $(AR)
+	@$(ECHO)  Rc........ $(RC)
+	@$(ECHO)
+	@$(ECHO)  Mv........ $(MVPROG)
+	@$(ECHO)  Cp........ $(CPPROG)
+	@$(ECHO)  Rm........ $(RMPROG)
+	@$(ECHO)  GInstall.. $(GINSTALL)
+	@$(ECHO)  Echo...... $(ECHO)
+	@$(ECHO)  Shell..... $(SHELL)
+	@$(ECHO)  Date...... $(DATE)
+	@$(ECHO)  FPCMake... $(FPCMAKE)
+	@$(ECHO)  PPUMove... $(PPUMOVE)
+	@$(ECHO)  Upx....... $(UPXPROG)
+	@$(ECHO)  Zip....... $(ZIPPROG)
+	@$(ECHO)
+	@$(ECHO)  == Object info ==
+	@$(ECHO)
+	@$(ECHO)  Target Loaders........ $(TARGET_LOADERS)
+	@$(ECHO)  Target Units.......... $(TARGET_UNITS)
+	@$(ECHO)  Target Implicit Units. $(TARGET_IMPLICITUNITS)
+	@$(ECHO)  Target Programs....... $(TARGET_PROGRAMS)
+	@$(ECHO)  Target Dirs........... $(TARGET_DIRS)
+	@$(ECHO)  Target Examples....... $(TARGET_EXAMPLES)
+	@$(ECHO)  Target ExampleDirs.... $(TARGET_EXAMPLEDIRS)
+	@$(ECHO)
+	@$(ECHO)  Clean Units......... $(CLEAN_UNITS)
+	@$(ECHO)  Clean Files......... $(CLEAN_FILES)
+	@$(ECHO)
+	@$(ECHO)  Install Units....... $(INSTALL_UNITS)
+	@$(ECHO)  Install Files....... $(INSTALL_FILES)
+	@$(ECHO)
+	@$(ECHO)  == Install info ==
+	@$(ECHO)
+	@$(ECHO)  DateStr.............. $(DATESTR)
+	@$(ECHO)  ZipName.............. $(ZIPNAME)
+	@$(ECHO)  ZipPrefix............ $(ZIPPREFIX)
+	@$(ECHO)  ZipCrossPrefix....... $(ZIPCROSSPREFIX)
+	@$(ECHO)  ZipSuffix............ $(ZIPSUFFIX)
+	@$(ECHO)  FullZipName.......... $(FULLZIPNAME)
+	@$(ECHO)  Install FPC Package.. $(INSTALL_FPCPACKAGE)
+	@$(ECHO)
+	@$(ECHO)  Install base dir..... $(INSTALL_BASEDIR)
+	@$(ECHO)  Install binary dir... $(INSTALL_BINDIR)
+	@$(ECHO)  Install library dir.. $(INSTALL_LIBDIR)
+	@$(ECHO)  Install units dir.... $(INSTALL_UNITDIR)
+	@$(ECHO)  Install source dir... $(INSTALL_SOURCEDIR)
+	@$(ECHO)  Install doc dir...... $(INSTALL_DOCDIR)
+	@$(ECHO)  Install example dir.. $(INSTALL_EXAMPLEDIR)
+	@$(ECHO)  Install data dir..... $(INSTALL_DATADIR)
+	@$(ECHO)
+	@$(ECHO)  Dist destination dir. $(DIST_DESTDIR)
+	@$(ECHO)  Dist zip name........ $(DIST_ZIPNAME)
+	@$(ECHO)
+.PHONY: fpc_info
+fpc_info: $(INFORULES)
+.PHONY: fpc_makefile fpc_makefiles fpc_makefile_sub1 fpc_makefile_sub2 \
+	fpc_makefile_dirs
+fpc_makefile:
+	$(FPCMAKE) -w -T$(OS_TARGET) Makefile.fpc
+fpc_makefile_sub1:
+ifdef TARGET_DIRS
+	$(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_DIRS))
+endif
+ifdef TARGET_EXAMPLEDIRS
+	$(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_EXAMPLEDIRS))
+endif
+fpc_makefile_sub2: $(addsuffix _makefile_dirs,$(TARGET_DIRS) $(TARGET_EXAMPLEDIRS))
+fpc_makefile_dirs: fpc_makefile_sub1 fpc_makefile_sub2
+fpc_makefiles: fpc_makefile fpc_makefile_dirs
+all: fpc_all
+debug: fpc_debug
+smart: fpc_smart
+release: fpc_release
+units: fpc_units
+examples:
+shared: fpc_shared
+install: fpc_install
+sourceinstall: fpc_sourceinstall
+exampleinstall: fpc_exampleinstall
+distinstall:
+zipinstall:
+zipsourceinstall:
+zipexampleinstall:
+zipdistinstall:
+clean: fpc_clean
+distclean: fpc_distclean
+cleanall: fpc_cleanall
+info: fpc_info
+makefiles: fpc_makefiles
+.PHONY: all debug smart release units examples shared install sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall clean distclean cleanall info makefiles
+ifneq ($(wildcard fpcmake.loc),)
+include fpcmake.loc
+endif
+.NOTPARALLEL:

+ 26 - 0
packages/fcl-db/src/sql/Makefile.fpc

@@ -0,0 +1,26 @@
+#
+# Makefile.fpc for SQL FCL db units
+#
+
+[package]
+main=fcl-db
+
+[target]
+units=fpsqltree fpsqlscanner fpsqlparser
+rsts=fpsqltree fpsqlscanner fpsqlparser
+
+[require]
+packages=fcl-base
+
+[compiler]
+options=-S2h
+unitdir=../dbase
+
+[install]
+fpcpackage=y
+
+[default]
+fpcdir=../../../..
+
+[rules]
+.NOTPARALLEL:

+ 3864 - 0
packages/fcl-db/src/sql/fpsqlparser.pas

@@ -0,0 +1,3864 @@
+{
+    This file is part of the Free Component Library
+    Copyright (c) 2010 by the Free Pascal development team
+
+    SQL source syntax parser
+
+    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 fpsqlparser;
+{ $define debugparser}
+{ $define debugexpr}
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpsqlscanner, fpsqltree;
+
+Type
+  TParseTypeFlag = (ptfAllowDomainName,ptfAlterDomain,ptfAllowConstraint,
+                    ptProcedureParam,ptfTableFieldDef,ptfCast,ptfExternalFunction,
+                    ptfExternalFunctionResult);
+  TParseTypeFlags = Set of TParseTypeFlag;
+
+  TExpressionOption = (eoCheckConstraint,eoTableConstraint,eoComputedBy,eoOnlyNull,
+                       eoFieldValue,eoSelectvalue,eoParamValue,eoWhereClause,eoJoin,
+                       eoHaving,eoListValue, eoIF);
+  TExpressionOptions = set of TExpressionOption;
+  TSelectFlag = (sfSingleTon,sfUnion,sfInto);
+  TSelectFlags = Set of TSelectFlag;
+
+  { TSQLParser }
+
+  TSQLParser = Class(TObject)
+  Private
+    FInput : TStream;
+    FScanner : TSQLScanner;
+    FCurrent : TSQLToken;
+    FCurrentString : String;
+    FPrevious : TSQLToken;
+    FFreeScanner : Boolean;
+    FPeekToken: TSQLToken;
+    FPeekTokenString: String;
+    Procedure CheckEOF;
+  protected
+    Procedure UnexpectedToken; overload;
+    Procedure UnexpectedToken(AExpected : TSQLTokens); overload;
+    // All elements must be created with this factory function
+    Function CreateElement(AElementClass : TSQLElementClass; APArent : TSQLElement)  : TSQLElement; virtual;
+    function CreateLiteral(AParent: TSQLElement): TSQLLiteral;
+    Function CreateIdentifier(AParent : TSQLElement; Const AName : TSQLStringType) : TSQLIdentifierName;
+    procedure Expect(aToken: TSQLToken);
+    procedure Expect(aTokens: TSQLTokens);
+    procedure Consume(aToken: TSQLToken);
+    Procedure Error(Msg : String);
+    Procedure Error(Fmt : String; Args : Array of const);
+    // Expression support
+    function ParseExprLevel1(AParent: TSQLElement; EO : TExpressionOptions): TSQLExpression;
+    function ParseExprLevel2(AParent: TSQLElement; EO : TExpressionOptions): TSQLExpression;
+    function ParseExprLevel3(AParent: TSQLElement; EO : TExpressionOptions): TSQLExpression;
+    function ParseExprLevel4(AParent: TSQLElement; EO : TExpressionOptions): TSQLExpression;
+    function ParseExprLevel5(AParent: TSQLElement; EO : TExpressionOptions): TSQLExpression;
+    function ParseExprLevel6(AParent: TSQLElement; EO : TExpressionOptions): TSQLExpression;
+    function ParseExprPrimitive(AParent: TSQLElement; EO : TExpressionOptions): TSQLExpression;
+    function ParseInoperand(AParent: TSQLElement): TSQLExpression;
+    // Lists, primitives
+    function ParseIdentifierList(AParent: TSQLElement; AList: TSQLelementList): integer;
+    function ParseValueList(AParent: TSQLElement; EO : TExpressionOptions): TSQLElementList;
+    function ParseSQLValue(AParent: TSQLElement): TSQLExpression;
+    function ParseCheckConstraint(AParent: TSQLElement; TableConstraint : Boolean = False): TSQLExpression;
+    // Create/Alter statements
+    function ParseAddTableElement(AParent: TSQLElement): TSQLAlterTableAddElementOperation;
+    function ParseAlterTableElement(AParent: TSQLElement): TSQLAlterTableOperation;
+    function ParseDropTableElement(AParent: TSQLElement): TSQLDropTableElementOperation;
+    function ParseFieldConstraint(AParent: TSQLElement): TSQLFieldConstraint;
+    function ParseForeignKeyDefinition(AParent: TSQLElement): TSQLForeignKeyDefinition;
+    Procedure ParseCharTypeDefinition(Out DT: TSQLDataType; Out Len: Integer; Out ACharset : TSQLStringType);
+    procedure ParseBlobDefinition(var ASegmentSize, ABlobType: Integer; Var ACharset : TSQLStringType);
+    function ParseTypeDefinition(AParent: TSQLElement; Flags: TParseTypeFlags): TSQLTypeDefinition;
+    function ParseTableFieldDef(AParent: TSQLElement): TSQLTableFieldDef;
+    function ParseTableConstraint(AParent: TSQLElement): TSQLTableConstraintDef;
+    function ParseCreateDomainStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
+    function ParseCreateExceptionStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
+    function ParseCreateGeneratorStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
+    function ParseCreateRoleStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
+    function ParseCreateIndexStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
+    function ParseCreateProcedureStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
+    function ParseCreateTableStatement(AParent: TSQLElement): TSQLCreateOrAlterStatement;
+    function ParseAlterTableStatement(AParent: TSQLElement): TSQLAlterTableStatement;
+    function ParseCreateViewStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
+    function ParseCreateTriggerStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
+    function ParseSetGeneratorStatement(AParent: TSQLElement) : TSQLSetGeneratorStatement;
+    function ParseCreateDatabaseStatement(AParent: TSQLElement; IsAlter: Boolean ): TSQLCreateDatabaseStatement;
+    function ParseCreateShadowStatement(AParent: TSQLElement; IsAlter: Boolean ): TSQLCreateShadowStatement;
+    function ParseAlterDatabaseStatement(AParent: TSQLElement; IsAlter: Boolean ): TSQLAlterDatabaseStatement;
+    function ParseSecondaryFile(AParent: TSQLElement): TSQLDatabaseFileInfo;
+    function ParseDeclareFunctionStatement(AParent: TSQLElement): TSQLDeclareExternalFunctionStatement;
+    function ParseDeclareStatement(AParent: TSQLElement): TSQLStatement;
+    // GRANT parsing
+    procedure ParseGranteeList(AParent: TSQLElement; List: TSQLElementList; AllowObject, AllowGroup,AllowPublic : Boolean; IsRevoke: Boolean = False);
+    function ParseGrantExecuteStatement(AParent: TSQLElement): TSQLProcedureGrantStatement;
+    function ParseGrantRoleStatement(AParent: TSQLElement): TSQLRoleGrantStatement;
+    function ParseGrantTableStatement(AParent: TSQLElement): TSQLTableGrantStatement;
+    // REVOKE parsing
+    function ParseRevokeExecuteStatement(AParent: TSQLElement): TSQLProcedureRevokeStatement;
+    function ParseRevokeRoleStatement(AParent: TSQLElement): TSQLRoleRevokeStatement;
+    function ParseRevokeTableStatement(AParent: TSQLElement): TSQLTableRevokeStatement;
+    // SELECT parsing
+    function ParseExprAggregate(AParent: TSQLElement; EO: TExpressionOptions): TSQLAggregateFunctionExpression;
+    procedure ParseFromClause(AParent: TSQLSelectStatement; AList: TSQLElementList);
+    procedure ParseGroupBy(AParent: TSQLSelectStatement; AList: TSQLElementList);
+    procedure ParseOrderBy(AParent: TSQLSelectStatement; AList: TSQLElementList);
+    procedure ParseSelectFieldList(AParent: TSQLSelectStatement; AList: TSQLElementList; Singleton : Boolean);
+    function ParseForUpdate(AParent: TSQLSelectStatement): TSQLElementList;
+    function ParseSelectPlan(AParent: TSQLElement): TSQLSelectPlan;
+    function ParseTableRef(AParent: TSQLSelectStatement): TSQLTableReference;
+    procedure ParseIntoList(AParent: TSQLElement; List: TSQLElementList);
+    // EXECUTE parsing
+    function ParseExecuteProcedureStatement(AParent: TSQLElement): TSQLExecuteProcedureStatement;
+    // Stored procedure parsing
+    function ParseAssignStatement(AParent: TSQLElement): TSQLAssignStatement;
+    function ParseExceptionStatement(AParent: TSQLElement): TSQLExceptionStatement;
+    function ParseForStatement(AParent: TSQLElement): TSQLForStatement;
+    function ParseIfStatement(AParent: TSQLElement): TSQLIFStatement;
+    function ParsePostEventStatement(AParent: TSQLElement): TSQLPostEventStatement;
+    procedure ParseProcedureParamList(AParent: TSQLElement; AList: TSQLElementList);
+    procedure ParseCreateProcedureVariableList(AParent: TSQLElement; AList: TSQLElementList);
+    function ParseProcedureStatement(AParent: TSQLElement): TSQLStatement;
+    procedure ParseStatementBlock(AParent: TSQLElement; Statements: TSQLElementList);
+    function ParseWhenStatement(AParent: TSQLElement): TSQLWhenStatement;
+    function ParseWhileStatement(AParent: TSQLElement): TSQLWhileStatement;
+  Public
+    Constructor Create(AInput: TStream);
+    Constructor Create(AScanner : TSQLScanner);
+    Destructor Destroy; override;
+    Function ParseSelectStatement(AParent : TSQLElement; Flags : TSelectFlags = []) : TSQLSelectStatement;
+    Function ParseUpdateStatement(AParent : TSQLElement) : TSQLUpdateStatement;
+    Function ParseInsertStatement(AParent : TSQLElement) : TSQLInsertStatement;
+    Function ParseDeleteStatement(AParent : TSQLElement) : TSQLDeleteStatement;
+    Function ParseCreateStatement(AParent : TSQLElement; IsAlter : Boolean = False) : TSQLCreateOrAlterStatement;
+    Function ParseDropStatement(AParent : TSQLElement) : TSQLDropStatement;
+    Function ParseRollbackStatement(AParent : TSQLElement) : TSQLRollbackStatement;
+    Function ParseCommitStatement(AParent : TSQLElement) : TSQLCommitStatement;
+    Function ParseSetStatement(AParent : TSQLElement) : TSQLStatement;
+    Function ParseConnectStatement(AParent : TSQLElement) : TSQLConnectStatement;
+    Function ParseGrantStatement(AParent: TSQLElement): TSQLGrantStatement;
+    Function ParseRevokeStatement(AParent: TSQLElement): TSQLGrantStatement;
+    Function Parse : TSQLElement;
+    Function ParseScript(AllowPartial : Boolean = False) : TSQLElementList;
+    // Auxiliary stuff
+    Function CurrentToken : TSQLToken;
+    Function CurrentTokenString : String;
+    Function GetNextToken : TSQLToken;
+    Function PeekNextToken : TSQLToken;
+    Function PreviousToken : TSQLToken;
+    Function IsEndOfLine : Boolean;
+    function CurSource: String;
+    Function CurLine : Integer;
+    Function CurPos : Integer;
+  end;
+
+  { ESQLParser }
+
+  ESQLParser = Class(Exception)
+  private
+    FCol: Integer;
+    FFileName: String;
+    FLine: Integer;
+  Public
+    Property Line : Integer Read FLine Write FLine;
+    Property Col : Integer Read FCol Write FCol;
+    Property FileName : String Read FFileName Write FFileName;
+  end;
+
+Function StringToSQLExtractElement(Const S : TSQLStringType; Out Res : TSQLExtractElement) : Boolean;
+
+implementation
+
+uses typinfo;
+
+Resourcestring
+  SerrUnmatchedBrace  = 'Expected ).';
+  SErrCommaOrBraceExpected = 'Expected , or ).';
+  SErrUnexpectedToken = 'Unexpected token: %s';
+  SErrUnexpectedTokenOf = 'Unexpected token: %s, expected one of %s';
+  SErrTokenMismatch   = 'Unexpected token: ''%s'', expected: ''%s''';
+  SErrExpectedDBObject = 'Expected database object type. Got: ''%s''';
+  SErrDomainNotAllowed = 'Domain name not allowed in typ definition.';
+  SErrExpectedChar = 'Expected CHAR or CHARACTER, got "%s"';
+  SERRVaryingNotAllowed = 'VARYING not allowed at this point.';
+  SErrUnknownBooleanOp = 'Unknown boolean operation';
+  SErrUnknownComparison = 'unknown Comparison operation';
+  SErrIntegerExpected = 'Integer expression expected';
+  SErrInvalidUseOfCollate = 'Invalid use of COLLATE';
+  SErrCannotAlterGenerator = 'Alter generator statement unknown';
+  SErrInvalidLiteral = 'Invalid literal: "%s"';
+  SErrNoAggregateAllowed = 'Aggregate function not allowed.';
+  SErrAsteriskOnlyInCount = '* allowed only in COUNT aggregate';
+  SErrUpperOneArgument = 'Only one argument for UPPER allowed';
+  SErrHavingWithoutGroupBy = 'HAVING without GROUP BY clause not allowed';
+  SErrNoAsteriskInSingleTon = '* not allowed in singleton select';
+  SErrUnionFieldCountMatch =  'Field count mismatch in select union : %d <> %d';
+  SErrInvalidExtract = 'Invalid element for extract: %s';
+
+Function StringToSQLExtractElement(Const S : TSQLStringType; Out Res : TSQLExtractElement) : Boolean;
+
+Var
+  I : TSQLExtractElement;
+  SU : TSQLStringTYpe;
+
+begin
+  Result:=False;
+  SU:=Uppercase(S);
+  For I:=Low(TSQLExtractElement) to High(TSQLExtractElement) do
+    If ExtractElementNames[i]=SU then
+      begin
+      Res:=I;
+      Exit(True);
+      end;
+end;
+
+{ TSQLParser }
+
+procedure TSQLParser.Expect(aToken: TSQLToken);
+begin
+  {$ifdef debugparser}  Writeln('Expecting : ',GetEnumName(TypeInfo(TSQLToken),Ord(AToken)), ' As string: ',TokenInfos[AToken]);{$endif debugparser}
+  If (CurrentToken<>aToken) then
+    Error(SerrTokenMismatch,[CurrenttokenString,TokenInfos[aToken]]);
+end;
+
+procedure TSQLParser.Expect(aTokens: TSQLTokens);
+
+begin
+  if not (CurrentToken in aTokens) then
+    UnexpectedToken(aTokens);
+end;
+
+
+procedure TSQLParser.Consume(aToken: TSQLToken);
+begin
+  Expect(aToken);
+  GetNextToken;
+end;
+
+function TSQLParser.CurSource: String;
+begin
+  Result:=FScanner.CurFilename;
+end;
+
+function TSQLParser.CurLine: Integer;
+begin
+  Result:=FScanner.CurRow;
+end;
+
+function TSQLParser.CurPos: Integer;
+begin
+  Result:=FScanner.CurColumn;
+end;
+
+procedure TSQLParser.Error(Msg: String);
+
+Var
+  ErrAt : String;
+  E : ESQLParser;
+
+begin
+  If Assigned(FScanner) then
+    If FScanner.CurFilename<>'' then
+      ErrAt:=Format('Error: file "%s" line %d, pos %d: ',[FScanner.CurFileName,FScanner.CurRow,FScanner.CurColumn])
+    else
+      ErrAt:=Format('Error: line %d, pos %d: ',[FScanner.Currow,FScanner.CurColumn]);
+   E:=ESQLParser.Create(ErrAt+Msg);
+   If Assigned(FScanner) then
+     begin
+     E.Line:=FScanner.CurRow;
+     E.Col:=FScanner.CurColumn;
+     E.FileName:=FScanner.CurFilename;
+     end;
+   Raise E;
+end;
+
+procedure TSQLParser.Error(Fmt: String; Args: array of const);
+begin
+  Error(Format(Fmt,Args));
+end;
+
+function TSQLParser.CreateElement(AElementClass: TSQLElementClass;
+  APArent: TSQLElement): TSQLElement;
+begin
+  Result:=AElementClass.Create(AParent);
+  Result.Source:=CurSource;
+  Result.SourceLine:=CurLine;
+  Result.SourcePos:=CurPos;
+end;
+
+Function TSQLParser.ParseTableRef(AParent : TSQLSelectStatement) : TSQLTableReference;
+Var
+  T : TSQLSimpleTablereference;
+  J  : TSQLJoinTableReference;
+
+begin
+   If (CurrentToken=tsqlBraceOpen) then
+     begin
+     GetNextToken;
+     Result:=ParseTableRef(AParent);
+     Consume(tsqlBraceClose)
+     end
+   else
+     begin
+     Expect(tsqlIdentifier);
+     T:=TSQLSimpleTableReference(CreateElement(TSQLSimpleTableReference,AParent));
+     Result:=T;
+     T.ObjectName:=CreateIdentifier(T,CurrentTokenString);
+     GetNextToken;
+     If CurrentToken=tsqlBraceOpen then
+       begin
+       T.Params:=ParseValueList(AParent,[eoParamValue]);
+       GetNextToken;
+       end;
+     if (CurrentToken=tsqlIdentifier) then
+       begin
+       T.AliasName:=CreateIdentifier(T,CurrentTokenString);
+       GetNextToken;
+       end;
+     end;
+   Repeat
+     If CurrentToken in [tsqlInner,tsqlJoin,tsqlOuter,tsqlLeft,tsqlRight] then
+       begin
+       J:=TSQLJoinTableReference(CreateElement(TSQLJoinTableReference,AParent));
+       J.Left:=Result;
+       Result:=J;
+       Case CurrentToken of
+          tsqlInner : J.JoinType:=jtInner;
+          tsqlJoin  : J.JoinType:=jtNone;
+          tsqlOuter : J.JoinType:=jtOuter;
+          tsqlLeft  : J.JoinType:=jtLeft;
+          tsqlRight : J.JoinType:=jtRight;
+       end;
+       if CurrentToken<>tsqlJoin then
+         GetNextToken;
+       Consume(tsqlJoin);
+       J.Right:=ParseTableRef(AParent);
+       Consume(tsqlOn);
+       J.JoinClause:=ParseExprLevel1(J,[eoJOIN]);
+       end;
+  until Not (CurrentToken in [tsqlInner,tsqlJoin,tsqlOuter,tsqlLeft,tsqlRight]);
+end;
+
+Procedure TSQLParser.ParseFromClause(AParent : TSQLSelectStatement; AList : TSQLElementList);
+
+Var
+  T : TSQLTableReference;
+  Done : Boolean;
+
+begin
+  // On entry, we are on the FROM keyword.
+  Consume(tsqlFrom);
+  Repeat
+    T:=ParseTableRef(AParent);
+    AList.Add(T);
+    Done:=(CurrentToken<>tsqlComma);
+    If not Done then
+      GetNextToken;
+  until Done;
+end;
+
+Procedure TSQLParser.ParseSelectFieldList(AParent : TSQLSelectStatement; AList : TSQLElementList; Singleton : Boolean);
+Var
+  F : TSQLSelectField;
+  B : Boolean;
+
+begin
+  // On entry, we're on the token preceding the field list.
+  B:=True;
+  Repeat
+    GetNextToken;
+    If B then
+      begin
+      if (CurrentToken=tsqlDistinct) then
+        begin
+        AParent.Distinct:=True;
+        GetNextToken;
+        end
+      else if (CurrentToken=tsqlAll) then
+        begin
+        AParent.All:=True;
+        GetNextToken;
+        end;
+      B:=False;
+      end;
+    If (CurrentToken=tsqlMul) then
+      begin
+      If Singleton then
+        Error(SErrNoAsteriskInSingleTon);
+      AList.Add(CreateElement(TSQLSelectAsterisk,AParent));
+      GetNextToken;
+      end
+    else
+      begin
+      F:=TSQLSelectField(CreateElement(TSQLSelectField,AParent));
+      AList.Add(F);
+      F.Expression:=ParseExprLevel1(AParent,[eoSelectvalue]);
+      If CurrentToken in [tsqlAs,Tsqlidentifier] then
+        begin
+        If currentToken=tsqlAs then
+          GetNextToken;
+        Expect(tsqlIdentifier);
+        F.AliasName:=CreateIdentifier(F,CurrentTokenString);
+        GetNextToken;
+        end;
+      end;
+    Expect([tsqlComma,tsqlFrom]);
+  until (CurrentToken=tsqlFROM);
+end;
+
+Procedure TSQLParser.ParseGroupBy(AParent : TSQLSelectStatement; AList : TSQLElementList);
+
+Var
+  N : TSQLStringType;
+
+begin
+  // On entry we're on the GROUP token.
+  Consume(tsqlGroup);
+  Expect(tsqlBy);
+  Repeat
+    GetNextToken;
+    Expect(tsqlIdentifier);
+    N:=CurrentTokenString;
+    GetNextToken;
+    If (CurrentToken=tsqlDot) then
+      begin
+      GetNextToken;
+      Expect(tsqlIdentifier);
+      N:=N+'.'+CurrentTokenString;
+      GetNextToken;
+      end;
+    AList.Add(CreateIdentifier(AParent,N));
+
+  until (CurrentToken<>tsqlComma);
+end;
+
+Function TSQLParser.ParseForUpdate(AParent : TSQLSelectStatement) : TSQLElementList;
+
+begin
+  // On entry we're on the FOR token.
+  Consume(tsqlFor);
+  Expect(tsqlUpdate);
+  Result:=TSQLElementList.Create(True);
+  try
+    Repeat
+      GetNextToken;
+      Expect(tsqlIdentifier);
+      Result.Add(CreateIdentifier(AParent,CurrentTokenString));
+    until (CurrentToken<>tsqlComma);
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+Procedure TSQLParser.ParseOrderBy(AParent : TSQLSelectStatement; AList : TSQLElementList);
+
+Var
+  O : TSQLOrderByElement;
+  F : TSQLElement;
+
+begin
+  // On entry we're on the ORDER token.
+  Consume(tsqlOrder);
+  Expect(tsqlBy);
+  Repeat
+    GetNextToken;
+    Case CurrentToken of
+      tsqlIdentifier :
+        F:=CreateIdentifier(AParent,CurrentTokenString);
+      tsqlIntegerNumber :
+        begin
+        F:=TSQLIntegerLiteral(CreateElement(TSQLIntegerLiteral,AParent));
+        TSQLIntegerLiteral(F).Value:=StrToInt(CurrentTokenString);
+        end
+    else
+      UnexpectedToken([tsqlIdentifier,tsqlIntegerNumber]);
+    end;
+    try
+      O:=TSQLOrderByElement(CreateElement(TSQLOrderByElement,APArent));
+      AList.Add(O);
+      O.Field:=F;
+      F:=Nil;
+    except
+      FreeAndNil(F);
+      Raise;
+    end;
+    GetNextToken;
+    If (CurrentToken=tsqlCollate) then
+       begin
+       GetNextToken;
+       Expect(tsqlidentifier);
+       O.Collation:=CreateIdentifier(O,CurrentTokenString);
+       GetNextToken;
+       end;
+    If (CurrentToken in [tsqlDesc,tsqlAsc,tsqlDescending,tsqlAscending]) then
+      begin
+      If (CurrentToken in [tsqlDesc,tsqlDescending]) then
+        O.OrderBy:=obDescending
+      else
+        O.OrderBy:=obAscending;
+      GetNextToken;
+      end;
+  until (CurrentToken<>tsqlComma);
+end;
+
+Function TSQLParser.ParseSelectPlan(AParent : TSQLElement) : TSQLSelectPlan;
+
+Var
+  E : TSQLSelectPlanExpr;
+  I : TSQLSelectPlanItem;
+  L : TSQLElementList;
+  N : TSQLStringType;
+
+begin
+  Result:=Nil;
+  try
+    Case CurrentToken of
+    tsqlIdentifier :
+      begin
+      If Not (AParent is TSQLSelectPlanExpr) then
+        UnexpectedToken([tsqlJoin,tsqlmerge,tsqlSort]);
+      N:=CurrentTokenString;
+      Case GetNextToken of
+      tsqlNatural:
+        begin
+        I:=TSQLSelectNaturalPlan(CreateElement(TSQLSelectNaturalPlan,AParent));
+        Result:=I;
+        end;
+      tsqlIndex :
+        begin
+        I:=TSQLSelectIndexedPlan(CreateElement(TSQLSelectIndexedPlan,AParent));
+        Result:=I;
+        L:=TSQLSelectIndexedPlan(I).Indexes;
+        GetNextToken;
+        expect(tsqlBraceOpen);
+        Repeat
+          GetNextToken;
+          Expect(tsqlidentifier);
+          L.Add(CreateIdentifier(Result,CurrentTokenString));
+          GetNextToken;
+          Expect([tsqlComma,tsqlBraceClose]);
+        until (CurrentToken=tsqlBraceClose);
+        end;
+       tsqlOrder:
+         begin
+         GetNextToken;
+         expect(tsqlIdentifier);
+         I:=TSQLSelectOrderedPlan(CreateElement(TSQLSelectOrderedPlan,AParent));
+         Result:=I;
+         TSQLSelectOrderedPlan(I).OrderIndex:=CreateIdentifier(I,CurrentTokenstring);
+         end;
+      else
+        Unexpectedtoken([tsqlNatural,tsqlIndex,tsqlOrder]);
+      end;
+      I.TableName:=CreateIdentifier(I,N);
+      end;
+    tsqlJoin,
+    tsqlmerge,
+    tsqlSort,
+    tsqlBraceOpen:
+      begin
+      E:=TSQLSelectPlanExpr(CreateElement(TSQLSelectPlanExpr,AParent));
+      Result:=E;
+      Case CurrentToken of
+        tsqlJoin,
+        tsqlBraceOpen : E.Jointype:=pjtJoin;
+        tsqlSort  : E.JoinType:=pjtSort;
+        tsqlMerge : E.JoinType:=pjtMerge;
+      end;
+      If (CurrentToken<>tsqlBraceOpen) then
+        GetNextToken;
+      expect(tsqlBraceOpen);
+      repeat
+        GetNextToken;
+        E.Items.Add(ParseSelectPlan(E));
+        Expect([tsqlComma,tsqlBraceClose]);
+      until (CurrentToken=tsqlBraceClose);
+      end;
+    else
+      UnexpectedToken([tsqlIdentifier,tsqlJoin,tsqlmerge,tsqlSort]);
+    end;
+    GetNextToken;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseSelectStatement(AParent: TSQLElement; Flags : TSelectFlags = []): TSQLSelectStatement;
+
+begin
+  // On entry, we're on the SELECT keyword
+  Expect(tsqlSelect);
+  Result:=TSQLSelectStatement(CreateElement(TSQLSelectStatement,AParent));
+  try
+    If (PeekNextToken=tsqlTransaction) then
+      begin
+      Consume(tsqlSelect);
+      GetNextToken;
+      Expect(TSQLIdentifier);
+      Result.TransactionName:=CreateIdentifier(Result,CurrentTokenString);
+      end;
+    ParseSelectFieldList(Result,Result.Fields,sfSingleton in Flags);
+    // On return, we are on the FROM keyword.
+    ParseFromClause(Result,Result.Tables);
+    If CurrentToken=tsqlWhere then
+      begin
+      GetNextToken;
+      Result.Where:=ParseExprLevel1(Result,[eoWhereClause]);
+      end;
+    if CurrentToken=tsqlGroup then
+      ParseGroupBy(Result,Result.GroupBy);
+    if CurrentToken=tsqlHaving then
+      begin
+      If (Result.GroupBy.Count=0) then
+        Error(SErrHavingWithoutGroupBy);
+      GetNextToken;
+      Result.Having:=ParseExprLevel1(Result,[eoHaving]);
+      end;
+    if (CurrentToken=tsqlUnion) then
+      begin
+      GetNextToken;
+      If (CurrentToken=tsqlAll) then
+        begin
+        Result.UnionAll:=True;
+        GetNextToken;
+        end;
+      Result.Union:=ParseSelectStatement(Result,Flags + [sfunion]);
+      If (Result.Fields.count<>Result.Union.Fields.Count) then
+        Error(SErrUnionFieldCountMatch,[Result.Fields.Count,Result.Union.Fields.Count])
+      end;
+    if (CurrentToken=tsqlPlan) then
+      begin
+      GetNextToken;
+      Result.Plan:=ParseSelectPlan(Result);
+      end;
+    if not (sfUnion in Flags) then
+      begin
+      if (CurrentToken=tsqlOrder) then
+        ParseOrderBy(Result,Result.OrderBy);
+      if (CurrentToken=tsqlFOR) then
+        Result.ForUpdate:=ParseForUpdate(Result);
+      end;
+    if (sfInto in Flags) then
+       begin
+       if (CurrentToken=tsqlInto) then
+         begin
+         Result.Into:=TSQLElementList.Create(true);
+         ParseIntoList(Result,Result.Into);
+         end;
+       end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseUpdateStatement(AParent: TSQLElement
+  ): TSQLUpdateStatement;
+
+Var
+  P : TSQLUpdatePair;
+  N : String;
+begin
+  // On entry, we're on the UPDATE keyword
+  Consume(tsqlUpdate);
+  Expect(tsqlidentifier);
+  Result:=TSQLUpdateStatement(CreateElement(TSQLUpdateStatement,AParent));
+  try
+    Result.TableName:=CreateIdentifier(Result,CurrentTokenString);
+    GetNextToken;
+    Expect(tsqlSet);
+    Repeat
+      GetNextToken;
+      Expect(tsqlIdentifier);
+      P:=TSQLUpdatePair(CreateElement(TSQLUpdatePair,Result));
+      Result.Values.Add(P);
+      N:=CurrentTokenString;
+      GetNextToken;
+      If (CurrentToken=tsqlDot) then
+        begin
+        GetNextToken;
+        Expect(TSQLIdentifier);
+        N:=N+'.'+CurrentTokenString;
+        GetNextToken;
+        end;
+      Consume(tsqlEq);
+      P.FieldName:=CreateIdentifier(P,N);
+      P.Value:=ParseExprLevel1(P,[eoFieldValue]);
+    until (CurrentToken<>tsqlComma);
+    If (CurrentToken=tsqlWhere) then
+      begin
+      GetNextToken;
+      Result.WhereClause:=ParseExprLevel1(P,[eoWhereClause]);
+      end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseInsertStatement(AParent: TSQLElement): TSQLInsertStatement;
+
+begin
+  // On entry, we're on the INSERT statement
+  Consume(tsqlInsert);
+  Consume(tsqlInto);
+  Expect(tsqlidentifier);
+  Result:=TSQLInsertStatement(CreateElement(TSQLinsertStatement,AParent));
+  try
+    Result.TableName:=CreateIdentifier(Result,CurrentTokenString);
+    GetNextToken;
+    If CurrentToken=tsqlBraceOpen then
+      begin
+      Result.Fields:=TSQLElementList.Create(True);
+      Repeat
+        GetNextToken;
+        Expect(tsqlIdentifier);
+        Result.Fields.Add(CreateIdentifier(Result,CurrentTokenString));
+        GetNextToken;
+        Expect([tsqlBraceClose,tsqlComma]);
+      Until (CurrentToken=tsqlBraceClose);
+      GetNextToken;
+      end;
+    Case CurrentToken of
+      tsqlSelect :
+        Result.Select:=ParseSelectStatement(Result);
+      tsqlValues :
+        begin
+        GetNextToken;
+        Result.Values:=ParsevalueList(Result,[eoFieldValue]);
+        GetNextToken; // consume )
+        end;
+    else
+      UnexpectedToken([tsqlselect,tsqlValues]);
+    end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseDeleteStatement(AParent: TSQLElement
+  ): TSQLDeleteStatement;
+begin
+  // On entry, we're on the DELETE token.
+  consume(tsqlDelete);
+  consume(tsqlFrom);
+  Expect(tsqlidentifier);
+  Result:=TSQLDeleteStatement(CreateElement(TSQLDeleteStatement,AParent));
+  try
+    Result.TableName:=CreateIdentifier(Result,CurrentTokenString);
+    GetNextToken;
+    if CurrentToken=tsqlIdentifier then
+      begin
+      Result.AliasName:=CreateIdentifier(Result,CurrentTokenString);
+      GetNextToken;
+      end;
+    if CurrentToken=tsqlwhere then
+      begin
+      Consume(tsqlWhere);
+      Result.WhereClause:=ParseExprLevel1(Result,[eoWhereClause]);
+      end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParseTableFieldDef(AParent : TSQLElement) : TSQLTableFieldDef;
+begin
+  // on entry, we're on the field name
+  Result:=TSQLTableFieldDef(CreateElement(TSQLTableFieldDef,AParent));
+  try
+    Result.FieldName:=CreateIdentifier(Result,CurrentTokenString);
+    if PeekNextToken = tsqlComputed then
+      begin
+      GetNextToken;
+      Consume(tsqlComputed);
+      If CurrentToken=tsqlBy then
+        GetNextToken;
+      Consume(tsqlBraceopen);
+      Result.ComputedBy:=ParseExprLevel1(Result,[eoComputedBy]);
+      Consume(tsqlBraceClose);
+      end
+    else
+      Result.FieldType:=ParseTypeDefinition(Result,[ptfAllowDomainName,ptfAllowConstraint,ptfTableFieldDef]);
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseTableConstraint(AParent: TSQLElement
+  ): TSQLTableConstraintDef;
+
+  Procedure ParseFieldList(R : TSQLTableFieldsConstraintDef);
+
+  begin
+    GetNextToken;
+    Consume(tsqlBraceOpen);
+    ParseIdentifierList(AParent,R.FieldList);
+//    Consume(tsqlBraceClose);
+  end;
+
+Var
+  N : TSQLStringType;
+  K : TSQLTableForeignKeyConstraintDef;
+
+begin
+  If CurrentToken=tsqlConstraint then
+    begin
+    GetNextToken;
+    Expect(tsqlIdentifier);
+    N:=CurrentTokenString;
+    GetNextToken
+    end;
+  Result:=Nil;
+  try
+    Case CurrentToken of
+    tsqlUnique :
+      begin
+      Result:=TSQLTableUniqueConstraintDef(CreateElement(TSQLTableUniqueConstraintDef,AParent));
+      ParseFieldList(TSQLTableFieldsConstraintDef(Result));
+      end;
+    tsqlPrimary :
+      begin
+      GetNextToken;
+      Expect(tsqlKey);
+      Result:=TSQLTablePrimaryKeyConstraintDef(CreateElement(TSQLTablePrimaryKeyConstraintDef,AParent));
+      ParseFieldList(TSQLTableFieldsConstraintDef(Result));
+      end;
+    tsqlForeign :
+      begin
+      GetNextToken;
+      Expect(tsqlKey);
+      K:=TSQLTableForeignKeyConstraintDef(CreateElement(TSQLTableForeignKeyConstraintDef,AParent));
+      Result:=K;
+      ParseFieldList(TSQLTableFieldsConstraintDef(Result));
+      Expect(tsqlReferences);
+      K.Definition:=ParseForeignKeyDefinition(K);
+      end;
+    tsqlCheck:
+      begin
+      Result:=TSQLTableCheckConstraintDef(CreateElement(TSQLTableCheckConstraintDef,AParent));
+      TSQLTableCheckConstraintDef(Result).Check:=ParseCheckConstraint(Result,True);
+      end
+    else
+      UnexpectedToken([tsqlUnique,tsqlPrimary,tsqlForeign,tsqlCheck]);
+    end;
+    If (N<>'') then
+      Result.ConstraintName:=CreateIdentifier(Result,N);
+  //  GetNextToken;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseCreateTableStatement(AParent: TSQLElement): TSQLCreateOrAlterStatement;
+
+Var
+  C : TSQLCreateTableStatement;
+  HC : Boolean;
+
+begin
+  // On enter, we're on the TABLE token.
+  Consume(tsqlTable);
+  C:=TSQLCreateTableStatement(CreateElement(TSQLCreateTableStatement,AParent));
+  try
+    Expect(tsqlIdentifier);
+    C.ObjectName:=CreateIdentifier(C,CurrentTokenstring);
+    GetNextToken;
+    If (CurrentToken=tsqlExternal) then
+      begin
+      GetNextToken;
+      If (CurrentToken=tsqlFile) then
+        GetNextToken;
+      Expect(tsqlString);
+      C.ExternalFileName:=CreateLiteral(C) as TSQLStringLiteral;
+      GetNextToken;
+      end;
+    Expect(tsqlBraceOpen);
+    HC:=False;
+    Repeat
+      GetNextToken;
+      Case CurrentToken of
+        tsqlIdentifier :
+          begin
+          if HC then
+            UnexpectedToken;
+          C.FieldDefs.Add(ParseTableFieldDef(C));
+          end;
+        tsqlCheck,
+        tsqlConstraint,
+        tsqlForeign,
+        tsqlPrimary,
+        tsqlUnique:
+          begin
+          C.Constraints.Add(ParseTableConstraint(C));
+          HC:=true;
+          end
+      else
+         UnexpectedToken([tsqlIdentifier,tsqlCheck, tsqlConstraint,tsqlForeign,tsqlPrimary,tsqlUnique]);
+      end;
+      expect([tsqlBraceClose,tsqlComma]);
+    until (CurrentToken=tsqlBraceClose);
+    GetNextToken;
+    Result:=C;
+  except
+    FreeandNil(C);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseDropTableElement(AParent : TSQLElement) : TSQLDropTableElementOperation;
+
+Var
+  C : Boolean;
+begin
+  // On entry, we are on DROP token
+  C:=(GetNextToken=tsqlConstraint);
+  If C then
+    GetNextToken;
+  Expect(tsqlidentifier);
+  If C then
+    Result:=TSQLDropTableConstraintOperation(CreateElement(TSQLDropTableConstraintOperation,AParent))
+  else
+    Result:=TSQLDropTableFieldOperation(CreateElement(TSQLDropTableFieldOperation,AParent));
+  Result.ObjectName:=CreateIdentifier(Result,CurrentTokenString);
+  GetNextToken;
+end;
+
+function TSQLParser.ParseAddTableElement(AParent : TSQLElement) : TSQLAlterTableAddElementOperation;
+
+begin
+  Result:=Nil;
+  try
+    Case GetNextToken of
+      tsqlIdentifier :
+        begin
+        Result:=TSQLAlterTableAddElementOperation(CreateElement(TSQLAlterTableAddFieldOPeration,AParent));
+        Result.Element:=ParseTableFieldDef(Result);
+        end;
+      tsqlCheck,
+      tsqlConstraint,
+      tsqlForeign,
+      tsqlPrimary,
+      tsqlUnique:
+        begin
+        Result:=TSQLAlterTableAddElementOperation(CreateElement(TSQLAlterTableAddConstraintOperation,AParent));
+        Result.Element:=ParseTableConstraint(Result);
+        end
+    else
+      UnexpectedToken([tsqlIdentifier,tsqlCheck, tsqlConstraint,tsqlForeign,tsqlPrimary,tsqlUnique]);
+    end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseAlterTableElement(AParent : TSQLElement) : TSQLAlterTableOperation;
+
+Var
+  N : TSQLStringType;
+
+begin
+  Result:=Nil;
+  If GetnextToken=tsqlColumn then
+    GetNextToken;
+  expect(tsqlidentifier);
+  N:=CurrentTokenString;
+  try
+    Case GetNextToken of
+      tsqlTo :
+        begin
+        GetNextToken;
+        Result:=TSQLAlterTableOperation(CreateElement(TSQLAlterTableFieldNameOperation,AParent));
+        TSQLAlterTableFieldNameOperation(Result).NewName:=CreateIdentifier(Result,CurrentTokenString);
+        GetNextToken;
+        end;
+      tsqltype:
+        begin
+        Result:=TSQLAlterTableOperation(CreateElement(TSQLAlterTableFieldTypeOperation,AParent));
+        TSQLAlterTableFieldTypeOperation(Result).NewType:= ParseTypeDefinition(Result,[ptfAllowDomainName,ptfAllowConstraint,ptfTableFieldDef]);
+        end;
+      tsqlPosition:
+        begin
+        GetNextToken;
+        Expect(tsqlIntegerNumber);
+        Result:=TSQLAlterTableOperation(CreateElement(TSQLAlterTableFieldPositionOperation,AParent));
+        TSQLAlterTableFieldPositionOperation(Result).NewPosition:=StrToInt(CurrentTokenString);
+        GetNextToken;
+        end
+    else
+      UnexpectedToken([tsqlTo,tsqltype,tsqlPosition]);
+    end;
+    Result.ObjectName:=CreateIdentifier(Result,N);
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseAlterTableStatement(AParent: TSQLElement): TSQLAlterTableStatement;
+
+begin
+  // On enter, we're on the TABLE token.
+  Consume(tsqlTable);
+  Result:=TSQLAlterTableStatement(CreateElement(TSQLAlterTableStatement,AParent));
+  try
+    Expect(tsqlIdentifier);
+    Result.ObjectName:=CreateIdentifier(Result,CurrentTokenstring);
+    Repeat
+      GetNextToken;
+      Case CurrentToken of
+        tsqlAdd:
+          begin
+          Result.Operations.Add(ParseAddTableElement(Result));
+          end;
+        tsqlAlter:
+          begin
+          Result.Operations.Add(ParseAlterTableElement(Result));
+          end;
+        tsqlDrop :
+          begin
+          Result.Operations.add(ParseDropTableElement(Result));
+          end;
+      else
+         UnexpectedToken([tsqlAdd,tsqlAlter,tsqlDrop]);
+      end;
+    until (CurrentToken<>tsqlComma);
+  except
+    FreeandNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseCreateIndexStatement(AParent: TSQLElement; IsAlter: Boolean
+  ): TSQLCreateOrAlterStatement;
+
+Var
+  O : TIndexOptions;
+  C : TSQLCreateIndexStatement;
+  A : TSQLAlterIndexStatement;
+begin
+  O:=[];
+  // On enter, we're on the UNIQUE, ASCENDING, DESCENDING or INDEX token
+  If IsAlter then
+    begin
+    expect(tsqlIndex);
+    Consume(tsqlIndex);
+    A:=TSQLAlterIndexStatement(CreateElement(TSQLAlterIndexStatement,APArent));
+    try
+      Expect(tsqlIdentifier);
+      A.ObjectName:=CreateIdentifier(A,CurrentTokenString);
+      GetNextToken;
+      Expect([tsqlActive,tsqlInactive]);
+      A.Inactive:=CurrentToken=tsqlInactive;
+      GetNextToken; // Token after ) or (in)Active
+      Result:=A;
+    except
+      FReeAndNil(A);
+      Raise;
+    end;
+    end
+  else
+    begin
+    C:=TSQLCreateIndexStatement(CreateElement(TSQLCreateIndexStatement,APArent));
+    try
+      If (CurrentToken=tsqlUnique) then
+        begin
+        GetNextToken;
+        Include(O,ioUnique);
+        end;
+      If (CurrentToken=tsqlAscending) then
+        begin
+        GetNextToken;
+        Include(O,ioAscending);
+        end
+      else If (CurrentToken=tsqlDescending) then
+        begin
+        GetNextToken;
+        Include(O,ioDescending);
+        end;
+      C.Options:=O;
+      Consume(tsqlIndex);
+      Expect(tsqlIdentifier);
+      C.ObjectName:=CreateIdentifier(C,CurrentTokenString);
+      GetNextToken;
+      Consume(tsqlOn);
+      Expect(tsqlIdentifier);
+      C.TableName:=Createidentifier(C,CurrentTokenString); // name of table
+      GetNextToken;
+      Consume(tsqlBraceOpen);
+      ParseIdentifierList(C,C.FieldNames);
+      Result:=C;
+    except
+      FreeAndNil(C);
+      Raise;
+    end;
+    end;
+end;
+
+function TSQLParser.ParseCreateViewStatement(AParent: TSQLElement; IsAlter: Boolean
+  ): TSQLCreateOrAlterStatement;
+
+Var
+  V : TSQLCreateViewStatement;
+
+begin
+  // on entry, we're on the VIEW token.
+  If IsAlter then
+    UnexpectedToken;
+  Result:=Nil;
+  Consume(tsqlView);
+  Expect(tsqlIdentifier);
+  V:=TSQLCreateViewStatement(CreateElement(TSQLCreateViewStatement,APArent));
+  Result:=V;
+  try
+    V.ObjectName:=CreateIdentifier(V,CurrentTokenString);
+    GetNextToken;
+    If (CurrentToken=tsqlBraceOpen) then
+      begin
+      GetNextToken;
+      ParseIdentifierList(Result,V.Fields);
+      end;
+    Consume(tsqlAs);
+    V.Select:=ParseSelectStatement(V,[]);
+    If (CurrentToken=tsqlWith) then
+      begin
+      GetNextToken;
+      Consume(tsqlCheck);
+      Consume(tsqlOption);
+      V.WithCheckOption:=True;
+      end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+Procedure TSQLParser.ParseProcedureParamList(AParent: TSQLElement; AList : TSQLElementList);
+
+Var
+  P : TSQLProcedureParamDef;
+
+begin
+  // On Entry, we're on the ( token
+  Repeat
+    GetNextToken;
+    Expect(tsqlIdentifier);
+    P:=TSQLProcedureParamDef(CreateElement(TSQLProcedureParamDef,AParent));
+    try
+      Alist.Add(P);
+    except
+      P.free;
+      Raise;
+    end;
+    P.ParamName:=CreateIdentifier(P,CurrentTokenString);
+    // Typedefinition will go to next token
+    P.ParamType:=ParseTypeDefinition(P,[ptProcedureParam]);
+  Until (CurrentToken<>tsqlComma);
+  Consume(tsqlBraceClose);
+end;
+
+Procedure TSQLParser.ParseCreateProcedureVariableList(AParent: TSQLElement; AList : TSQLElementList);
+
+Var
+  P : TSQLProcedureParamDef;
+
+begin
+  // On Entry, we're on the DECLARE token
+  Repeat
+    Consume(tsqlDeclare);
+    Consume(tsqlVariable);
+    Expect(tsqlIdentifier);
+    P:=TSQLProcedureParamDef(CreateElement(TSQLProcedureParamDef,AParent));
+    Try
+      AList.Add(P);
+    except
+      P.Free;
+      Raise;
+    end;
+    P.ParamName:=CreateIdentifier(P,CurrentTokenString);
+    // Typedefinition will go to next token
+    P.ParamType:=ParseTypeDefinition(P,[ptProcedureParam]);
+    Consume(tsqlSemicolon);
+  Until (CurrentToken<>tsqlDeclare);
+end;
+
+Function TSQLParser.ParseIfStatement(AParent : TSQLElement) : TSQLIFStatement;
+
+Var
+  Pt : TSQLToken;
+
+begin
+  // On Entry, we're on the IF token
+  Consume(tsqlIf);
+  Consume(tsqlBraceOpen);
+  Result:=TSQLIFStatement(CreateElement(TSQLIFStatement,AParent));
+  try
+    Result.Condition:=ParseExprLevel1(AParent,[eoIF]);
+    Consume(tsqlBraceClose);
+    Consume(tsqlThen);
+    Result.TrueBranch:=ParseProcedureStatement(Result);
+    If (CurrentToken=tsqlSemicolon) and (PeekNextToken=tsqlElse) then
+      begin
+      PT:=CurrentToken;
+      GetNextToken;
+      end
+    else if (CurrentToken=tsqlElse) then
+      if not (PreviousToken=tsqlEnd) then
+        UnexpectedToken;
+    If CurrentToken=tsqlElse then
+      begin
+      GetNextToken;
+      Result.FalseBranch:=ParseProcedureStatement(Result);
+      end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+
+procedure TSQLParser.ParseIntoList(AParent : TSQLElement; List : TSQLElementList);
+
+begin
+  // On Entry, we're on the INTO token
+  Repeat
+    GetNextToken;
+    If (currentToken=tsqlColon) then
+      Consume(tsqlColon);
+    Expect(tsqlIdentifier);
+    List.Add(CreateIdentifier(AParent,CurrentTokenString));
+    GetNextToken;
+  Until (CurrentToken<>tsqlComma);
+end;
+
+Function TSQLParser.ParseForStatement(AParent : TSQLElement) : TSQLForStatement;
+
+begin
+  // On Entry, we're on the FOR token
+  Consume(tsqlFor);
+  Expect(tsqlSelect);
+  Result:=TSQLForStatement(CreateElement(TSQLForStatement,AParent));
+  try
+    Result.Select:=ParseSelectStatement(Result,[]);
+    Expect(tsqlInto);
+    ParseIntoList(Result,Result.FieldList);
+    Consume(tsqlDo);
+    Result.Statement:=ParseProcedureStatement(Result);
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParseExceptionStatement(AParent : TSQLElement) : TSQLExceptionStatement;
+
+begin
+  // On Entry, we're on the EXCEPTION token
+  Consume(tsqlException);
+  Expect(tsqlIdentifier);
+  Result:=TSQLExceptionStatement(CreateElement(TSQLExceptionStatement,AParent));
+  try
+    Result.ExceptionName:=CreateIdentifier(Result,CurrentTokenString);
+    GetNextToken;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParseAssignStatement(AParent : TSQLElement) : TSQLAssignStatement;
+
+Var
+  N  : TSQLStringType;
+
+begin
+  // On entry, we're on the identifier token;
+  expect(tsqlIdentifier);
+  Result:=TSQLAssignStatement(CreateElement(TSQLAssignStatement,AParent));
+  try
+    N:=CurrentTokenString;
+    GetNextToken;
+    If (CurrentToken=tsqlDot) and (Uppercase(N)='NEW') then
+      begin
+      GetNextToken;
+      Expect(tsqlIdentifier);
+      N:=N+'.'+CurrentTokenString;
+      GetNextToken;
+      end;
+    Result.Variable:=CreateIdentifier(Result,N);
+    Consume(tsqlEq);
+    Result.Expression:=ParseExprLevel1(Result,[]);
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParsePostEventStatement(AParent : TSQLElement) : TSQLPostEventStatement;
+
+begin
+  // On Entry, we're on the POST_EVENT token
+  Consume(tsqlPostEvent);
+  Result:=TSQLPostEventStatement(CreateElement(TSQLPostEventStatement,AParent));
+  try
+    Case CurrentToken of
+      tsqlIdentifier : Result.ColName:=CreateIdentifier(Result,CurrentTokenString);
+      tsqlString : Result.EventName:=CurrentTokenString;
+    else
+      UnexpectedToken([tsqlIdentifier,tsqlString]);
+    end;
+    GetNextToken;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParseWhileStatement(AParent : TSQLElement) : TSQLWhileStatement;
+
+begin
+  // On entry, we're on the WHILE Token
+  Consume(tsqlWhile);
+  Consume(tsqlBraceOpen);
+  Result:=TSQLWhileStatement(CreateElement(TSQLWhileStatement,AParent));
+  try
+    Result.Condition:=ParseExprLevel1(Result,[eoIF]);
+    Consume(tsqlBraceClose);
+    Consume(tsqlDO);
+    Result.Statement:=ParseProcedureStatement(Result);
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParseWhenStatement(AParent : TSQLElement) : TSQLWhenStatement;
+
+Var
+  E : TSQLWhenException;
+  S : TSQLWhenSQLError;
+  G : TSQLWhenGDSError;
+
+begin
+  Consume(tsqlWhen);
+  Result:=TSQLWhenStatement(CreateElement(TSQLWhenStatement,AParent));
+  try
+    if (CurrentToken=tsqlAny) then
+      begin
+      Result.AnyError:=True;
+      GetNextToken
+      end
+    else
+      Repeat
+        if (Result.Errors.Count>0) then
+          GetNextToken;
+        Case CurrentToken of
+          tsqlException:
+            begin
+            GetNextToken;
+            Expect(tsqlIdentifier);
+            E:=TSQLWhenException(CreateElement(TSQLWhenException,AParent));
+            E.ExceptionName:=CreateIdentifier(E,CurrentTokenString);
+            Result.Errors.Add(E);
+            end;
+          tsqlSQLCode:
+            begin
+            GetNextToken;
+            Expect(tsqlIntegerNumber);
+            S:=TSQLWhenSQLError(CreateElement(TSQLWhenSQLError,AParent));
+            S.ErrorCode:=StrToInt(CurrentTokenString);
+            Result.Errors.Add(S);
+            end;
+          tsqlGDSCODE:
+            begin
+            GetNextToken;
+            Expect(tsqlIntegerNumber);
+            G:=TSQLWhenGDSError(CreateElement(TSQLWhenGDSError,AParent));
+            G.GDSErrorNumber:=StrToInt(CurrentTokenString);
+            Result.Errors.Add(G);
+            end;
+        else
+          UnexpectedToken([tsqlException,tsqlSQLCode,tsqlGDSCODE]);
+        end;
+        GetNextToken;
+      until (CurrentToken<>tsqlComma);
+    consume(tsqlDo);
+    Result.Statement:=ParseProcedureStatement(Result);
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParseProcedureStatement(AParent : TSQLElement) : TSQLStatement;
+
+begin
+  Result:=Nil;
+  Case CurrentToken of
+    tsqlBegin :
+      begin
+      Result:=TSQLStatementBlock(CreateElement(TSQLStatementBlock,AParent));
+      ParseStatementBlock(Result,TSQLStatementBlock(Result).Statements);
+      end;
+    tsqlIf         : Result:=ParseIfStatement(AParent);
+    tsqlFor        : Result:=ParseForStatement(AParent);
+    tsqlException  : Result:=ParseExceptionStatement(AParent);
+    tsqlIdentifier : Result:=ParseAssignStatement(AParent);
+    tsqlExecute    : Result:=ParseExecuteProcedureStatement(AParent);
+    tsqlExit       : begin
+                     Result:=TSQLExitStatement(CreateElement(TSQLExitStatement,AParent));
+                     GetNextToken;
+                     end;
+    tsqlSuspend    : begin
+                     Result:=TSQLSuspendStatement(CreateElement(TSQLSuspendStatement,AParent));
+                     GetNextToken;
+                     end;
+    tsqlPostEvent  : Result:=ParsePostEventStatement(AParent);
+    tsqlWhile      : Result:=ParseWhileStatement(AParent);
+    tsqlWhen       : Result:=ParseWhenStatement(AParent);
+    tsqlSelect     : Result:=ParseSelectStatement(AParent,[sfInto]);
+    tsqlInsert     : Result:=ParseInsertStatement(AParent);
+    tsqlDelete     : Result:=ParseDeleteStatement(AParent);
+    tsqlUpdate     : Result:=ParseUpdateStatement(AParent);
+  else
+    UnexpectedToken;
+  end;
+end;
+
+Procedure TSQLParser.ParseStatementBlock(AParent: TSQLElement; Statements : TSQLElementList);
+
+Var
+  S: TSQLStatement;
+
+begin
+  Consume(tsqlBegin);
+  While (CurrentToken<>tsqlEnd) do
+    begin
+    S:=ParseProcedureStatement(AParent);
+    Statements.Add(S);
+    if not (PreviousToken=tsqlEnd) then
+      Consume(tsqlSemicolon);
+    end;
+  Consume(tsqlEnd);
+end;
+
+function TSQLParser.ParseCreateProcedureStatement(AParent: TSQLElement; IsAlter: Boolean
+  ): TSQLCreateOrAlterStatement;
+
+Var
+  P : TSQLAlterCreateProcedureStatement;
+
+begin
+  // On entry, we're on the PROCEDURE statement.
+  Consume(tsqlProcedure);
+  expect(tsqlIdentifier);
+  If IsAlter then
+    P:=TSQLAlterProcedureStatement(CreateElement(TSQLAlterProcedureStatement,AParent))
+  else
+    P:=TSQLCreateProcedureStatement(CreateElement(TSQLCreateProcedureStatement,AParent));
+  Result:=P;
+  try
+    Result.ObjectName:=CreateIdentifier(P,CurrentTokenString);
+    GetNextToken;
+    If (CurrentToken=tsqlBraceOpen) then
+      ParseProcedureParamList(Result,P.InputVariables);
+    If (CurrentToken=tsqlReturns) then
+      begin
+      GetNextToken;
+      expect(tsqlBraceOpen);
+      ParseProcedureParamList(Result,P.OutputVariables);
+      end;
+    Consume(tsqlAs);
+    if (CurrentToken=tsqlDeclare) then
+      ParseCreateProcedureVariableList(Result,P.LocalVariables);
+    expect(tsqlBegin);
+    ParseStatementBlock(Result,P.Statements);
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseCreateGeneratorStatement(AParent: TSQLElement; IsAlter: Boolean
+  ): TSQLCreateOrAlterStatement;
+begin
+  GetNextToken;
+  Expect(tsqlIdentifier);
+  If IsAlter then
+    Error(SErrCannotAlterGenerator);
+  Result:=TSQLCreateOrAlterStatement(CreateElement(TSQLCreateGeneratorStatement,AParent));
+  try
+    Result.ObjectName:=CreateIdentifier(Result,CurrentTokenString);
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+  GetNextToken; // Comma;
+end;
+
+function TSQLParser.ParseCreateRoleStatement(AParent: TSQLElement;
+  IsAlter: Boolean): TSQLCreateOrAlterStatement;
+begin
+  If IsAlter then
+    UnexpectedToken; // no ALTER ROLE
+  GetNextToken;
+  Expect(tsqlIdentifier);
+  Result:=TSQLCreateOrAlterStatement(CreateElement(TSQLCreateRoleStatement,AParent));
+  Result.ObjectName:=CreateIdentifier(Result,CurrentTokenString);
+  GetNextToken; // Comma;
+end;
+
+Procedure TSQLParser.ParseCharTypeDefinition(Out DT : TSQLDataType; Out Len : Integer; Out ACharset : TSQLStringType);
+
+begin
+  Len:=0;
+  Case CurrentToken of
+    tsqlNCHAR     : dt:=sdtNchar;
+    tsqlVarChar   : dt:=sdtVarChar;
+    tsqlCharacter,
+    tsqlChar      : dt:=sdtChar;
+    tsqlCString   : dt:=sdtCstring;
+    tsqlNational  :
+     begin
+     dt:=sdtNChar;
+     GetNextToken;
+     expect([tsqlCharacter,tsqlChar]);
+     end;
+  end;
+  GetNextToken; // VARYING, Start of size, CHARACTER SET or end
+  If (CurrentToken=tsqlVarying) then  // CHAR VARYING or CHARACTER VARYING;
+    begin
+    If (dt in [sdtNCHAR,sdtChar]) then
+      begin
+      if dt=sdtNCHAR then
+        dt:=sdtNVARCHAR
+      else
+        dt:=sdtVarChar;
+      GetNextToken
+      end
+    else
+      Error(SERRVaryingNotAllowed);
+    end;
+  If (CurrentToken=tsqlBraceOpen) then  // (LEN)
+    begin
+    GetNextToken;
+    Expect(tsqlIntegerNumber);
+    len:=StrToInt(CurrentTokenString);
+    GetNextToken;
+    Expect(tsqlBraceClose);
+    GetNextToken;
+    end
+  else if (dt=sdtCstring) then
+    UnexpectedToken;
+  if (CurrentToken=tsqlCharacter) then // Character SET NNN
+    begin
+    if (dt=sdtCstring) then
+      UnexpectedToken;
+    GetNextToken;
+    Consume(tsqlSet);
+    Expect(tsqlIdentifier);
+    ACharSet:=CurrentTokenString;
+    GetNextToken;
+    end;
+end;
+
+Procedure TSQLParser.ParseBlobDefinition(Var ASegmentSize,ABlobType : Integer; Var ACharset : TSQLStringType);
+
+begin
+  // On entry, we are on the blob token.
+  GetNextToken;
+  If (CurrentToken=tsqlBraceOpen) then // (segment[,subtype])
+    begin
+    GetNextToken;
+    Expect(tsqlIntegerNumber);
+    ASegmentSize:=StrtoInt(CurrentTokenString);
+    GetNextToken;
+    If (CurrentToken=tsqlComma) then
+       begin
+       GetNextToken;
+       Expect(tsqlIntegerNumber);
+       ABlobType:=StrtoInt(CurrentTokenString);
+       GetNextToken;
+       end;
+    Consume(tsqlBraceClose);
+    If CurrentToken in [tsqlSubtype,tsqlSegment] then
+      Error(SErrUnexpectedToken,[CurrentTokenString]);
+    end
+  else
+    begin
+    If CurrentToken=tsqlSubtype then   // SUB_TYPE T
+      begin
+      GetNextToken;
+      Expect(tsqlIntegerNumber);
+      ABlobType:=StrtoInt(CurrentTokenString);
+      GetNextToken;
+      end;
+    If (CurrentToken=tsqlSegment) then // SEGMENT SIZE S
+      begin
+      GetNextToken;
+      Consume(tsqlSize);
+      Expect(tsqlIntegerNumber);
+      ASegmentSize:=StrtoInt(CurrentTokenString);
+      GetNextToken;
+      end;
+    end;
+  if (CurrentToken=tsqlCharacter) then  // CHARACTER SET NNN
+    begin
+    GetNextToken;
+    Consume(tsqlSet);
+    Expect(tsqlIdentifier);
+    ACharSet:=CurrentTokenString;
+    GetNextToken;
+    end;
+end;
+
+Function TSQLParser.ParseForeignKeyDefinition(AParent : TSQLElement) : TSQLForeignKeyDefinition;
+
+  // On entry, we're on ON Return true if On delete
+  Function ParseForeignKeyAction (Out Res : TForeignKeyAction) : Boolean;
+
+  begin
+    GetNextToken;
+    Case CurrentToken of
+      tsqlDelete,
+      tsqlUpdate: Result:=CurrentToken=tsqlDelete;
+    else
+      UnexpectedToken([tsqlDelete,tsqlupdate]);
+    end;
+    Case GetNextToken of
+      tsqlNo :
+        begin
+        GetNextToken;
+        expect(tsqlAction);
+        Res:=fkaNoAction;
+        end;
+      tsqlCascade :
+        Res:=fkaCascade;
+      tsqlSet:
+        begin
+        Case GetNextToken of
+          tsqlDefault :
+            Res:=fkaSetDefault;
+          tsqlNull:
+            Res:=fkaSetNull;
+        else
+          UnexpectedToken([tsqlDefault,tsqlNull]);
+        end;
+        end
+    else
+      UnexpectedToken([tsqlNo,tsqlCascade,tsqlSet]);
+    end;
+    GetNextToken;
+  end;
+
+Var
+  FKA : TForeignKeyAction;
+
+begin
+  Result:=Nil;
+  // on entry, we are on the 'REFERENCES' token
+  GetNextToken;
+  Expect(tsqlidentifier);
+  Result:=TSQLForeignKeyDefinition(CreateElement(TSQLForeignKeyDefinition,AParent));
+  try
+    Result.TableName:=CreateIdentifier(Result,CurrentTokenString);
+    GetNextToken;
+    If (CurrentToken=tsqlBraceOpen) then
+      begin
+      GetNextToken;
+      ParseidentifierList(Result,Result.FieldList);
+      end;
+    if (CurrentToken=tsqlOn) then
+      begin
+      If ParseForeignKeyAction(FKA) then
+        Result.OnDelete:=FKA
+      else
+        Result.OnUpdate:=FKA;
+      end;
+    if (CurrentToken=tsqlOn) then
+      begin
+      If ParseForeignKeyAction(FKA) then
+        Result.OnDelete:=FKA
+      else
+        Result.OnUpdate:=FKA;
+      end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParseFieldConstraint(AParent : TSQLElement) : TSQLFieldConstraint;
+
+Var
+  N : TSQLStringType;
+  K : TSQLForeignKeyFieldConstraint;
+  C : TSQLCheckFieldConstraint;
+  L : TSQLFieldConstraintList;
+  P : Boolean;
+begin
+  Result:=Nil;
+  L:=Nil;
+  P:=False;
+  try
+    Repeat
+      If (Result<>Nil) then
+        begin
+        L:=TSQLFieldConstraintList.Create(AParent);
+        L.List.Add(Result);
+        Result:=Nil;
+        end;
+      If CurrentToken=tsqlConstraint then
+        begin
+        GetNextToken;
+        Expect(tsqlIdentifier);
+        N:=CurrentTokenString;
+        GetNextToken
+        end;
+        Case CurrentToken of
+        tsqlUnique :
+          begin
+          If P then
+            Error('Only one primary/unique field constraint allowed');
+          Result:=TSQLFieldConstraint(CreateElement(TSQLUniqueFieldConstraint,AParent));
+          GetNextToken;
+          P:=True;
+          end;
+        tsqlPrimary :
+          begin
+          If P then
+            Error('Only one primary/unique field constraint allowed');
+          GetNextToken;
+          Expect(tsqlKey);
+          Result:=TSQLFieldConstraint(CreateElement(TSQLPrimaryKeyFieldConstraint,AParent));
+          GetNextToken;
+          P:=True;
+          end;
+        tsqlReferences :
+          begin
+          K:=TSQLForeignKeyFieldConstraint(CreateElement(TSQLForeignKeyFieldConstraint,AParent));
+          Result:=K;
+          K.Definition:=ParseForeignKeyDefinition(K);
+          end;
+        tsqlCheck :
+          begin
+          C:=TSQLCheckFieldConstraint(CreateElement(TSQLCheckFieldConstraint,AParent));
+          Result:=C;
+          C.Expression:=ParseCheckConstraint(K,True);
+          end
+        else
+          UnexpectedToken([tsqlUnique,tsqlPrimary,tsqlReferences,tsqlCheck]);
+        end;
+      If (N<>'') then
+        Result.ConstraintName:=CreateIdentifier(Result,N);
+    Until Not (CurrentToken in [tsqlUnique,tsqlPrimary,tsqlReferences,tsqlCheck,tsqlConstraint]);
+    If Assigned(L) then
+      begin
+      L.List.Add(Result);
+      Result:=L;
+      end;
+  except
+    If (L<>Result) then
+      FReeAndNil(L);
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParseTypeDefinition(AParent : TSQLElement; Flags : TParseTypeFlags) : TSQLTypeDefinition;
+
+Var
+  TN : String;
+  AD : Integer;
+  DT : TSQLDataType;
+  AA : Boolean; // Allow Array
+  GN : Boolean; // Do GetNextToken ?
+  NN : Boolean; // Not Null ?
+  sc,prec : Integer;
+  bt : integer;
+  D : TSQLTypeDefinition;
+  cs : TSQLStringType;
+  Coll : TSQLCollation;
+  C : TSQLFieldConstraint;
+
+begin
+ // We are positioned on the token prior to the type definition.
+  AA:=True;
+  GN:=True;
+  prec:=0;
+  sc:=0;
+  bt:=0;
+  NN:=True;
+  Coll:=Nil;
+  Case GetNextToken of
+    tsqlIdentifier :
+      If not (ptfAllowDomainName in Flags) then
+        Error(SErrDomainNotAllowed)
+      else
+        begin
+        DT:=sdtDomain;
+        TN:=CurrentTokenString;
+        end;
+     tsqlInt,
+     tsqlInteger :
+       dt:=sdtInteger;
+     tsqlSmallInt :
+       dt:=sdtSmallInt;
+     tsqlDate:
+       dt:=sdtDate;
+     tsqlTimeStamp:
+       dt:=sdtDateTime;
+     tsqlFloat:
+       dt:=sdtFloat;
+     tsqlTime:
+       dt:=sdtTime;
+     tsqlDecimal,
+     tsqlNumeric:
+       begin
+       if CurrentToken=tsqlDecimal then
+         dt:=sdtDecimal
+       else
+         dt:=sdtNumeric;
+       GetNextToken;
+       GN:=False;
+       If (CurrentToken=tsqlBraceOpen) then
+         begin
+         GetNextToken;
+         Expect(tsqlIntegerNumber);
+         prec:=StrToInt(CurrentTokenString);
+         if (GetNextToken=tsqlBraceClose) then
+           sc:=0
+         else
+           begin
+           GetNextToken;
+           Expect(tsqlIntegerNumber);
+           sc:=StrToInt(CurrentTokenString);
+           GetNextToken;
+           Expect(tsqlBraceClose);
+           end;
+         GetNextToken; // position on first token after closing brace. GN=False !
+         end;
+       end;
+    tsqlCstring,
+    tsqlChar,
+    tsqlNChar,
+    tsqlVarChar,
+    tsqlCharacter,
+    tsqlNational :
+      begin
+      If (CurrentToken=tsqlCstring) and  Not (([ptfExternalFunction,ptfExternalFunctionResult]*Flags) <> []) then
+       UnexpectedToken;
+      GN:=False;
+      ParseCharTypeDefinition(DT,Prec,cs);
+      end;
+    tsqlBlob :
+      begin
+      dt:=sdtBlob;
+      GN:=False;
+      ParseBlobDefinition(prec,bt,cs);
+      end;
+  else
+    UnexpectedToken;
+  end;
+  If GN then
+    GetNextToken;
+  // We are now on array or rest of type.
+  If (CurrentToken=tsqlSquareBraceOpen) then
+    begin
+    GetNextToken;
+    Expect(tsqlIntegerNumber);
+    AD:=Strtoint(CurrentTokenString);
+    GetNextToken;
+    Expect(tsqlSquareBraceClose);
+    GetNextToken;
+    end
+  else
+    AD:=0;
+  // Collation is here in domain (needs checking ?)
+  If (CurrentToken=tsqlCollate) then
+    begin
+    If not (dt in [sdtChar,sdtVarchar,sdtNchar,sdtNVarChar,sdtBlob]) then
+      Error(SErrInvalidUseOfCollate);
+    GetNextToken;
+    Expect(tsqlIdentifier);
+    Coll:=TSQLCollation(CreateElement(TSQLCollation,AParent));
+    Coll.Name:=CurrentTokenString;
+    GetNextToken;
+    end
+  else
+    Coll:=Nil;
+  C:=Nil;
+  D:=TSQLTypeDefinition(CreateElement(TSQLTypeDefinition,AParent));
+  try
+    D.DataType:=DT;
+    D.TypeName:=TN;
+    D.Len:=PRec;
+    D.Scale:=Sc;
+    D.BlobType:=bt;
+    D.ArrayDim:=AD;
+    D.Charset:=CS;
+    D.Collation:=Coll;
+    D.Constraint:=C;
+    if (not (ptfAlterDomain in Flags)) then // Alternative is to raise an error in each of the following
+      begin
+      If (CurrentToken=tsqlDefault) then
+          begin
+          GetNextToken;
+          D.DefaultValue:=CreateLiteral(D);
+          GetNextToken;
+          end;
+      if (CurrentToken=tsqlNot) then
+        begin
+        GetNextToken;
+        Expect(tsqlNULL);
+        D.NotNull:=True;
+        GetNextToken;
+        end;
+      If (CurrentToken=tsqlCheck) and not (ptfTableFieldDef in Flags) then
+        begin
+        D.Check:=ParseCheckConstraint(D,False);
+        // Parsecheckconstraint is on next token.
+        end;
+      // Constraint is before collation.
+      if CurrentToken in [tsqlConstraint,tsqlCheck,tsqlUnique,tsqlprimary,tsqlReferences] then
+        begin
+        If Not (ptfAllowConstraint in Flags) then
+          UnexpectedToken;
+        D.Constraint:=ParseFieldConstraint(AParent);
+        end;
+      // table definition can have PRIMARY KEY CHECK
+      If (CurrentToken=tsqlCheck) and (ptfTableFieldDef in Flags) then
+        begin
+        D.Check:=ParseCheckConstraint(D,False);
+        // Parsecheckconstraint is on next token.
+        end;
+      // Collation is after constraint in table
+      If (CurrentToken=tsqlCollate) then
+        begin
+        If not (dt in [sdtChar,sdtVarchar,sdtNchar,sdtNVarChar,sdtBlob]) then
+          Error(SErrInvalidUseOfCollate);
+        GetNextToken;
+        Expect(tsqlIdentifier);
+        Coll:=TSQLCollation(CreateElement(TSQLCollation,AParent));
+        Coll.Name:=CurrentTokenString;
+        GetNextToken;
+        end
+      else
+        Coll:=Nil;
+      If (CurrentToken=tsqlBy) and (ptfExternalFunctionResult in Flags) then
+        begin
+        GetNextToken;
+        Consume(tsqlValue);
+        D.ByValue:=True;
+        end;
+      end;
+    Result:=D;
+  except
+    FreeAndNil(D);
+    Raise;
+  end;
+end;
+
+function TSQLParser.CreateLiteral(AParent : TSQLElement) : TSQLLiteral;
+
+begin
+  Result:=Nil;
+  Case CurrentToken of
+    tsqlIntegerNumber:
+      begin
+      Result:=TSQLLiteral(CreateElement(TSQLIntegerLiteral,AParent));
+      TSQLIntegerLiteral(Result).Value:=StrToInt(CurrentTokenString);
+      end;
+    tsqlString:
+      begin
+      Result:=TSQLLiteral(CreateElement(TSQLStringLiteral,AParent));
+      TSQLStringLiteral(Result).Value:=CurrentTokenString;
+      end;
+    tsqlFloatNumber:
+      begin
+      Result:=TSQLLiteral(CreateElement(TSQLFloatLiteral,AParent));
+      TSQLFloatLiteral(Result).Value:=StrToFloat(CurrentTokenString);
+      end;
+    tsqlNull :
+      Result:=TSQLLiteral(CreateElement(TSQLNullLiteral,AParent));
+    tsqlValue :
+        Result:=TSQLLiteral(CreateElement(TSQLValueLiteral,AParent));
+    tsqlUSER :
+      Result:=TSQLLiteral(CreateElement(TSQLUserLiteral,AParent));
+  else
+    Error(SErrInvalidLiteral,[CurrentTokenString]);
+  end;
+end;
+
+procedure TSQLParser.CheckEOF;
+
+begin
+  If CurrentToken=tsqlEOF then
+    Error('Unexpected end of command');
+end;
+
+Function TSQLParser.ParseExprLevel1(AParent : TSQLElement; EO : TExpressionOptions) : TSQLExpression;
+
+var
+  tt: TSQLToken;
+  B : TSQLBinaryExpression;
+  Right: TSQLExpression;
+  L : TSQLLiteralExpression;
+
+begin
+  Result:=ParseExprLevel2(AParent,EO);
+  Try
+    while (CurrentToken in [tsqlAnd,tsqlOr{,tsqlIs}]) do
+      begin
+      tt:=CurrentToken;
+      GetNextToken;
+      CheckEOF;
+      B:=TSQLBinaryExpression(CreateElement(TSQLBinaryExpression,AParent));
+      B.Left:=TSQLExpression(Result);
+      Result:=B;
+      If tt=tsqlIs then
+        begin
+        If CurrentToken=tsqlNot then
+           begin
+//           B.Operation:=boIsNot;
+           GetNextToken;
+           end
+        else
+          B.Operation:=boIs;
+        Expect(tsqlNull);
+        L:=TSQLLiteralExpression(CreateElement(TSQLLiteralExpression,AParent));
+        L.Literal:=CreateLiteral(AParent);
+        B.Right:=L;
+        GetNexttoken;
+        end
+      else
+        begin
+        case tt of
+          tsqlOr  : B.Operation:=boOr;
+          tsqlAnd : B.Operation:=boAnd;
+        Else
+          Error(SErrUnknownBooleanOp)
+        end;
+        B.Right:=ParseExprLevel2(AParent,EO);
+        end;
+      end;
+  Except
+    Result.Free;
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParseInoperand(AParent : TSQLElement) : TSQLExpression;
+
+Var
+  S : TSQLSelectExpression;
+  L : TSQLListExpression;
+  Done : Boolean;
+
+begin
+  // On entry, we're on the first token after IN token, which is the ( token.
+  Consume(tsqlBraceopen);
+  try
+    If (CurrentToken=tsqlSelect) then
+      begin
+      S:=TSQLSelectExpression(CreateElement(TSQLSelectExpression,APArent));
+      Result:=S;
+      S.Select:=ParseSelectStatement(AParent,[sfSingleton]);
+      Consume(tsqlBraceClose);
+      end
+    else
+      begin
+      L:=TSQLListExpression(CreateElement(TSQLListExpression,AParent));
+      Result:=L;
+      Repeat
+         L.List.Add(ParseExprLevel1(L,[eoListValue]));
+         Expect([tsqlBraceClose,tsqlComma]);
+         Done:=(CurrentToken=tsqlBraceClose);
+         GetNextToken;
+      until Done;
+
+      end;
+  except
+    FreeAndNil(Result);
+  end;
+end;
+
+Function TSQLParser.ParseExprLevel2(AParent : TSQLElement; EO : TExpressionOptions) : TSQLExpression;
+var
+  tt: TSQLToken;
+  Right : TSQLExpression;
+  B : TSQLBinaryExpression;
+  T : TSQLTernaryExpression;
+  O : TSQLBinaryOperation;
+  U : TSQLUnaryExpression;
+  I,bw,doin : Boolean;
+
+begin
+  {$ifdef debugexpr}  Writeln('Level 2 ',TokenInfos[CurrentToken],': ',CurrentTokenString);{$endif debugexpr}
+  Result:=ParseExprLevel3(AParent,EO);
+  try
+    if (CurrentToken in sqlComparisons) then
+      begin
+      tt:=CurrentToken;
+      I:=CurrentToken=tsqlnot;
+      CheckEOF;
+      GetNextToken;
+      CheckEOF;
+      if I then
+        begin
+        tt:=CurrentToken;
+        if Not (tt in sqlInvertableComparisons) then
+          Error(SErrUnexpectedToken,[CurrentTokenString]);
+        GetNextToken;
+        If (tt=tsqlStarting) and (CurrentToken=tsqlWith) then
+          GetNextToken;
+        end
+      else
+        if (CurrentToken=tsqlNot) then
+          begin
+          GetNextToken;
+          if not (tt=tsqlis) then
+            UnexpectedToken;
+          I:=true;
+          end;
+
+
+      bw:=False;
+      doin:=false;
+      Case tt of
+        tsqlLT : O:=boLT;
+        tsqlLE : O:=boLE;
+        tsqlGT : O:=boGT;
+        tsqlGE : O:=boGE;
+        tsqlEq : O:=boEq;
+        tsqlNE : O:=boNE;
+        tsqlLike : O:=boLike;
+        tsqlIn : doin:=true;
+        tsqlis : O:=boIs;
+        tsqlContaining : O:=boContaining;
+        tsqlStarting : O:=boStarting;
+        tsqlBetween : bw:=true;
+      Else
+        Error(SErrUnknownComparison)
+      end;
+      If doIn then
+        begin
+        Right:=ParseInOperand(AParent);
+        B:=TSQLBinaryExpression(CreateElement(TSQLBinaryExpression,AParent));
+        B.Operation:=boIn;
+        B.Left:=Result;
+        Result:=B;
+        B.Right:=Right;
+        end
+      else
+        begin
+        Right:=ParseExprLevel3(AParent,EO);
+        If (O=boLike) and (CurrentToken=tsqlEscape) then
+          begin
+          GetNextToken;
+          T:=TSQLTernaryExpression(CreateElement(TSQLTernaryExpression,AParent));
+          T.Left:=Result;
+          Result:=T;
+          T.Middle:=Right;
+          T.Right:=ParseExprLevel3(AParent,EO);
+          T.Operation:=toLikeEscape
+          end
+        else If bw then
+          begin
+          Consume(tsqlAnd);
+          T:=TSQLTernaryExpression(CreateElement(TSQLTernaryExpression,AParent));
+          T.Left:=Result;
+          Result:=T;
+          T.Middle:=Right;
+          T.Right:=ParseExprLevel3(AParent,EO);
+          T.Operation:=toBetween;
+          end
+        else
+          begin
+          B:=TSQLBinaryExpression(CreateElement(TSQLBinaryExpression,AParent));
+          B.Operation:=O;
+          B.Left:=Result;
+          Result:=B;
+          B.Right:=Right;
+          end;
+        end;
+      If I then
+        if B.Operation=boIs then
+          B.Operation:=boIsNot
+        else
+          begin
+          U:=TSQLUnaryExpression(CreateElement(TSQLUnaryExpression,AParent));
+          U.Operand:=Result;
+          U.Operation:=uoNot;
+          Result:=U;
+          end;
+      end;
+  Except
+    Result.Free;
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParseExprLevel3(AParent : TSQLElement; EO : TExpressionOptions) : TSQLExpression;
+
+  Function NegativeNumber : Boolean; inline;
+
+  begin
+    Result:=(CurrentToken in [tsqlIntegerNumber,tsqlFloatNumber]) and (StrToInt(CurrentTokenString)<0)
+  end;
+
+var
+  tt : TSQLToken;
+  right : TSQLExpression;
+  B : TSQLBinaryExpression;
+
+
+begin
+{$ifdef debugexpr}  Writeln('Level 3 ',TokenInfos[CurrentToken],': ',CurrentTokenString);{$endif debugexpr}
+  Result:=ParseExprLevel4(AParent,EO);
+  try
+    {$ifdef debugexpr}  Writeln('Level 3 continues ',TokenInfos[CurrentToken],': ',CurrentTokenString);{$endif debugexpr}
+    // Scanner returns -N as an negative number, not as - (positive number)
+    // NegativeNumber is for the case A-1 or so: convert to A + -1
+    while (CurrentToken in [tsqlConcatenate,tsqlPlus,tsqlMinus]) or NegativeNumber do
+      begin
+      tt:=CurrentToken;
+      If NegativeNumber then
+        tt:=tsqlPlus // Pretend we've eaten +
+      else
+        begin
+        GetNextToken;
+        CheckEOF;
+        end;
+      Right:=ParseExprLevel4(AParent,EO);
+      B:=TSQLBinaryExpression(CreateElement(TSQLBinaryExpression,AParent));
+      B.Left:=Result;
+      Result:=B;
+      B.Right:=Right;
+      Case tt of
+        tsqlPlus  : B.Operation:=boAdd;
+        tsqlMinus : B.Operation:=boSubtract;
+        tsqlConcatenate : B.Operation:=boConcat;
+      end;
+      end;
+  Except
+    Result.Free;
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParseExprLevel4(AParent : TSQLElement; EO : TExpressionOptions) : TSQLExpression;
+
+var
+  tt : TSQLToken;
+  right : TSQLExpression;
+  B : TSQLBinaryExpression;
+
+begin
+{$ifdef debugexpr}  Writeln('Level 4 ',TokenInfos[CurrentToken],': ',CurrentTokenString);{$endif debugexpr}
+  Result:=ParseExprLevel5(AParent,EO);
+  try
+    while (CurrentToken in [tsqlMul,tsqlDiv]) do
+      begin
+      tt:=CurrentToken;
+      GetNextToken;
+      CheckEOF;
+      Right:=ParseExprLevel5(AParent,EO);
+      B:=TSQLBinaryExpression(CreateElement(TSQLBinaryExpression,AParent));
+      B.Left:=Result;
+      B.Right:=Right;
+      Case tt of
+        tsqlMul : B.Operation:=boMultiply;
+        tsqlDiv : B.Operation:=boDivide;
+      end;
+      end;
+  Except
+    Result.Free;
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParseExprLevel5(AParent : TSQLElement; EO : TExpressionOptions) : TSQLExpression;
+
+Var
+  tt : tsqltoken;
+  U : TSQLUnaryExpression;
+begin
+{$ifdef debugexpr}  Writeln('Level 5 ',TokenInfos[CurrentToken],': ',CurrentTokenString);{$endif debugexpr}
+  tt:=tsqlunknown;
+  if (CurrentToken in [tsqlNot,tsqlPlus,tsqlMinus]) then
+    begin
+    tt:=CurrentToken;
+    GetNextToken;
+    CheckEOF;
+    end;
+  Result:=ParseExprLevel6(AParent,EO);
+  try
+    If tt<>tsqlUnknown then
+      begin
+      U:=TSQLunaryExpression(CreateElement(TSQLunaryExpression,AParent));
+      if tt=tsqlNot then
+        U.Operation:=uoNot
+      else
+        U.Operation:=uoMinus;
+      U.Operand:=Result;
+      Result:=U;
+      end;
+  except
+    FreeandNil(Result);
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParseExprLevel6(AParent : TSQLElement ; EO : TExpressionOptions ) : TSQLExpression;
+
+
+
+begin
+{$ifdef debugexpr}  Writeln('Level 6 ',TokenInfos[CurrentToken],': ',CurrentTokenString);{$endif debugexpr}
+  if (CurrentToken=tsqlBraceOpen) then
+    begin
+    GetNextToken;
+    If (CurrentToken<>tsqlselect) then
+      Result:=ParseExprLevel1(AParent,EO)
+    else
+      begin
+      Result:=TSQLExpression(CreateElement(TSQLSelectExpression,AParent));
+      try
+        TSQLSelectExpression(Result).Select:=ParseSelectStatement(Result,[sfSingleTon]);
+      except
+        FreeAndNil(Result);
+        Raise;
+      end;
+      end;
+    try
+      if (CurrentToken<>tsqlBraceClose) then
+        Error(SerrUnmatchedBrace);
+      GetNextToken;
+    Except
+      Result.Free;
+      Raise;
+    end;
+    end
+  else
+    Result:=ParseExprPrimitive(AParent,EO);
+end;
+
+Function TSQLParser.ParseIdentifierList(AParent : TSQLElement; AList : TSQLelementList) : integer;
+
+Var
+  Done : Boolean;
+
+begin
+  // on entry, we're on first identifier
+  Expect(tsqlIdentifier);
+  Result:=0;
+  Done:=False;
+  repeat
+    if CurrentToken=tsqlComma then
+      GetNextToken;
+    Expect(tsqlIdentifier);
+    AList.add(CreateIdentifier(AParent,CurrentTokenString));
+    Inc(Result);
+  until (GetNextToken<>tsqlComma);
+  Expect(tsqlBraceClose);
+  GetNextToken;
+end;
+
+Function TSQLParser.ParseValueList(AParent : TSQLElement; EO : TExpressionOptions) : TSQLElementList;
+
+Var
+    E : TSQLExpression;
+
+begin
+  Result:=Nil;
+  E:=Nil;
+  // First token is (
+  Expect(tsqlBraceOpen);
+  Repeat
+    GetNextToken;
+    If (CurrentToken<>tsqlBraceClose) then
+      E:=ParseExprLevel1(AParent,EO);
+    If (E<>Nil) then
+      begin
+      If Result=Nil then
+        Result:=TSQLElementList.Create(True);
+      Result.Add(E);
+      end;
+    Expect([tsqlComma,tsqlBraceClose]);
+  Until CurrentToken=tsqlBraceClose;
+end;
+
+procedure TSQLParser.UnexpectedToken;
+begin
+  Error(SErrUnexpectedToken,[CurrentTokenString]);
+end;
+
+procedure TSQLParser.UnexpectedToken(AExpected: TSQLTokens);
+
+Var
+  S : String;
+  I : TSQLToken;
+
+begin
+  S:='';
+  For I:=Low(TSQLToken) to High(TSQLToken) do
+    if I in AExpected then
+      begin
+      If (S<>'') then
+        S:=S+',';
+      S:=S+TokenInfos[i];
+      end;
+  Error(SErrUnexpectedTokenOf,[CurrentTokenString,S]);
+end;
+
+function TSQLParser.CreateIdentifier(AParent : TSQLElement; Const AName: TSQLStringType
+  ): TSQLIdentifierName;
+begin
+  Result:=TSQLIdentifierName(CreateElement(TSQLIdentifierName,AParent));
+  Result.Name:=AName;
+end;
+
+
+Function TSQLParser.ParseExprAggregate(AParent : TSQLElement; EO : TExpressionOptions) : TSQLAggregateFunctionExpression;
+begin
+  Result:=TSQLAggregateFunctionExpression(CreateElement(TSQLAggregateFunctionExpression,AParent));
+  try
+    Case CurrentToken of
+      tsqlCount : Result.Aggregate:=afCount;
+      tsqlSum : Result.Aggregate:=afSum;
+      tsqlAvg : Result.Aggregate:=afAvg;
+      tsqlMax : Result.Aggregate:=afMax;
+      tsqlMin : Result.Aggregate:=afMin;
+    end;
+    GetNextToken;
+    Consume(tsqlBraceOpen);
+    If CurrentToken=tsqlMul then
+      begin
+      If Result.Aggregate<>afCount then
+        Error(SErrAsteriskOnlyInCount);
+      Result.OPtion:=aoAsterisk;
+      GetNextToken;
+      end
+    else
+      begin
+      if (CurrentToken in [tsqlAll,tsqlDistinct]) then
+        begin
+        If CurrentToken=tsqlAll then
+          Result.Option:=aoAll
+        else
+          Result.Option:=aoDistinct;
+        GetNextToken;
+        end;
+      Result.Expression:=ParseExprLevel1(Result,EO);
+      end;
+    Consume(tsqlBraceClose);
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParseExprPrimitive(AParent : TSQLElement; EO : TExpressionOptions) : TSQLExpression;
+
+Var
+  L : TSQLElementList;
+  N : String;
+  C : TSQLElementClass;
+  E : TSQLExtractElement;
+
+begin
+  Result:=Nil;
+  try
+  {$ifdef debugexpr}  Writeln('Primitive ',TokenInfos[CurrentToken],': ',CurrentTokenString);{$endif debugexpr}
+    Case CurrentToken of
+      tsqlintegerNumber,
+      tsqlString,
+      tsqlFloatNumber,
+      tsqlNull, // True and False belong here
+      tsqlValue,
+      tsqlUser:
+        begin
+        Result:=TSQLLiteralExpression(CreateElement(TSQLLiteralExpression,AParent));
+        TSQLLiteralExpression(Result).Literal:=CreateLiteral(AParent);
+        GetNextToken;
+        end;
+      tsqlCast:
+        begin
+        GetNextToken;
+        Consume(tsqlBraceOpen);
+        Result:=TSQLCastExpression(CreateElement(TSQLCastExpression,AParent));
+        TSQLCastExpression(Result).Value:=ParseExprLevel1(Result,EO);
+        Expect(tsqlAs);
+        TSQLCastExpression(Result).NewType:=ParseTypeDefinition(Result,[ptfCast]);
+        Consume(tsqlBraceClose);
+        end;
+      tsqlExtract:
+        begin
+        GetNextToken;
+        Consume(tsqlBraceOpen);
+        Expect(tsqlIdentifier);
+        if not StringToSQLExtractElement(CurrentTokenString,E) then
+          Error(SErrInvalidExtract,[CurrentTokenString]);
+        Consume(tsqlIdentifier);
+        Consume(tsqlFrom);
+        Result:=TSQLExtractExpression(CreateElement(TSQLExtractExpression,AParent));
+        TSQLExtractExpression(Result).Element:=E;
+        TSQLExtractExpression(Result).Value:=ParseExprLevel1(Result,EO);
+        Consume(tsqlBraceClose);
+        end;
+      tsqlExists,
+      tsqlAll,
+      tsqlAny,
+      tsqlSome,
+      tsqlSingular:
+        begin
+        Case CurrentToken of
+          tsqlExists   : C:=TSQLexistsExpression;
+          tsqlAll      : C:=TSQLAllExpression;
+          tsqlAny      : C:=TSQLAnyExpression;
+          tsqlSome     : C:=TSQLSomeExpression;
+          tsqlSingular : C:=TSQLSingularExpression;
+        end;
+        GetNextToken;
+        Consume(tsqlBraceOpen);
+        Result:=TSQLSelectionExpression(CreateElement(C,AParent));
+        TSQLSelectionExpression(Result).Select:=ParseSelectStatement(Result,[]);
+        Consume(tsqlBraceClose);
+        end;
+      tsqlCount,
+      tsqlSum,
+      tsqlAvg,
+      tsqlMax,
+      tsqlMin :
+        begin
+        If not ([eoSelectValue,eoHaving]*EO <> []) then
+          Error(SErrNoAggregateAllowed);
+        Result:=ParseExprAggregate(APArent,EO);
+        end;
+      tsqlUpper :
+        begin
+          GetNextToken;
+          L:=ParseValueList(AParent,EO);
+          If L.Count<>1 then
+            begin
+            FreeAndNil(L);
+            Error(SErrUpperOneArgument);
+            end;
+          GetNextToken; // Consume );
+          Result:=TSQLFunctionCallExpression(CreateElement(TSQLFunctionCallExpression,AParent));
+          TSQLFunctionCallExpression(Result).IDentifier:='UPPER';
+          TSQLFunctionCallExpression(Result).Arguments:=L;
+        end;
+      tsqlGenID :
+        begin
+        GetNextToken;
+        Consume(tsqlBraceOpen);
+        expect(tsqlIdentifier);
+        N:=CurrentTokenString;
+        GetNextToken;
+        Consume(tsqlComma);
+        Result:=TSQLGenIDExpression(CreateElement(TSQLGenIDExpression,AParent));
+        TSQLGenIDExpression(Result).Generator:=CreateIdentifier(Result,N);
+        TSQLGenIDExpression(Result).Value:=ParseExprLevel1(AParent,EO);
+        Consume(tsqlBraceClose);
+        end;
+      tsqlColon:
+        begin
+        if (([eoCheckConstraint,eoTableConstraint,eoComputedBy] * EO)<>[]) then
+          Error(SErrUnexpectedToken,[CurrentTokenString]);
+        GetNextToken;
+        expect(tsqlIdentifier);
+        N:=CurrentTokenString;
+        Result:=TSQLParameterExpression(CreateElement(TSQLParameterExpression,AParent));
+        TSQLParameterExpression(Result).Identifier:=CreateIdentifier(Result,N);
+        Consume(tsqlIdentifier);
+        end;
+      tsqlIdentifier:
+        begin
+        N:=CurrentTokenString;
+        If (GetNextToken<>tsqlBraceOpen) then
+          begin
+          If (eoCheckConstraint in EO) and not (eoTableConstraint in EO) then
+            Error(SErrUnexpectedToken,[CurrentTokenString]);
+          If (CurrentToken=tsqlDot) then
+            begin
+            GetNextToken;
+            Expect(tsqlIdentifier);
+            N:=N+'.'+CurrentTokenString;
+            GetNextToken;
+            end;
+          // plain identifier
+          Result:=TSQLIdentifierExpression(CreateElement(TSQLIdentifierExpression,APArent));
+          TSQLIdentifierExpression(Result).IDentifier:=CreateIdentifier(Result,N);
+          // Array access ?
+          If (CurrentToken=tsqlSquareBraceOpen) then
+             begin
+             If (GetNextToken<>tsqlIntegerNumber) then
+                Error(SErrIntegerExpected);
+             TSQLIdentifierExpression(Result).ElementIndex:=StrToInt(CurrentTokenString);
+             GetNextToken;
+             Consume(tsqlSquareBraceClose);
+             end;
+          end
+        else
+          begin
+          L:=ParseValueList(AParent,EO);
+          GetNextToken; // Consume );
+          // Function call
+          Result:=TSQLFunctionCallExpression(CreateElement(TSQLFunctionCallExpression,AParent));
+          TSQLFunctionCallExpression(Result).IDentifier:=N;
+          TSQLFunctionCallExpression(Result).Arguments:=L;
+          end;
+        end;
+      else
+        UnexpectedToken;
+      end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseSQLValue(AParent : TSQLElement) : TSQLExpression;
+
+Var
+  E : TSQLExpression;
+begin
+  E:=ParseExprLevel1(AParent,[]);
+  Result:=E;
+end;
+
+function TSQLParser.ParseCheckConstraint(AParent : TSQLElement; TableConstraint : Boolean = False) : TSQLExpression;
+
+Var
+  EO : TExpressionOptions;
+
+begin
+  // We are on the 'CHECK' token.
+  GetNextToken;
+  Consume(tsqlBraceOpen);
+  EO:=[eoCheckConstraint];
+  If TableConstraint then
+    EO:=EO+[eoTableConstraint];
+  Result:=ParseExprLevel1(AParent,EO);
+  Consume(tsqlBraceClose);
+end;
+
+function TSQLParser.ParseCreateDomainStatement(AParent: TSQLElement; IsAlter: Boolean
+  ): TSQLCreateOrAlterStatement;
+
+var
+  D : TSQLCreateDomainStatement;
+  A : TSQLAlterDomainStatement;
+  N : TSQLStringType;
+  NN : Boolean;
+
+begin
+  Result:=Nil;
+  GetNextToken;
+  Expect(tsqlIdentifier);
+  N:=CurrentTokenString;
+  If not IsAlter then
+    begin
+    D:=TSQLCreateDomainStatement(CreateElement(TSQLCreateDomainStatement,AParent));
+    try
+      D.ObjectName:=CreateIdentifier(D,N);
+      If (PeekNextToken=tsqlAs) then
+        GetNextToken;
+      D.TypeDefinition:=ParseTypeDefinition(D,[])
+    except
+      FreeAndNil(D);
+      Raise;
+    end;
+    Result:=D;
+    end
+  else
+    begin
+    A:=Nil;
+    NN:=False;
+    try
+      Case GetNextToken of
+        tsqlSet:
+          begin
+          GetNextToken;
+          Expect(tsqlDefault);
+          GetNextToken;
+          A:=TSQLAlterDomainSetDefaultStatement(CreateElement(TSQLAlterDomainSetDefaultStatement,APArent));
+          TSQLAlterDomainSetDefaultStatement(A).DefaultValue:=CreateLiteral(A);
+          end;
+        tsqlDrop:
+          begin
+          Case GetNextToken of
+            tsqlDefault : A:=TSQLAlterDomainDropDefaultStatement(CreateElement(TSQLAlterDomainDropDefaultStatement,APArent));
+            tsqlConstraint : A:=TSQLAlterDomainDropCheckStatement(CreateElement(TSQLAlterDomainDropCheckStatement,APArent));
+          else
+            Error(SErrUnexpectedToken,[CurrentTokenString]);
+          end;
+          end;
+        tsqlAdd:
+          begin
+          if (GetNextToken=tsqlConstraint) then
+            GetNextToken;
+          Expect(tsqlCheck);
+          A:=TSQLAlterDomainAddCheckStatement(CreateElement(TSQLAlterDomainAddCheckStatement,APArent));
+          TSQLAlterDomainAddCheckStatement(A).Check:=ParseCheckConstraint(A);
+          NN:=True;
+          end;
+        tsqlType:
+          begin
+          A:=TSQLAlterDomainTypeStatement(CreateElement(TSQLAlterDomainTypeStatement,AParent));
+          TSQLAlterDomainTypeStatement(A).NewType:=ParseTypeDefinition(A,[ptfAlterDomain]);
+          NN:=True;
+          end;
+        tsqlIdentifier:
+          begin
+          A:=TSQLAlterDomainRenameStatement(CreateElement(TSQLAlterDomainRenameStatement,APArent));
+          TSQLAlterDomainRenameStatement(A).NewName:=CreateIdentifier(A,CurrentTokenString);
+          end;
+      else
+        UnexpectedToken([tsqlSet,tsqlIdentifier,tsqlAdd,tsqlType,tsqlDrop]);
+      end;
+      A.ObjectName:=CreateIdentifier(A,N);
+      Result:=A;
+      If not NN then
+        GetNextToken;
+    except
+      FreeAndNil(A);
+      Raise;
+    end;
+    end;
+end;
+
+function TSQLParser.ParseCreateExceptionStatement(AParent: TSQLElement;
+  IsAlter: Boolean): TSQLCreateOrAlterStatement;
+
+var
+  E : TSQLCreateExceptionStatement;
+  N : TSQLStringType;
+
+begin
+  GetNextToken;
+  Expect(tsqlIdentifier);
+  N:=CurrentTokenString;
+  try
+    if IsAlter then
+      E:=TSQLCreateExceptionStatement(CreateElement(TSQLAlterExceptionStatement,AParent))
+    else
+      E:=TSQLCreateExceptionStatement(CreateElement(TSQLCreateExceptionStatement,AParent));
+    E.ObjectName:=CreateIdentifier(E,N);
+    GetNextToken;
+    Expect(tsqlString);
+    E.ExceptionMessage:=TSQLStringLiteral(CreateElement(TSQLStringLiteral,E));
+    E.ExceptionMessage.Value:=CurrentTokenString;
+    GetNextToken;
+  except
+    FreeAndNil(E);
+    Raise;
+  end;
+  Result:=E;
+end;
+
+function TSQLParser.ParseCreateTriggerStatement(AParent: TSQLElement; IsAlter: Boolean
+  ): TSQLCreateOrAlterStatement;
+
+Var
+  T : TSQLAlterCreateTriggerStatement;
+
+begin
+  // On entry, we're on the 'TRIGGER' token.
+  Consume(tsqlTrigger);
+  If IsAlter then
+    T:=TSQLAlterTriggerStatement(CreateElement(TSQLAlterTriggerStatement,APArent))
+  else
+    T:=TSQLCreateTriggerStatement(CreateElement(TSQLCreateTriggerStatement,APArent));
+  Result:=T;
+  try
+    Expect(tsqlidentifier);
+    Result.ObjectName:=CreateIdentifier(Result,CurrentTokenString);
+    getnexttoken;
+    If Not IsAlter then
+      begin
+      Consume(tsqlfor);
+      Expect(tsqlidentifier);
+      T.TableName:=CreateIdentifier(Result,CurrentTokenString);
+      GetNextToken;
+      end;
+    if (CurrentToken in [tsqlActive,tsqlInactive]) then
+      begin
+      If CurrentToken=tsqlActive then
+        T.State:=tsActive
+      else
+        T.State:=tsInactive;
+      GetNextToken;
+      end;
+    Expect([tsqlBefore,tsqlAfter]);
+    if CurrentToken=tsqlBefore then
+      T.Moment:=tmBefore
+    else
+      T.Moment:=tmAfter;
+    Repeat
+      GetNextToken;
+      Expect([tsqlDelete,tsqlInsert,tsqlUpdate]);
+      Case CurrentToken of
+        tsqlDelete : T.Operations:=T.Operations+[toDelete];
+        tsqlUpdate : T.Operations:=T.Operations+[toUpdate];
+        tsqlInsert : T.Operations:=T.Operations+[toInsert];
+      end;
+      GetNextToken;
+    Until (CurrentToken<>tsqlOr);
+    If CurrentToken=tsqlPosition then
+      begin
+      GetNextToken;
+      Expect(tsqlIntegerNumber);
+      T.Position:=StrToInt(CurrentTokenString);
+      GetNextToken;
+      end;
+    Consume(tsqlAs);
+    if (CurrentToken=tsqlDeclare) then
+      ParseCreateProcedureVariableList(Result,T.LocalVariables);
+    expect(tsqlBegin);
+    ParseStatementBlock(Result,T.Statements);
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseSetGeneratorStatement(AParent: TSQLElement
+  ): TSQLSetGeneratorStatement;
+begin
+  // On entry, we're on the 'GENERATOR' token
+  Consume(tsqlGenerator) ;
+  try
+    Result:=TSQLSetGeneratorStatement(CreateElement(TSQLSetGeneratorStatement,AParent));
+    expect(tsqlidentifier);
+    Result.ObjectName:=CreateIdentifier(Result,CurrentTokenString);
+    GetNextToken;
+    consume(tsqlto);
+    expect(tsqlIntegerNumber);
+    Result.NewValue:=StrToInt(CurrentTokenString);
+    GetNextToken;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseSecondaryFile(AParent: TSQLElement) : TSQLDatabaseFileInfo;
+
+Var
+  I : INteger;
+  Last : TSQLToken;
+
+begin
+  // On entry, we're on the FILE token
+  Consume(tsqlFile);
+  Result:=TSQLDatabaseFileInfo(CreateElement(TSQLDatabaseFileInfo,APArent));
+  try
+    Expect(tsqlString);
+    Result.FileName:=CurrentTokenString;
+    getNextToken;
+    I:=0;
+    last:=tsqlEOF;
+    While (I<2) and (CurrentToken in [tsqlLength,tsqlStarting]) do
+      begin
+      Inc(I);
+      If (CurrentToken=tsqlLength) then
+        begin
+        If Last=tsqlLength then
+          UnexpectedToken;
+        Last:=tsqlLength;
+        GetNextToken;
+        if (CurrentToken=tsqlEq) then
+          GetNextToken;
+        Expect(tsqlIntegerNumber);
+        Result.Length:=StrToInt(CurrentTokenString);
+        GetNextToken;
+        If CurrentToken in [tsqlPage,tsqlPages] then
+          GetNextToken;
+        end
+      else if (CurrentToken=tsqlStarting) then
+        begin
+        If Last=tsqlStarting then
+          UnexpectedToken;
+        Last:=tsqlStarting;
+        GetNextToken;
+        if (CurrentToken=tsqlAt) then
+          begin
+          GetNextToken;
+          If CurrentToken=tsqlPage then
+            GetNextToken;
+          end;
+        Expect(tsqlIntegerNumber);
+        Result.StartPage:=StrToInt(CurrentTokenString);
+        GetNextToken;
+        end;
+      end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseCreateDatabaseStatement(AParent: TSQLElement; IsAlter: Boolean) : TSQLCreateDatabaseStatement;
+
+begin
+  // On entry, we're on the DATABASE or SCHEMA token
+  Result:=TSQLCreateDatabaseStatement(CreateElement(TSQLCreateDatabaseStatement,AParent));
+  try
+    Result.UseSchema:=(CurrentToken=tsqlSchema);
+    GetNextToken;
+    Expect(tsqlString);
+    Result.FileName:=CurrentTokenString;
+    GetNextToken;
+    If (CurrentToken=tsqlUSER) then
+      begin
+      GetNextToken;
+      Expect(tsqlString);
+      Result.UserName:=CurrentTokenString;
+      GetNextToken;
+      end;
+    If (CurrentToken=tsqlPassword) then
+      begin
+      GetNextToken;
+      Expect(tsqlString);
+      Result.Password:=CurrentTokenString;
+      GetNextToken;
+      end;
+    If (CurrentToken=tsqlPageSize) then
+      begin
+      GetNextToken;
+      if CurrentToken=tsqlEq then
+        GetNextToken;
+      Expect(tsqlIntegerNumber);
+      Result.Pagesize:=StrtoIntDef(CurrentTokenString,0);
+      GetNextToken;
+      end;
+    If (CurrentToken=tsqlLength) then
+      begin
+      GetNextToken;
+      if (CurrentToken=tsqlEq) then
+        GetNextToken;
+      Expect(tsqlIntegerNumber);
+      Result.Length:=StrtoIntDef(CurrentTokenString,0);
+      GetNextToken;
+      If CurrentToken in [tsqlPage,tsqlPages] then
+        GetNextToken;
+      end;
+    If (CurrentToken=tsqlDefault) then
+      begin
+      GetNextToken;
+      Consume(tsqlCharacter);
+      Consume(tsqlSet);
+      Expect(tsqlidentifier);
+      Result.CharSet:=CreateIdentifier(Result,CurrentTokenString);
+      GetNextToken;
+      end;
+    While (CurrentToken=tsqlFile) do
+      Result.SecondaryFiles.Add(ParseSecondaryFile(Result));
+  except
+    FreeAndNil(Result);
+    Raise
+  end;
+end;
+
+function TSQLParser.ParseCreateShadowStatement(AParent: TSQLElement;
+  IsAlter: Boolean): TSQLCreateShadowStatement;
+begin
+  // On entry, we're on the SHADOW token.
+  if IsAlter then
+    UnexpectedToken;
+  Consume(tsqlShadow);
+  Result:=TSQLCreateShadowStatement(CreateElement(TSQLCreateShadowStatement,AParent));
+  try
+    Expect(tsqlIntegerNumber);
+    Result.Number:=StrToInt(CurrentTokenString);
+    GetNextToken;
+    If (CurrentToken=tsqlManual) then
+      begin
+      Result.Manual:=True;
+      GetNextToken;
+      end
+    else If (CurrentToken=tsqlAuto) then
+      GetNextToken;
+    if (CurrentToken=tsqlConditional) then
+      begin
+      Result.Conditional:=True;
+      GetNextToken;
+      end;
+    expect(tsqlString);
+    Result.FileName:=CurrentTokenString;
+    GetNextToken;
+    If (CurrentToken=tsqlLength) then
+      begin
+      GetNextToken;
+      if (CurrentToken=tsqlEq) then
+        GetNextToken;
+      Expect(tsqlIntegerNumber);
+      Result.Length:=StrtoIntDef(CurrentTokenString,0);
+      GetNextToken;
+      If CurrentToken in [tsqlPage,tsqlPages] then
+        GetNextToken;
+      end;
+    While (CurrentToken=tsqlFile) do
+      Result.SecondaryFiles.Add(ParseSecondaryFile(Result));
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseAlterDatabaseStatement(AParent: TSQLElement;
+  IsAlter: Boolean): TSQLAlterDatabaseStatement;
+begin
+  // On entry, we're on the DATABASE or SCHEMA token.
+  Result:=TSQLAlterDatabaseStatement(CreateElement(TSQLAlterDatabaseStatement,APArent));
+  try
+    Result.UseSchema:=CurrentToken=tsqlSchema;
+    GetNextToken;
+    expect(tsqlAdd);
+    While (CurrentToken in [tsqlAdd,tsqlFile]) do
+      begin
+      if CurrentToken=tsqlAdd then
+        GetNextToken;
+      Expect(tsqlFile);
+      Result.Operations.Add(ParseSecondaryFile(Result));
+      end;
+    if Result.Operations.Count=0 then
+      UnexpectedToken([tsqlAdd]);
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+
+end;
+
+function TSQLParser.ParseCreateStatement(AParent: TSQLElement; IsAlter: Boolean
+  ): TSQLCreateOrAlterStatement;
+begin
+  Case GetNextToken of
+    tsqlTable      :  if IsAlter then
+                        Result:=ParseAlterTableStatement(AParent)
+                      else
+                        Result:=ParseCreateTableStatement(AParent);
+
+    tsqlUnique,
+    tsqlAscending,
+    tsqlDescending,
+    tsqlIndex      : Result:=ParseCreateIndexStatement(AParent,IsAlter);
+    tsqlView       : Result:=ParseCreateViewStatement(AParent,IsAlter);
+    tsqlProcedure  : Result:=ParseCreateProcedureStatement(AParent,IsAlter);
+    tsqlDomain     : Result:=ParseCreateDomainStatement(AParent,IsAlter);
+    tsqlGenerator  : Result:=ParseCreateGeneratorStatement(AParent,IsAlter);
+    tsqlException  : Result:=ParseCreateExceptionStatement(AParent,IsAlter);
+    tsqlTrigger    : Result:=ParseCreateTriggerStatement(AParent,IsAlter);
+    tsqlRole       : Result:=ParseCreateRoleStatement(AParent,IsAlter);
+    tsqlSchema,
+    tsqlDatabase   : If IsAlter then
+                       Result:=ParseAlterDatabaseStatement(AParent,IsAlter)
+                     else
+                       Result:=ParseCreateDatabaseStatement(AParent,IsAlter);
+    tsqlShadow       : Result:=ParseCreateShadowStatement(AParent,IsAlter);
+  else
+     Error(SErrExpectedDBObject,[CurrentTokenString]);
+  end;
+end;
+
+function TSQLParser.ParseDropStatement(AParent: TSQLElement
+  ): TSQLDropStatement;
+
+Var
+   C : TSQLElementClass;
+
+begin
+  // We're positioned on the DROP token.
+  C:=Nil;
+  Case GetNextToken of
+    {
+    Filter,
+    }
+    tsqlExternal : begin
+                   GetNextToken;
+                   Expect(tsqlFunction);
+                   C:=TSQLDropExternalFunctionStatement;
+                   end;
+    tsqlShadow     : C:=TSQLDropShadowStatement;
+    tsqlRole       : C:=TSQLDropRoleStatement;
+    tsqlDatabase   : C:=TSQLDropDatabaseStatement;
+    tsqlException  : C:=TSQLDropExceptionStatement;
+    tsqlTable      : C:=TSQLDropTableStatement;
+    tsqlIndex      : C:=TSQLDropIndexStatement;
+    tsqlView       : C:=TSQLDropViewStatement;
+    tsqlProcedure  : C:=TSQLDropProcedureStatement;
+    tsqlDomain     : C:=TSQLDropDomainStatement;
+    tsqlGenerator  : C:=TSQLDropGeneratorStatement;
+    tsqlTrigger    : C:=TSQLDropTriggerStatement;
+  else
+     Error(SErrExpectedDBObject,[CurrentTokenString]);
+  end;
+  GetNextToken;
+  If C=TSQLDropShadowStatement then
+    Expect(tsqlIntegerNumber)
+  else
+    Expect(tsqlIdentifier);
+  Result:=TSQLDropStatement(CreateElement(C,AParent));
+  Result.ObjectName:=CreateIdentifier(Result,CurrentTokenString);
+  GetNextToken; // Comma
+end;
+
+function TSQLParser.ParseRollbackStatement(AParent: TSQLElement
+  ): TSQLRollBackStatement;
+
+
+begin
+  // On entry, we're on the ROLLBACK statement
+  Consume(tsqlRollBack);
+  Result:=TSQLRollBackStatement(CreateElement(TSQLRollBackStatement,AParent));
+  try
+    If (CurrentToken=tsqlTransaction) then
+      begin
+      GetNextToken;
+      expect(tsqlidentifier);
+      Result.TransactionName:=CreateIdentifier(Result,CurrentTokenString);
+      GetNextToken;
+      end;
+    Result.Work:=(CurrentToken=tsqlWork);
+    if Result.Work then
+      GetNextToken;
+    Result.Release:=(CurrentToken=tsqlRelease);
+    if Result.Release then
+      GetNextToken;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseCommitStatement(AParent: TSQLElement
+  ): TSQLCommitStatement;
+begin
+  Consume(tsqlCommit);
+  Result:=TSQLCommitStatement(CreateElement(TSQLCommitStatement,AParent));
+  try
+    Result.Work:=(CurrentToken=tsqlWork);
+    if Result.Work then
+      GetNextToken;
+    If (CurrentToken=tsqlTransaction) then
+      begin
+      GetNextToken;
+      expect(tsqlidentifier);
+      Result.TransactionName:=CreateIdentifier(Result,CurrentTokenString);
+      GetNextToken;
+      end;
+    Result.Release:=(CurrentToken=tsqlRelease);
+    if Result.Release then
+      GetNextToken;
+    Result.Retain:=(CurrentToken=tsqlRetain);
+    if Result.Retain then
+      begin
+      GetNextToken;
+      If CurrentToken=tsqlSnapshot then
+        GetNextToken;
+      end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseExecuteProcedureStatement(AParent: TSQLElement): TSQLExecuteProcedureStatement;
+
+Var
+  NeedClose,
+  Done : Boolean;
+  TN : TSQLStringType;
+
+begin
+  Result:=Nil;
+  // On Entry, we're on the EXECUTE statement
+  Consume(tsqlExecute);
+  Consume(tsqlProcedure);
+  If (CurrentToken=tsqlTransaction) then
+    begin
+    GetNextToken;
+    Expect(TSQLIdentifier);
+    TN:=CurrentTokenString;
+    GetNextToken;
+    end;
+  Expect(tsqlIdentifier);
+  Result:=TSQLExecuteProcedureStatement(CreateELement(TSQLExecuteProcedureStatement,AParent));
+  try
+    Result.ProcedureName:=CreateIdentifier(Result,CurrentTokenString);
+    if (TN<>'') then
+      Result.TransactionName:=CreateIdentifier(Result,TN);
+    GetNextToken;
+    // ( is optional. It CAN be part of a (SELECT, and then it is NOT part of the brackets around the params.
+    NeedClose:=(CurrentToken=tsqlBraceOpen) and (PeekNextToken<>tsqlSelect);
+    If NeedClose then
+      GetNextToken;
+    Done:=False;
+    If Not (CurrentToken in [tsqlSemicolon,tsqlEOF,tsqlReturningValues]) then
+      Repeat
+        Result.Params.Add(ParseExprLevel1(Result,[eoFieldValue]));
+        If CurrentToken=tsqlComma then
+          GetNextToken
+        else if (CurrentToken=tsqlBraceClose) then
+          begin
+          if Not NeedClose then
+            UnexpectedToken;
+          Done:=True;
+          GetNextToken;
+          end
+        else
+          begin
+          If NeedClose then
+            UnexpectedToken([tsqlBraceClose]);
+          Expect([tsqlEOF,tsqlSemicolon,tsqlReturningValues]);
+          Done:=True;
+          end;
+      until Done;
+    if (CurrentToken=tsqlReturningValues) then
+      begin
+      GetNextToken;
+      NeedClose:=(CurrentToken=tsqlBraceOpen);
+      If NeedClose then
+        Consume(tsqlBraceOpen);
+      Repeat
+        if CurrentToken=tsqlComma then
+          GetNextToken;
+        if CurrentToken=tsqlColon then
+          GetNextToken;
+        Expect(tsqlIdentifier);
+        Result.Returning.Add(CreateIdentifier(Result,CurrentTokenString));
+        GetNextToken;
+      until (CurrentToken<>tsqlComma);
+      If NeedClose then
+        Consume(tsqlBraceClose);
+      end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseSetStatement(AParent: TSQLElement): TSQLStatement;
+begin
+  // On Entry, we're on the SET statement
+  Consume(tsqlSet);
+  Case CurrentToken of
+    tsqlGenerator : Result:=ParseSetGeneratorStatement(AParent)
+  else
+    // For the time being
+    UnexpectedToken;
+  end;
+end;
+
+function TSQLParser.ParseConnectStatement(AParent: TSQLElement
+  ): TSQLConnectStatement;
+begin
+  // On entry, we're on CONNECT
+  consume(tsqlConnect);
+  Expect(tsqlString);
+  Result:=TSQLConnectStatement(CreateElement(TSQLConnectStatement,AParent));
+  try
+    Result.DatabaseName:=CurrentTokenString;
+    GetNextToken;
+    If CurrentToken=tsqlUSER then
+      begin
+      GetNextToken;
+      Expect(tsqlString);
+      Result.UserName:=CurrentTokenString;
+      GetNextToken;
+      end;
+    If CurrentToken=tsqlPassword then
+      begin
+      GetNextToken;
+      Expect(tsqlString);
+      Result.Password:=CurrentTokenString;
+      GetNextToken;
+      end;
+    If CurrentToken=tsqlRole then
+      begin
+      GetNextToken;
+      Expect(tsqlString);
+      Result.Role:=CurrentTokenString;
+      GetNextToken;
+      end;
+    If CurrentToken=tsqlCache then
+      begin
+      GetNextToken;
+      Expect(tsqlIntegerNumber);
+      Result.Cache:=StrtoIntDef(CurrentTokenString,0);
+      GetNextToken;
+      end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+constructor TSQLParser.Create(AInput: TStream);
+begin
+  FInput:=AInput;
+  FCurrent:=TSQLUnknown;
+  FScanner:=TSQLScanner.Create(FInput);
+  FFreeScanner:=True;
+end;
+
+constructor TSQLParser.Create(AScanner: TSQLScanner);
+begin
+  FCurrent:=TSQLUnknown;
+  FScanner:=AScanner;
+  FFreeScanner:=False;
+end;
+
+destructor TSQLParser.Destroy;
+begin
+  If FFreeScanner then
+    FreeAndNil(FScanner);
+  inherited Destroy;
+end;
+
+Function TSQLParser.ParseDeclareFunctionStatement(AParent : TSQLElement) : TSQLDeclareExternalFunctionStatement;
+
+begin
+  // On entry, we're on the EXTERNAL token
+  Consume(tsqlExternal);
+  Consume(tsqlFunction);
+  Expect(tsqlidentifier);
+  Result:=TSQLDeclareExternalFunctionStatement(CreateElement(TSQLDeclareExternalFunctionStatement,AParent));
+  try
+    Result.ObjectName:=CreateIdentifier(Result,CurrentTokenString);
+    If (PeekNextToken=tsqlReturns) then
+      GetNextToken
+    else
+      Repeat
+        Result.Arguments.Add(Self.ParseTypeDefinition(Result,[ptfExternalFunction]));
+      Until (CurrentToken<>tsqlComma);
+    Expect(tsqlReturns);
+    Result.ReturnType:=ParseTypeDefinition(Result,[ptfExternalFunctionResult]);
+    Result.FreeIt:=(CurrentToken=tsqlFreeIt);
+    If Result.FreeIt then
+      GetNextToken;
+    Consume(tsqlEntryPoint);
+    Expect(tsqlString);
+    Result.EntryPoint:=CurrentTokenString;
+    GetNextToken;
+    Consume(tsqlModuleName);
+    Expect(tsqlString);
+    Result.ModuleName:=CurrentTokenstring;
+    GetNextToken;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+Function TSQLParser.ParseDeclareStatement(AParent : TSQLElement) : TSQLStatement;
+
+
+begin
+  // On entry, we're on the DECLARE statement
+  Consume(tsqlDeclare);
+  // For the moment, only 'DECLARE EXTERNAL FUNCTION' is supported
+  Case CurrentToken of
+    tsqlExternal : Result:=ParseDeclareFunctionStatement(AParent);
+  else
+    UnexpectedToken([tsqlExternal]);
+  end;
+
+end;
+
+procedure TSQLParser.ParseGranteeList(AParent: TSQLElement;
+  List: TSQLElementList; AllowObject, AllowGroup, AllowPublic: Boolean; IsRevoke: Boolean = False);
+
+Type
+  TSQLGranteeClass = Class of TSQLGrantee;
+
+  Function CreateGrantee(NextIdentifier : Boolean; AClass : TSQLGranteeClass) : TSQLGrantee;
+  begin
+    if NextIdentifier then
+      begin
+      GetNextToken;
+      Expect(tsqlIdentifier);
+      end;
+    Result:=TSQLGrantee(CreateElement(AClass,AParent));
+    Result.Name:=CurrentTokenString;
+    List.Add(Result);
+  end;
+
+Var
+  E : TSQLTokens;
+
+begin
+  if IsRevoke then
+    Consume(tsqlFrom)
+  else
+    Consume(tsqlTo);
+  E:=[tsqlIdentifier,tsqlUser];
+  If AllowObject then
+    E:=E+[tsqlProcedure,tsqlView,tsqlTrigger,tsqlPublic]
+  else If AllowPublic then
+    E:=E+[tsqlPublic];
+  If AllowGroup then
+    E:=E+[tsqlGROUP];
+  Expect(E);
+  Repeat
+    If CurrentToken=tsqlComma then
+      GetNextToken;
+    Case CurrentToken of
+      tsqlUser,
+      tsqlIdentifier :
+          CreateGrantee(CurrentToken=tsqlUser,TSQLUserGrantee);
+      TsqlGroup :
+        begin
+        If Not AllowGroup then
+          UnexpectedToken;
+        CreateGrantee(true,TSQLGroupGrantee);
+        end;
+      TsqlPublic :
+        begin
+        If Not (AllowPublic or AllowObject)  then
+          UnexpectedToken;
+        CreateGrantee(False,TSQLPublicGrantee);
+        end;
+      TsqlTrigger:
+        begin
+        If Not AllowObject then
+          UnexpectedToken;
+        CreateGrantee(True,TSQLTriggerGrantee);
+        end;
+      TsqlView:
+        begin
+        If Not AllowObject then
+          UnexpectedToken;
+        CreateGrantee(true,TSQLViewGrantee);
+        end;
+      TsqlProcedure:
+        begin
+        If Not AllowObject then
+          UnexpectedToken;
+        CreateGrantee(true,TSQLProcedureGrantee);
+        end;
+    end;
+  Until (GetNextToken<>tsqlComma);
+
+end;
+
+function TSQLParser.ParseGrantTableStatement(AParent: TSQLElement): TSQLTableGrantStatement;
+
+Var
+  C : TSQLColumnPrivilege;
+  P : TSQLPrivilege;
+
+begin
+  Result:=TSQLTableGrantStatement(CreateElement(TSQLTableGrantStatement,APArent));
+  try
+    // On entry, we're on the first ALL/SELECT/UPDATE/INSERT/DELETE/REFERENCE etc. token.
+    if CurrentToken=tsqlAll then
+      begin
+      Result.Privileges.Add(CreateElement(TSQLAllPrivilege,Result));
+      If GetNextToken=tsqlPrivileges then
+        GetNextToken;
+      end
+    else
+      Repeat
+        P:=Nil;
+        C:=Nil;
+        if CurrentToken=tsqlComma then
+          GetNextToken;
+        Case CurrentToken of
+          tsqlSelect : P:=TSQLSelectPrivilege(CreateElement(TSQLSelectPrivilege,Result));
+          tsqlInsert : P:=TSQLInsertPrivilege(CreateElement(TSQLInsertPrivilege,Result));
+          tsqlDelete : P:=TSQLDeletePrivilege(CreateElement(TSQLDeletePrivilege,Result));
+          tsqlUpdate,
+          tsqlReferences :
+            begin
+            if CurrentToken=tsqlUpdate then
+              C:=TSQLUpdatePrivilege(CreateElement(TSQLUpdatePrivilege,AParent))
+            else
+              C:=TSQLReferencePrivilege(CreateElement(TSQLReferencePrivilege,AParent));
+            P:=C;
+            GetNextToken;
+            If (CurrentToken=tsqlBraceOpen) then
+              begin
+              GetNextToken;
+              C.Columns:=TSQLElementList.Create(True);
+              ParseIdentifierList(C,C.Columns);
+              end;
+            end;
+        else
+          UnexpectedToken([tsqlselect,tsqlInsert,tsqlDelete,tsqlUpdate,tsqlReferences]);
+        end;
+        Result.Privileges.Add(P);
+        If C=Nil then
+          GetNextToken;
+      Until (CurrentToken<>tsqlComma);
+    Consume(tsqlOn);
+    Expect(tsqlidentifier);
+    Result.TableName:=CreateIdentifier(Result,CurrentTokenString);
+    GetNextToken;
+    ParseGranteeList(Result,Result.Grantees,True,True,True);
+    If (CurrentToken=tsqlWith) then
+      begin
+      Consume(tsqlWith);
+      Consume(tsqlGrant);
+      Consume(tsqlOption);
+      Result.GrantOption:=True;
+      end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseRevokeExecuteStatement(AParent: TSQLElement
+  ): TSQLProcedureRevokeStatement;
+BEGIN
+  // On entry, we're on the EXECUTE token
+  Consume(tsqlExecute);
+  Consume(tsqlOn);
+  Consume(tsqlProcedure);
+  Expect(tsqlIdentifier);
+  Result:=TSQLProcedureRevokeStatement(CreateElement(TSQLProcedureRevokeStatement,AParent));
+  try
+    Result.ProcedureName:=CreateIdentifier(Result,CurrentTokenString);
+    GetNextToken;
+    ParseGranteeList(Result,Result.Grantees,True,False,True,True);
+    If (CurrentToken=tsqlWith) then
+      begin
+      Consume(tsqlWith);
+      Consume(tsqlGrant);
+      Consume(tsqlOption);
+      Result.GrantOption:=True;
+      end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseRevokeRoleStatement(AParent: TSQLElement
+  ): TSQLRoleRevokeStatement;
+begin
+  Result:=Nil;
+  // On entry, we're on the identifier token
+  expect(tsqlIdentifier);
+  Result:=TSQLRoleRevokeStatement(CreateElement(TSQLRoleRevokeStatement,AParent));
+  try
+    Repeat
+      if CurrentToken=tsqlComma then
+        GetNextToken;
+      expect(tsqlIdentifier);
+      Result.Roles.Add(CreateIDentifier(Aparent,CurrentTokenString));
+    Until (GetNextToken<>tsqlComma);
+    Expect(tsqlFrom);
+    ParseGranteeList(Result,Result.Grantees,False,False,True,True);
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseRevokeTableStatement(AParent: TSQLElement
+  ): TSQLTableRevokeStatement;
+Var
+  C : TSQLColumnPrivilege;
+  P : TSQLPrivilege;
+
+begin
+  Result:=TSQLTableRevokeStatement(CreateElement(TSQLTableRevokeStatement,APArent));
+  try
+    // On entry, we're on the first GRANT,ALL/SELECT/UPDATE/INSERT/DELETE/REFERENCE etc. token.
+    If (CurrentToken=tsqlGrant) then
+      begin
+      Consume(tsqlGrant);
+      Consume(tsqlOption);
+      Consume(tsqlFor);
+      Result.GrantOption:=True;
+      end;
+    if CurrentToken=tsqlAll then
+      begin
+      Result.Privileges.Add(CreateElement(TSQLAllPrivilege,Result));
+      If GetNextToken=tsqlPrivileges then
+        GetNextToken;
+      end
+    else
+      Repeat
+        P:=Nil;
+        C:=Nil;
+        if CurrentToken=tsqlComma then
+          GetNextToken;
+        Case CurrentToken of
+          tsqlSelect : P:=TSQLSelectPrivilege(CreateElement(TSQLSelectPrivilege,Result));
+          tsqlInsert : P:=TSQLInsertPrivilege(CreateElement(TSQLInsertPrivilege,Result));
+          tsqlDelete : P:=TSQLDeletePrivilege(CreateElement(TSQLDeletePrivilege,Result));
+          tsqlUpdate,
+          tsqlReferences :
+            begin
+            if CurrentToken=tsqlUpdate then
+              C:=TSQLUpdatePrivilege(CreateElement(TSQLUpdatePrivilege,AParent))
+            else
+              C:=TSQLReferencePrivilege(CreateElement(TSQLReferencePrivilege,AParent));
+            P:=C;
+            GetNextToken;
+            If (CurrentToken=tsqlBraceOpen) then
+              begin
+              GetNextToken;
+              C.Columns:=TSQLElementList.Create(True);
+              ParseIdentifierList(C,C.Columns);
+              end;
+            end;
+        else
+          UnexpectedToken([tsqlselect,tsqlInsert,tsqlDelete,tsqlUpdate,tsqlReferences]);
+        end;
+        Result.Privileges.Add(P);
+        If C=Nil then
+          GetNextToken;
+      Until (CurrentToken<>tsqlComma);
+    Consume(tsqlOn);
+    Expect(tsqlidentifier);
+    Result.TableName:=CreateIdentifier(Result,CurrentTokenString);
+    GetNextToken;
+    ParseGranteeList(Result,Result.Grantees,True,True,True,True);
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseGrantExecuteStatement(AParent: TSQLElement): TSQLProcedureGrantStatement;
+
+begin
+  // On entry, we're on the EXECUTE token
+  Consume(tsqlExecute);
+  Consume(tsqlOn);
+  Consume(tsqlProcedure);
+  Expect(tsqlIdentifier);
+  Result:=TSQLProcedureGrantStatement(CreateElement(TSQLProcedureGrantStatement,AParent));
+  try
+    Result.ProcedureName:=CreateIdentifier(Result,CurrentTokenString);
+    GetNextToken;
+    ParseGranteeList(Result,Result.Grantees,True,False,True);
+    If (CurrentToken=tsqlWith) then
+      begin
+      Consume(tsqlWith);
+      Consume(tsqlGrant);
+      Consume(tsqlOption);
+      Result.GrantOption:=True;
+      end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseGrantRoleStatement(AParent: TSQLElement): TSQLRoleGrantStatement;
+
+begin
+  Result:=Nil;
+  // On entry, we're on the identifier token
+  expect(tsqlIdentifier);
+  Result:=TSQLRoleGrantStatement(CreateElement(TSQLRoleGrantStatement,AParent));
+  try
+    Repeat
+      if CurrentToken=tsqlComma then
+        GetNextToken;
+      expect(tsqlIdentifier);
+      Result.Roles.Add(CreateIDentifier(Aparent,CurrentTokenString));
+    Until (GetNextToken<>tsqlComma);
+    Expect(tsqlTo);
+    ParseGranteeList(Result,Result.Grantees,False,False,True);
+    If (CurrentToken=tsqlWith) then
+      begin
+      Consume(tsqlWith);
+      Consume(tsqlAdmin);
+      Consume(tsqlOption);
+      Result.AdminOption:=True;
+      end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseGrantStatement(AParent: TSQLElement): TSQLGrantStatement;
+
+begin
+  // On entry, we're on the GRANT token
+  Result:=Nil;
+  try
+    Consume(tsqlGrant);
+    Case CurrentToken of
+      tsqlExecute: Result:=ParseGrantExecutestatement(AParent);
+      tsqlAll,
+      tsqlUpdate,
+      tsqlReferences,
+      tsqlInsert,
+      tsqldelete,
+      tsqlSelect : Result:=ParseGrantTablestatement(AParent);
+      tsqlIdentifier : Result:=ParseGrantRolestatement(AParent);
+    else
+      UnExpectedToken([tsqlIdentifier, tsqlExecute, tsqlall,
+                       tsqlUpdate, tsqldelete, tsqlReferences, tsqlInsert, tsqlSelect]);
+    end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.ParseRevokeStatement(AParent: TSQLElement
+  ): TSQLGrantStatement;
+begin
+  // On entry, we're on the GRANT token
+  Result:=Nil;
+  try
+    Consume(tsqlRevoke);
+    Case CurrentToken of
+      tsqlExecute: Result:=ParseRevokeExecutestatement(AParent);
+      tsqlGrant,
+      tsqlAll,
+      tsqlUpdate,
+      tsqlReferences,
+      tsqlInsert,
+      tsqldelete,
+      tsqlSelect : Result:=ParseRevokeTablestatement(AParent);
+      tsqlIdentifier : Result:=ParseRevokeRolestatement(AParent);
+    else
+      UnExpectedToken([tsqlIdentifier, tsqlExecute,tsqlgrant,tsqlall,
+                       tsqlUpdate, tsqldelete, tsqlReferences, tsqlInsert, tsqlSelect]);
+    end;
+  except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+function TSQLParser.Parse: TSQLElement;
+begin
+  GetNextToken;
+  Case CurrentToken of
+    tsqlSelect : Result:=ParseSelectStatement(Nil,[]);
+    tsqlUpdate : Result:=ParseUpdateStatement(Nil);
+    tsqlInsert : Result:=ParseInsertStatement(Nil);
+    tsqlDelete : Result:=ParseDeleteStatement(Nil);
+    tsqlCreate,
+    tsqlAlter : Result:=ParseCreateStatement(Nil,(tsqlAlter=CurrentToken));
+    tsqlDrop  : Result:=ParseDropStatement(Nil);
+    tsqlSet : Result:=ParseSetStatement(Nil);
+    tsqlRollback : Result:=ParseRollBackStatement(Nil);
+    tsqlCommit : Result:=ParseCommitStatement(Nil);
+    tsqlExecute : Result:=ParseExecuteProcedureStatement(Nil);
+    tsqlConnect : Result:=ParseConnectStatement(Nil);
+    tsqlDeclare : Result:=ParseDeclareStatement(Nil);
+    tsqlGrant : Result:=ParseGrantStatement(Nil);
+    tsqlRevoke : Result:=ParseRevokeStatement(Nil);
+  else
+    UnexpectedToken;
+  end;
+  if Not (CurrentToken in [tsqlEOF,tsqlSemicolon]) then
+    begin
+    FreeAndNil(Result);
+    if (CurrentToken=tsqlBraceClose) then
+      Error(SerrUnmatchedBrace);
+    Error(SErrUnexpectedToken,[CurrentTokenString]);
+    end;
+end;
+
+function TSQLParser.ParseScript(AllowPartial : Boolean = False): TSQLElementList;
+
+Var
+   E : TSQLElement;
+
+begin
+  Result:=TSQLElementList.Create(True);
+  try
+    E:=Parse;
+    While (E<>Nil) do
+      begin
+      Result.Add(E);
+      E:=Parse;
+      end;
+  except
+    If Not AllowPartial then
+      begin
+      FreeAndNil(Result);
+      Raise;
+      end;
+  end;
+end;
+
+function TSQLParser.CurrentToken: TSQLToken;
+begin
+  Result:=FCurrent;
+end;
+
+function TSQLParser.CurrentTokenString: String;
+begin
+  Result:=FCurrentString;
+end;
+
+function TSQLParser.GetNextToken: TSQLToken;
+begin
+  FPrevious:=FCurrent;
+  If (FPeekToken<>tsqlunknown) then
+     begin
+     FCurrent:=FPeekToken;
+     FCurrentString:=FPeekTokenString;
+     FPeekToken:=tsqlUnknown;
+     FPeekTokenString:='';
+     end
+  else
+    begin
+    FCurrent:=FScanner.FetchToken;
+    FCurrentString:=FScanner.CurTokenString;
+    end;
+  Result:=FCurrent;
+  {$ifdef debugparser}Writeln('GetNextToken : ',GetEnumName(TypeInfo(TSQLToken),Ord(FCurrent)), ' As string: ',FCurrentString);{$endif debugparser}
+end;
+
+function TSQLParser.PeekNextToken: TSQLToken;
+begin
+  If (FPeekToken=tsqlUnknown) then
+    begin
+    FPeekToken:=FScanner.FetchToken;
+    FPeekTokenString:=FScanner.CurTokenString;
+    end;
+  {$ifdef debugparser}Writeln('PeekNextToken : ',GetEnumName(TypeInfo(TSQLToken),Ord(FPeekToken)), ' As string: ',FPeekTokenString);{$endif debugparser}
+  Result:=FPeekToken;
+end;
+
+function TSQLParser.PreviousToken: TSQLToken;
+begin
+  Result:=FPRevious;
+end;
+
+function TSQLParser.IsEndOfLine: Boolean;
+begin
+  Result:=FScanner.IsEndOfLine;
+end;
+
+end.
+

+ 948 - 0
packages/fcl-db/src/sql/fpsqlscanner.pp

@@ -0,0 +1,948 @@
+{
+    This file is part of the Free Component Library
+    Copyright (c) 2010 by the Free Pascal development team
+
+    SQL source lexical scanner
+
+    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.
+
+ **********************************************************************}
+
+{$mode objfpc}
+{$h+}
+
+unit fpsqlscanner;
+
+interface
+
+uses SysUtils, Classes, Contnrs;
+
+resourcestring
+  SErrInvalidCharacter = 'Invalid character ''%s''';
+  SErrOpenString = 'string exceeds end of line';
+  SErrIncludeFileNotFound = 'Could not find include file ''%s''';
+  SErrIfXXXNestingLimitReached = 'Nesting of $IFxxx too deep';
+  SErrInvalidPPElse = '$ELSE without matching $IFxxx';
+  SErrInvalidPPEndif = '$ENDIF without matching $IFxxx';
+  SInvalidHexadecimalNumber = 'Invalid decimal number';
+  SErrInvalidNonEqual = 'SyntaxError: != or !== expected';
+  SBarExpected = '| character expected';
+
+type
+
+   TSQLToken = (tsqlUnknown,
+   // Specials
+   tsqlEOF,tsqlWhiteSpace,tsqlString, tsqlIdentifier,tsqlIntegerNumber, tsqlFloatNumber, tsqlComment,
+   tsqlBraceOpen,tsqlBraceClose,tsqlSquareBraceOpen,tsqlSquareBraceClose,
+   tsqlPlaceHolder,tsqlCOMMA,tsqlCOLON, tsqlDOT,tsqlSEMICOLON, tsqlGT,tsqlLT,
+   tsqlPLUS,tsqlMINUS,tsqlMUL,tsqlDIV,tsqlConcatenate,
+   tsqlEQ,tsqlGE, tsqlLE, tsqlNE,
+   { Reserved words start here. They must be last }
+   tsqlALL, tsqlAND, tsqlANY, tsqlASC, tsqlASCENDING, tsqlAVG, tsqlALTER, tsqlAdd, tsqlActive, tsqlAction, tsqlAs,tsqlAt, tsqlAuto,tsqlAfter,tsqlAdmin,
+   tsqlBETWEEN, tsqlBY, tsqlBLOB,tsqlBegin,  tsqlBefore,
+   tsqlCOLLATE, tsqlCONTAINING, tsqlCOUNT, tsqlCREATE, tsqlCOLUMN, tsqlCONSTRAINT, tsqlChar,tsqlCHARACTER, tsqlCHECK, tsqlComputed,tsqlCASCADE, tsqlCast, tsqlCommit,tsqlConnect,tsqlCache,tsqlConditional,tsqlCString,
+   tsqlDESC, tsqlDESCENDING, tsqlDISTINCT, tsqlDEFAULT, tsqlDELETE, tsqlDO, tsqlDECLARE, tsqlDROP, tsqlDomain, tsqlDecimal, tsqlDate,tsqlDatabase,
+   tsqlESCAPE, tsqlEXISTS, tsqlELSE, tsqlException,   tsqlExternal, tsqlExecute, tsqlEnd,tsqlExit,tsqlEntrypoint,tsqlExtract,
+   tsqlFROM, tsqlFULL, tsqlFOREIGN, tsqlFOR, tsqlFUNCTION, tsqlFLOAT, tsqlFile,tsqlFreeIt,
+   tsqlGenerator, tsqlGROUP, tsqlGenID,tsqlGDSCODE,tsqlGrant,
+   tsqlHAVING,
+   tsqlIF, tsqlIN, tsqlINNER, tsqlINSERT, tsqlINT, tsqlINTEGER, tsqlINTO, tsqlIS, tsqlINDEX,  tsqlInactive,
+   tsqlJOIN,
+   tsqlKEY,
+   tsqlLEFT, tsqlLIKE, tsqlLength,
+   tsqlMAX, tsqlMIN, tsqlMERGE, tsqlManual, tsqlModuleName,
+   tsqlNOT, tsqlNULL, tsqlNUMERIC , tsqlNChar, tsqlNATIONAL,tsqlNO, tsqlNatural,
+   tsqlON, tsqlOR, tsqlORDER, tsqlOUTER, tsqlOption,
+   tsqlPRIMARY,  tsqlProcedure, tsqlPosition, tsqlPlan, tsqlPassword, tsqlPage,tsqlPages,tsqlPageSize,tsqlPostEvent,tsqlPrivileges,tsqlPublic,
+   tsqlRIGHT, tsqlROLE, tsqlReferences, tsqlRollBack, tsqlRelease,  tsqlretain,  tsqlReturningValues,tsqlReturns, tsqlrevoke,
+   tsqlSELECT, tsqlSET, tsqlSINGULAR, tsqlSOME, tsqlSTARTING, tsqlSUM, tsqlSKIP,tsqlSUBTYPE,tsqlSize,tsqlSegment, tsqlSORT, tsqlSnapShot,tsqlSchema,tsqlShadow,tsqlSuspend,tsqlSQLCode,tsqlSmallint,
+   tSQLTABLE, tsqlTrigger,tsqlTime,tsqlTimeStamp,tsqlType, tsqlTo, tsqlTransaction,tsqlThen,
+   tsqlUNION, tsqlUPDATE, tsqlUPPER,  tsqlUNIQUE, tsqlUSER,
+   tsqlValue, tsqlVALUES, tsqlVARIABLE,  tsqlVIEW, tsqlVARCHAR,TSQLVARYING,
+   tsqlWHERE, tsqlWITH, tsqlWHILE, tsqlWork, tsqlWhen
+ );
+   TSQLTokens = set of TSQLToken;
+
+const
+  FirstKeyword = tsqlAll;
+  LastKeyWord = tsqlWhen;
+  sqlComparisons = [tsqleq,tsqlGE,tsqlLE,tsqlNE,tsqlGT,tsqlLT,tsqlIn, tsqlis,
+                    tsqlbetween,tsqlLike,tsqlContaining,tsqlStarting,tsqlnot];
+  sqlInvertableComparisons = [tsqlLike,tsqlContaining,tsqlStarting,tsqlin,tsqlis, tsqlbetween];
+
+  TokenInfos: array[TSQLToken] of string = ('unknown',
+       // Specials
+       'EOF','whitespace','String', 'identifier','integer number','float number', 'comment',
+       '(',')', '[',']',
+       '?',',',':','.',';','>','<',
+       '+','-','*','/','||',
+       '=','>=','<=','<>',
+       // Identifiers last
+       'ALL', 'AND', 'ANY', 'ASC', 'ASCENDING', 'AVG', 'ALTER', 'ADD','ACTIVE','ACTION', 'AS', 'AT', 'AUTO', 'AFTER', 'ADMIN',
+       'BETWEEN', 'BY', 'BLOB','BEGIN', 'BEFORE',
+       'COLLATE', 'CONTAINING', 'COUNT', 'CREATE', 'COLUMN', 'CONSTRAINT', 'CHAR','CHARACTER','CHECK', 'COMPUTED','CASCADE','CAST', 'COMMIT', 'CONNECT', 'CACHE','CONDITIONAL', 'CSTRING',
+       'DESC', 'DESCENDING', 'DISTINCT',  'DEFAULT', 'DELETE', 'DO', 'DECLARE', 'DROP', 'DOMAIN', 'DECIMAL', 'DATE','DATABASE',
+       'ESCAPE', 'EXISTS', 'ELSE', 'EXCEPTION', 'EXTERNAL','EXECUTE', 'END','EXIT','ENTRY_POINT','EXTRACT',
+       'FROM', 'FULL','FOREIGN', 'FOR', 'FUNCTION', 'FLOAT','FILE', 'FREE_IT',
+       'GENERATOR', 'GROUP', 'GEN_ID','GDSCODE','GRANT',
+       'HAVING',
+       'IF', 'IN', 'INNER', 'INSERT', 'INT', 'INTEGER', 'INTO', 'IS', 'INDEX', 'INACTIVE',
+       'JOIN',
+       'KEY',
+       'LEFT', 'LIKE', 'LENGTH',
+       'MAX', 'MIN', 'MERGE', 'MANUAL', 'MODULE_NAME',
+       'NOT', 'NULL', 'NUMERIC','NCHAR','NATIONAL', 'NO', 'NATURAL',
+       'ON', 'OR', 'ORDER', 'OUTER', 'OPTION',
+       'PRIMARY', 'PROCEDURE','POSITION','PLAN', 'PASSWORD','PAGE','PAGES','PAGE_SIZE','POST_EVENT','PRIVILEGES','PUBLIC',
+       'RIGHT', 'ROLE', 'REFERENCES', 'ROLLBACK','RELEASE', 'RETAIN', 'RETURNING_VALUES', 'RETURNS','REVOKE',
+       'SELECT', 'SET', 'SINGULAR', 'SOME', 'STARTING', 'SUM', 'SKIP','SUB_TYPE', 'SIZE', 'SEGMENT', 'SORT', 'SNAPSHOT','SCHEMA','SHADOW','SUSPEND','SQLCODE','SMALLINT',
+       'TABLE','TRIGGER',  'TIME','TIMESTAMP',  'TYPE', 'TO', 'TRANSACTION','THEN',
+       'UNION', 'UPDATE', 'UPPER', 'UNIQUE', 'USER',
+       'VALUE','VALUES','VARIABLE', 'VIEW','VARCHAR','VARYING',
+       'WHERE', 'WITH', 'WHILE','WORK','WHEN'
+  );
+
+Type
+  TLineReader = class
+  public
+    function IsEOF: Boolean; virtual; abstract;
+    function ReadLine: string; virtual; abstract;
+  end;
+
+  { TStreamLineReader }
+
+  TStreamLineReader = class(TLineReader)
+  private
+    FStream : TStream;
+    Buffer : Array[0..1024] of Byte;
+    FBufPos,
+    FBufLen : Integer;
+    procedure FillBuffer;
+  public
+    Constructor Create(AStream : TStream);
+    function IsEOF: Boolean; override;
+    function ReadLine: string; override;
+  end;
+
+  TFileLineReader = class(TLineReader)
+  private
+    FTextFile: Text;
+    FileOpened: Boolean;
+  public
+    constructor Create(const AFilename: string);
+    destructor Destroy; override;
+    function IsEOF: Boolean; override;
+    function ReadLine: string; override;
+  end;
+
+  ESQLScannerError       = class(Exception);
+
+  { TSQLScanner }
+  TSQLScannerOption = (soReturnComments,
+                       soReturnWhiteSpace,
+                       soBackslashEscapes,
+                       soNoDoubleDelimIsChar,
+                       soDoubleQuoteStringLiteral,  // Default: single quote is string literal
+                       soSingleQuoteIdentifier,     // Default: double quote is identifier. Ignored if soDoubleQuoteStringLiteral is not specified
+                       soBackQuoteIdentifier        // Default: double quote is identifier
+                       );
+  TSQLScannerOptions = Set of TSQLScannerOption;
+
+  TSQLScanner = class
+  private
+    FOptions: TSQLScannerOptions;
+    FReturnComments: Boolean;
+    FReturnWhiteSpace: Boolean;
+    FSourceFile: TLineReader;
+    FSourceFilename: string;
+    FCurRow: Integer;
+    FCurToken: TSQLToken;
+    FCurTokenString: string;
+    FCurLine: string;
+    TokenStr: PChar;
+    FSourceStream : TStream;
+    FOwnSourceFile : Boolean;
+    FKeyWords : TFPHashList;
+    FExclude : TStringList;
+    function CommentDiv: TSQLToken;
+    function DoIdentifier : TSQLToken;
+    function DoMultiLineComment: TSQLToken;
+    function DoNumericLiteral: TSQLToken;
+    function DoSingleLineComment: TSQLToken;
+    function DoStringLiteral: TSQLToken;
+    function DoWhiteSpace: TSQLToken;
+    function FetchLine: Boolean;
+    function GetCurColumn: Integer;
+    function GetExcludeKeywords: TStrings;
+    function ReadUnicodeEscape: WideChar;
+    procedure SetExcludeKeywords(const AValue: TStrings);
+    procedure Setoptions(const AValue: TSQLScannerOptions);
+    procedure ClearKeywords(Sender: TObject);
+  protected
+    Procedure BuildKeyWords; virtual;
+    procedure Error(const Msg: string);overload;
+    procedure Error(const Msg: string; Args: array of Const);overload;
+  public
+    constructor Create(ALineReader: TLineReader);
+    constructor Create(AStream : TStream);
+    destructor Destroy; override;
+    procedure OpenFile(const AFilename: string);
+    Function FetchToken: TSQLToken;
+    Function IsEndOfLine : Boolean;
+    Property Options : TSQLScannerOptions Read FOptions Write Setoptions;
+    property SourceFile: TLineReader read FSourceFile;
+    property CurFilename: string read FSourceFilename;
+    property CurLine: string read FCurLine;
+    property CurRow: Integer read FCurRow;
+    property CurColumn: Integer read GetCurColumn;
+    property CurToken: TSQLToken read FCurToken;
+    property CurTokenString: string read FCurTokenString;
+    Property ExcludeKeywords : TStrings Read GetExcludeKeywords Write SetExcludeKeywords;
+  end;
+
+
+implementation
+
+Var
+  IdentifierTokens : array[FirstKeyword..LastKeyWord] of TSQLToken;
+  IdentifierTokensOK : Boolean;
+
+Resourcestring
+  SErrUNknownToken = 'Unknown token: %s';
+
+Procedure BuildIdentifierTokens;
+
+Var
+  T : TSQLToken;
+
+begin
+  For T:=FirstKeyword to LastKeyWord do
+    IdentifierTokens[T]:=T;
+end;
+
+constructor TFileLineReader.Create(const AFilename: string);
+begin
+  inherited Create;
+  Assign(FTextFile, AFilename);
+  Reset(FTextFile);
+  FileOpened := true;
+end;
+
+destructor TFileLineReader.Destroy;
+begin
+  if FileOpened then
+    Close(FTextFile);
+  inherited Destroy;
+end;
+
+function TFileLineReader.IsEOF: Boolean;
+begin
+  Result := EOF(FTextFile);
+end;
+
+function TFileLineReader.ReadLine: string;
+begin
+  ReadLn(FTextFile, Result);
+end;
+
+constructor TSQLScanner.Create(ALineReader: TLineReader);
+begin
+  inherited Create;
+  FSourceFile := ALineReader;
+  FKeywords:=TFPHashList.Create;
+end;
+
+constructor TSQLScanner.Create(AStream: TStream);
+begin
+  FSourceStream:=ASTream;
+  FOwnSourceFile:=True;
+  Create(TStreamLineReader.Create(AStream));
+end;
+
+destructor TSQLScanner.Destroy;
+begin
+  If FOwnSourceFile then
+    FSourceFile.Free;
+  FreeAndNil(FKeywords);
+  inherited Destroy;
+end;
+
+procedure TSQLScanner.OpenFile(const AFilename: string);
+begin
+  FSourceFile := TFileLineReader.Create(AFilename);
+  FOwnSourceFile:=True;
+  FSourceFilename := AFilename;
+end;
+
+
+procedure TSQLScanner.Error(const Msg: string);
+begin
+  raise ESQLScannerError.Create(Msg);
+end;
+
+procedure TSQLScanner.Error(const Msg: string; Args: array of Const);
+begin
+  raise ESQLScannerError.CreateFmt(Msg, Args);
+end;
+
+function TSQLScanner.FetchLine: Boolean;
+begin
+  if FSourceFile.IsEOF then
+  begin
+    FCurLine := '';
+    TokenStr := nil;
+    Result := false;
+  end else
+  begin
+    FCurLine := FSourceFile.ReadLine;
+    TokenStr := PChar(CurLine);
+    Result := true;
+    Inc(FCurRow);
+  end;
+end;
+
+function TSQLScanner.DoWhiteSpace : TSQLToken;
+
+begin
+  Result:=tsqlWhitespace;
+  repeat
+    Inc(TokenStr);
+    if TokenStr[0] = #0 then
+      if not FetchLine then
+       begin
+       FCurToken := Result;
+       exit;
+       end;
+  until not (TokenStr[0] in [#9, ' ']);
+end;
+
+function TSQLScanner.DoSingleLineComment : TSQLToken;
+
+Var
+  TokenStart : PChar;
+  Len : Integer;
+
+begin
+  Inc(TokenStr);
+  TokenStart := TokenStr;
+  while TokenStr[0] <> #0 do
+     Inc(TokenStr);
+  Len:=TokenStr-TokenStart;
+  SetLength(FCurTokenString, Len);
+  if (Len>0) then
+    Move(TokenStart^,FCurTokenString[1],Len);
+  Result := tsqlComment;
+end;
+
+function TSQLScanner.DoMultiLineComment : TSQLToken;
+
+Var
+  TokenStart : PChar;
+  Len,OLen : Integer;
+  PrevToken : Char;
+
+begin
+  Inc(TokenStr);
+  TokenStart := TokenStr;
+  FCurTokenString := '';
+  OLen:= 0;
+  PrevToken:=#0;
+  while Not ((TokenStr[0]='/') and (PrevToken='*')) do
+    begin
+    if (TokenStr[0]=#0) then
+      begin
+      Len:=TokenStr-TokenStart+1;
+      SetLength(FCurTokenString,OLen+Len);
+      if Len>1 then
+        Move(TokenStart^,FCurTokenString[OLen+1],Len-1);
+      Inc(OLen,Len);
+      FCurTokenString[OLen]:=#10;
+      if not FetchLine then
+        begin
+        Result := tsqlEOF;
+        FCurToken := Result;
+        exit;
+        end;
+      TokenStart := TokenStr;
+      PrevToken:=#0;
+      end
+    else
+      begin
+      PrevToken:=TokenStr[0];
+      Inc(TokenStr);
+      end;
+    end;
+  Len:=TokenStr-TokenStart-1; // -1 for *
+  SetLength(FCurTokenString, Olen+Len);
+  if (Len>0) then
+    begin
+    Move(TokenStart^, FCurTokenString[Olen + 1], Len);
+    end;
+  If TokenStr[0]<>#0 then
+    Inc(TokenStr);
+  Result := tsqlComment;
+end;
+
+function TSQLScanner.CommentDiv : TSQLToken;
+
+begin
+  FCurTokenString := '';
+  Inc(TokenStr);
+  if (TokenStr[0]='*') then
+    Result:=DoMultiLineComment
+  else
+    Result:=tsqlDiv;
+end;
+
+Function TSQLScanner.ReadUnicodeEscape : WideChar;
+
+Var
+  S : String;
+  I : Integer;
+
+begin
+  S:='0000';
+  For I:=1 to 4 do
+    begin
+    Inc(TokenStr);
+    Case TokenStr[0] of
+      '0'..'9','A'..'F','a'..'f' :
+        S[i]:=Upcase(TokenStr[0]);
+    else
+      Error(SErrInvalidCharacter, [TokenStr[0]]);
+    end;
+    end;
+  // Takes care of conversion... This needs improvement !!
+  Result:=WideChar(StrToInt('$'+S));
+end;
+
+procedure TSQLScanner.SetExcludeKeywords(const AValue: TStrings);
+begin
+  With ExcludeKeywords do
+    begin
+    Clear;
+    AddStrings(AValue);
+    end;
+end;
+
+procedure TSQLScanner.Setoptions(const AValue: TSQLScannerOptions);
+
+Const
+   F = [soDoubleQuoteStringLiteral,soSingleQuoteIdentifier];
+
+begin
+  FOptions:=AValue;
+  if ((Foptions * F) = [soSingleQuoteIdentifier]) then
+    Exclude(FOptions,soSingleQuoteIdentifier);
+end;
+
+procedure TSQLScanner.BuildKeyWords;
+
+Var
+  I : TSQLToken;
+
+begin
+  If Not IdentifierTokensOK then
+    BuildIdentifierTokens;
+  If FKeywords.Count>0 then
+    FKeywords.Clear;
+  for I:=FirstKeyword to LastKeyword do
+    if (not Assigned(FExclude)) or (FExclude.INdexOf(TokenInfos[I])=-1) then
+      FKeywords.Add(TokenInfos[I],@IdentifierTokens[i]);
+end;
+
+function TSQLScanner.DoStringLiteral: TSQLToken;
+
+Var
+  Delim : Char;
+  TokenStart : PChar;
+  Len,OLen : Integer;
+  S : String;
+
+  Procedure AppendBufToTokenString(DoNextToken : Boolean);
+
+  begin
+    SetLength(FCurTokenString, OLen + Len+Length(S));
+    if Len > 0 then
+      Move(TokenStart^, FCurTokenString[OLen + 1], Len);
+    If Length(S)>0 then
+      Move(S[1],FCurTokenString[OLen + Len+1],Length(S));
+    Inc(OLen, Len+Length(S));
+    If DoNextToken then
+      Inc(TokenStr);
+    TokenStart := TokenStr+1;
+  end;
+
+  Function CheckTokenBuf : Boolean;
+
+  begin
+    Result:=(TokenStr[0]<>#0);
+    If Not Result then
+      begin
+      S:='';
+      Len:=TokenStr-TokenStart;
+      AppendBufToTokenString(False);
+      Result:=FetchLine;
+      TokenStart:=TokenStr;
+      end;
+  end;
+
+begin
+  Delim:=TokenStr[0];
+  Inc(TokenStr);
+  TokenStart := TokenStr;
+  OLen := 0;
+  FCurTokenString := '';
+  while not (TokenStr[0]=#0) do
+    begin
+    If (TokenStr[0]=Delim) then
+      begin
+      if (not (soNoDoubleDelimIsChar in options)) and (TokenStr[1]=Delim) then
+        begin
+        S:=Delim;
+        Len := TokenStr - TokenStart;
+        AppendBufToTokenString(True);
+        end
+      else
+        Break;
+      end
+    else if (TokenStr[0]='\') and (soBackSlashEscapes in Options) then
+      begin
+      // Save length
+      Len := TokenStr - TokenStart;
+      Inc(TokenStr);
+      if not CheckTokenBuf then
+        Error(SErrOpenString);
+      // Read escaped token
+      Case TokenStr[0] of
+        '"' : S:='"';
+        '''' : S:='''';
+        't' : S:=#9;
+        'b' : S:=#8;
+        'n' : S:=#10;
+        'r' : S:=#13;
+        'f' : S:=#12;
+        '\' : S:='\';
+        '/' : S:='/';
+        'u' : begin
+              S:=ReadUniCodeEscape;
+              end;
+      else
+        Error(SErrInvalidCharacter, [TokenStr[0]]);
+      end;
+      AppendBufToTokenString(False);
+      end;
+    Inc(TokenStr);
+    if not CheckTokenBuf then
+      Error(SErrOpenString);
+    end;
+  if Not CheckTokenBuf then
+    Error(SErrOpenString);
+  S:='';
+  Len := TokenStr - TokenStart;
+  AppendBufToTokenString(True);
+  Result := tsqlString;
+end;
+
+function TSQLScanner.DoNumericLiteral :TSQLToken;
+
+Var
+  TokenStart : PChar;
+  Len : Integer;
+  isFloat : boolean;
+
+begin
+  TokenStart := TokenStr;
+  IsFloat:=False;
+  while true do
+    begin
+    Inc(TokenStr);
+    case TokenStr[0] of
+      'x':
+        If (TokenStart[0]='0') and ((TokenStr-TokenStart)=1) then
+          begin
+          Inc(TokenStr);
+          while Upcase(TokenStr[0]) in ['0'..'9','A'..'F'] do
+            Inc(TokenStr);
+          end
+        else
+          Error(SInvalidHexadecimalNumber);
+      '.':
+        begin
+          isfloat:=true;
+          if TokenStr[1] in ['0'..'9', 'e', 'E'] then
+          begin
+            Inc(TokenStr);
+            repeat
+              Inc(TokenStr);
+            until not (TokenStr[0] in ['0'..'9', 'e', 'E','-','+']);
+          end;
+          break;
+        end;
+      '0'..'9': ;
+      'e', 'E':
+        begin
+          isFloat:=true;
+          Inc(TokenStr);
+          if TokenStr[0] in ['-','+']  then
+            Inc(TokenStr);
+          while TokenStr[0] in ['0'..'9'] do
+            Inc(TokenStr);
+          break;
+        end;
+      else
+        break;
+    end;
+  end;
+  Len:=TokenStr-TokenStart;
+  Setlength(FCurTokenString, Len);
+  if (Len>0) then
+  Move(TokenStart^,FCurTokenString[1],Len);
+  If IsFloat then
+    Result := tsqlFloatNumber
+  else
+    Result:=tsqlIntegerNumber;
+end;
+
+function TSQLScanner.DoIdentifier : TSQLToken;
+
+Var
+  TokenStart:PChar;
+  Len : Integer;
+  I : TSQLToken;
+  S : ShortString;
+  P : ^TSQLToken;
+
+begin
+  Result:=tsqlIdentifier;
+  TokenStart := TokenStr;
+  repeat
+    Inc(TokenStr);
+    If (TokenStr[0]='\') and (TokenStr[1]='u') then
+  until not (TokenStr[0] in ['A'..'Z', 'a'..'z', '0'..'9', '_','$']);
+  Len:=(TokenStr-TokenStart);
+  SetLength(FCurTokenString,Len);
+  if Len > 0 then
+    Move(TokenStart^,FCurTokenString[1],Len);
+  S:=UpperCase(FCurTokenString);
+  // Check if this is a keyword or identifier
+  // !!!: Optimize this!
+  If FKeyWords.Count=0 then
+    BuildKeyWords;
+  P:=FKeyWords.Find(S);
+  If (P<>Nil) then
+    Result:=P^;
+  { I:=FirstKeyword;
+  While (Result=tsqlIdentifier) and (I<=Lastkeyword) do
+    begin
+    if (S=TokenInfos[i]) then
+      begin
+      Result := i;
+      FCurToken := Result;
+      exit;
+      end;
+    I:=Succ(I);
+    end;}
+end;
+
+function TSQLScanner.FetchToken: TSQLToken;
+
+begin
+  Repeat
+    if TokenStr = nil then
+      if not FetchLine then
+        begin
+        Result := tsqlEOF;
+        FCurToken := Result;
+        exit;
+        end;
+    FCurTokenString := '';
+    case TokenStr[0] of
+      #0:         // Empty line
+        begin
+        FetchLine;
+        Result := tsqlWhitespace;
+        end;
+      '/' :
+         Result:=CommentDiv;
+      #9, ' ',#10,#13:
+         Result := DoWhiteSpace;
+      '''':
+        begin
+        Result:=DoStringLiteral;
+        if (soSingleQuoteIdentifier in Options) then
+          result:=tsqlIdentifier;
+        end;
+      '"':
+        begin
+        Result:=DoStringLiteral;
+        If (soDoubleQuoteStringLiteral in options) then
+          Result:=tsqlString
+        else
+          Result:=tsqlIdentifier;
+        end;
+      '`':
+        begin
+        Result:=DoStringLiteral;
+        If (soBackQuoteIdentifier in options) then
+          Result:=tsqlIdentifier
+        else
+          Error(SErrUnknownToken,['`']);
+        end;
+      '0'..'9':
+         Result:=DoNumericLiteral;
+      '?':
+         begin
+         Inc(TokenStr);
+         Result:=tsqlPlaceHolder;
+         end;
+      '!':
+        begin
+        Inc(TokenStr);
+        If TokenStr[0]='>' then
+          Result:=tsqlLE
+        else if (TokenStr[0]='<') then
+          Result:=tsqlGE
+        else if (TokenStr[0]='=') then
+          Result:=tsqlNE
+        else
+          Result:=tsqlUnknown;
+        Inc(TokenStr);
+        end;
+     '|':
+         begin
+         Inc(TokenStr);
+         If Tokenstr[0]='|' then
+           begin
+           Inc(TokenStr);
+           Result := tsqlConcatenate
+           end
+         else
+           Error(SBarExpected);
+         end;
+    '(':
+      begin
+      Inc(TokenStr);
+      Result := tsqlBraceOpen;
+      end;
+    ')':
+      begin
+      Inc(TokenStr);
+      Result := tsqlBraceClose;
+      end;
+    '[':
+      begin
+      Inc(TokenStr);
+      Result := tsqlSquareBraceOpen;
+      end;
+    ']':
+      begin
+      Inc(TokenStr);
+      Result := tsqlSquareBraceClose;
+      end;
+    '*':
+      begin
+      Inc(TokenStr);
+      Result := tsqlMul;
+      end;
+    '+':
+      begin
+      Inc(TokenStr);
+      Result := tsqlPlus;
+      end;
+    ',':
+      begin
+        Inc(TokenStr);
+        Result := tsqlComma;
+      end;
+    '-':
+      begin
+      Inc(TokenStr);
+      If (TokenStr[0]='-') then
+        begin
+        Inc(TokenStr);
+        Result:=DoSingleLineComment
+        end
+      else if (TokenStr[0] in ['0'..'9']) then
+        begin
+        Result:=DoNumericLiteral;
+        If (Result in [tsqlIntegerNumber,tsqlFloatNumber]) then
+          FCurTokenString:='-'+FCurTokenString;
+        end
+      else
+        Result := tsqlMinus;
+      end;
+    '.':
+      begin
+      Inc(TokenStr);
+      Result := tsqlDot;
+      end;
+    ':':
+      begin
+      Inc(TokenStr);
+      Result := tsqlColon;
+      end;
+    ';':
+      begin
+      Inc(TokenStr);
+      Result := tsqlSemicolon;
+      end;
+    '<':
+      begin
+      Inc(TokenStr);
+      if TokenStr[0] = '>' then
+        begin
+        Inc(TokenStr);
+        Result := tsqlNE;
+        end
+      else if (TokenStr[0] = '=') then
+        begin
+        Inc(TokenStr);
+        Result := tsqlLE;
+        end
+      else
+        Result := tsqlLT;
+      end;
+    '=':
+      begin
+      Inc(TokenStr);
+      Result := tsqleQ;
+      end;
+    '>':
+      begin
+      Inc(TokenStr);
+      if TokenStr[0] = '=' then
+	begin
+        Inc(TokenStr);
+        Result:=tsqlGE;
+        end
+      else
+        Result := tsqlGT;
+      end;
+   'a'..'z',
+   'A'..'Z':
+     Result:=DoIdentifier;
+   else
+     Error(SErrUnknownToken,[TokenStr[0]]);
+   end; // Case
+  Until (Not (Result in [tsqlComment,tsqlWhitespace])) or
+        ((Result=tsqlComment) and (soReturnComments in options)) or
+        ((Result=tsqlWhiteSpace) and (soReturnWhiteSpace in Options));
+  FCurToken:=Result;
+end;
+
+function TSQLScanner.IsEndOfLine: Boolean;
+begin
+  Result:=(TokenStr=Nil) or (TokenStr[0] in [#0,#10,#13]);
+end;
+
+function TSQLScanner.GetCurColumn: Integer;
+begin
+  Result := TokenStr - PChar(FCurLine);
+end;
+
+Procedure TSQLScanner.ClearKeywords(Sender : TObject);
+
+begin
+  If Assigned(FKeywords) then
+    FKeywords.Clear;
+end;
+
+function TSQLScanner.GetExcludeKeywords: TStrings;
+begin
+  If FExclude=Nil then
+    begin
+    FExclude:=TStringList.Create;
+    FExclude.Duplicates:=dupIgnore;
+    FExclude.Sorted:=true;
+    FExclude.OnChange:=@ClearKeywords;
+    end;
+  Result:=FExclude;
+end;
+
+{ TStreamLineReader }
+
+constructor TStreamLineReader.Create(AStream: TStream);
+begin
+  FStream:=AStream;
+  FBufPos:=0;
+  FBufLen:=0;
+end;
+
+function TStreamLineReader.IsEOF: Boolean;
+begin
+  Result:=(FBufPos>=FBufLen);
+  If Result then
+    begin
+    FillBuffer;
+    Result:=(FBufLen=0);
+    end;
+end;
+
+procedure TStreamLineReader.FillBuffer;
+
+begin
+  FBufLen:=FStream.Read(Buffer,SizeOf(Buffer)-1);
+  Buffer[FBufLen]:=0;
+  FBufPos:=0;
+end;
+
+function TStreamLineReader.ReadLine: string;
+
+Var
+  FPos,OLen,Len: Integer;
+  PRun : PByte;
+
+begin
+  FPos:=FBufPos;
+  SetLength(Result,0);
+  Repeat
+    PRun:=@Buffer[FBufPos];
+    While (FBufPos<FBufLen) and Not (PRun^ in [10,13]) do
+      begin
+      Inc(PRun);
+      Inc(FBufPos);
+      end;
+    If (FBufPos=FBufLen) then
+      begin
+      Len:=FBufPos-FPos;
+      If (Len>0) then
+        begin
+        Olen:=Length(Result);
+        SetLength(Result,OLen+Len);
+        Move(Buffer[FPos],Result[OLen+1],Len);
+        end;
+      FillBuffer;
+      FPos:=FBufPos;
+      end;
+  until (FBufPos=FBufLen) or (PRun^ in [10,13]);
+  Len:=FBufPos-FPos+1;
+  If (Len>0) then
+    begin
+    Olen:=Length(Result);
+    SetLength(Result,OLen+Len);
+    Move(Buffer[FPos],Result[OLen+1],Len);
+    end;
+  If (PRun^ in [10,13]) and (FBufPos<FBufLen) then
+    begin
+    Inc(FBufPos);
+    // Check #13#10
+    If (PRun^=13) then
+      begin
+      If (FBufPos=FBufLen) then
+        FillBuffer;
+      If (FBufPos<FBufLen) and (Buffer[FBufpos]=10) then
+        begin
+        Inc(FBufPos);
+        Result:=Result+#10;
+        end;
+      end;
+    end;
+end;
+
+end.

+ 4806 - 0
packages/fcl-db/src/sql/fpsqltree.pp

@@ -0,0 +1,4806 @@
+{
+    This file is part of the Free Component Library
+    Copyright (c) 2010 by the Free Pascal development team
+
+    SQL Abstract syntax tree
+
+    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 fpsqltree;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, contnrs;
+
+Type
+  TSQLStringType = String;
+  TSQLFormatOption = (sfoDoubleQuotes,           // Use double quote character for string literals
+                      sfoBackslashEscape,        // Backslash escapes in string literals
+                      sfoSingleQuoteIdentifier,  // quote Identifiers using '
+                      sfoDoubleQuoteIdentifier,  // quote Identifiers using "
+                      sfoBackQuoteIdentifier,    // quote Identifiers using `
+                      sfoLowercaseKeyword,       // Lowercase SQL keywords
+                      sfoOneFieldPerLine,        // One field per line in SELECT, Update, Insert
+                      sfoIndentFields,           // Indent fields (indent=2 space characters)
+                      sfoOneTablePerLine,        // One table per line in select FROM clause
+                      sfoIndentTables,           // Indent tables in FROM clause
+                      sfoNoBracketRightJoin,     // In join, Do not put ( ) around right table if it is also a join
+                      sfoBracketLeftJoin,        // In join, put ( ) around left table if it is also a join
+                      sfoWhereOnSeparateLine,    // Put WHERE clause on a separate line
+                      sfoIndentWhere,            // Indent WHERE clause
+                      sfoOneGroupByFieldPerLine, // One field per line in GROUP BY
+                      sfoIndentGroupByFields,    // Indent GROUP BY fields (indent=2 space characters)
+                      sfoHavingOnSeparateLine,   // Put HAVING clause on a separate line
+                      sfoIndentHaving,           // Indent HAVING clause
+                      sfoUnionOnSeparateLine,    // Put UNION on separate line
+                      sfoOneOrderByFieldPerLine, // One field per line in ORDER BY
+                      sfoIndentOrderByFields,    // Indent ORDER BY fields (indent=2 space characters)
+                      sfoPlanOnSeparateLine,     // Put HAVING clause on a separate line
+                      sfoIndentPlan,             // Indent HAVING clause
+                      sfoOneLogicalPerLine,      // in AND or OR clauses, put newline before AND or OR
+                      sfoListNoSpaceBeforeComma, // In comma-separated lists, do not put space before ,
+                      sfoListNoSpaceAfterComma,  // In comma-separated lists, do not put space after ,
+                      sfoForceAscending,         // In ORDER BY, explicitly write ASC
+                      sfoMultilineDeclareFunction, // Separate parts of 'Declare function' with newlines
+                      sfoMultilineCreateDatabase,  // Separate parts of create/alter database with newlines
+                      sfoMultilineCreateShadow,    // Separate additional filespecs of create/alter shadow with newlines
+                      sfoIndentProcedureBlock      // Indent statements inside procedure/trigger statement block
+                      );
+  TSQLFormatOptions = Set of TSQLFormatOption;
+
+Const
+  sfoUseSeparateLines = [sfoOneFieldPerLine, sfoOneTablePerLine, sfoWhereOnSeparateLine,
+                         sfoOneGroupByFieldPerLine, sfoHavingOnSeparateLine, sfoUnionOnSeparateLine,
+                         sfoOneOrderByFieldPerLine, sfoPlanOnSeparateLine, sfoOneLogicalPerLine];
+Const
+  sfoUseIndentedLines = sfoUseSeparateLines // no use without it...
+                        + [sfoIndentFields, sfoIndentTables, sfoIndentWhere,
+                           sfoIndentGroupByFields, sfoIndentHaving, sfoIndentOrderByFields,
+                           sfoIndentPlan];
+Type
+
+  { TSQLElement }
+
+  TSQLElement = Class(TObject)
+  private
+    Fline: Integer;
+    FParent: TSQLElement;
+    FPos: Integer;
+    FSource: String;
+  Public
+    Constructor Create(AParent : TSQLElement); virtual;
+    destructor destroy; override;
+    function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; virtual; abstract;
+    Property Parent: TSQLElement Read FParent;
+    Property Source : String Read FSource write FSource;
+    Property SourceLine : Integer Read Fline Write Fline;
+    Property SourcePos : Integer Read FPos Write FPos;
+  end;
+  TSQLElementClass = Class of TSQLElement;
+
+  { TSQLElementList }
+
+  TSQLElementList = Class(TObjectList)
+  private
+    function GetE(AIndex : Integer): TSQLElement;
+    procedure SetE(AIndex : Integer; const AValue: TSQLElement);
+  Public
+    Property Elements[AIndex : Integer] : TSQLElement Read GetE Write SetE; default;
+  end;
+
+  TSQLLiteral = Class(TSQLElement);
+
+  { TSQLNullLiteral }
+
+  TSQLNullLiteral = Class(TSQLLiteral)
+  Public
+    function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLUserLiteral }
+
+  TSQLUserLiteral = Class(TSQLLiteral)
+  Public
+    function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLValueLiteral }
+
+  TSQLValueLiteral = Class(TSQLLiteral)
+  Public
+    function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLIntegerLiteral }
+
+  TSQLIntegerLiteral = Class(TSQLLiteral)
+  private
+    FValue: Integer;
+  Public
+    function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Value : Integer Read FValue Write FValue;
+  end;
+
+  { TSQLFloatLiteral }
+
+  TSQLFloatLiteral = Class(TSQLLiteral)
+  private
+    FValue: Double;
+  Public
+    function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Value : Double Read FValue Write FValue;
+  end;
+
+  { TSQLStringLiteral }
+
+  TSQLStringLiteral = Class(TSQLLiteral)
+  private
+    FValue: TSQLStringType;
+  Public
+    function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Value : TSQLStringType Read FValue Write FValue;
+  end;
+
+  { TSQLIdentifierElement }
+
+  TSQLIdentifierName = Class(TSQLElement)
+  Private
+    FName: TSQLStringType;
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Name : TSQLStringType Read FName Write FName;
+  end;
+
+  TSQLCollation = Class(TSQLIdentifierName);
+
+  { TSQLExpression }
+
+  TSQLExpression = Class(TSQLElement)
+  Public
+    Function UseBrackets : Boolean; virtual;
+  end;
+
+  TSQLUnaryOperation = (uoNot,uoMinus);
+
+  { TSQLLiteralExpression }
+
+  TSQLLiteralExpression = Class(TSQLExpression)
+  private
+    FLiteral: TSQLLiteral;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Literal : TSQLLiteral Read FLiteral write FLiteral;
+  end;
+
+  { TSQLIdentifierExpression }
+
+  TSQLIdentifierExpression = Class(TSQLExpression)
+  private
+    FElementIndex: Integer;
+    FIdentifier: TSQLIdentifierName;
+  Public
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Identifier : TSQLIdentifierName Read FIdentifier Write FIdentifier;
+    Property ElementIndex : Integer Read FElementIndex Write FElementIndex;
+  end;
+
+  { TSQLParameterExpression }
+
+  TSQLParameterExpression = Class(TSQLExpression)
+  private
+    FIdentifier: TSQLIdentifierName;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Identifier : TSQLIdentifierName Read FIdentifier Write FIdentifier;
+  end;
+
+  { TSQLListExpression }
+
+  TSQLListExpression = Class(TSQLExpression)
+  private
+    FList: TSQLElementList;
+  Public
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property List : TSQLElementList Read FList;
+  end;
+
+  TSQLSelectStatement = Class;
+
+  { TSQLSelectionExpression }
+
+  TSQLSelectionExpression = Class(TSQLExpression)
+  private
+    FSelect: TSQLSelectStatement;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Select : TSQLSelectStatement Read FSelect Write FSelect;
+  end;
+
+  { TSQLSelectExpression }
+
+  TSQLSelectExpression = Class(TSQLSelectionExpression)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLExistsExpression }
+
+  TSQLExistsExpression = Class(TSQLSelectionExpression)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLSingularExpression }
+
+  TSQLSingularExpression = Class(TSQLSelectionExpression)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLAllExpression }
+
+  TSQLAllExpression = Class(TSQLSelectionExpression)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLSomeExpression }
+
+  TSQLSomeExpression = Class(TSQLSelectionExpression)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLAnyExpression }
+
+  TSQLAnyExpression = Class(TSQLSelectionExpression)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLUnaryExpression }
+
+  TSQLUnaryExpression = Class(TSQLExpression)
+  private
+    FOperand: TSQLExpression;
+    FOperation: TSQLUnaryOperation;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Operation : TSQLUnaryOperation Read FOperation Write FOperation;
+    Property Operand : TSQLExpression Read FOperand Write FOperand;
+  end;
+
+  TSQLBinaryOperation = (boAnd, boOr, boEQ, boLT, boGT, boLE, boGE, boNE,
+                         boConcat,boAdd, boSubtract, boMultiply, boDivide, boIn,
+                         boIs, boIsNot, boLike, boContaining, boStarting);
+
+  { TSQLBinaryExpression }
+
+  TSQLBinaryExpression = Class(TSQLExpression)
+  private
+    FLeft: TSQLExpression;
+    FOperation: TSQLBinaryoperation;
+    FRight: TSQLExpression;
+  Public
+    Destructor Destroy; override;
+    Function UseBrackets : Boolean; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Operation : TSQLBinaryoperation Read FOperation Write FOperation;
+    Property Left : TSQLExpression Read FLeft Write FLeft;
+    Property Right : TSQLExpression Read FRight Write FRight;
+  end;
+
+  TSQLTernaryOperation = (toLikeEscape,toBetween);
+
+  { TSQLTernaryExpression }
+
+  TSQLTernaryExpression = Class(TSQLExpression)
+  private
+    FLeft: TSQLExpression;
+    FMiddle: TSQLExpression;
+    FOperation: TSQLTernaryoperation;
+    FRight: TSQLExpression;
+  Public
+    Destructor Destroy; override;
+    Function UseBrackets : Boolean; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Operation : TSQLTernaryoperation Read FOperation Write FOperation;
+    Property Left : TSQLExpression Read FLeft Write FLeft;
+    Property Middle : TSQLExpression Read FMiddle Write FMiddle;
+    Property Right : TSQLExpression Read FRight Write FRight;
+  end;
+
+  { TSQLGenIDExpression }
+
+  TSQLGenIDExpression = Class(TSQLExpression)
+  private
+    FIdentifier: TSQLIdentifierName;
+    FValue: TSQLExpression;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Generator : TSQLIdentifierName Read FIdentifier Write FIdentifier;
+    Property Value : TSQLExpression Read FValue Write FValue;
+  end;
+
+  { TSQLFunctionCallExpression }
+
+  TSQLFunctionCallExpression = Class(TSQLExpression)
+  private
+    FArguments:TSQLElementList;
+    FIdentifier: TSQLStringType;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Identifier : TSQLStringType Read FIdentifier Write FIdentifier;
+    Property Arguments : TSQLElementList Read FArguments Write Farguments;
+  end;
+
+  TSQLAggregateFunction = (afCount,afSum,afAVG,afMax,afMin);
+  TSQLAggregateOption = (aoNone,aoAsterisk,aoAll,aoDistinct);
+
+  { TSQLAggregateFunctionExpression }
+
+  TSQLAggregateFunctionExpression = Class(TSQLExpression)
+  private
+    Fagg: TSQLAggregateFunction;
+    FExpression: TSQLExpression;
+    FOption: TSQLAggregateOption;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Aggregate : TSQLAggregateFunction Read Fagg Write Fagg;
+    Property Expression : TSQLExpression Read FExpression Write FExpression;
+    Property Option :TSQLAggregateOption Read FOption Write FOption;
+  end;
+
+  { TSQLForeignKeyDefinition }
+  // fkaNone when none was specified. fkaNoAction is when NO ACTION is specified.
+  TForeignKeyAction = (fkaNone,fkaNoAction,fkaCascade,fkaSetDefault,fkaSetNull);
+  TSQLForeignKeyDefinition = Class(TSQLElement)
+  private
+    FFieldList: TSQLElementList;
+    FOnDelete: TForeignKeyAction;
+    FOnUpdate: TForeignKeyAction;
+    FTableName: TSQLIdentifierName;
+  Public
+    Constructor Create(AParent: TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property TableName : TSQLIdentifierName Read FTableName Write FTableName;
+    Property FieldList : TSQLElementList Read FFieldList;
+    Property OnDelete : TForeignKeyAction Read FOnDelete Write FOnDelete;
+    Property OnUpdate : TForeignKeyAction Read FOnUpdate Write FOnUpdate;
+  end;
+
+
+  { TSQLFieldConstraint }
+
+  { TSQLConstraintDef }
+
+  TSQLConstraintDef = Class(TSQLElement)
+  private
+    FConstraintName: TSQLIdentifierName;
+  Public
+    Destructor Destroy;override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    property ConstraintName : TSQLIdentifierName Read FConstraintName Write FConstraintName;
+  end;
+  TSQLFieldConstraint = Class(TSQLConstraintDef);
+
+  { TSQLUniqueFieldConstraint }
+
+  TSQLUniqueFieldConstraint = Class(TSQLFieldConstraint)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLPrimaryKeyFieldConstraint }
+
+  TSQLPrimaryKeyFieldConstraint = Class(TSQLFieldConstraint)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+
+  { TSQLForeignKeyFieldConstraint }
+
+  TSQLForeignKeyFieldConstraint = Class(TSQLFieldConstraint)
+  private
+    FDef: TSQLForeignKeyDefinition;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Definition : TSQLForeignKeyDefinition Read FDef Write FDEf;
+  end;
+
+  { TSQLCheckFieldConstraint }
+
+  TSQLCheckFieldConstraint = Class(TSQLFieldConstraint)
+  private
+    FExpression: TSQLExpression;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Expression : TSQLExpression Read FExpression Write FExpression;
+  end;
+
+  { TSQLFieldConstraintList }
+
+  TSQLFieldConstraintList = Class(TSQLFieldConstraint)
+  private
+    FList : TSQLElementList;
+  public
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property List : TSQLElementList Read FList;
+  end;
+  TSQLTableConstraintDef = Class(TSQLConstraintDef);
+
+  { TSQLTableCheckConstraintDef }
+
+  TSQLTableCheckConstraintDef = Class(TSQLTableConstraintDef)
+  private
+    FCheck: TSQLExpression;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Check : TSQLExpression Read FCheck Write FCheck;
+  end;
+
+  { TSQLTableFieldsConstraintDef }
+
+  TSQLTableFieldsConstraintDef = Class(TSQLTableConstraintDef)
+  private
+    FFieldList: TSQLElementList;
+  Public
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Function FieldListSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+    Property FieldList : TSQLElementList Read FFieldList;
+  end;
+
+  { TSQLTableUniqueConstraintDef }
+
+  TSQLTableUniqueConstraintDef = Class(TSQLTableFieldsConstraintDef)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLTablePrimaryKeyConstraintDef }
+
+  TSQLTablePrimaryKeyConstraintDef = Class(TSQLTableFieldsConstraintDef)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLTableForeignKeyConstraintDef }
+
+  TSQLTableForeignKeyConstraintDef = Class(TSQLTableFieldsConstraintDef)
+  private
+    FDef: TSQLForeignKeyDefinition;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Definition : TSQLForeignKeyDefinition Read FDef Write FDEf;
+  end;
+
+  { TSQLTypeDefinition }
+  TSQLDataType = (sdtDomain,sdtSmallInt,sdtInteger,sdtFloat,sdtDoublePrecision,
+                  sdtDecimal, sdtNumeric, sdtDate,sdtDateTime,sdtTime,
+                  sdtChar,sdtVarChar, sdtNChar, sdtNVarChar, sdtCstring,
+                  sdtBlob);
+
+
+  TSQLTypeDefinition = Class(TSQLElement)
+  private
+    FArrayDim: Integer;
+    FBlobType: Integer;
+    FByValue: Boolean;
+    FCharSet: TSQLStringType;
+    FCollation: TSQLCollation;
+    FCheck: TSQLExpression;
+    FConstraint : TSQLFieldConstraint;
+    FDataType: TSQLDataType;
+    FDefault: TSQLLiteral;
+    FNotNull: Boolean;
+    Flen: Integer;
+    FScale: Byte;
+    FtypeName: String;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property DataType : TSQLDataType Read FDataType Write FDataType;
+    Property TypeName : String Read FtypeName Write FTypeName;
+    Property Len : Integer Read Flen Write Flen; // Length of string or precision for BCD
+    Property Scale : Byte Read FScale Write FScale;
+    Property ArrayDim : Integer Read FArrayDim Write FArrayDim;
+    Property BlobType : Integer Read FBlobType Write FBlobType;
+    Property NotNull : Boolean Read FNotNull Write FNotNull;
+    Property Collation : TSQLCollation Read FCollation Write FCollation;
+    Property Check : TSQLExpression Read FCheck Write FCheck;
+    Property DefaultValue : TSQLLiteral Read FDefault Write FDefault;
+    Property Charset : TSQLStringType Read FCharSet Write FCharset;
+    Property Constraint : TSQLFieldConstraint Read FConstraint Write FConstraint;
+    Property ByValue : Boolean Read FByValue Write FByValue;
+  end;
+
+  { TSQLCastExpression }
+
+  TSQLCastExpression =Class(TSQLExpression)
+  private
+    FNewType: TSQLTypeDefinition;
+    FValue: TSQLExpression;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Value : TSQLExpression Read FValue Write FValue;
+    Property NewType : TSQLTypeDefinition Read FNewType Write FNewType;
+  end;
+
+  { TSQLExtractExpression }
+  TSQLExtractElement = (eeYear,eeMonth,eeDay,eeHour,eeMinute,eeSecond,eeWeekDay,eeYearDay);
+  TSQLExtractExpression =Class(TSQLExpression)
+  private
+    FElement : TSQLExtractElement;
+    FValue : TSQLExpression;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Value : TSQLExpression Read FValue Write FValue;
+    Property Element: TSQLExtractElement Read FElement Write FElement;
+  end;
+
+
+  TSQLStatement = Class(TSQLElement);
+
+  TSQLDMLStatement = Class(TSQLStatement);
+  TSQLDDLStatement = Class(TSQLStatement);
+
+
+  { TSelectField }
+
+  TSQLSelectElement = Class(TSQLElement);
+  TSQLSelectAsterisk = Class(TSQLSelectElement);
+
+  { TSQLSelectField }
+
+  TSQLSelectField = Class(TSQLSelectElement)
+  private
+    FAliasName: TSQLIDentifierName;
+    FExpression: TSQLExpression;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Expression : TSQLExpression Read FExpression Write FExpression;
+    Property AliasName : TSQLIDentifierName Read FAliasName Write FAliasName;
+  end;
+
+  { TSQLTableReference }
+
+  TSQLTableReference = Class(TSQLElement);
+
+  { TSQLSimpleTableReference }
+
+  TSQLSimpleTableReference = Class(TSQLTableReference)
+  private
+    FAliasName: TSQLIDentifierName;
+    FObjectName: TSQLIdentifierName;
+    FParams: TSQLElementList;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property ObjectName : TSQLIdentifierName Read FObjectName Write FObjectName;
+    Property Params : TSQLElementList Read FParams Write FParams;
+    Property AliasName : TSQLIDentifierName Read FAliasName Write FAliasName;
+  end;
+
+  { TSQLJoinTableReference }
+  TSQLJoinType = (jtNone,jtInner,jtLeft,jtRight,jtOuter);
+  TSQLJoinTableReference = Class(TSQLTableReference)
+  private
+    FJoinClause: TSQLExpression;
+    FJoinType: TSQLJoinType;
+    FLeft: TSQLTablereference;
+    FRight: TSQLTableReference;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Left : TSQLTablereference Read FLeft Write FLeft;
+    Property Right : TSQLTableReference Read FRight Write FRight;
+    Property JoinType : TSQLJoinType Read FJoinType Write FJoinType;
+    Property JoinClause : TSQLExpression Read FJoinClause Write FJoinClause;
+  end;
+
+  TSQLSelectPlan = Class(TSQLElement);
+
+  { TSQLSelectPlanItem }
+
+  TSQLSelectPlanItem = Class(TSQLSelectPlan)
+  private
+    FTableName: TSQLIdentifierName;
+  Public
+    Destructor Destroy; Override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property TableName : TSQLIdentifierName Read FTableName Write FTableName;
+  end;
+
+  { TSQLSelectNaturalPlan }
+
+  TSQLSelectNaturalPlan = Class(TSQLSelectPlanItem)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLSelectIndexedPlan }
+
+  TSQLSelectIndexedPlan = Class(TSQLSelectPlanItem)
+  private
+    FIndexes: TSQLElementList;
+  Public
+    Constructor Create(AParent: TSQLElement); override;
+    Destructor Destroy; Override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Indexes : TSQLElementList Read FIndexes;
+  end;
+
+  { TSQLSelectOrderedPlan }
+
+  TSQLSelectOrderedPlan = Class(TSQLSelectPlanItem)
+  private
+    FIndex: TSQLIdentifierName;
+  Public
+    Destructor Destroy; Override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property OrderIndex : TSQLIdentifierName Read FIndex Write FIndex;
+  end;
+
+  TPlanJoinType = (pjtJoin,pjtSort,pjtMerge);
+
+  { TSQLSelectPlanExpr }
+
+  TSQLSelectPlanExpr = Class(TSQLSelectPlan)
+  private
+    FItems: TSQLElementList;
+    FJoinType: TPLanJoinType;
+  Public
+    Constructor Create(AParent: TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Items : TSQLElementList Read FItems;
+    Property JoinType : TPLanJoinType Read FJoinType Write FJOinType;
+  end;
+
+  TSQLOrderDirection = (obAscending,obDescending);
+
+  { TSQLOrderByElement }
+
+  TSQLOrderByElement = Class(TSQLElement)
+  private
+    FCollation: TSQLIdentifierName;
+    FField: TSQLElement;
+    FOrderBy: TSQLOrderDirection;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Field : TSQLElement Read FField Write FField;
+    Property Collation : TSQLIdentifierName Read FCollation Write FCollation;
+    Property OrderBy : TSQLOrderDirection Read FOrderBy write FOrderBy;
+  end;
+
+  { TSQLSelectStatement }
+
+  TSQLSelectStatement = Class(TSQLDMLStatement)
+  private
+    FAll: Boolean;
+    FDistinct: Boolean;
+    FEndAt: TSQLExpression;
+    FFields: TSQLElementList;
+    FForUpdate: TSQLElementList;
+    FInto: TSQLElementList;
+    FOrderBy: TSQLElementList;
+    FGroupBy: TSQLElementList;
+    FHaving: TSQLExpression;
+    FPlan: TSQLSelectPlan;
+    FStartAt: TSQLExpression;
+    FTables: TSQLElementList;
+    FTN: TSQLidentifierName;
+    FUnion: TSQLSelectStatement;
+    FUnionAll: Boolean;
+    FWhere: TSQLExpression;
+  Public
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property TransactionName : TSQLidentifierName Read FTN Write FTN;
+    Property Tables : TSQLElementList Read FTables;
+    Property Fields : TSQLElementList Read FFields;
+    Property Where : TSQLExpression read FWhere write FWhere;
+    Property GroupBy : TSQLElementList Read FGroupBy;
+    Property Having : TSQLExpression Read FHaving Write FHaving;
+    Property Orderby : TSQLElementList Read FOrderBy;
+    Property ForUpdate : TSQLElementList Read FForUpdate Write FForUpdate;
+    Property Union : TSQLSelectStatement Read FUnion Write FUnion;
+    Property Plan : TSQLSelectPlan Read FPlan Write FPlan;
+    Property Distinct : Boolean Read FDistinct Write FDistinct;
+    Property All : Boolean Read FAll Write FAll;
+    Property UnionAll : Boolean Read FUnionAll Write FUnionAll;
+    property StartAt : TSQLExpression Read FStartAt Write FStartAt;
+    Property EndAt : TSQLExpression Read FEndAt Write FEndAt;
+    Property Into : TSQLElementList Read FInto Write FInto;
+  end;
+
+  { TSQLInsertStatement }
+
+  { TSQLTableDMLStatement }
+
+  TSQLTableDMLStatement = Class(TSQLDMLStatement)
+  private
+    FTableName: TSQLIdentifierName;
+  Public
+    Destructor Destroy; override;
+    Property TableName : TSQLIdentifierName Read FTableName Write FTableName;
+  end;
+
+  TSQLInsertStatement = Class(TSQLTableDMLStatement)
+  private
+    FFields: TSQLElementList;
+    FSelect: TSQLSelectStatement;
+    FValues: TSQLElementList;
+    procedure SetSelect(const AValue: TSQLSelectStatement);
+    procedure SetValues(const AValue: TSQLElementList);
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Fields : TSQLElementList Read FFields Write FFields;
+    Property Values : TSQLElementList Read FValues Write SetValues;
+    Property Select : TSQLSelectStatement Read FSelect Write SetSelect;
+  end;
+
+  { TSQLUpdatePair }
+
+  TSQLUpdatePair = Class(TSQLElement)
+  private
+    FFieldName: TSQLidentifierName;
+    FValue: TSQLExpression;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property FieldName : TSQLidentifierName Read FFieldName Write FFieldName;
+    Property Value : TSQLExpression Read FValue Write FValue;
+  end;
+
+  { TSQLUpdateStatement }
+
+  TSQLUpdateStatement = Class(TSQLTableDMLStatement)
+  private
+    FValues: TSQLElementList;
+    FWhereClause: TSQLExpression;
+  Public
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Values : TSQLElementList Read FValues;
+    Property WhereClause : TSQLExpression Read FWhereClause Write FWhereClause;
+  end;
+
+  { TSQLDeleteStatement }
+
+  TSQLDeleteStatement = Class(TSQLDMLStatement)
+  private
+    FAliasName: TSQLIdentifierName;
+    FTableName: TSQLIdentifierName;
+    FWhereClause: TSQLExpression;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property TableName : TSQLIdentifierName Read FTableName Write FTableName;
+    Property AliasName : TSQLIdentifierName Read FAliasName Write FAliasName;
+    Property WhereClause : TSQLExpression Read FWhereClause Write FWhereClause;
+  end;
+
+
+  { TSQLTransactionStatement }
+
+  TSQLTransactionStatement = Class(TSQLStatement)
+  private
+    FRelease: Boolean;
+    FTransactionName: TSQLIdentifierName;
+    FWork: Boolean;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property TransactionName : TSQLIdentifierName Read FTransactionName Write FTransactionName;
+    Property Work : Boolean Read FWork Write FWork;
+    Property Release : Boolean Read FRelease Write FRelease;
+  end;
+
+  { TSQLRollBackStatement }
+
+  TSQLRollBackStatement = Class(TSQLTransactionStatement)
+  public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLCommitStatement }
+
+  TSQLCommitStatement  = Class(TSQLTransactionStatement)
+  private
+    FRetain: Boolean;
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Retain : Boolean Read FRetain Write FRetain;
+  end;
+
+  { TSQLExecuteProcedureStatement }
+
+  TSQLExecuteProcedureStatement = Class(TSQLStatement)
+  private
+    FOutParams: TSQLElementList;
+    FParams: TSQLElementList;
+    FPN: TSQLIdentifierName;
+    FTN: TSQLIdentifierName;
+  Public
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property TransactionName : TSQLIdentifierName Read FTN Write FTN;
+    Property ProcedureName : TSQLIdentifierName Read FPN Write FPN;
+    Property Params : TSQLElementList Read FParams;
+    Property Returning : TSQLElementList Read FOutParams;
+  end;
+
+  { TSQLCreateOrAlterStatement }
+
+  TSQLCreateOrAlterStatement = Class(TSQLDDLStatement)
+  private
+    FDBO: TSQLIdentifierName;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property ObjectName : TSQLIdentifierName Read FDBO Write FDBO;
+  end;
+
+  { Generator }
+
+  TSQLCreateOrAlterGenerator = Class(TSQLCreateOrAlterStatement);
+
+  { TSQLCreateGeneratorStatement }
+
+  TSQLCreateGeneratorStatement = Class(TSQLCreateOrAlterGenerator)
+  public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+  { TSQLSetGeneratorStatement }
+
+  TSQLSetGeneratorStatement = Class(TSQLCreateOrAlterGenerator)
+  private
+    FNewValue: Integer;
+  Public
+    Property NewValue : Integer Read FNewValue Write FNewValue;
+  end;
+
+  { TSQLCreateRoleStatement }
+
+  TSQLCreateRoleStatement = Class(TSQLCreateOrAlterStatement)
+  public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TDomain }
+
+  { TSQLCreateDomainStatement }
+
+  TSQLCreateDomainStatement = Class(TSQLCreateOrAlterStatement)
+  private
+    FType: TSQLTypeDefinition;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property TypeDefinition : TSQLTypeDefinition Read FType Write FType;
+  end;
+
+  { TSQLAlterDomainStatement }
+
+  TSQLAlterDomainStatement = Class(TSQLCreateOrAlterStatement)
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLAlterDomainDropDefaultStatement }
+
+  TSQLAlterDomainDropDefaultStatement = Class(TSQLAlterDomainStatement)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLAlterDomainDropCheckStatement }
+
+  TSQLAlterDomainDropCheckStatement = Class(TSQLAlterDomainStatement)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLAlterDomainSetDefaultStatement }
+
+  TSQLAlterDomainSetDefaultStatement = Class(TSQLAlterDomainStatement)
+  private
+    FDefault: TSQLLiteral;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property DefaultValue : TSQLLiteral Read FDefault Write FDefault;
+  end;
+
+  { TSQLAlterDomainRenameStatement }
+
+  TSQLAlterDomainRenameStatement = Class(TSQLAlterDomainStatement)
+  private
+    FNewName : TSQLIdentifierName;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property NewName : TSQLIdentifierName Read FNewName Write FNewName;
+  end;
+
+  { TSQLAlterDomainTypeStatement }
+
+  TSQLAlterDomainTypeStatement = Class(TSQLAlterDomainStatement)
+  private
+    FNewtype: TSQLTypeDefinition;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property NewType : TSQLTypeDefinition Read FNewtype Write FNewType;
+  end;
+
+  { TSQLAlterDomainAddCheckStatement }
+
+  TSQLAlterDomainAddCheckStatement = Class(TSQLAlterDomainStatement)
+  private
+    FCheck : TSQLExpression;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Check : TSQLExpression Read FCheck Write FCheck;
+  end;
+
+  { TSQLCreateExceptionStatement }
+
+  TSQLCreateExceptionStatement = Class(TSQLCreateOrAlterStatement)
+  private
+    FMessage: TSQLStringLiteral;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property ExceptionMessage : TSQLStringLiteral Read Fmessage Write FMessage;
+  end;
+  TSQLAlterExceptionStatement = Class(TSQLCreateExceptionStatement);
+
+  TIndexOption = (ioAscending,ioDescending,ioUnique);
+  TIndexOptions = Set of TIndexOption;
+
+  { TSQLCreateIndexStatement }
+  TSQLCreateOrAlterIndexStatement = Class(TSQLCreateOrAlterStatement);
+  TSQLCreateIndexStatement = Class(TSQLCreateOrAlterIndexStatement)
+  private
+    FOptions: TIndexOptions;
+    FFieldNames: TSQLElementList;
+    FTableName: TSQLIdentifierName;
+  Public
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Property TableName : TSQLIdentifierName Read FTableName Write FTableName;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Options : TIndexOptions Read FOptions Write FOptions;
+    Property FieldNames : TSQLElementList Read FFieldNames;
+  end;
+
+  { TSQLAlterIndexStatement }
+
+  TSQLAlterIndexStatement = Class(TSQLCreateOrAlterIndexStatement)
+  private
+    FInactive: Boolean;
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Inactive : Boolean Read FInactive Write FInactive;
+  end;
+
+  { TDeclareExternalFunctionStatement }
+
+  { TSQLDeclareExternalFunctionStatement }
+
+  TSQLDeclareExternalFunctionStatement = Class(TSQLCreateOrAlterStatement)
+  private
+    FArguments: TSQLElementList;
+    FEntryPoint: TSQLStringType;
+    FFreeIt: Boolean;
+    FModuleName: TSQLStringType;
+    FReturnType: TSQLTypeDefinition;
+  Public
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property ModuleName : TSQLStringType Read FModuleName Write FModuleName;
+    Property EntryPoint : TSQLStringType Read FEntryPoint Write FEntryPoint;
+    Property ReturnType : TSQLTypeDefinition Read FReturnType Write FReturnType;
+    Property Arguments : TSQLElementList Read FArguments;
+    Property FreeIt : Boolean Read FFreeIt Write FFreeit;
+  end;
+
+  { TSQLTableFieldDef }
+
+  TSQLTableFieldDef = Class(TSQLElement)
+  private
+    FComputedBy: TSQLExpression;
+    FFieldName: TSQLIdentifierName;
+    FFieldType: TSQLTypeDefinition;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property FieldName : TSQLIdentifierName Read FFieldName Write FFieldName;
+    Property FieldType : TSQLTypeDefinition Read FFieldType Write FFieldType;
+    Property ComputedBy : TSQLExpression Read FComputedBy Write FComputedBy;
+  end;
+
+  { TSQLCreateOrAlterTableStatement }
+
+  TSQLCreateOrAlterTableStatement = Class(TSQLCreateOrAlterStatement);
+
+  { TSQLCreateTableStatement }
+
+  TSQLCreateTableStatement = Class(TSQLCreateOrAlterTableStatement)
+  private
+    FConstraints: TSQLElementList;
+    FExternalFile: TSQLStringLiteral;
+    FFieldDefs: TSQLElementList;
+  Public
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property ExternalFileName : TSQLStringLiteral Read FExternalFile Write FExternalFile;
+    Property FieldDefs : TSQLElementList Read FFieldDefs;
+    Property Constraints : TSQLElementList Read FConstraints;
+  end;
+
+  { TSQLAlterTableOperation }
+  TSQLAlterTableOperation = Class(TSQLElement)
+  private
+    FName: TSQLIdentifierName;
+  public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property ObjectName : TSQLIdentifierName Read FName Write FName;
+  end;
+
+  { TSQLDropTableElementOperation }
+
+  TSQLDropTableElementOperation = Class(TSQLAlterTableOperation);
+
+  { TSQLDropTableFieldOperation }
+
+  TSQLDropTableFieldOperation = Class(TSQLDropTableElementOperation)
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLDropTableConstraintOperation }
+
+  TSQLDropTableConstraintOperation = Class(TSQLDropTableElementOperation)
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLAlterTableFieldNameOperation }
+
+  TSQLAlterTableFieldNameOperation = Class(TSQLAlterTableOperation)
+  private
+    FNewName: TSQLIdentifierName;
+  public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property NewName : TSQLIdentifierName Read FNewName Write FNewName;
+  end;
+
+  { TSQLAlterTableFieldTypeOperation }
+
+  TSQLAlterTableFieldTypeOperation = Class(TSQLAlterTableOperation)
+  private
+    FNewtype: TSQLTypeDefinition;
+  public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property NewType : TSQLTypeDefinition Read FNewType Write FNewType;
+  end;
+
+  { TSQLAlterTableFieldPositionOperation }
+
+  TSQLAlterTableFieldPositionOperation = Class(TSQLAlterTableOperation)
+  private
+    FNewPosition: Integer;
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property NewPosition : Integer Read FNewPosition Write FNewPosition;
+  end;
+
+  { TSQLAddTableElementOperation }
+
+  TSQLAlterTableAddElementOperation = Class(TSQLElement)
+  private
+    FElement: TSQLElement;
+  public
+    Destructor Destroy; override;
+    Property Element : TSQLElement Read FElement Write FElement;
+  end;
+
+  { TSQLAlterTableAddFieldOperation }
+
+  TSQLAlterTableAddFieldOperation = Class(TSQLAlterTableAddElementOperation)
+  private
+    function GetF: TSQLTableFieldDef;
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property FieldDef : TSQLTableFieldDef Read GetF;
+  end;
+
+  { TSQLAlterTableAddConstraintOperation }
+
+  TSQLAlterTableAddConstraintOperation = Class(TSQLAlterTableAddElementOperation)
+  private
+    function GetC: TSQLTableConstraintDef;
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property ConstraintDef : TSQLTableConstraintDef Read GetC;
+  end;
+
+  { TSQLAlterTableStatement }
+
+  TSQLAlterTableStatement = Class(TSQLCreateOrAlterTableStatement)
+  private
+    FOperations: TSQLElementList;
+  Public
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Operations : TSQLElementList Read FOperations;
+  end;
+
+  { TSQLAlterCreateViewStatement }
+
+  TSQLAlterCreateViewStatement = Class(TSQLCreateOrAlterStatement)
+  private
+    FFields: TSQLElementList;
+    FSelect: TSQLSelectStatement;
+    FWCo: Boolean;
+  Public
+    Constructor Create(APArent : TSQLElement); override;
+    destructor destroy; override;
+    Property Fields : TSQLElementList Read FFields;
+    Property Select : TSQLSelectStatement Read FSelect Write FSelect;
+    Property WithCheckOption : Boolean Read FWCo Write FWCO;
+  end;
+
+  { TSQLCreateViewStatement }
+
+  TSQLCreateViewStatement = Class(TSQLAlterCreateViewStatement)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLAlterCreateDatabaseStatement }
+
+  TSQLAlterCreateDatabaseStatement = Class(TSQLCreateOrAlterStatement)
+  private
+    FUseSchema: Boolean;
+  Public
+    Property UseSchema : Boolean Read FUseSchema write FUseSchema;
+  end;
+
+  { TSQLDatabaseFileInfo }
+
+  TSQLDatabaseFileInfo =Class(TSQLElement)
+  private
+    FFileName: TSQLStringType;
+    FLength: Integer;
+    FStartPage: Integer;
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property FileName : TSQLStringType Read FFileName Write FFileName;
+    Property Length : Integer Read FLength Write Flength;
+    Property StartPage : Integer Read FStartPage Write FStartPage;
+  end;
+
+  { TSQLCreateDatabaseStatement }
+
+  TSQLCreateDatabaseStatement = Class(TSQLAlterCreateDatabaseStatement)
+  private
+    FCharSet: TSQLIdentifierName;
+    FFileName: TSQLStringType;
+    Flength: INteger;
+    FPageSize: Integer;
+    FPassword: TSQLStringType;
+    FSecondaryFiles: TSQLElementList;
+    FUserName: TSQLStringType;
+  Public
+    constructor Create(AParent: TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property FileName : TSQLStringType Read FFileName Write FFileName;
+    Property UserName : TSQLStringType Read FUserName Write FUserName;
+    property Password : TSQLStringType Read FPassword write FPassword;
+    Property PageSize : Integer Read FPageSize Write FPageSize;
+    Property Length  : INteger Read Flength Write Flength;
+    Property CharSet : TSQLIdentifierName Read FCharSet Write FCharset;
+    Property SecondaryFiles : TSQLElementList Read FSecondaryFiles;
+  end;
+
+  { TSQLAlterDatabaseStatement }
+
+  TSQLAlterDatabaseStatement = Class(TSQLAlterCreateDatabaseStatement)
+  private
+    FOperations: TSQLElementList;
+  Public
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Operations : TSQLElementList Read FOperations Write FOperations;
+  end;
+
+  { TSQLCreateShadowStatement }
+
+  TSQLCreateShadowStatement = Class(TSQLCreateOrAlterStatement)
+  private
+    FConditional: Boolean;
+    FFileName: String;
+    FLength: Integer;
+    FManual: Boolean;
+    FNumber: Integer;
+    FSecondaryFiles: TSQLElementList;
+  Public
+    constructor Create(AParent: TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Number : Integer Read FNumber Write FNumber;
+    Property Manual : Boolean Read FManual Write FManual;
+    Property Conditional : Boolean Read FConditional Write FConditional;
+    Property FileName : TSQLStringtype Read FFileName write FFileName;
+    Property Length : Integer Read FLength Write FLength;
+    Property SecondaryFiles : TSQLElementList Read FSecondaryFiles;
+  end;
+
+  { TSQLProcedureParamDef }
+
+  TSQLProcedureParamDef = Class(TSQLElement)
+  private
+    FParamName: TSQLIdentifierName;
+    FParamType: TSQLTypeDefinition;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property ParamName : TSQLIdentifierName Read FParamName Write FParamName;
+    Property ParamType : TSQLTypeDefinition Read FParamType Write FParamType;
+  end;
+
+  { TSQLStatementBlock }
+
+  TSQLStatementBlock = Class(TSQLStatement)
+  private
+    FStatements: TSQLElementList;
+  Public
+    Constructor Create(AParent: TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Statements : TSQLElementList Read FStatements Write FStatements;
+  end;
+
+  { TSQLAssignStatement }
+
+  TSQLAssignStatement = Class(TSQLStatement)
+  private
+    FExpression: TSQLExpression;
+    FVar: TSQLIdentifierName;
+  public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Variable : TSQLIdentifierName Read FVar Write FVar;
+    Property Expression : TSQLExpression Read FExpression Write FExpression;
+  end;
+
+  { TSQLIFStatement }
+
+  TSQLIFStatement = Class(TSQLStatement)
+  private
+    FCondition: TSQLExpression;
+    FFalseBranch: TSQLStatement;
+    FTrueBranch: TSQLStatement;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Condition : TSQLExpression Read FCondition Write FCondition;
+    Property TrueBranch : TSQLStatement Read FTrueBranch Write FTrueBranch;
+    Property FalseBranch : TSQLStatement Read FFalseBranch Write FFalseBranch;
+  end;
+
+  { TSQLForStatement }
+
+  TSQLForStatement = Class(TSQLStatement)
+  private
+    FFieldList: TSQLElementList;
+    FSelect: TSQLSelectStatement;
+    FStatement: TSQLStatement;
+  Public
+    Constructor Create(AParent: TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Select : TSQLSelectStatement Read FSelect Write FSelect;
+    Property FieldList : TSQLElementList Read FFieldList Write FFieldList;
+    Property Statement : TSQLStatement Read FStatement Write FStatement;
+  end;
+
+  { TSQLWhileStatement }
+
+  TSQLWhileStatement = Class(TSQLStatement)
+  private
+    FCondition: TSQLExpression;
+    FStatement: TSQLStatement;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Condition : TSQLExpression Read FCondition Write FCondition;
+    Property Statement : TSQLStatement Read FStatement Write FStatement;
+  end;
+
+  { TSQLWhenError }
+
+  TSQLWhenError = Class(TSQLElement);
+
+  { TSQLWhenSQLErrorCode }
+
+  TSQLWhenSQLError = Class(TSQLWhenError)
+  private
+    FErrorCode: Integer;
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property ErrorCode : Integer Read FErrorCode Write FErrorCode;
+  end;
+
+  { TSQLWhenException }
+
+  TSQLWhenException = Class(TSQLWhenError)
+  private
+    FEN: TSQLIdentifierName;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property ExceptionName : TSQLIdentifierName Read FEN Write FEN;
+  end;
+
+  { TSQLWhenGDSErrorCode }
+
+  TSQLWhenGDSError = Class(TSQLWhenError)
+  private
+    FErrorNumber: Integer;
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property GDSErrorNumber : Integer Read FErrorNumber Write FErrorNumber;
+  end;
+
+  { TSQLWhenStatement }
+
+  TSQLWhenStatement = Class(TSQLStatement)
+  private
+    FAnyError: Boolean;
+    FErrors: TSQLElementList;
+    FStatement: TSQLStatement;
+  Public
+    Constructor Create(APArent : TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property AnyError : Boolean Read FAnyError Write FAnyError;
+    Property Errors : TSQLElementList Read FErrors Write FErrors;
+    Property Statement : TSQLStatement Read FStatement Write FStatement;
+  end;
+
+  { TSQLExceptionStatement }
+
+  TSQLExceptionStatement = Class(TSQLStatement)
+  private
+    FEN: TSQLIdentifierName;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property ExceptionName : TSQLIdentifierName Read FEN Write FEN;
+  end;
+
+  { TSQLExitStatement }
+
+  TSQLExitStatement = Class(TSQLStatement)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLSuspendStatement }
+
+  TSQLSuspendStatement = Class(TSQLStatement)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLPostEventStatement }
+
+  TSQLPostEventStatement = Class(TSQLStatement)
+  private
+    FCN: TSQLIdentifierName;
+    FEN: TSQLStringType;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property ColName : TSQLIdentifierName Read FCN Write FCN;
+    Property EventName : TSQLStringType Read FEN Write FEN;
+  end;
+
+  { TSQLCreateOrAlterProcedureTriggerStatement }
+
+  TSQLCreateOrAlterProcedureTriggerStatement = Class(TSQLCreateOrAlterStatement)
+  private
+    FLocalVariables: TSQLElementList;
+    FStatements: TSQLElementList;
+  Public
+    constructor Create(AParent: TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property LocalVariables : TSQLElementList Read FLocalVariables Write FLocalVariables;
+    Property Statements : TSQLElementList Read FStatements Write FStatements;
+  end;
+
+
+  { TSQLAlterCreateProcedureStatement }
+
+  TSQLAlterCreateProcedureStatement = Class(TSQLCreateOrAlterProcedureTriggerStatement)
+  private
+    FInputVariables: TSQLElementList;
+    FOutputVariables: TSQLElementList;
+  Public
+    constructor Create(AParent: TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property InputVariables : TSQLElementList Read FInputVariables Write FInputVariables;
+    Property OutputVariables : TSQLElementList Read FOutputVariables Write FOutputVariables;
+  end;
+
+  { TSQLCreateProcedureStatement }
+
+  TSQLCreateProcedureStatement = Class(TSQLAlterCreateProcedureStatement);
+  TSQLAlterProcedureStatement = Class(TSQLAlterCreateProcedureStatement);
+
+  TTriggerState = (tsNone,tsActive,tsInactive);
+  TTriggerMoment = (tmBefore,tmAfter);
+  TTriggerOperation = (toDelete,toInsert,toUpdate);
+  TTriggerOperations = set of TTriggerOperation;
+
+  { TSQLAlterCreateTriggerStatement }
+
+  TSQLAlterCreateTriggerStatement = Class(TSQLCreateOrAlterProcedureTriggerStatement)
+  private
+    FMoment: TTriggerMoment;
+    FOperations: TTriggerOperations;
+    FPosition: Integer;
+    FState: TTriggerState;
+    FTableName: TSQLIdentifierName;
+  Public
+    Destructor destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property TableName : TSQLIdentifierName Read FTableName Write FTableName;
+    Property State : TTriggerState Read FState Write FState;
+    Property Moment : TTriggerMoment Read FMoment Write FMoment;
+    Property Operations : TTriggerOperations Read FOperations Write FOperations;
+    Property Position : Integer Read FPosition Write FPosition;
+  end;
+  TSQLCreateTriggerStatement = Class(TSQLAlterCreateTriggerStatement);
+  TSQLAlterTriggerStatement = Class(TSQLAlterCreateTriggerStatement);
+
+
+  { TSQLDropStatement }
+
+  TSQLDropStatement = Class(TSQLDDLStatement)
+  private
+    FIdentifier: TSQLIdentifierName;
+  Public
+    Destructor Destroy; override;
+    Function SQLObjectType(Options : TSQLFormatOptions) : String; virtual; abstract;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property ObjectName : TSQLIdentifierName Read FIdentifier Write FIdentifier;
+  end;
+
+  { TSQLDropTableStatement }
+
+  TSQLDropTableStatement = Class(TSQLDropStatement)
+    Function SQLObjectType (Options : TSQLFormatOptions): String; override;
+  end;
+
+  { TSQLDropIndexStatement }
+
+  TSQLDropIndexStatement = Class(TSQLDropStatement)
+    Function SQLObjectType (Options : TSQLFormatOptions): String; override;
+  end;
+
+  { TSQLDropViewStatement }
+
+  TSQLDropViewStatement = Class(TSQLDropStatement)
+    Function SQLObjectType (Options : TSQLFormatOptions): String; override;
+  end;
+
+  { TSQLDropProcedureStatement }
+
+  TSQLDropProcedureStatement = Class(TSQLDropStatement)
+    Function SQLObjectType (Options : TSQLFormatOptions) : String; override;
+  end;
+
+  { TSQLDropDomainStatement }
+
+  TSQLDropDomainStatement = Class(TSQLDropStatement)
+    Function SQLObjectType (Options : TSQLFormatOptions): String; override;
+  end;
+
+  { TSQLDropGeneratorStatement }
+
+  TSQLDropGeneratorStatement = Class(TSQLDropStatement)
+    Function SQLObjectType (Options : TSQLFormatOptions) : String; override;
+  end;
+
+  { TSQLDropTriggerStatement }
+
+  TSQLDropTriggerStatement = Class(TSQLDropStatement)
+    Function SQLObjectType (Options : TSQLFormatOptions): String; override;
+  end;
+
+  { TSQLDropExceptionStatement }
+
+  TSQLDropExceptionStatement = Class(TSQLDropStatement)
+    Function SQLObjectType (Options : TSQLFormatOptions): String; override;
+  end;
+
+  { TSQLDropDatabaseStatement }
+
+  TSQLDropDatabaseStatement  = Class(TSQLDropStatement)
+    Function SQLObjectType (Options : TSQLFormatOptions): String; override;
+  end;
+
+  { TSQLDropRoleStatement }
+
+  TSQLDropRoleStatement = Class(TSQLDropStatement)
+    Function SQLObjectType (Options : TSQLFormatOptions): String; override;
+  end;
+
+  { TSQLDropExternalFunctionStatement }
+
+  TSQLDropExternalFunctionStatement = Class(TSQLDropStatement)
+    Function SQLObjectType (Options : TSQLFormatOptions): String; override;
+  end;
+
+  { TSQLDropShadowStatement }
+
+  TSQLDropShadowStatement = Class(TSQLDropStatement)
+    Function SQLObjectType (Options : TSQLFormatOptions): String; override;
+  end;
+ {
+ TSQLDROPFilterStatement = Class(TSQLDropStatement);
+}
+
+  { TSQLConnectStatement }
+
+  TSQLConnectStatement = Class(TSQLStatement)
+  private
+    FCache: Integer;
+    FDBN: TSQLStringType;
+    FPWD: TSQLStringType;
+    FRole: TSQLStringType;
+    FUN: TSQLStringType;
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property DatabaseName : TSQLStringType Read FDBN  Write FDBN;
+    Property UserName : TSQLStringType Read FUN Write FUN;
+    Property Password : TSQLStringType Read FPWD Write FPWD;
+    Property Role : TSQLStringType Read FRole Write FRole;
+    Property Cache : Integer Read FCache Write FCache;
+  end;
+
+  TSQLPrivilegeKind = (pkSelect,pkInsert,pkDelete,pkUpdate,pkReference);
+  { TSQLPrivilege }
+
+  TSQLPrivilege = Class(TSQLElement);
+
+  { TSQLInsertPrivilege }
+
+  TSQLInsertPrivilege = Class(TSQLPrivilege)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLDeletePrivilege }
+
+  TSQLDeletePrivilege = Class(TSQLPrivilege)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLSelectPrivilege }
+
+  TSQLSelectPrivilege = Class(TSQLPrivilege)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLAllPrivilege }
+
+  TSQLAllPrivilege = Class(TSQLPrivilege)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLColumnPrivilege }
+
+  TSQLColumnPrivilege = Class(TSQLPrivilege)
+  private
+    FColumns: TSQLElementList;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Columns : TSQLElementList Read FColumns Write FColumns;
+  end;
+
+  { TSQLUpdatePrivilege }
+
+  TSQLUpdatePrivilege = Class(TSQLColumnPrivilege)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLReferencePrivilege }
+
+  TSQLReferencePrivilege = Class(TSQLColumnPrivilege)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  TSQLGrantee = Class(TSQLIdentifierName);
+
+  TSQLUserGrantee = Class(TSQLGrantee);
+
+  { TSQLGroupGrantee }
+
+  TSQLGroupGrantee = Class(TSQLGrantee)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLProcedureGrantee }
+
+  TSQLProcedureGrantee = Class(TSQLGrantee)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLViewGrantee }
+
+  TSQLViewGrantee = Class(TSQLGrantee)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLTriggerGrantee }
+
+  TSQLTriggerGrantee = Class(TSQLGrantee)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLPublicGrantee }
+
+  TSQLPublicGrantee = Class(TSQLGrantee)
+  Public
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLGrantStatement }
+
+  TSQLGrantStatement = Class(TSQLStatement)
+  private
+    FGrantees: TSQLElementList;
+  Public
+    Function GranteesAsSQL(Options : TSQLFormatOptions; AIndent : Integer; IsRevoke : Boolean = False) : TSQLStringType;
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Property Grantees : TSQLElementList Read FGrantees;
+  end;
+  TSQLRevokeStatement = TSQLGrantStatement;
+  { TSQLTableGrantStatement }
+
+  TSQLTableGrantStatement = Class(TSQLGrantStatement)
+  private
+    FGrantOption: Boolean;
+    FPrivileges: TSQLElementList;
+    FTableName: TSQLIdentifierName;
+  Public
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property TableName : TSQLIdentifierName Read FTableName Write FTableName;
+    Property Privileges : TSQLElementList Read FPrivileges;
+    Property GrantOption : Boolean Read FGrantOption Write FGrantOption;
+  end;
+
+  { TSQLTableRevokeStatement }
+
+  TSQLTableRevokeStatement = Class(TSQLTableGrantStatement)
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+  { TSQLProcedureGrantStatement }
+
+  TSQLProcedureGrantStatement = Class(TSQLGrantStatement)
+  private
+    FGrantOption: Boolean;
+    FProcedureName: TSQLIdentifierName;
+  Public
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property ProcedureName : TSQLIdentifierName Read FProcedureName Write FProcedureName;
+    Property GrantOption : Boolean Read FGrantOption Write FGrantOption;
+  end;
+
+  { TSQLProcedureRevokeStatement }
+
+  TSQLProcedureRevokeStatement = Class(TSQLProcedureGrantStatement)
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+  { TSQLRoleGrantStatement }
+
+  TSQLRoleGrantStatement = Class(TSQLGrantStatement)
+  private
+    FAdminOption: Boolean;
+    FRoles: TSQLElementList;
+  Public
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+    Property Roles : TSQLElementList Read FRoles;
+    Property AdminOption : Boolean Read FAdminOption Write FAdminOption;
+  end;
+
+  { TSQLRoleRevokeStatement }
+
+  TSQLRoleRevokeStatement = Class(TSQLRoleGrantStatement)
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
+  end;
+
+Const
+  CharTypes = [sdtChar,sdtVarChar,sdtNChar,sdtNVarChar,sdtCString];
+  ExtractElementNames : Array[TSQLExtractElement] of String
+          = ('YEAR','MONTH','DAY','HOUR','MINUTE','SECOND','WEEKDAY','YEARDAY');
+
+// Format a SQL keyword according to OPTIONS
+Function SQLKeyWord(Const AWord : TSQLStringType; Options : TSQLFormatOptions) : TSQLStringType;
+Function SQLListSeparator(Options: TSQLFormatOptions) : String;
+Procedure GetSepPrefixIndent(DoNewLine,DoIndent : Boolean; Var Sep,Prefix : TSQLStringType; Var AIndent : Integer);
+Function SQLFormatString(Const AValue : TSQLStringType; Options : TSQLFormatOptions) : TSQLStringType;
+
+implementation
+
+{ TSQLElementList }
+
+Function SQLFormatString(Const AValue : TSQLStringType; Options : TSQLFormatOptions) : TSQLStringType;
+
+begin
+  If sfoDoubleQuotes in Options then
+    Result:='"'+StringReplace(AValue,'"','""',[rfreplaceAll])+'"'
+  else
+    Result:=''''+StringReplace(AValue,'''','''''',[rfreplaceAll])+'''';
+end;
+
+
+Function SQLKeyWord(Const AWord : TSQLStringType; Options : TSQLFormatOptions) : TSQLStringType;
+
+
+begin
+  If (sfoLowercaseKeyword in Options) then
+    Result:=LowerCase(AWord)
+  else
+    Result:=AWord;
+end;
+
+Function SQLListSeparator(Options: TSQLFormatOptions) : String;
+
+begin
+  Result:=' , ';
+  If (SfoListNoSpaceBeforeComma in Options) then
+    Delete(Result,1,1);
+  If (SfoListNoSpaceAfterComma in Options) then
+    Delete(Result,Length(Result),1);
+end;
+
+Procedure GetSepPrefixIndent(DoNewLine,DoIndent : Boolean; Var Sep,Prefix : TSQLStringType; Var AIndent : Integer);
+
+begin
+  Prefix:='';
+  AIndent:=0;
+  If DoNewLine then
+    begin
+    Sep:=','+SlineBreak;
+    If DoIndent then
+      begin
+      Prefix:='  ';
+      Aindent:=2;
+      end
+    end
+  else
+    Sep:=', ';
+end;
+
+function TSQLElementList.GetE(AIndex : Integer): TSQLElement;
+begin
+  Result:=TSQLElement(Items[AIndex]);
+end;
+
+procedure TSQLElementList.SetE(AIndex : Integer; const AValue: TSQLElement);
+begin
+  Items[AIndex]:=AValue;
+end;
+
+{ TSQLIntegerLiteral }
+
+
+function TSQLIntegerLiteral.GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+begin
+  Result:=IntToStr(FValue);
+end;
+
+{ TSQLFloatLiteral }
+
+function TSQLFloatLiteral.GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+begin
+  // Needs improvement.
+  Result:=FloatToStr(FValue);
+end;
+
+{ TSQLStringElement }
+
+function TSQLStringLiteral.GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+
+begin
+  Result:=SQLFormatString(Value,Options);
+end;
+
+{ TSQLElement }
+
+constructor TSQLElement.Create(AParent: TSQLElement);
+begin
+  FParent:=AParent;
+end;
+
+destructor TSQLElement.destroy;
+begin
+  inherited destroy;
+end;
+
+{ TSQLSelectStatement }
+
+constructor TSQLSelectStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FFields:=TSQLElementList.create(True);
+  FTables:=TSQLElementList.Create(True);
+  FGroupBy:=TSQLElementList.Create(True);
+  FOrderBy:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLSelectStatement.Destroy;
+begin
+  FreeAndNil(FFields);
+  FreeAndNil(FTables);
+  FreeAndNil(FGroupBy);
+  FreeAndNil(FOrderBy);
+  FreeAndNil(FWhere);
+  FreeAndNil(FHaving);
+  FreeAndNil(FStartAt);
+  FreeAndNil(FEndAt);
+  FreeAndNil(FUnion);
+  FreeAndNil(FPlan);
+  FreeAndNil(FForUpdate);
+  FreeAndNil(FTN);
+  FreeAndNil(FInto);
+  inherited Destroy;
+end;
+
+
+function TSQLSelectStatement.GetAsSQL(Options: TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+
+Var
+  NewLinePending : Boolean;
+
+  Procedure AddList(Const AKeyWord : String; List : TSQLElementList; UseNewLine,UseIndent : boolean);
+
+  Var
+    S,Pref,Sep : TSQLStringType;
+    I,Ind : Integer;
+
+  begin
+    if Not Assigned(List) or (List.Count=0) then
+      exit;
+    If (AkeyWord<>'') then
+      If NewlinePending then
+        Result:=Result+sLinebreak+SQLKeyWord(AKeyWord,Options)
+      else
+        Result:=Result+' '+SQLKeyWord(AKeyWord,Options);
+    GetSepPrefixIndent(UseNewLine,UseIndent,Sep,Pref,Ind);
+    For I:=0 to List.Count-1 do
+      begin
+      If (S<>'') then
+          S:=S+Sep;
+      S:=S+Pref+List[I].GetAsSQL(Options,AIndent+Ind);
+      end;
+    NewLinePending:=UseNewLine;
+    If UseNewline then
+      Result:=Result+sLinebreak+S
+    else
+      Result:=Result+' '+S;
+  end;
+
+  Procedure AddExpression(Const AKeyWord : TSQLStringType;AExpression  : TSQLElement; UseNewLine,UseIndent : boolean);
+
+  Var
+    S,Pref,Sep : TSQLStringType;
+    Ind : Integer;
+
+  begin
+    If Not Assigned(AExpression) then
+      Exit;
+    If NewlinePending then
+      S:=slineBreak
+    else
+      S:=' ';
+    Result:=Result+S;
+    If UseNewline then
+      S:=slineBreak
+    else
+      S:=' ';
+    Result:=Result+SQLKeyWord(AKeyword,Options)+S;
+    GetSepPrefixIndent(UseNewLine,UseIndent,Sep,Pref,Ind);
+    Result:=Result+Pref+AExpression.GetAsSQL(Options,0{AIndent+Ind});
+    NewLinePending:=UseNewLine;
+  end;
+
+Var
+  Ind : Boolean;
+
+begin
+  Result:=SQLKeyWord('SELECT',Options);
+  If Distinct then
+    Result:=Result+' '+SQLKeyword('DISTINCT',Options);
+  NewLinePending:=(sfoOneFieldPerLine in Options);
+  AddList('',Fields,(sfoOneFieldPerLine in Options),(sfoIndentFields in Options));
+  AddList('FROM',Tables,(sfoOneTablePerLine in Options),(sfoIndentTables in Options));
+  AddExpression('WHERE',Where,(sfoWhereOnSeparateLine in Options),(sfoIndentWhere in Options));
+  AddList('GROUP BY',GroupBy,(sfoOneGroupByFieldPerLine in Options),(sfoIndentGroupByFields in Options));
+  AddExpression('HAVING',Having,(sfoHavingOnSeparateLine in Options),(sfoIndentHaving in Options));
+  If Assigned(Union) then
+    NewLinePending:=NewLinePending or (sfoUnionOnSeparateLine in Options);
+  AddExpression('UNION',Union,(sfoUnionOnSeparateLine in Options),False);
+  If Assigned(Plan) then
+    NewLinePending:=NewLinePending or (sfoPlanOnSeparateLine in Options);
+  AddExpression('PLAN',Plan,(sfoPlanOnSeparateLine in Options),(sfoIndentPlan in Options));
+  AddList('ORDER BY',OrderBy,(sfoOneOrderByFieldPerLine in Options),(sfoIndentOrderByFields in Options));
+end;
+
+{ TSQLInsertStatement }
+
+procedure TSQLInsertStatement.SetSelect(const AValue: TSQLSelectStatement);
+begin
+  FreeAndNil(FValues);
+  FSelect:=AValue;
+end;
+
+procedure TSQLInsertStatement.SetValues(const AValue: TSQLElementList);
+begin
+  FreeAndNil(FSelect);
+  FValues:=AValue;
+end;
+
+
+destructor TSQLInsertStatement.Destroy;
+begin
+  FreeAndNil(FFields);
+  FreeAndNil(Fvalues);
+  FreeAndNil(FSelect);
+  inherited Destroy;
+end;
+
+function TSQLInsertStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  S,Pref,Sep : TSQLStringType;
+  I,Ind : Integer;
+  UseNewLine : Boolean;
+
+begin
+  Result:=SQLKeyword('INSERT INTO ',Options);
+  If Assigned(FTableName) then
+    Result:=Result+TableName.GetAsSQL(Options,AIndent);
+  UseNewLine:=sfoOneFieldPerLine in Options;
+  If UseNewLine then
+     Result:=Result+sLineBreak
+  else
+     Result:=Result+' ';
+  If Assigned(FFields) and (Fields.Count>0) then
+    begin
+    GetSepPrefixIndent(useNewLine,sfoIndentFields in Options,Sep,Pref,Ind);
+    For I:=0 to Fields.Count-1 do
+      begin
+      If (S<>'') then
+          S:=S+Sep;
+      If I>0 then
+        S:=S+Pref;
+      S:=S+Fields[I].GetAsSQL(Options,AIndent+Ind);
+      end;
+    S:=Pref+'('+S+')';
+    If UseNewLine then
+       Result:=Result+S+sLineBreak
+    else
+       Result:=Result+S+' ';
+    end;
+  If Assigned(FSelect) then
+    Result:=Result+Select.GetAsSQL(Options,AIndent)
+  else if Assigned(FValues) then
+    begin
+    Result:=Result+SQLKeyword('VALUES',Options);
+    GetSepPrefixIndent(useNewLine,sfoIndentFields in Options,Sep,Pref,Ind);
+    S:='';
+    For I:=0 to Values.Count-1 do
+      begin
+      If (S<>'') then
+        S:=S+Sep;
+      If I>0 then
+        S:=S+Pref;
+      S:=S+Values[I].GetAsSQL(Options,AIndent+Ind);
+      end;
+    S:=Pref+'('+S+')';
+    If UseNewLine then
+       Result:=Result+sLineBreak+S
+    else
+       Result:=Result+' '+S;
+    end;
+end;
+
+{ TSQLIdentifierName }
+
+function TSQLIdentifierName.GetAsSQL(Options: TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+begin
+  // Maybe add quoting options later on ?
+  Result:=FName;
+  If sfoSingleQuoteIdentifier in Options then
+    Result:=''''+Result+''''
+  else if sfoDoubleQuoteIdentifier in Options then
+    Result:='"'+Result+'"'
+  else if sfoBackQuoteIdentifier in Options then
+    Result:='`'+Result+'`'
+  else
+    Result:=UpperCase(Result);
+end;
+
+{ TSQLDropStatement }
+
+destructor TSQLDropStatement.Destroy;
+begin
+  FreeAndNil(FIdentifier);
+  inherited Destroy;
+end;
+
+function TSQLDropStatement.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+begin
+  Result:=SQLKeyWord('DROP '+SQLObjectType(Options)+' ',Options);
+  If Assigned(FIdentifier) then
+    Result:=Result+ObjectName.GetAsSQl(Options,AIndent);
+end;
+
+{ TSQLCreateOrAlterStatement }
+
+destructor TSQLCreateOrAlterStatement.Destroy;
+begin
+  FreeAndNil(FDBO);
+  inherited Destroy;
+end;
+
+function TSQLCreateOrAlterStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  If Assigned(FDBO) then
+    Result:=FDBO.GetAsSQL(Options, AIndent);
+end;
+
+{ TSQLCreateDomainStatement }
+
+destructor TSQLCreateDomainStatement.Destroy;
+begin
+  FreeAndNil(FType);
+  inherited Destroy;
+end;
+
+function TSQLCreateDomainStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('CREATE DOMAIN ',Options)+inherited GetAsSQL(Options, AIndent);
+  If Assigned(FType) then
+    Result:=Result+' '+FType.GetAsSQL(Options,AIndent);
+end;
+
+{ TSQLTypeDefinition }
+
+destructor TSQLTypeDefinition.Destroy;
+begin
+  FreeAndNil(FCollation);
+  FreeAndNil(FConstraint);
+  FreeAndNil(FDefault);
+  FreeAndNil(FConstraint);
+  inherited Destroy;
+end;
+
+function TSQLTypeDefinition.GetAsSQL(Options: TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+
+Var
+  Opcodes : Array[TSQLDataType] of TSQLStringType
+          = ('','SMALLINT','INT','FLOAT','DOUBLE PRECISION',
+             'DECIMAL','NUMERIC','DATE','TIMESTAMP','TIME',
+             'CHAR','VARCHAR','NATIONAL CHARACTER','NATIONAL CHARACTER VARYING','CSTRING',
+             'BLOB');
+
+begin
+  If DataType=sdtDomain then
+    Result:=SQLKeyWord(UpperCase(TypeName),Options)
+  else
+    Result:=SQLKeyWord(OpCodes[DataType],Options);
+  If (Len>0) then
+    If (DataType in CharTypes) then
+      Result:=Result+Format('(%d)',[Len])
+    else if (DataType in [sdtNumeric,sdtDecimal]) then
+      begin
+      If (Scale=0) then
+        Result:=Result+Format('(%d)',[Len])
+      else
+        Result:=Result+Format('(%d,%d)',[Len,Scale])
+      end;
+  If DataType=sdtBlob then
+    begin
+    Result:=Result+SQLKeyWord(' SUB_TYPE ',Options)+IntToStr(BlobType);
+    If Len>0 then
+      Result:=Result+SQLKeyWord(' SEGMENT_SIZE ',Options)+IntToStr(Len);
+    end;
+  If (CharSet<>'') then
+    Result:=Result+SQLKeyWord(' CHARACTER SET ',Options)+CharSet;
+  If (ArrayDim<>0) then
+     Result:=Result+Format(' [%d]',[ArrayDim]);
+  If Assigned(FDefault) then
+    Result:=Result+SQLKeyWord(' DEFAULT ',Options)+DefaultValue.GetAsSQL(Options,AIndent);
+  If NotNull then
+    Result:=Result+SQLKeyWord(' NOT NULL',Options);
+  If Assigned(Constraint) then
+    Result:=Result+' '+Constraint.GetAsSQl(Options,AIndent)
+  else if Assigned(Check) then
+    Result:=Result+SQLKeyWord(' CHECK ',Options)+'('+Check.GetAsSQl(Options,AIndent)+')';
+  If Assigned(Collation) then
+    Result:=Result+SQLKeyWord(' COLLATION ',Options)+Collation.GetAsSQl(Options,AIndent);
+end;
+
+
+{ TSQLLiteralExpression }
+
+destructor TSQLLiteralExpression.Destroy;
+begin
+  FreeAndNil(FLiteral);
+  inherited Destroy;
+end;
+
+function TSQLLiteralExpression.GetAsSQL(Options: TSQLFormatOptions; AIndent : Integer = 0
+  ): TSQLStringType;
+begin
+  If Assigned(Literal) then
+    Result:=Literal.GetAsSQL(Options)
+  else
+    Result:='';
+end;
+
+{ TSQLUnaryExpression }
+
+destructor TSQLUnaryExpression.Destroy;
+begin
+  FreeAndNil(Foperand);
+  inherited Destroy;
+end;
+
+function TSQLUnaryExpression.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  If Assigned(FOperand) then
+    Result:=Operand.GetAsSQL(Options, AIndent);
+  Case Operation of
+    uoNot   : Result:=SQLKeyWord('NOT',Options)+' ('+Result+')';
+    uoMinus : Result:='-'+Result;
+  end;
+end;
+
+{ TSQLBinaryExpression }
+
+destructor TSQLBinaryExpression.Destroy;
+begin
+  FreeAndNil(FLeft);
+  FreeAndNil(FRight);
+  inherited Destroy;
+end;
+
+function TSQLBinaryExpression.UseBrackets: Boolean;
+begin
+  Result:=True;
+end;
+
+function TSQLBinaryExpression.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Const
+  OpCodes : Array[TSQLBinaryOperation] of string =
+          ('AND', 'OR', '=', '<', '>', '<=', '>=', '<>',
+           '||','+', '-', '*', '/', 'IN',
+           'IS', 'IS NOT', 'LIKE', 'CONTAINING','STARTING WITH');
+
+Var
+  L,R,S : TSQLStringType;
+
+begin
+  If Assigned(Fleft) then
+    begin
+    L:=Left.GetAsSQL(Options, AIndent);
+    If Left.UseBrackets then
+      L:='('+L+')';
+    end;
+  If Assigned(FRight) then
+    begin
+    R:=Right.GetAsSQL(Options, AIndent);
+    If Right.UseBrackets then
+      R:='('+R+')';
+    end;
+  Result:=L;
+  S:=SQLKeyWord(Opcodes[Operation],Options);
+  If (Operation in [boOR,boAnd]) and (sfoOneLogicalPerLine in Options) then
+    Result:=Result+sLineBreak
+  else
+    Result:=Result+' ';
+  Result:=Result+S+' '+R;
+end;
+
+{ TSQLFunctionCallExpression }
+
+destructor TSQLFunctionCallExpression.Destroy;
+begin
+  FreeAndNil(Farguments);
+  inherited Destroy;
+end;
+
+function TSQLFunctionCallExpression.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  I : Integer;
+  Sep : String;
+
+begin
+  Sep:=SQLListSeparator(Options);
+  If Assigned(FArguments) and (FArguments.Count>0) then
+    For I:=0 to FArguments.Count-1 do
+      begin
+      If (Result<>'') then
+        Result:=Result+Sep;
+      Result:=Result+Farguments[i].GetAsSQL(Options,AIndent);
+      end;
+  Result:=SQLKeyWord(Identifier,Options)+'('+Result+')';
+
+end;
+
+{ TSQLTernaryExpression }
+
+destructor TSQLTernaryExpression.Destroy;
+begin
+  FreeAndNil(FLeft);
+  FreeAndNil(FMiddle);
+  FreeAndNil(FRight);
+  inherited Destroy;
+end;
+
+function TSQLTernaryExpression.UseBrackets: Boolean;
+begin
+  Result:=True;
+end;
+
+function TSQLTernaryExpression.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  M,L,R : TSQLStringType;
+
+begin
+  If Assigned(FMiddle) then
+    M:=FMiddle.GetAsSQL(Options,AIndent);
+  If Assigned(FLeft) then
+    L:=FLeft.GetAsSQL(Options,AIndent);
+  If Assigned(FRight) then
+    R:=FRight.GetAsSQL(Options,AIndent);
+  If Operation=toLikeEscape then
+    Result:=L+' '+
+            SQLKeyWord('LIKE',Options)+' '+
+            M+' '+
+            SQLKeyWord('ESCAPE',Options)+' '+
+            R
+  else if Operation=toBetween then
+    Result:=L+' '+
+            SQLKeyWord('BETWEEN',Options)+' '+
+            M+' '+
+            SQLKeyWord('AND',Options)+' '+
+            R;
+end;
+
+{ TSQLAlterDomainSetDefaultStatement }
+
+destructor TSQLAlterDomainSetDefaultStatement.Destroy;
+begin
+  FreeAndnil(FDefault);
+  inherited Destroy;
+end;
+
+function TSQLAlterDomainSetDefaultStatement.GetAsSQL(
+  Options: TSQLFormatOptions; AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  Result:=Result+SQLKeyWord(' SET DEFAULT ',Options);
+  If Assigned(FDefault) then
+    Result:=Result+DefaultValue.GetAsSQL(Options,AIndent);
+end;
+
+{ TSQLAlterDomainTypeStatement }
+
+destructor TSQLAlterDomainTypeStatement.Destroy;
+begin
+  FreeAndNil(FNewType);
+  inherited Destroy;
+end;
+
+function TSQLAlterDomainTypeStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent)+SQLKeyWord(' TYPE ',Options);
+  If Assigned(FNewType) then
+    Result:=Result+NewType.GetAsSQL(Options,AIndent);
+end;
+
+{ TSQLAlterDomainAddCheckStatement }
+
+destructor TSQLAlterDomainAddCheckStatement.Destroy;
+begin
+  FreeAndNil(FCheck);
+  inherited Destroy;
+end;
+
+function TSQLAlterDomainAddCheckStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  If Assigned(FCheck) then
+    Result:=Result+SQLKeyWord(' ADD CHECK ',Options)+Check.GetASSQL(Options,AIndent);
+end;
+
+
+{ TSQLCreateIndexStatement }
+
+constructor TSQLCreateIndexStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FFieldNames:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLCreateIndexStatement.Destroy;
+begin
+  FreeAndNil(FFieldNames);
+  FreeAndNil(FTableName);
+  inherited Destroy;
+end;
+
+function TSQLCreateIndexStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  I : Integer;
+  S,Sep : TSQLStringType;
+
+begin
+  Result:=SQLKeyWord('CREATE ',Options);
+  If (ioUnique in Self.Options) then
+    Result:=Result+SQLKeyWord('UNIQUE ',Options);
+  If ioAscending in Self.Options then
+    Result:=Result+SQLKeyWord('ASCENDING ',Options)
+  else If ioDescending in Self.Options then
+    Result:=Result+SQLKeyWord('DESCENDING ',Options);
+  Result:=Result+SQLKeyWord('INDEX ',Options)+inherited GetAsSQL(Options, AIndent);
+  Result:=Result+SQLKeyWord(' ON ',Options);
+  If Assigned(FTableName) then
+    Result:=Result+FTableName.GetAsSQL(Options,AIndent);
+  If (FieldNames.Count>0) then
+     begin
+     Sep:=SQLListSeparator(Options);
+     S:='';
+     For I:=0 to FieldNames.Count-1 do
+       begin
+       If (S<>'') then
+         S:=S+Sep;
+       S:=S+FieldNames[i].GetAsSQL(Options,AIndent);
+       end;
+     S:='('+S+')';
+     end;
+  Result:=Result+' '+S;
+end;
+
+{ TSQLCreateTableStatement }
+
+constructor TSQLCreateTableStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FFieldDefs:=TSQLElementList.Create(True);
+  FConstraints:=TSQLElementList.Create(true);
+end;
+
+destructor TSQLCreateTableStatement.Destroy;
+begin
+  FreeAndNil(FexternalFile);
+  FreeAndNil(FFieldDefs);
+  FreeAndNil(FConstraints);
+  inherited Destroy;
+end;
+
+function TSQLCreateTableStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  Sep,Pref : TSQLStringType;
+  I,Ind : Integer;
+  S : String;
+
+begin
+  GetSepPrefixIndent(sfoOneFieldPerLine in Options,sfoIndentfields in Options,Sep,Pref,Ind);
+  For I:=0 to FieldDefs.Count-1 do
+    begin
+    If (Result<>'') then
+      Result:=Result+Sep;
+    Result:=Result+Pref+FieldDefs[i].GetAsSQL(Options,Ind+AIndent);
+    end;
+  For I:=0 to Constraints.Count-1 do
+    begin
+    If (Result<>'') then
+      Result:=Result+Sep;
+    Result:=Result+Pref+Constraints[i].GetAsSQL(Options,Ind+AIndent);
+    end;
+  If (sfoOneFieldPerLine in Options) then
+    Result:=' ('+sLineBreak+Result+')'
+  else
+    Result:=' ('+Result+')';
+  S:=SQLKeyWord('CREATE TABLE ',Options)+inherited GetAsSQL(Options, AIndent);
+  If Assigned(FExternalFile) then
+    S:=S+SQLKeyWord(' EXTERNAL FILE ',Options)+ExternalFileName.GetAsSQL(Options,AIndent);
+  Result:=S+Result;
+end;
+
+{ TSQLTableFieldDef }
+
+destructor TSQLTableFieldDef.Destroy;
+begin
+  FreeAndNil(FFieldName);
+  FreeAndNil(FFieldType);
+  FreeAndNil(FComputedBy);
+  inherited Destroy;
+end;
+
+function TSQLTableFieldDef.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer): TSQLStringType;
+begin
+  If Assigned(FFieldName) then
+    Result:=FieldName.GetAsSQL(Options, AIndent);
+  if Assigned(FComputedBy) then
+    Result:=Result+SQLKeyword(' COMPUTED BY ',OPtions)+ComputedBy.GetAsSQL(Options,AIndent)
+  else if Assigned(FFieldType) then
+    Result:=Result+' '+FieldType.GetAsSQL(Options,AIndent);
+end;
+
+{ TSQLConstraintDef }
+
+destructor TSQLConstraintDef.Destroy;
+begin
+  FreeAndNil(FConstraintName);
+  Inherited;
+end;
+
+function TSQLConstraintDef.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+begin
+  If Assigned(FConstraintName) then
+    Result:=SQLKeyWord('CONSTRAINT ',Options)+FConstraintname.GetAsSQl(Options,AIndent);
+end;
+
+{ TSQLForeignKeyFieldConstraint }
+
+destructor TSQLForeignKeyFieldConstraint.Destroy;
+begin
+  FreeAndNil(FDef);
+  inherited Destroy;
+end;
+
+function TSQLForeignKeyFieldConstraint.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  If (Result<>'') then
+    Result:=Result+' ';
+  If Assigned(FDef) then
+    Result:=Result+SQLKeyWord('REFERENCES ',Options)+Definition.GetAsSQL(Options,AIndent);
+end;
+
+{ TSQLForeignKeyDefinition }
+
+constructor TSQLForeignKeyDefinition.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FFieldList:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLForeignKeyDefinition.Destroy;
+begin
+  FreeAndNil(FTableName);
+  FreeAndNil(FFieldList);
+  inherited Destroy;
+end;
+
+function TSQLForeignKeyDefinition.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  Codes : Array[TForeignKeyAction] of string
+        = ('','NO ACTION','CASCADE','SET DEFAULT','SET NULL');
+Var
+  Sep : String;
+  I : Integer;
+
+begin
+  Sep:=SQLListSeparator(Options);
+  For I:=0 to FieldList.Count-1 do
+    begin
+    If (Result<>'') then
+      Result:=Result+Sep;
+    Result:=Result+FieldList[i].GetAsSQl(Options,AIndent);
+    end;
+  Result:='('+Result+')';
+  If Assigned(FTableName) then
+    Result:=TableName.GetAsSQl(Options,AIndent)+' '+Result;
+  If OnUpdate<>fkaNone then
+    Result:=Result+SQLKeyWord(' ON UPDATE '+Codes[OnUpdate],Options);
+  If OnDelete<>fkaNone then
+    Result:=Result+SQLKeyWord(' ON DELETE '+Codes[OnDelete],Options);
+end;
+
+{ TSQLTableFieldsConstraintDef }
+
+constructor TSQLTableFieldsConstraintDef.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FFieldList:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLTableFieldsConstraintDef.Destroy;
+begin
+  FreeAndNil(FFieldList);
+  inherited Destroy;
+end;
+
+function TSQLTableFieldsConstraintDef.FieldListSQL(Options: TSQLFormatOptions;
+  AIndent: Integer = 0): TSQLStringType;
+
+Var
+  I : Integer;
+  Sep : String;
+
+begin
+  Result:='';
+  Sep:=SQLListSeparator(Options);
+  For I:=0 to FieldList.Count-1 do
+    begin
+    If (Result<>'') then
+      Result:=Result+Sep;
+    Result:=Result+Fieldlist[I].GetAsSQL(Options,AIndent);
+    end;
+  Result:='('+Result+')';
+end;
+
+{ TSQLTableForeignKeyConstraintDef }
+
+destructor TSQLTableForeignKeyConstraintDef.Destroy;
+begin
+  FreeAndNil(FDef);
+  inherited Destroy;
+end;
+
+function TSQLTableForeignKeyConstraintDef.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  If (Result<>'') then
+    Result:=Result+' ';
+  Result:=Result+SQLKeyWord('FOREIGN KEY',Options)+' '+FieldListSQl(Options,AIndent);
+  If Assigned(FDef) then
+    Result:=Result+' '+SQLKeyWord('REFERENCES',Options)+' '+Definition.GetAsSQL(Options, AIndent);
+end;
+
+{ TSQLTableCheckConstraintDef }
+
+destructor TSQLTableCheckConstraintDef.Destroy;
+begin
+  FreeAndNil(FCheck);
+  inherited Destroy;
+end;
+
+function TSQLTableCheckConstraintDef.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  If (Result<>'') then
+    Result:=Result+' ';
+  If Assigned(FCheck) then
+    Result:=Result+SQLKeyWord('CHECK',Options)+' ('+FCheck.GetAsSQL(Options,AIndent)+')';
+end;
+
+{ TSQLDropTableElementOperation }
+
+destructor TSQLAlterTableOperation.Destroy;
+begin
+  FreeAndNil(FName);
+  inherited Destroy;
+end;
+
+function TSQLAlterTableOperation.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  If Assigned(FName) then
+    Result:=FName.GetAsSQL(Options, AIndent);
+end;
+
+{ TSQLAlterTableStatement }
+
+constructor TSQLAlterTableStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FOperations:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLAlterTableStatement.Destroy;
+begin
+  FreeAndNil(FOperations);
+  inherited Destroy;
+end;
+
+function TSQLAlterTableStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  Ind,I : Integer;
+  Sep,Pref : TSQLStringType;
+
+
+begin
+  GetSepPrefixIndent(sfoOneFieldPerLine in Options,sfoIndentFields in Options,Sep,Pref,Ind);
+  For I:=0 to Operations.Count-1 do
+    begin
+    If (Result<>'') then
+      Result:=Result+Sep;
+    Result:=Result+Pref+Operations[i].GetAsSQL(OPtions,Ind+AIndent);
+    end;
+  If sfoOneFieldPerLine in Options then
+    Pref:=slineBreak
+  else
+    Pref:=' ';
+  Result:=SQLKeyWord('ALTER TABLE ',Options)+inherited GetAsSQL(Options, AIndent)+Pref+Result;
+end;
+
+{ TSQLAddTableElementOperation }
+
+destructor TSQLAlterTableAddElementOperation.Destroy;
+begin
+  FreeAndNil(FElement);
+  inherited Destroy;
+end;
+
+{ TSQLAlterTableFieldNameOperation }
+
+destructor TSQLAlterTableFieldNameOperation.Destroy;
+begin
+  FreeAndNil(FNewname);
+  inherited Destroy;
+end;
+
+function TSQLAlterTableFieldNameOperation.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyword('ALTER COLUMN ',Options)+inherited GetAsSQL(Options, AIndent);
+  If Assigned(FNewName) then
+    Result:=Result+SQLKeyWord(' TO ',Options)+NewName.GetAsSQl(Options,AIndent);
+end;
+
+{ TSQLAlterTableFieldTypeOperation }
+
+destructor TSQLAlterTableFieldTypeOperation.Destroy;
+begin
+  FreeAndNil(FNewType);
+  inherited Destroy;
+end;
+
+function TSQLAlterTableFieldTypeOperation.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyword('ALTER COLUMN ',Options)+inherited GetAsSQL(Options, AIndent);
+  If Assigned(FNewType) then
+    Result:=Result+SQLKeyWord(' TYPE ',Options)+NewType.GetAsSQL(Options,AIndent);
+end;
+
+{ TSQLAlterTableAddFieldOperation }
+
+function TSQLAlterTableAddFieldOperation.GetF: TSQLTableFieldDef;
+begin
+  Result:=Element as TSQLTableFieldDef;
+end;
+
+function TSQLAlterTableAddFieldOperation.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyword('ADD ',Options);
+  If (FieldDef<>Nil) then
+    Result:=Result+FieldDef.GetAsSQL(Options, AIndent);
+end;
+
+{ TSQLAlterTableAddConstraintOperation }
+
+function TSQLAlterTableAddConstraintOperation.GetC: TSQLTableConstraintDef;
+begin
+  Result:=Element as TSQLTableConstraintDef;
+end;
+
+function TSQLAlterTableAddConstraintOperation.GetAsSQL(
+  Options: TSQLFormatOptions; AIndent: Integer): TSQLStringType;
+begin
+  If(ConstraintDef<>Nil) And (ConstraintDef.ConstraintName<>Nil) then
+    Result:=SQLKeyWord('ADD ',Options)
+  else
+    Result:=SQLKeyWord('ADD CONSTRAINT ',Options);
+  If (ConstraintDef<>Nil) then
+    Result:=Result+ConstraintDef.GetAsSQL(Options, AIndent);
+end;
+
+{ TSQLCheckFieldConstraint }
+
+destructor TSQLCheckFieldConstraint.Destroy;
+begin
+  FreeAndNil(FExpression);
+  inherited Destroy;
+end;
+
+function TSQLCheckFieldConstraint.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  If (Result<>'') then
+    Result:=Result+' ';
+  If Assigned(FExpression) then
+    Result:=Result+SQLKeyWord('CHECK',Options)+' ('+Expression.GetAsSQL(Options,AIndent)+')';
+end;
+
+{ TSQLDeleteStatement }
+
+destructor TSQLDeleteStatement.Destroy;
+begin
+  FreeAndNil(FTableName);
+  FreeAndNil(FAliasName);
+  FreeAndNil(FWhereClause);
+  inherited Destroy;
+end;
+
+function TSQLDeleteStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  Sep,Pref : TSQLStringType;
+
+begin
+  Result:=SQLKeyWord('DELETE FROM ',Options);
+  If Assigned(FTableName) then
+   Result:=Result+TableName.GetAsSQL(Options,AIndent);
+  If Assigned(FAliasName) then
+   Result:=Result+' '+AliasName.GetAsSQL(Options,AIndent);
+  If Assigned(FWhereClause) then
+    begin
+    If (sfoWhereOnSeparateLine in Options)  then
+      begin
+      Sep:=sLineBreak;
+      If (sfoIndentWhere in options) then
+        Pref:=sLineBreak+'  '
+      else
+        Pref:=sLineBreak;
+      end
+    else
+      begin
+      Sep:=' ';
+      Pref:=' ';
+      end;
+    Result:=Result+Sep+SQLKeyWord('WHERE',Options);
+    Result:=Result+Pref+WhereClause.GetAsSQL(Options,AIndent+Length(Pref));
+    end;
+end;
+
+{ TSQLTableDMLStatement }
+
+destructor TSQLTableDMLStatement.Destroy;
+begin
+  FreeAndNil(FTableName);
+  inherited Destroy;
+end;
+
+{ TSQLUpdatePair }
+
+destructor TSQLUpdatePair.Destroy;
+begin
+  FreeAndNil(FFieldName);
+  FreeAndNil(FValue);
+  inherited Destroy;
+end;
+
+function TSQLUpdatePair.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+
+Var
+  F,V : TSQLStringType;
+
+begin
+  If Assigned(FFieldName) then
+    F:=FFieldName.GetAsSQl(Options,AIndent);
+  If Assigned(FValue) then
+    V:=FValue.GetAsSQl(Options,AIndent);
+  Result:=F+' = '+V;
+end;
+
+{ TSQLUpdateStatement }
+
+constructor TSQLUpdateStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FValues:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLUpdateStatement.Destroy;
+begin
+  FreeAndNil(FValues);
+  FreeAndNil(FWhereClause);
+  inherited Destroy;
+end;
+
+function TSQLUpdateStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+Var
+   S,Sep,Pref : TSQLStringType;
+   I,Ind : Integer;
+   useNewLine : Boolean;
+
+begin
+  SQLListseparator(Options);
+  useNewLine:=sfoOneFieldPerline in options;
+  GetSepPrefixIndent(useNewLine,sfoIndentFields in Options,Sep,Pref,Ind);
+  S:='';
+  For I:=0 to Values.Count-1 do
+    begin
+    If (S<>'') then
+      S:=S+Sep;
+    S:=S+Pref+Values[i].GetAsSQL(Options,AIndent+Ind);
+    end;
+  Delete(Sep,1,1); // remove comma
+  Result:=SQLKeyWord('UPDATE ',Options);
+  If Assigned(FTableName) then
+    Result:=Result+TableName.GetAsSQL(Options,AIndent)+' ';
+  Result:=Result+SQLKeyWord('SET',Options)+Sep+S;
+  If Assigned(FWhereClause) then
+    begin
+    If (sfoWhereOnSeparateLine in Options) or useNewLine then
+      begin
+      Sep:=sLineBreak;
+      if not (sfoWhereOnSeparateLine in Options) then
+        Pref:=' '
+      else
+        If (sfoIndentWhere in options) then
+          Pref:=sLineBreak+'  '
+        else
+          Pref:=sLineBreak;
+      end
+    else
+      begin
+      Sep:=' ';
+      Pref:=' ';
+      end;
+    Result:=Result+Sep+SQLKeyWord('WHERE',Options);
+    Result:=Result+Pref+WhereClause.GetAsSQL(Options,AIndent+Length(Pref));
+    end;
+end;
+
+{ TSQLSelectField }
+
+destructor TSQLSelectField.Destroy;
+begin
+  FreeAndNil(FExpression);
+  FreeAndNil(FAliasName);
+  inherited Destroy;
+end;
+
+function TSQLSelectField.GetAsSQL(Options: TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+begin
+  If Assigned(FExpression) then
+    Result:=FExpression.GetAsSQL(Options);
+  If Assigned(FAliasName) then
+    Result:=Result+' AS '+FAliasName.GetAsSQL(Options);
+end;
+
+{ TSQLSimpleTableReference }
+
+destructor TSQLSimpleTableReference.Destroy;
+begin
+  FreeAndNil(FObjectName);
+  FreeAndNil(FParams);
+  FreeAndNil(FAliasName);
+  inherited Destroy;
+end;
+
+function TSQLSimpleTableReference.GetAsSQL(Options: TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+
+Var
+  I : integer;
+
+begin
+  If Assigned(FParams) and (FParams.Count>0) then
+    begin
+    For I:=0 to FParams.Count-1 do
+      begin
+      If (Result<>'') then
+        Result:=Result+' , ';
+      Result:=Result+FParams[I].GetAsSQL(Options);
+      end;
+    Result:='('+Result+')';
+    end;
+  If Assigned(FObjectname) then
+    Result:= FObjectName.GetAsSQL(Options)+Result;
+  if Assigned(FAliasName) then
+    Result:=Result+' '+FAliasName.GetAsSQL(Options);
+end;
+
+{ TSQLJoinTableReference }
+
+destructor TSQLJoinTableReference.Destroy;
+begin
+  FreeAndNil(FLeft);
+  FreeAndNil(FRight);
+  FreeAndNil(FJoinClause);
+  inherited Destroy;
+end;
+
+function TSQLJoinTableReference.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Const
+  Opcodes : Array[TSQLJoinTYpe] of String
+          = ('','INNER ','LEFT ','RIGHT ','OUTER ');
+
+Var
+  L,R,O,Sep,prefix : TSQLStringType;
+  Ind : Integer;
+
+begin
+  GetSepPrefixIndent(sfoOneTablePerLine in Options,sfoIndentTables in Options,Sep,Prefix,Ind);
+  Delete(Sep,1,1); // remove comma
+  If Assigned(Left) then
+    begin
+    L:=Left.getAsSQL(Options,AIndent);
+    If (sfoBracketLeftJoin in options) and (Left is TSQLJoinTableReference)  then
+      L:='('+L+')';
+    end;
+  If Assigned(Right) then
+    begin
+    R:=Right.getAsSQL(Options,AIndent+Ind);
+    If (Not (sfoNoBracketRightJoin in options)) and (Right is TSQLJoinTableReference)  then
+      R:='('+R+')';
+    end;
+  If Assigned(JoinClause) then
+    O:=JoinClause.GetAsSQL(Options,AIndent);
+  Result:=L+Sep;
+  Result:=Result+Prefix+SQLKEYWORD(Opcodes[JoinType]+'JOIN ',Options)+R;
+  If (O<>'') then
+    Result:=Result+SQLKeyWord(' ON ',Options)+'('+O+')';
+end;
+
+{ TSQLAggregateFunctionExpression }
+
+destructor TSQLAggregateFunctionExpression.Destroy;
+begin
+  FreeAndNil(FExpression);
+  inherited Destroy;
+end;
+
+function TSQLAggregateFunctionExpression.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Const
+  OpCodes : Array[TSQLAggregateFunction] of string = ('COUNT','SUM','AVG','MAX','MIN');
+Var
+  E : TSQLStringType;
+
+begin
+  Result:=SQLKeyWord(Opcodes[Aggregate],Options);
+  Case Option of
+    aoAsterisk : E:='*';
+    aoAll      : E:=SQLKeyword('ALL',Options);
+    aoDistinct : E:=SQLKeyWord('DISTINCT',Options);
+  end;
+  If Assigned(FExpression) and (Option<>aoAsterisk) then
+    begin
+    If E<>'' then
+      E:=E+' ';
+    E:=E+Expression.GetAsSQl(Options,AIndent);
+    end;
+  Result:=Result+'('+E+')';
+end;
+
+{ TSQLGenIDExpression }
+
+destructor TSQLGenIDExpression.Destroy;
+begin
+  FreeAndNil(FValue);
+  FreeAndNil(FIdentifier);
+  inherited Destroy;
+end;
+
+function TSQLGenIDExpression.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  G,E : TSQLStringType;
+begin
+  If Assigned(FIdentifier) then
+    G:=FIdentifier.GetAsSQl(Options,AIndent);
+  If Assigned(FValue) then
+    E:=FValue.GetAsSQl(Options,AIndent);
+
+  Result:=SQLKeyword('GEN_ID',options)+'('+G+','+E+')';
+end;
+
+{ TSQLCastExpression }
+
+destructor TSQLCastExpression.Destroy;
+begin
+  FreeAndNil(FValue);
+  FreeAndNil(FNewType);
+  inherited Destroy;
+end;
+
+function TSQLCastExpression.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('CAST(',Options);
+  If Assigned(FValue) then
+    Result:=Result+FValue.GetAsSQL(Options, AIndent);
+  Result:=Result+SQLKeyWord(' AS ',Options);
+  If Assigned(FNewType) then
+    Result:=Result+FNewType.GetAsSQL(Options, AIndent);
+  Result:=Result+')';
+end;
+
+{ TSQLOrderByElement }
+
+destructor TSQLOrderByElement.Destroy;
+begin
+  FreeAndNil(FField);
+  FreeAndNil(FCollation);
+  inherited Destroy;
+end;
+
+function TSQLOrderByElement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Const
+  OpCodes : Array[TSQLOrderDirection] of TSQLStringType
+          = ('ASC','DESC');
+
+begin
+  If Assigned(FField) then
+    Result:=FField.GetAsSQL(Options, AIndent);
+  If (OrderBy=obDescending) or (sfoForceAscending in Options) then
+    Result:=Result+' '+SQLKeyWord(Opcodes[OrderBy],Options);
+  If (Collation<>Nil) then
+    Result:=Result+' '+Collation.GetAsSQL(Options,AIndent);
+end;
+
+{ TSQLSelectIndexedPlan }
+
+constructor TSQLSelectIndexedPlan.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FIndexes:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLSelectIndexedPlan.Destroy;
+begin
+  FreeAndNil(FIndexes);
+  inherited Destroy;
+end;
+
+function TSQLSelectIndexedPlan.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  I : Integer;
+  Sep : TSQLStringType;
+begin
+  Sep:=SQLListSeparator(Options);
+  For I:=0 to FIndexes.Count-1 do
+    begin
+    If Result<>'' then
+      Result:=Result+Sep;
+    Result:=Result+Findexes[I].GetAsSQL(Options,AIndent);
+    end;
+  Result:=' ('+Result+')';
+  Result:=inherited GetAsSQL(Options, AIndent)+ SQLKeyword(' INDEX',Options)+Result;
+end;
+
+{ TSQLSelectPlanItem }
+
+destructor TSQLSelectPlanItem.Destroy;
+begin
+  FreeandNil(FTableName);
+  inherited Destroy;
+end;
+
+function TSQLSelectPlanItem.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  If Assigned(FTableName) then
+    Result:=FTableName.GetAsSQL(Options, AIndent);
+end;
+
+{ TSQLSelectOrderedPlan }
+
+destructor TSQLSelectOrderedPlan.Destroy;
+begin
+  FReeAndNil(FIndex);
+  inherited Destroy;
+end;
+
+function TSQLSelectOrderedPlan.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  If Assigned(FIndex) then
+    Result:=Result+SQLKeyWord(' ORDER ',Options)+FIndex.GetAsSQL(Options,AIndent);
+end;
+
+{ TSQLSelectPlanExpr }
+
+constructor TSQLSelectPlanExpr.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  Fitems:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLSelectPlanExpr.Destroy;
+begin
+  FreeAndNil(FItems);
+  inherited Destroy;
+end;
+
+function TSQLSelectPlanExpr.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Const
+  Opcodes : Array[TPLanJoinType] of TSQLStringType
+          = ('JOIN ','SORT ','MERGE ');
+Var
+  I : Integer;
+  Sep : String;
+begin
+  Sep:=SQLListSeparator(Options);
+  For I:=0 to Fitems.Count-1 do
+    begin
+    If (Result<>'') then
+      Result:=Result+Sep;
+    Result:=Result+Fitems[I].GetAsSQl(Options,AIndent);
+    end;
+  Result:='('+Result+')';
+  Result:=SQLKeyWord(Opcodes[JoinType],Options)+Result;
+end;
+
+{ TSQLSelectionExpression }
+
+destructor TSQLSelectionExpression.Destroy;
+begin
+  FreeAndNil(FSelect);
+  inherited Destroy;
+end;
+
+function TSQLSelectionExpression.GetAsSQL(Options: TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+begin
+  If Assigned(FSelect) then
+    Result:=Select.GetAsSQL(Options);
+end;
+
+{ TSQLListExpression }
+
+constructor TSQLListExpression.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FList:=TSQLElementList.Create(true);
+end;
+
+destructor TSQLListExpression.Destroy;
+begin
+  FreeAndNil(Flist);
+  inherited Destroy;
+end;
+
+
+function TSQLListExpression.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  I : integer;
+  Sep : String;
+
+begin
+  Sep:=SQLListSeparator(Options);
+  For I:=0 to List.Count-1 do
+    begin
+    If (Result<>'') then
+      Result:=Result+Sep;
+    Result:=Result+List[i].GetAsSQL(Options, AIndent);
+    end;
+  Result:='('+Result+')';
+end;
+
+{ TSQLTransactionStatement }
+
+destructor TSQLTransactionStatement.Destroy;
+begin
+  FreeAndNil(FTransactionName);
+  inherited Destroy;
+end;
+
+function TSQLTransactionStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  If Assigned(FTransactionName) then
+    Result:=SQLKeyWord(' TRANSACTION ',Options)+TransactionName.GetAsSQL(Options, AIndent);
+  If Work then
+    Result:=Result+SQLKeyWord(' WORK',Options);
+  If Release then
+    Result:=Result+SQLKeyWord(' RELEASE',Options);
+end;
+
+{ TSQLExecuteProcedureStatement }
+
+constructor TSQLExecuteProcedureStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FParams:=TSQLElementList.Create(true);
+  FOutParams:=TSQLElementList.Create(true);
+end;
+
+destructor TSQLExecuteProcedureStatement.Destroy;
+begin
+  FreeAndNil(FParams);
+  FreeAndNil(FOutParams);
+  FreeAndNil(FPN);
+  FreeAndNil(FTN);
+  inherited Destroy;
+end;
+
+function TSQLExecuteProcedureStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  S,Sep : TSQLStringType;
+  I: Integer;
+
+begin
+  Result:=SQLKeyWord('EXECUTE PROCEDURE',Options);
+  If Assigned(FTN) then
+    Result:=Result+' '+TransactionName.GetAsSQl(Options,AIndent);
+  If Assigned(FPN) then
+    Result:=Result+' '+ProcedureName.GetAsSQl(Options,AIndent);
+  Sep:=SQLListSeparator(Options);
+  If (Params.Count>0) then
+    begin
+    For I:=0 to Params.Count-1 do
+       begin
+       If (S<>'') then
+         S:=S+Sep;
+       S:=S+Params[i].GetAsSQL(Options,AIndent);
+       end;
+    S:='('+S+')';
+    end;
+  Result:=Result+S;
+  If (Returning.Count>0) then
+    begin
+    S:='';
+    For I:=0 to Returning.Count-1 do
+       begin
+       If (S<>'') then
+         S:=S+Sep;
+       S:=S+':'+Returning[i].GetAsSQL(Options,AIndent);
+       end;
+    S:=SQLKeyWord(' RETURNING_VALUES ',Options)+S;
+    Result:=Result+S;
+    end;
+end;
+
+{ TSQLAlterDatabaseStatement }
+
+constructor TSQLAlterDatabaseStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  Foperations:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLAlterDatabaseStatement.Destroy;
+begin
+  FreeAndNil(FOperations);
+  inherited Destroy;
+end;
+
+function TSQLAlterDatabaseStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  I : Integer;
+  Sep : TSQLStringType;
+begin
+  If sfoMultilineCreateDatabase in Options then
+    Sep:=sLineBreak+'  '
+  else
+    Sep:=' ';
+  Result:=SQLKeyWord('ALTER ',Options);
+  If UseSchema then
+    Result:=Result+SQLKeyWord('SCHEMA',Options)
+  else
+    Result:=Result+SQLKeyWord('DATABASE',Options);
+  Result:=Result+SqlKeyWord(' ADD',Options);
+  For I:=0 To Operations.Count-1 do
+    Result:=Result+Sep+Operations[i].GetAsSQL(Options,Aindent);
+end;
+
+{ TSQLCreateDatabaseStatement }
+
+constructor TSQLCreateDatabaseStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FSecondaryFiles:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLCreateDatabaseStatement.Destroy;
+begin
+  FreeAndNil(FSecondaryFiles);
+  FreeAndNil(FCHarSet);
+  inherited Destroy;
+end;
+
+function TSQLCreateDatabaseStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  Sep : String;
+  I : Integer;
+begin
+  If sfoMultilineCreateDatabase in Options then
+    Sep:=sLineBreak+'  '
+  else
+    Sep:=' ';
+  Result:=SQLKeyWord('CREATE ',Options);
+  If UseSchema then
+    Result:=Result+SQLKeyWord('SCHEMA ',Options)
+  else
+    Result:=Result+SQLKeyWord('DATABASE ',Options);
+  Result:=Result+SQLFormatString(FileName,Options);
+  If (UserName<>'') then
+    begin
+    Result:=Result+Sep+SQLKeyWord('USER ',Options)+SQLFormatString(UserName,Options);
+    If (Password<>'') then
+      Result:=Result+SQLKeyWord(' PASSWORD ',Options)+SQLFormatString(Password,Options);
+    end;
+  If (PageSize<>0) then
+    Result:=Result+Sep+SQLKeyWord('PAGE_SIZE ',Options)+IntToStr(PageSize);
+  If (Length<>0) then
+    Result:=Result+Sep+SQLKeyWord('LENGTH ',Options)+IntToStr(Length);
+  If Assigned(FCharset) then
+    Result:=Result+Sep+SQLKeyWord('DEFAULT CHARACTER SET ',Options)+Charset.GetAsSQl(Options,AIndent);
+  For I:=0 to SecondaryFiles.Count-1 do
+    Result:=Result+Sep+SecondaryFiles[i].GetAsSQL(Options,AIndent);
+end;
+
+{ TSQLAlterCreateViewStatement }
+
+constructor TSQLAlterCreateViewStatement.Create(APArent: TSQLElement);
+
+begin
+  inherited Create(APArent);
+  FFields:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLAlterCreateViewStatement.destroy;
+begin
+  FreeAndNil(FFields);
+  FreeAndNil(FSelect);
+  inherited destroy;
+end;
+
+{ TSQLCreateShadowStatement }
+
+constructor TSQLCreateShadowStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FSecondaryFiles:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLCreateShadowStatement.Destroy;
+begin
+  FreeAndNil(FSecondaryFiles);
+  inherited Destroy;
+end;
+
+function TSQLCreateShadowStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  Sep: TSQLStringType;
+  I : Integer;
+
+begin
+  If sfoMultilineCreateShadow in Options then
+    Sep:=sLineBreak+'  '
+  else
+    Sep:=' ';
+  Result:=SQLKeyWord('CREATE SHADOW ',Options)+intToStr(Number);
+  If Manual then
+    Result:=Result+SQLKeyWord(' MANUAL',Options);
+  If Conditional then
+    Result:=Result+SQLKeyWord(' CONDITIONAL',Options);
+  Result:=Result+' '+SQLFormatString(FileName,Options);
+  If (Length<>0) then
+    Result:=Result+SQLKeyWord(' LENGTH ',Options)+IntToStr(Length)+SQLKeyWord(' PAGES',Options);
+  For I:=0 to SecondaryFiles.Count-1 do
+    Result:=Result+Sep+SecondaryFiles[i].GetAsSQL(Options,AIndent);
+end;
+
+{ TSQLCreateProcedureStatement }
+
+constructor TSQLAlterCreateProcedureStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FInputVariables:=TSQLElementList.Create(True);
+  FOutputVariables:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLAlterCreateProcedureStatement.Destroy;
+begin
+  FreeAndNil(FInputVariables);
+  FreeAndNil(FOutputVariables);
+  inherited Destroy;
+end;
+
+function TSQLAlterCreateProcedureStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  S,Sep : TSQLStringType;
+  I : Integer;
+
+begin
+  If Self is TSQLAlterProcedureStatement then
+    Result:=SQLKeyword('ALTER ',Options)
+  else
+    Result:=SQLKeyword('CREATE ',Options);
+  Result:=Result+SQLKeyWord('PROCEDURE ',Options);
+  If (ObjectName<>Nil) then
+    Result:=Result+ObjectName.GetAsSQL(Options, AIndent);
+  Sep:=SQLListSeparator(Options);
+  For I:=0 to InputVariables.Count-1 do
+    begin
+    If (S<>'') then
+      S:=S+Sep;
+    S:=S+InputVariables[i].GetAsSQL(Options,AIndent);
+    end;
+  If (S<>'') then
+    Result:=Result+' ('+S+')';
+  S:='';
+  For I:=0 to OutputVariables.Count-1 do
+    begin
+    If (S<>'') then
+      S:=S+Sep;
+    S:=S+OutputVariables[i].GetAsSQL(Options,AIndent);
+    end;
+  If (S<>'') then
+    Result:=Result+sLineBreak+'RETURNS ('+S+')';
+  Result:=Result+sLineBreak+SQLKeyword('AS',Options)+sLineBreak;
+  Result:=Result+Inherited GetAsSQL(Options,AIndent);
+end;
+
+{ TSQLProcedureParamDef }
+
+destructor TSQLProcedureParamDef.Destroy;
+begin
+  FreeAndNil(FParamName);
+  FreeAndNil(FParamType);
+  inherited Destroy;
+end;
+
+function TSQLProcedureParamDef.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  If Assigned(FParamName) then
+    Result:=ParamName.getAsSQL(OPtions,AIndent);
+  If Assigned(FParamType) then
+    Result:=Result+' '+ParamType.getAsSQL(OPtions,AIndent);
+end;
+
+{ TSQLStatementBlock }
+
+constructor TSQLStatementBlock.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FStatements:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLStatementBlock.Destroy;
+begin
+  FreeAndNil(FStatements);
+  inherited Destroy;
+end;
+
+
+Function SQLIndentStatement(S : String; Options: TSQLFormatOptions) : String;
+
+Var
+  L : TStringList;
+  I : Integer;
+  Sep : String;
+
+begin
+  L:=TStringList.Create;
+  Sep:='  ';
+  try
+    L.Text:=S;
+    If (L.Count>0) then
+     Result:=Sep+L[0];
+    Sep:=sLineBreak+Sep;
+    For i:=1 to L.Count-1 do
+      Result:=Result+Sep+L[i];
+  finally
+    L.Free;
+  end;
+end;
+
+function TSQLStatementBlock.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  I,J : Integer;
+  S : String;
+begin
+  Result:=SQLKeyword('BEGIN',Options)+slineBreak;
+  For I:=0 to Statements.Count-1 do
+    begin
+    If (S<>'') then
+      S:=S+sLineBreak;
+    S:=S+Statements[i].GetAsSQL(Options,AIndent);
+    If Not (Statements[i] is TSQLStatementBlock) then
+     S:=S+';';
+    end;
+  Result:=Result+SQLIndentStatement(S,Options);
+  Result:=Result+SlineBreak+SQLKeyWord('END',Options);
+end;
+
+{ TSQLIFStatement }
+
+destructor TSQLIFStatement.Destroy;
+begin
+  FreeAndNil(FCondition);
+  FreeAndNil(FFalseBranch);
+  FreeAndNil(FTrueBranch);
+  inherited Destroy;
+end;
+
+function TSQLIFStatement.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+begin
+  Result:=SQLKeyWord('IF (',Options);
+  If Assigned(FCondition) then
+    Result:=Result+Condition.GetAsSQL(Options,AIndent);
+  Result:=Result+SQLKeyWord(') THEN',Options)+sLineBreak;
+  If Assigned(FTrueBranch) then
+    Result:=Result+SQLindentStatement(TrueBranch.GetAsSQL(Options,AIndent),Options);
+  If Assigned(FFalseBranch) then
+    begin
+    Result:=Result+sLineBreak+SQLKeyWord('ELSE',Options)+sLineBreak;
+    Result:=Result+SQLindentStatement(FalseBranch.GetAsSQL(Options,AIndent),Options)
+    end;
+end;
+
+{ TSQLForStatement }
+
+constructor TSQLForStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FFieldList:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLForStatement.Destroy;
+begin
+  FreeAndNil(FFieldList);
+  FreeAndNil(FSelect);
+  FreeAndNil(FStatement);
+  inherited Destroy;
+end;
+
+function TSQLForStatement.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+
+Var
+  S,Sep,Prefix : TSQLStringType;
+  I,Ind : Integer;
+  DoNewLine : Boolean;
+
+begin
+  Result:=SQLKeyWord('FOR ',Options);
+  If Assigned(FSelect) then
+    Result:=Result+Select.GetAsSQL(Options,AIndent)+sLineBreak;
+  Result:=Result+SQLKeyWord('INTO',Options);
+  DoNewLine:=sfoOneFieldPerLine in Options;
+  GetSepPrefixIndent(DoNewLine,sfoIndentFields in Options,Sep,Prefix,Ind);
+  For I:=0 to FieldList.Count-1 do
+    begin
+    If (S<>'') then
+      S:=S+Sep;
+    S:=S+Prefix+':'+FieldList[i].GetAsSQl(Options,AIndent);
+    end;
+  Result:=Result+sLineBreak+S+sLineBreak+SQLKeyWord('DO',Options)+sLineBreak;
+  If Assigned(FStatement) then
+    Result:=Result+SQLIndentStatement(Statement.GetAsSQL(Options,AIndent),Options)
+end;
+
+{ TSQLExceptionStatement }
+
+destructor TSQLExceptionStatement.Destroy;
+begin
+  FreeAndNil(FEN);
+  inherited Destroy;
+end;
+
+function TSQLExceptionStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('EXCEPTION ',Options);
+  If Assigned(FEN) then
+    Result:=Result+ExceptionName.GetAsSQL(Options, AIndent);
+end;
+
+{ TSQLPostEventStatement }
+
+destructor TSQLPostEventStatement.Destroy;
+begin
+  FreeAndNil(FCN);
+  inherited Destroy;
+end;
+
+function TSQLPostEventStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('POST_EVENT ',Options);
+  If EventName<>'' then
+    Result:=Result+SQLFormatString(EventName,Options)
+  else
+    Result:=Result+ColName.GetAsSQl(Options,AIndent);
+end;
+
+{ TSQLAssignStatement }
+
+destructor TSQLAssignStatement.Destroy;
+begin
+  FreeAndNil(FVar);
+  FreeAndNil(FExpression);
+  inherited Destroy;
+end;
+
+function TSQLAssignStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  if assigned(FVar) then
+    Result:=Variable.GetAsSQl(Options,AIndent);
+  If Assigned(FExpression) then
+    Result:=Result+' = '+Expression.GetAsSQL(Options, AIndent);
+end;
+
+{ TSQLWhileStatement }
+
+destructor TSQLWhileStatement.Destroy;
+begin
+  FreeAndNil(FCondition);
+  FreeAndNil(FStatement);
+  inherited Destroy;
+end;
+
+function TSQLWhileStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('WHILE (',Options);
+  If Assigned(FCondition) then
+    Result:=Result+Condition.GetAsSQL(Options, AIndent);
+  Result:=Result+SQLKeyWord(') DO',Options)+sLineBreak;
+  If Assigned(FStatement) then
+    Result:=Result+SQLIndentStatement(Statement.GetAsSQL(Options,AIndent),Options);
+end;
+
+{ TSQLWhenException }
+
+destructor TSQLWhenException.Destroy;
+begin
+  FReeAndNil(FEN);
+  inherited Destroy;
+end;
+
+function TSQLWhenException.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+begin
+  Result:=SQLKeyWord('EXCEPTION ',Options);
+  If Assigned(FEN) then
+    Result:=Result+ExceptionName.GetAsSQL(Options, AIndent);;
+end;
+
+{ TSQLWhenStatement }
+
+constructor TSQLWhenStatement.Create(APArent: TSQLElement);
+begin
+  inherited Create(APArent);
+  FErrors:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLWhenStatement.Destroy;
+begin
+  FreeAndNil(FErrors);
+  FreeAndNil(FStatement);
+  inherited Destroy;
+end;
+
+function TSQLWhenStatement.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+
+Var
+  I : Integer;
+  S,Sep : TSQLStringType;
+
+begin
+  Result:=SQLKeyWord('WHEN ',Options);
+  If AnyError then
+    Result:=Result+SQLKeyWord('ANY',Options)
+  else
+    begin
+    S:='';
+    For I:=0 to Errors.Count-1 do
+      begin
+      Sep:=SQLListSeparator(Options);
+      If (S<>'') then
+        S:=S+Sep;
+      S:=S+Errors[i].GetAsSQL(Options,AIndent);
+      end;
+    Result:=Result+S;
+    end;
+  Result:=Result+SQLKeyWord(' DO',Options)+sLineBreak;
+  If Assigned(FStatement) then
+    Result:=Result+SQLIndentStatement(Statement.GetAsSQL(Options,AIndent),Options);
+end;
+
+{ TSQLCreateOrAlterProcedureTriggerStatement }
+
+constructor TSQLCreateOrAlterProcedureTriggerStatement.Create(
+  AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FLocalVariables:=TSQLElementList.Create(True);
+  FStatements:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLCreateOrAlterProcedureTriggerStatement.Destroy;
+begin
+  FreeAndNil(FLocalVariables);
+  FreeAndNil(FStatements);
+  inherited Destroy;
+end;
+
+function TSQLCreateOrAlterProcedureTriggerStatement.GetAsSQL(
+  Options: TSQLFormatOptions; AIndent: Integer): TSQLStringType;
+
+Var
+  I : Integer;
+  S : TSQLStringType;
+
+begin
+  For I:=0 to LocalVariables.Count-1 do
+    begin
+    Result:=Result+SQLKeyWord('DECLARE VARIABLE ',Options);
+    Result:=Result+LocalVariables[i].GetAsSQL(Options,AIndent)+';'+sLineBreak;
+    end;
+  Result:=Result+SQLKeyWord('BEGIN',Options)+sLineBreak;
+  For I:=0 to Statements.Count-1 do
+    begin
+    S:=Statements[i].GetAsSQL(Options,AIndent);
+    If sfoIndentProcedureBlock in Options then
+      S:=SQLIndentStatement(S,Options);
+    Result:=Result+S+';'+sLineBreak;
+    end;
+  Result:=Result+SQLKeyWord('END',Options);
+end;
+
+{ TSQLAlterCreateTriggerStatement }
+
+destructor TSQLAlterCreateTriggerStatement.destroy;
+begin
+  FreeAndNil(FTableName);
+  inherited destroy;
+end;
+
+function TSQLAlterCreateTriggerStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Const
+  SStates    : Array[TTriggerState]     of String = ('','ACTIVE','INACTIVE');
+  SMoment    : Array[TTriggerMoment]    of String = ('BEFORE','AFTER');
+  SOperation : Array[TTriggerOperation] of String = ('DELETE','INSERT','UPDATE');
+
+Var
+  A : Boolean;
+  S,Sep : TSQLStringType;
+  I : Integer;
+  O : TTriggerOperation;
+
+begin
+  A:=Self is TSQLAlterTriggerStatement;
+  If A then
+    Result:=SQLKeyword('ALTER ',Options)
+  else
+    Result:=SQLKeyword('CREATE ',Options);
+  Result:=Result+SQLKeyWord('TRIGGER ',Options);
+  If (ObjectName<>Nil) then
+    Result:=Result+ObjectName.GetAsSQL(Options, AIndent);
+  If Not A and Assigned(FTableName) then
+    Result:=Result+SQLKeyWord(' FOR ',Options)+TableName.GetAsSQL(Options, AIndent);
+  Result:=Result+sLineBreak;
+  If (State<>tsNone) then
+    Result:=Result+SStates[State]+sLineBreak;
+  Result:=Result+SQLKeyWord(SMoment[Moment]+' ',Options);
+  S:='';
+  for O:=Low(TTriggerOperation) to High(TTriggerOperation) do
+    if O in Operations then
+      begin
+      If S<>'' then
+        S:=S+SQLKeyWord(' OR ',Options);
+      S:=S+SQLKeyWord(SOperation[O],Options);
+      end;
+  Result:=Result+S+sLineBreak;
+  If (Position<>0) then
+    Result:=Result+SQLKeyWord('POSITION ',OPtions)+IntToStr(Position)+sLineBreak;
+  Result:=Result+SQLKeyword('AS',Options)+sLineBreak;
+  Result:=Result+Inherited GetAsSQL(Options,AIndent);
+end;
+
+{ TDeclareExternalFunctionStatement }
+
+constructor TSQLDeclareExternalFunctionStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  Farguments:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLDeclareExternalFunctionStatement.Destroy;
+begin
+  FreeAndNil(FArguments);
+  FreeAndNil(FReturnType);
+  inherited Destroy;
+end;
+
+function TSQLDeclareExternalFunctionStatement.GetAsSQL(
+  Options: TSQLFormatOptions; AIndent: Integer): TSQLStringType;
+
+Var
+  Sp,S,Sep : TSQLStringType;
+  I : Integer;
+
+begin
+  if (sfoMultilineDeclareFunction in Options) then
+    Sp:=sLineBreak+'  '
+  else
+    sp:=' ';
+  Result:=SQLKeyWord('DECLARE EXTERNAL FUNCTION ',Options)+inherited GetAsSQL(Options, AIndent);
+  If Arguments.Count>0 then
+    begin
+    Sep:=SQLlistSeparator(Options);
+    S:='';
+    For I:=0 to Arguments.Count-1 do
+      begin
+      If (S<>'') then
+        S:=S+Sep;
+      S:=S+Arguments[i].GetAsSQL(Options,AIndent);
+      end;
+    Result:=Result+Sp+S;
+    end;
+  If Assigned(FReturnType) then
+    Result:=Result+sp+SQLKeyWord('RETURNS ',Options)+ReturnType.GetAsSQL(Options,AIndent);
+  Result:=Result+sp+SQLKeyWord('ENTRY_POINT ',Options)+SQLFormatString(EntryPoint,Options);
+  Result:=Result+sp+SQLKeyWord('MODULE_NAME ',Options)+SQLFormatString(ModuleName,Options);
+end;
+
+{ TSQLIdentifierExpression }
+
+constructor TSQLIdentifierExpression.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FElementIndex:=-1;
+end;
+
+destructor TSQLIdentifierExpression.Destroy;
+begin
+  FreeAndNil(FIdentifier);
+  inherited Destroy;
+end;
+
+function TSQLIdentifierExpression.GetAsSQL(Options: TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+begin
+  If Assigned(FIdentifier) then
+    Result:= Identifier.GetAsSQL(Options);
+  If (ElementIndex<>-1) then
+    Result:=Result+Format('[%d]',[Elementindex]);
+end;
+
+{ TSQLSelectExpression }
+
+function TSQLSelectExpression.GetAsSQL(Options: TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+begin
+  Result:='('+inherited GetAsSQL(Options)+')';
+end;
+
+{ TSQLExistsExpression }
+
+function TSQLExistsExpression.GetAsSQL(Options: TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+begin
+  Result:=SQLKeyword('EXISTS',Options)+' ('+inherited GetAsSQL(Options)+')';
+end;
+
+{ TSQLSingularExpression }
+
+function TSQLSingularExpression.GetAsSQL(Options: TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+begin
+  Result:=SQLKeyWord('SINGULAR',Options)+' ('+inherited GetAsSQL(Options)+')';
+end;
+
+{ TSQLAllExpression }
+
+function TSQLAllExpression.GetAsSQL(Options: TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+begin
+  Result:=SQLKeyWord('ALL',Options)+' ('+inherited GetAsSQL(Options)+')';
+end;
+
+{ TSQLSomeExpression }
+
+function TSQLSomeExpression.GetAsSQL(Options: TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+begin
+  Result:=SQLKeyWord('SOME',Options)+' ('+inherited GetAsSQL(Options)+')';
+end;
+
+{ TSQLAnyExpression }
+
+function TSQLAnyExpression.GetAsSQL(Options: TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+begin
+  Result:=SQLKeyWord('ANY',Options)+' ('+inherited GetAsSQL(Options)+')';
+end;
+
+{ TSQLExpression }
+
+function TSQLExpression.UseBrackets: Boolean;
+begin
+  Result:=False;
+end;
+
+{ TSQLNullLiteral }
+
+function TSQLNullLiteral.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+begin
+  Result:=SQLKeyWord('NULL',Options);
+end;
+
+{ TSQLUserLiteral }
+
+function TSQLUserLiteral.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+begin
+  Result:=SQLKeyWord('USER',Options);
+end;
+
+{ TSQLValueLiteral }
+
+function TSQLValueLiteral.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+begin
+  Result:=SQLKeyWord('VALUE',Options);
+end;
+
+{ TSQLUniqueFieldConstraint }
+
+function TSQLUniqueFieldConstraint.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  If (Result<>'') then
+    Result:=Result+' ';
+  Result:=Result+SQLKeyWord('UNIQUE',Options);
+end;
+
+{ TSQLPrimaryKeyFieldConstraint }
+
+function TSQLPrimaryKeyFieldConstraint.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  If (Result<>'') then
+    Result:=Result+' ';
+  Result:=Result+SQLKeyWord('PRIMARY KEY',Options);
+end;
+
+{ TSQLTableUniqueConstraintDef }
+
+function TSQLTableUniqueConstraintDef.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  If (Result<>'') then
+    Result:=Result+' ';
+  Result:=Result+SQLKeyWord('UNIQUE',Options)+' '+FieldListSQl(Options,AIndent);
+end;
+
+{ TSQLTablePrimaryKeyConstraintDef }
+
+function TSQLTablePrimaryKeyConstraintDef.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  If (Result<>'') then
+    Result:=Result+' ';
+  Result:=Result+SQLKeyWord('PRIMARY KEY',Options)+' '+FieldListSQl(Options,AIndent);
+end;
+
+{ TSQLSelectNaturalPlan }
+
+function TSQLSelectNaturalPlan.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  Result:=Result+SQLKeyWord(' NATURAL',Options);
+end;
+
+{ TSQLRollBackStatement }
+
+function TSQLRollBackStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyword('ROLLBACK',Options)+Inherited GetAsSQL(Options,AIndent);
+end;
+
+{ TSQLCommitStatement }
+
+function TSQLCommitStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyword('COMMIT',Options)+Inherited GetAsSQL(Options,AIndent);
+  If Retain then
+    Result:=Result+SQLKeyWord(' RETAIN',Options);
+end;
+
+{ TSQLCreateGeneratorStatement }
+
+function TSQLCreateGeneratorStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('CREATE GENERATOR ',Options)+Inherited GetAsSQL(Options, AIndent);
+end;
+
+{ TSQLCreateRoleStatement }
+
+function TSQLCreateRoleStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('CREATE ROLE ',Options)+inherited GetAsSQL(Options, AIndent);
+end;
+
+{ TSQLAlterDomainDropDefaultStatement }
+
+function TSQLAlterDomainDropDefaultStatement.GetAsSQL(
+  Options: TSQLFormatOptions; AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent)+
+          SQLKeyword(' DROP DEFAULT',Options);
+end;
+
+{ TSQLAlterDomainDropCheckStatement }
+
+function TSQLAlterDomainDropCheckStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent)+
+          SQLKeyword(' DROP CHECK',Options);
+end;
+
+{ TSQLAlterDomainStatement }
+
+function TSQLAlterDomainStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('ALTER DOMAIN ',Options)+inherited GetAsSQL(Options, AIndent);
+end;
+
+{ TSQLAlterDomainRenameStatement }
+
+destructor TSQLAlterDomainRenameStatement.Destroy;
+begin
+  FreeAndNil(FNewName);
+  inherited Destroy;
+end;
+
+function TSQLAlterDomainRenameStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  If Assigned(FNewName) then
+    Result:=Result+' '+NewName.GetAsSQL(Options,AIndent);
+end;
+
+{ TSQLCreateExceptionStatement }
+
+destructor TSQLCreateExceptionStatement.Destroy;
+begin
+  FreeAndNil(FMessage);
+  inherited Destroy;
+end;
+
+function TSQLCreateExceptionStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  If Self is TSQLAlterExceptionStatement then
+    Result:=SQLKeyWord('ALTER ',Options)
+  else
+    Result:=SQLKeyWord('CREATE ',Options);
+  Result:=Result+SQLKeyWord('EXCEPTION ',Options)+inherited GetAsSQL(Options, AIndent);
+  If Assigned(FMessage) then
+    Result:=Result+' '+FMessage.GetAsSQL(Options,AIndent);
+end;
+
+{ TSQLAlterIndexStatement }
+
+function TSQLAlterIndexStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('ALTER INDEX ',Options)+inherited GetAsSQL(Options, AIndent);
+  If Inactive then
+    Result:=Result+SQLKeyWord(' INACTIVE',Options)
+  else
+    Result:=Result+SQLKeyWord(' ACTIVE',Options)
+end;
+
+{ TSQLDropTableFieldOperation }
+
+function TSQLDropTableFieldOperation.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('DROP ',OPtions)+inherited GetAsSQL(Options, AIndent);
+end;
+
+{ TSQLDropTableConstraintOperation }
+
+function TSQLDropTableConstraintOperation.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('DROP CONSTRAINT ',OPtions)+inherited GetAsSQL(Options, AIndent);
+end;
+
+{ TSQLAlterTableFieldPositionOperation }
+
+function TSQLAlterTableFieldPositionOperation.GetAsSQL(
+  Options: TSQLFormatOptions; AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyword('ALTER COLUMN ',Options)+inherited GetAsSQL(Options, AIndent);
+  Result:=Result+SQLKeyWord(' POSITION ',Options)+IntToStr(NewPosition);
+end;
+
+{ TSQLCreateViewStatement }
+
+function TSQLCreateViewStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  S,Sep : TSQLStringType;
+  I : Integer;
+
+begin
+  Result:=SQLKeyWord('CREATE VIEW ',Options)+inherited GetAsSQL(Options, AIndent);
+  If (Fields.Count>0) then
+    begin
+    S:='';
+    Sep:=SQLListSeparator(Options);
+    For I:=0 to Fields.Count-1 do
+      begin
+      If (S<>'') then
+        S:=S+Sep;
+      S:=S+Fields[i].GetAsSQl(Options,AIndent);
+      end;
+    S:=' ('+S+') AS ';
+    end
+  else
+    S:=' AS ';
+  Result:=Result+S;
+  If Assigned(FSelect) then
+    Result:=Result+Select.GetAsSQL(Options,AIndent)
+end;
+
+{ TSQLDatabaseFileInfo }
+
+function TSQLDatabaseFileInfo.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQlKeyWord('FILE ',OPtions)+SQLFormatString(FileName,Options);
+  If Length>0 then
+    Result:=Result+SQlKeyWord(' LENGTH ',Options)+IntToStr(Length)+SQlKeyWord(' PAGES',Options)
+  else if (StartPage>0) then
+    Result:=Result+SQlKeyWord(' STARTING AT ',Options)+IntToStr(StartPage);
+end;
+
+{ TSQLExitStatement }
+
+function TSQLExitStatement.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+begin
+  Result:=SQLKeyWord('EXIT',Options);
+end;
+
+{ TSQLSuspendStatement }
+
+function TSQLSuspendStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('SUSPEND',Options);
+end;
+
+{ TSQLWhenSQLError }
+
+function TSQLWhenSQLError.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+begin
+  Result:=SQLKeyWord('SQLCODE ',Options)+IntTostr(ErrorCode);
+end;
+
+{ TSQLWhenGDSError }
+
+function TSQLWhenGDSError.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+begin
+  Result:=SQLKeyWord('GDSCODE ',Options)+IntTostr(GDSErrorNumber);
+end;
+
+{ TSQLDropTableStatement }
+
+function TSQLDropTableStatement.SQLObjectType(Options : TSQLFormatOptions): String;
+begin
+  Result:='TABLE';
+end;
+
+{ TSQLDropIndexStatement }
+
+function TSQLDropIndexStatement.SQLObjectType(Options : TSQLFormatOptions): String;
+begin
+  Result:='INDEX';
+end;
+
+{ TSQLDropViewStatement }
+
+function TSQLDropViewStatement.SQLObjectType(Options : TSQLFormatOptions): String;
+begin
+  Result:='VIEW';
+end;
+
+{ TSQLDropProcedureStatement }
+
+function TSQLDropProcedureStatement.SQLObjectType(Options : TSQLFormatOptions): String;
+begin
+  Result:='PROCEDURE';
+end;
+
+{ TSQLDropDomainStatement }
+
+function TSQLDropDomainStatement.SQLObjectType(Options : TSQLFormatOptions): String;
+begin
+  Result:='DOMAIN';
+end;
+
+{ TSQLDropGeneratorStatement }
+
+function TSQLDropGeneratorStatement.SQLObjectType(Options : TSQLFormatOptions): String;
+begin
+  Result:='GENERATOR';
+end;
+
+{ TSQLDropTriggerStatement }
+
+function TSQLDropTriggerStatement.SQLObjectType(Options: TSQLFormatOptions
+  ): String;
+begin
+  Result:='TRIGGER';
+end;
+
+{ TSQLDropExceptionStatement }
+
+function TSQLDropExceptionStatement.SQLObjectType(Options: TSQLFormatOptions
+  ): String;
+begin
+  Result:='EXCEPTION';
+end;
+
+{ TSQLDropDatabaseStatement }
+
+function TSQLDropDatabaseStatement.SQLObjectType(Options: TSQLFormatOptions
+  ): String;
+begin
+  Result:='DATABASE';
+end;
+
+{ TSQLDropRoleStatement }
+
+function TSQLDropRoleStatement.SQLObjectType(Options: TSQLFormatOptions
+  ): String;
+begin
+  Result:='ROLE';
+end;
+
+{ TSQLDropExternalFunctionStatement }
+
+function TSQLDropExternalFunctionStatement.SQLObjectType(
+  Options: TSQLFormatOptions): String;
+begin
+  Result:='EXTERNAL FUNCTION';
+end;
+
+{ TSQLDropShadowStatement }
+
+function TSQLDropShadowStatement.SQLObjectType(Options: TSQLFormatOptions
+  ): String;
+begin
+  Result:='SHADOW';
+end;
+
+{ TSQLConnectStatement }
+
+function TSQLConnectStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('CONNECT ',Options)+SQLFormatString(DatabaseName,Options);
+  If (UserName<>'') then
+    Result:=Result+SQLKeyWord(' USER ',Options)+SQLFormatString(UserName,Options);
+  If (Password<>'') then
+    Result:=Result+SQLKeyWord(' PASSWORD ',Options)+SQLFormatString(Password,Options);
+  If (Cache<>0) then
+    Result:=Result+SQLKeyWord(' CACHE ',Options)+IntToStr(Cache);
+  If (Role<>'') then
+    Result:=Result+SQLKeyWord(' ROLE ',Options)+SQLFormatString(Role,Options);
+end;
+
+{ TSQLExtractExpression }
+
+destructor TSQLExtractExpression.Destroy;
+begin
+  FreeAndNil(FValue);
+  inherited Destroy;
+end;
+
+function TSQLExtractExpression.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+
+begin
+  Result:=SQLKeyWord('EXTRACT('+ExtractElementNames[Element]+' FROM ',Options);
+
+  If Assigned(FValue) then
+    Result:=Result+Value.GetAsSQL(Options, AIndent);
+
+  Result:=Result+')';
+end;
+
+{ TSQLParameterExpression }
+
+destructor TSQLParameterExpression.Destroy;
+begin
+  FreeAndNil(FIdentifier);
+  inherited Destroy;
+end;
+
+function TSQLParameterExpression.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=':';
+  If Assigned(FIdentifier) then
+   Result:=Result+IDentifier.GetAsSQL(Options, AIndent);
+end;
+
+{ TSQLFieldConstraintList }
+
+constructor TSQLFieldConstraintList.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FList:=TSQLElementList.Create;
+end;
+
+destructor TSQLFieldConstraintList.Destroy;
+begin
+  FreeAndNil(FList);
+  inherited Destroy;
+end;
+
+function TSQLFieldConstraintList.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  I : Integer;
+
+begin
+  For I:=0 to List.Count-1 do
+    begin
+    If (Result<>'') then
+      Result:=Result+' ';
+    Result:=Result+List[i].GetAsSQL(Options, AIndent);
+    end;
+end;
+
+
+{ TSQLColumnPrivilege }
+
+destructor TSQLColumnPrivilege.Destroy;
+begin
+  FreeAndNil(FColumns);
+  inherited Destroy;
+end;
+
+function TSQLColumnPrivilege.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  Sep : TSQLStringType;
+  I : Integer;
+begin
+  If Assigned(FColumns) then
+    begin
+    Sep:=SQLListSeparator(Options);
+    For I:=0 to Columns.Count-1 do
+      begin
+      If (Result<>'') then
+        Result:=Result+Sep;
+      Result:=Result+Columns[i].GetAsSql(Options);
+      end;
+    end;
+  If (Result<>'') then
+    Result:=' ('+Result+')';
+end;
+
+{ TSQLGrantStatement }
+
+function TSQLGrantStatement.GranteesAsSQL(Options: TSQLFormatOptions; AIndent : Integer; IsRevoke : Boolean = False): TSQLStringType;
+
+Var
+  Sep : TSQLStringType;
+  I : Integer;
+
+begin
+  Sep:=SQLListSeparator(Options);
+  For I:=0 to Grantees.Count-1 do
+    begin
+    If (Result<>'') then
+      Result:=Result+Sep;
+    Result:=Result+Grantees[i].GetAsSQl(Options,AIndent);
+    end;
+  If IsRevoke then
+    Result:=SQLKeyWord(' FROM ',Options)+Result
+  else
+    Result:=SQLKeyWord(' TO ',Options)+Result;
+end;
+
+constructor TSQLGrantStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FGrantees:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLGrantStatement.Destroy;
+begin
+  FreeAndNil(FGrantees);
+  inherited Destroy;
+end;
+
+{ TSQLTableGrantStatement }
+
+constructor TSQLTableGrantStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FPrivileges:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLTableGrantStatement.Destroy;
+begin
+  FreeAndNil(FPrivileges);
+  FreeAndNil(FTableName);
+  inherited Destroy;
+end;
+
+function TSQLTableGrantStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  Sep : TSQLStringType;
+  I : Integer;
+
+begin
+  Sep:=SQLListSeparator(Options);
+  For I:=0 to Privileges.Count-1 do
+    begin
+    If (Result<>'') then
+      Result:=Result+Sep;
+    Result:=Result+Privileges[i].GetAsSQL(Options,AIndent);
+    end;
+  Result:=SQLKeyWord('GRANT ',Options)+Result+SQLKeyWord(' ON ',Options);
+  If Assigned(FTableName) then
+    Result:=Result+FTableName.GetAsSQl(Options,AIndent);
+  Result:=Result+Self.GranteesAsSQL(Options,AIndent);
+  If GrantOption then
+    Result:=Result+SQLKeyWord(' WITH GRANT OPTION',Options);
+end;
+
+{ TSQLProcedureGrantStatement }
+
+destructor TSQLProcedureGrantStatement.Destroy;
+begin
+  FreeAndNil(FProcedureName);
+  inherited Destroy;
+end;
+
+function TSQLProcedureGrantStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('GRANT EXECUTE ON PROCEDURE ',OPtions);
+  If Assigned(FProcedureName) then
+    Result:=Result+FProcedureName.GetAsSQl(Options,AIndent);
+  Result:=Result+GranteesAsSQL(Options,AIndent);
+end;
+
+{ TSQLRoleGrantStatement }
+
+constructor TSQLRoleGrantStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FRoles:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLRoleGrantStatement.Destroy;
+begin
+  FreeAndNil(FRoles);
+  inherited Destroy;
+end;
+
+function TSQLRoleGrantStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  Sep : TSQLStringType;
+  I : Integer;
+begin
+   Sep:=SQLListSeparator(Options);
+   For I:=0 to Roles.Count-1 do
+      begin
+      If (Result<>'') then
+        Result:=Result+Sep;
+      Result:=Result+Roles[i].GetAsSQl(Options,AIndent);
+      end;
+  Result:=SQLKeyWord('GRANT ',Options)+Result;
+  Result:=Result+GranteesAsSQL(Options,AIndent);
+  If AdminOption then
+    Result:=Result+SQLKeyWord(' WITH ADMIN OPTION',OPtions);
+end;
+
+{ TSQLInsertPrivilege }
+
+function TSQLInsertPrivilege.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('INSERT',Options);
+end;
+
+{ TSQLDeletePrivilege }
+
+function TSQLDeletePrivilege.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('DELETE',Options);
+end;
+
+{ TSQLSelectPrivilege }
+
+function TSQLSelectPrivilege.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('SELECT',Options);
+end;
+
+{ TSQLAllPrivilege }
+
+function TSQLAllPrivilege.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+begin
+  Result:=SQLKeyWord('ALL PRIVILEGES',Options);
+end;
+
+{ TSQLUpdatePrivilege }
+
+function TSQLUpdatePrivilege.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  Result:=SQLKeyWord('UPDATE',Options)+Result;
+end;
+
+{ TSQLReferencePrivilege }
+
+function TSQLReferencePrivilege.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  Result:=SQLKeyWord('REFERENCES',Options)+Result;
+end;
+
+{ TSQLGroupGrantee }
+
+function TSQLGroupGrantee.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  Result:=SQLkeyWord('GROUP ',Options)+Result;
+end;
+
+{ TSQLProcedureGrantee }
+
+function TSQLProcedureGrantee.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  Result:=SQLkeyWord('PROCEDURE ',Options)+Result;
+end;
+
+{ TSQLViewGrantee }
+
+function TSQLViewGrantee.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  Result:=SQLkeyWord('VIEW ',Options)+Result;
+end;
+
+{ TSQLTriggerGrantee }
+
+function TSQLTriggerGrantee.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=inherited GetAsSQL(Options, AIndent);
+  Result:=SQLkeyWord('TRIGGER ',Options)+Result;
+end;
+
+{ TSQLPublicGrantee }
+
+function TSQLPublicGrantee.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer
+  ): TSQLStringType;
+begin
+  Result:=SQLKeyWord('PUBLIC',Options);
+end;
+
+{ TSQLTableRevokeStatement }
+
+function TSQLTableRevokeStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  S,Sep : TSQLStringType;
+  I : Integer;
+
+begin
+  Sep:=SQLListSeparator(Options);
+  S:='';
+  For I:=0 to Privileges.Count-1 do
+    begin
+    If (S<>'') then
+      S:=S+Sep;
+    S:=S+Privileges[i].GetAsSQL(Options,AIndent);
+    end;
+  Result:=SQLKeyWord('REVOKE ',Options);
+  If GrantOption then
+    Result:=Result+SQLKeyWord('GRANT OPTION FOR ',Options);
+  Result:=Result+S+SQLKeyWord(' ON ',Options);
+  If Assigned(FTableName) then
+    Result:=Result+FTableName.GetAsSQl(Options,AIndent);
+  Result:=Result+Self.GranteesAsSQL(Options,AIndent,True);
+end;
+
+{ TSQLProcedureRevokeStatement }
+
+function TSQLProcedureRevokeStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+begin
+  Result:=SQLKeyWord('REVOKE EXECUTE ON PROCEDURE ',OPtions);
+  If Assigned(FProcedureName) then
+    Result:=Result+FProcedureName.GetAsSQl(Options,AIndent);
+  Result:=Result+GranteesAsSQL(Options,AIndent,True);
+end;
+
+{ TSQLRoleRevokeStatement }
+
+function TSQLRoleRevokeStatement.GetAsSQL(Options: TSQLFormatOptions;
+  AIndent: Integer): TSQLStringType;
+
+Var
+  Sep : TSQLStringType;
+  I : Integer;
+begin
+  Sep:=SQLListSeparator(Options);
+  For I:=0 to Roles.Count-1 do
+    begin
+    If (Result<>'') then
+      Result:=Result+Sep;
+    Result:=Result+Roles[i].GetAsSQl(Options,AIndent);
+    end;
+  Result:=SQLKeyWord('REVOKE ',Options)+Result;
+  Result:=Result+GranteesAsSQL(Options,AIndent,True);
+end;
+
+end.
+

+ 108 - 63
packages/fcl-db/tests/Makefile

@@ -1,8 +1,8 @@
 #
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2009/12/31]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2010/11/23]
 #
 #
 default: all
 default: all
-MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
 BSDs = freebsd netbsd openbsd darwin
 BSDs = freebsd netbsd openbsd darwin
 UNIXs = linux $(BSDs) solaris qnx haiku
 UNIXs = linux $(BSDs) solaris qnx haiku
 LIMIT83fs = go32v2 os2 emx watcom
 LIMIT83fs = go32v2 os2 emx watcom
@@ -389,6 +389,9 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 override TARGET_UNITS+=toolsunit dbftoolsunit memdstoolsunit sqldbtoolsunit sdfdstoolsunit
 override TARGET_UNITS+=toolsunit dbftoolsunit memdstoolsunit sqldbtoolsunit sdfdstoolsunit
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override TARGET_UNITS+=toolsunit dbftoolsunit memdstoolsunit sqldbtoolsunit sdfdstoolsunit
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 override TARGET_UNITS+=toolsunit dbftoolsunit memdstoolsunit sqldbtoolsunit sdfdstoolsunit
 override TARGET_UNITS+=toolsunit dbftoolsunit memdstoolsunit sqldbtoolsunit sdfdstoolsunit
 endif
 endif
@@ -440,179 +443,188 @@ endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
 override TARGET_UNITS+=toolsunit dbftoolsunit memdstoolsunit sqldbtoolsunit sdfdstoolsunit
 override TARGET_UNITS+=toolsunit dbftoolsunit memdstoolsunit sqldbtoolsunit sdfdstoolsunit
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override TARGET_UNITS+=toolsunit dbftoolsunit memdstoolsunit sqldbtoolsunit sdfdstoolsunit
+endif
 ifeq ($(FULL_TARGET),i386-linux)
 ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
 ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-win32)
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-os2)
 ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-beos)
 ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-haiku)
 ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
 ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
 ifeq ($(FULL_TARGET),i386-qnx)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-netware)
 ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
 ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
 ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-emx)
 ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
 ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-wince)
 ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
 ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
 ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
 ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
 ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
 ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
 ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
 ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
 ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
 ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
 ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
 ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
 ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
 ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),arm-linux)
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
 ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),arm-darwin)
 ifeq ($(FULL_TARGET),arm-darwin)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),arm-wince)
 ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),arm-gba)
 ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),arm-nds)
 ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
 ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
 ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
 ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
 ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),avr-embedded)
 ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),armeb-linux)
 ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_EXAMPLES+=dbtestframework
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override TARGET_EXAMPLES+=dbtestframework testsqlfiles
 endif
 endif
 override INSTALL_FPCPACKAGE=y
 override INSTALL_FPCPACKAGE=y
 ifdef REQUIRE_UNITSDIR
 ifdef REQUIRE_UNITSDIR
@@ -1930,6 +1942,16 @@ REQUIRE_PACKAGES_ORACLE=1
 REQUIRE_PACKAGES_SQLITE=1
 REQUIRE_PACKAGES_SQLITE=1
 REQUIRE_PACKAGES_PXLIB=1
 REQUIRE_PACKAGES_PXLIB=1
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-FPCUNIT=1
+REQUIRE_PACKAGES_FCL-DB=1
+REQUIRE_PACKAGES_SQLITE=1
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_HASH=1
 REQUIRE_PACKAGES_HASH=1
@@ -2141,6 +2163,23 @@ REQUIRE_PACKAGES_FCL-XML=1
 REQUIRE_PACKAGES_FCL-FPCUNIT=1
 REQUIRE_PACKAGES_FCL-FPCUNIT=1
 REQUIRE_PACKAGES_FCL-DB=1
 REQUIRE_PACKAGES_FCL-DB=1
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-FPCUNIT=1
+REQUIRE_PACKAGES_FCL-DB=1
+REQUIRE_PACKAGES_IBASE=1
+REQUIRE_PACKAGES_POSTGRES=1
+REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
+REQUIRE_PACKAGES_ORACLE=1
+REQUIRE_PACKAGES_SQLITE=1
+REQUIRE_PACKAGES_PXLIB=1
+endif
 ifdef REQUIRE_PACKAGES_RTL
 ifdef REQUIRE_PACKAGES_RTL
 PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
 PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
 ifneq ($(PACKAGEDIR_RTL),)
 ifneq ($(PACKAGEDIR_RTL),)
@@ -2150,9 +2189,9 @@ else
 UNITDIR_RTL=$(PACKAGEDIR_RTL)
 UNITDIR_RTL=$(PACKAGEDIR_RTL)
 endif
 endif
 ifdef CHECKDEPEND
 ifdef CHECKDEPEND
-$(PACKAGEDIR_RTL)/$(FPCMADE):
-	$(MAKE) -C $(PACKAGEDIR_RTL) $(FPCMADE)
-override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(FPCMADE)
+$(PACKAGEDIR_RTL)/$(OS_TARGET)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_RTL)/$(OS_TARGET) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(OS_TARGET)/$(FPCMADE)
 endif
 endif
 else
 else
 PACKAGEDIR_RTL=
 PACKAGEDIR_RTL=
@@ -2895,6 +2934,9 @@ endif
 ifdef EXEFILES
 ifdef EXEFILES
 override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
 override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
 endif
 endif
+ifdef CLEAN_PROGRAMS
+override CLEANEXEFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEEXT), $(CLEAN_PROGRAMS)))
+endif
 ifdef CLEAN_UNITS
 ifdef CLEAN_UNITS
 override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
 override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
 endif
 endif
@@ -2941,6 +2983,9 @@ endif
 ifdef CLEANRSTFILES
 ifdef CLEANRSTFILES
 	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
 	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
 endif
 endif
+endif
+ifdef CLEAN_FILES
+	-$(DEL) $(CLEAN_FILES)
 endif
 endif
 	-$(DELTREE) units
 	-$(DELTREE) units
 	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
 	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)

+ 1 - 1
packages/fcl-db/tests/Makefile.fpc

@@ -6,7 +6,7 @@
 main=fcl
 main=fcl
 
 
 [target]
 [target]
-examples=dbtestframework
+examples=dbtestframework testsqlfiles 
 units=toolsunit dbftoolsunit memdstoolsunit sqldbtoolsunit sdfdstoolsunit
 units=toolsunit dbftoolsunit memdstoolsunit sqldbtoolsunit sdfdstoolsunit
 
 
 [install]
 [install]

+ 2550 - 0
packages/fcl-db/tests/tcgensql.pas

@@ -0,0 +1,2550 @@
+{
+    This file is part of the Free Component Library
+    Copyright (c) 2010 by the Free Pascal development team
+
+    SQL Syntax Tree SQL generation tests
+
+    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 tcgensql;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpcunit, testutils, testregistry,fpsqltree;
+
+type
+  TSQLDropStatementClass = Class of TSQLDropStatement;
+  TSQLGranteeClass = Class of TSQLGrantee;
+
+  { TTestGenerateSQL }
+
+  TTestGenerateSQL= class(TTestCase)
+  Private
+    FToFree:TSQLElement;
+  protected
+    procedure SetUp; override; 
+    procedure TearDown; override;
+    procedure DoTestDropStatement(AClass: TSQLDropStatementClass; const AObjectName: String);
+    procedure DoTestAlterCreateProcedure(S: TSQLAlterCreateProcedureStatement; PHEAD: String);
+    procedure DoTestAlterCreateTrigger(S: TSQLAlterCreateTriggerStatement; PHEAD: String);
+    Function CreateIdentifier(Const AName : TSQLStringType) : TSQLIdentifierName;
+    Function CreateGrantee(Const AName : TSQLStringType; AClass : TSQLGranteeClass = Nil) : TSQLGrantee;
+    Function CreateLiteral(Const AValue : Integer) : TSQLIntegerLiteral;
+    Function CreateLiteral(Const AValue : TSQLStringType) : TSQLStringLiteral;
+    Function CreateLiteral(Const AValue : Double) : TSQLFloatLiteral;
+    Function CreateTypeDefinition(Const ADataType : TSQLDataType; ALen : Integer = 0): TSQLTypeDefinition;
+    Function CreateLiteralExpression(Const ALiteral : TSQLLiteral) : TSQLLiteralExpression;
+    Function CreateIdentifierExpression(Const AName : TSQLStringtype) : TSQLIdentifierExpression;
+    Function CreateUnaryExpression(Const AOperand : TSQLExpression) : TSQLUnaryExpression;
+    Function CreateBinaryExpression(Const ALeft,ARight : TSQLExpression) : TSQLBinaryExpression;
+    Function CreateUpdatePair(Const AField : TSQLStringType; AValue : TSQLExpression) : TSQLUpdatePair;
+    Function CreateTernaryExpression(Const ALeft,AMiddle,ARight : TSQLExpression) : TSQLTernaryExpression;
+    Function CreateForeignKey(Const ATable : TSQLStringType; AFieldName1,AFieldName2 : TSQLStringType):TSQLForeignKeyDefinition;
+    Function CreateSelectField(Const AValue : TSQLExpression; Const AAlias : TSQLStringType) : TSQLSelectField;
+    Function CreateSimpleTableReference(Const ATableName : TSQLStringType; AAlias : TSQLStringType) : TSQLSimpleTableReference;
+    Function CreateJoinTablereference(Const ALeft,ARight : TSQLTableReference) : TSQLJoinTableReference;
+    Function CreateSelect(AField : TSQLExpression; ATable : TSQLStringType) : TSQLSelectStatement;
+    Procedure AssertSQL(Const AElement : TSQLElement; Const ASQL : TSQLStringType; AOptions : TSQLFormatOptions = []);
+  published
+    procedure TestIdentifier;
+    Procedure TestIntegerLiteral;
+    procedure TestStringLiteral;
+    Procedure TestFloatLiteral;
+    Procedure TestNullLiteral;
+    Procedure TestUserLiteral;
+    Procedure TestValueLiteral;
+    Procedure TestLiteralExpression;
+    Procedure TestSelectField;
+    Procedure TestSimpleTablereference;
+    Procedure TestSimpleSelect;
+    Procedure TestAnyExpression;
+    procedure TestAllExpression;
+    procedure TestExistsExpression;
+    procedure TestSomeExpression;
+    procedure TestSingularExpression;
+    Procedure TestUnaryExpression;
+    procedure TestBinaryExpression;
+    procedure TestListExpression;
+    procedure TestTernaryExpression;
+    Procedure TestGenIDExpression;
+    Procedure TestFunctionCall;
+    procedure TestAggregateFunction;
+    procedure TestForeignKey;
+    procedure TestUniqueFieldConstraint;
+    procedure TestPrimaryKeyFieldConstraint;
+    procedure TestForeignKeyFieldConstraint;
+    procedure TestCheckFieldConstraint;
+    procedure TestTableUniqueConstraintDef;
+    procedure TestTablePrimaryKeyConstraintDef;
+    procedure TestTableForeignKeyConstraintDef;
+    procedure TestTableCheckConstraintDef;
+    Procedure TestTypeDefinition;
+    Procedure TestCastExpression;
+    procedure TestJoinTableReference;
+    procedure TestPlanNatural;
+    procedure TestPlanIndex;
+    procedure TestPlanOrder;
+    procedure TestPlanExpression;
+    procedure TestOrderBy;
+    Procedure TestSelect;
+    procedure TestInsert;
+    procedure TestUpdatePair;
+    procedure TestUpdate;
+    procedure TestDelete;
+    procedure TestRollback;
+    procedure TestCommit;
+    procedure TestExecuteProcedure;
+    procedure TestCreateGenerator;
+    procedure TestCreateRole;
+    procedure TestCreateDomain;
+    procedure TestAlterDomainDropDefault;
+    procedure TestAlterDomainDropCheck;
+    Procedure TestAlterDomainSetDefault;
+    Procedure TestAlterDomainRename;
+    procedure TestAlterDomainNewType;
+    procedure TestAlterDomainAddCheck;
+    procedure TestCreateException;
+    procedure TestAlterException;
+    procedure TestCreateIndex;
+    procedure TestAlterIndex;
+    procedure TestDeclareExternalFunction;
+    procedure TestTableFieldDefinition;
+    procedure TestCreateTable;
+    procedure TestDropFieldOperation;
+    procedure TestDropConstraintOperation;
+    procedure TestAlterFieldNameOperation;
+    procedure TestAlterFieldTypeOperation;
+    procedure TestAlterFieldPositionOperation;
+    procedure TestAddFieldOperation;
+    procedure TestAddConstraintOperation;
+    procedure TestAlterTable;
+    procedure TestCreateView;
+    procedure TestDatabaseFileInfo;
+    procedure TestCreateDatabase;
+    procedure TestAlterDatabase;
+    procedure TestCreateShadow;
+    procedure TestSuspend;
+    procedure TestExit;
+    procedure TestBlock;
+    procedure TestAssignment;
+    procedure TestIf;
+    procedure TestFor;
+    procedure TestWhile;
+    Procedure TestWhenSQLError;
+    Procedure TestWhenGDSError;
+    Procedure TestWhenException;
+    Procedure TestWhen;
+    Procedure TestException;
+    Procedure TestPostEvent;
+    Procedure TestTriggerProcedure;
+    procedure TestCreateProcedure;
+    procedure TestAlterProcedure;
+    procedure TestCreateTrigger;
+    procedure TestAlterTrigger;
+    Procedure TestDropStatement;
+    procedure TestConnect;
+    procedure TestExtract;
+    procedure TestParamExpression;
+    Procedure TestGrantTable;
+    Procedure TestGrantProcedure;
+    Procedure TestGrantRole;
+    Procedure TestRevokeTable;
+    Procedure TestRevokeProcedure;
+    Procedure TestRevokeRole;
+  end;
+
+implementation
+
+procedure TTestGenerateSQL.SetUp; 
+begin
+  FToFree:=Nil;
+end; 
+
+procedure TTestGenerateSQL.TearDown; 
+begin
+  FreeAndNil(FToFree);
+end;
+
+function TTestGenerateSQL.CreateIdentifier(const AName: TSQLStringType
+  ): TSQLIdentifierName;
+begin
+  Result:=TSQLIdentifierName.Create(Nil);
+  Result.Name:=AName;
+  FToFree:=Result;
+end;
+
+function TTestGenerateSQL.CreateGrantee(const AName: TSQLStringType;
+  AClass: TSQLGranteeClass = Nil): TSQLGrantee;
+begin
+  If AClass=Nil then
+    AClass:=TSQLGrantee;
+  Result:=AClass.Create(Nil);
+  Result.Name:=AName;
+  FToFree:=Result;
+end;
+
+procedure TTestGenerateSQL.AssertSQL(const AElement: TSQLElement;
+  const ASQL: TSQLStringType; AOptions: TSQLFormatOptions = []);
+
+Var
+  S,S2 : TSQLStringType;
+  L : TStringList;
+  I : Integer;
+
+begin
+  S:=AElement.GetAsSQL(AOptions);
+  AssertEquals('Correct SQL',ASQL,S);
+end;
+
+
+function TTestGenerateSQL.CreateLiteral(const AValue: Integer
+  ): TSQLIntegerLiteral;
+begin
+  Result:=TSQLintegerLiteral.Create(Nil);
+  Result.Value:=AValue;
+  FToFree:=Result;
+end;
+
+function TTestGenerateSQL.CreateLiteral(const AValue: TSQLStringType
+  ): TSQLStringLiteral;
+begin
+  Result:=TSQLStringLiteral.Create(Nil);
+  Result.Value:=AValue;
+  FToFree:=Result;
+end;
+
+function TTestGenerateSQL.CreateLiteral(const AValue: Double
+  ): TSQLFloatLiteral;
+begin
+  Result:=TSQLFloatLiteral.Create(Nil);
+  Result.Value:=AValue;
+  FToFree:=Result;
+end;
+
+function TTestGenerateSQL.CreateTypeDefinition(const ADataType: TSQLDataType;
+  ALen: Integer): TSQLTypeDefinition;
+begin
+  Result:=TSQLTypeDefinition.Create(Nil);
+  Result.DataType:=ADataType;
+  Result.Len:=ALen;
+  FToFree:=Result;
+end;
+
+function TTestGenerateSQL.CreateLiteralExpression(const ALiteral: TSQLLiteral
+  ): TSQLLiteralExpression;
+begin
+  Result:=TSQLLiteralExpression.Create(Nil);
+  FToFree:=Result;
+  Result.Literal:=ALiteral;
+end;
+
+function TTestGenerateSQL.CreateIdentifierExpression(const AName: TSQLStringtype
+  ): TSQLIdentifierExpression;
+begin
+  Result:=TSQLidentifierExpression.Create(Nil);
+  Result.Identifier:=CreateIdentifier(AName);
+  FTofree:=Result;
+end;
+
+function TTestGenerateSQL.CreateUnaryExpression(const AOperand: TSQLExpression
+  ): TSQLUnaryExpression;
+begin
+  Result:=TSQLUnaryExpression.Create(Nil);
+  Result.Operand:=AOperand;
+  FTofree:=Result;
+end;
+
+function TTestGenerateSQL.CreateBinaryExpression(const ALeft,
+  ARight: TSQLExpression): TSQLBinaryExpression;
+begin
+  Result:=TSQLBinaryExpression.Create(Nil);
+  Result.Left:=ALeft;
+  Result.Right:=ARight;
+  FToFree:=Result;
+end;
+
+function TTestGenerateSQL.CreateUpdatePair(const AField: TSQLStringType;
+  AValue: TSQLExpression): TSQLUpdatePair;
+begin
+  Result:=TSQLUpdatePair.Create(Nil);
+  Result.FieldName:=CreateIdentifier(AFIeld);
+  Result.Value:=AValue;
+  FTofree:=Result;
+end;
+
+function TTestGenerateSQL.CreateTernaryExpression(const ALeft, AMiddle,
+  ARight: TSQLExpression): TSQLTernaryExpression;
+begin
+  Result:=TSQLTernaryExpression.Create(Nil);
+  Result.Left:=ALeft;
+  Result.Middle:=AMiddle;
+  Result.Right:=ARight;
+  FToFree:=Result;
+end;
+
+function TTestGenerateSQL.CreateForeignKey(const ATable: TSQLStringType;
+  AFieldName1, AFieldName2: TSQLStringType): TSQLForeignKeyDefinition;
+begin
+  Result:=TSQLForeignKeyDefinition.Create(Nil);
+  Result.TableName:=CreateIdentifier(ATable);
+  Result.FieldList.Add(CreateIdentifier(AFieldName1));
+  If (AFieldName2<>'') then
+    Result.FieldList.Add(CreateIdentifier(AFieldName2));
+  FToFree:=Result;
+end;
+
+function TTestGenerateSQL.CreateSelectField(const AValue: TSQLExpression;
+  const AAlias: TSQLStringType): TSQLSelectField;
+begin
+  Result:=TSQLSelectField.Create(Nil);
+  Result.Expression:=AValue;
+  If (AAlias<>'') then
+    Result.AliasName:=CreateIdentifier(AAlias);
+  FToFree:=Result;
+end;
+
+function TTestGenerateSQL.CreateSimpleTableReference(
+  const ATableName: TSQLStringType; AAlias: TSQLStringType
+  ): TSQLSimpleTableReference;
+begin
+  Result:=TSQLSimpleTableReference.Create(Nil);
+  Result.ObjectName:=CreateIdentifier(ATableName);
+  If AALias<>'' then
+    Result.AliasName:=CreateIdentifier(AAlias);
+  FTofree:=Result;
+end;
+
+function TTestGenerateSQL.CreateJoinTablereference(const ALeft,
+  ARight: TSQLTableReference): TSQLJoinTableReference;
+begin
+  Result:=TSQLJoinTableReference.Create(Nil);
+  Result.Left:=ALeft;
+  Result.Right:=ARight;
+  FTofree:=Result;
+end;
+
+function TTestGenerateSQL.CreateSelect(AField: TSQLExpression;
+  ATable: TSQLStringType): TSQLSelectStatement;
+begin
+  Result:=TSQLSelectStatement.Create(Nil);
+  Result.Fields.Add(AField);
+  Result.Tables.Add(CreateSimpleTableReference(ATable,''));
+  FToFree:=Result;
+end;
+
+procedure TTestGenerateSQL.TestIdentifier;
+
+Var
+  E : TSQLElement;
+begin
+  E:=CreateIdentifier('A');
+  AssertSQL(E,'A',[]);
+  AssertSQL(E,'"A"',[sfoDoubleQuoteIdentifier]);
+  AssertSQL(E,'`A`',[sfoBackQuoteIdentifier]);
+  AssertSQL(E,'''A''',[sfoSingleQuoteIdentifier]);
+end;
+
+procedure TTestGenerateSQL.TestIntegerLiteral;
+begin
+  AssertSQL(CreateLiteral(1),'1',[]);
+end;
+
+procedure TTestGenerateSQL.TestStringLiteral;
+
+Var
+  E : TSQLElement;
+
+begin
+  E:=CreateLiteral('A');
+  AssertSQL(E,'"A"',[sfoDoubleQuotes]);
+  AssertSQL(E,'''A''',[]);
+end;
+
+procedure TTestGenerateSQL.TestFloatLiteral;
+begin
+  // Needs improvement.
+  AssertSQL(CreateLiteral(1.2),FloatToStr(1.2));
+end;
+
+procedure TTestGenerateSQL.TestNullLiteral;
+begin
+  FToFree:=TSQLNullLiteral.Create(Nil);
+  AssertSQL(FToFree,'NULL');
+  AssertSQL(FToFree,'null',[sfoLowerCaseKeyword]);
+end;
+
+procedure TTestGenerateSQL.TestUserLiteral;
+begin
+  FToFree:=TSQLUserLiteral.Create(Nil);
+  AssertSQL(FToFree,'USER');
+  AssertSQL(FToFree,'user',[sfoLowerCaseKeyword]);
+end;
+
+procedure TTestGenerateSQL.TestValueLiteral;
+begin
+  FToFree:=TSQLValueLiteral.Create(Nil);
+  AssertSQL(FToFree,'VALUE');
+  AssertSQL(FToFree,'value',[sfoLowerCaseKeyword]);
+end;
+
+procedure TTestGenerateSQL.TestLiteralExpression;
+
+Var
+  E : TSQLStringLiteral;
+
+begin
+  E:=CreateLiteral('A');
+  AssertSQL(CreateLiteralExpression(E),E.GetAsSQL([]),[]);
+end;
+
+procedure TTestGenerateSQL.TestSelectField;
+
+Var
+  F : TSQLSelectField;
+
+begin
+  F:=CreateSelectField(CreateIdentifierExpression('A'),'');
+  AssertSQL(F,'A');
+  F.AliasName:=CreateIdentifier('B');
+  FTofree:=F;
+  AssertSQL(F,'A AS B');
+end;
+
+procedure TTestGenerateSQL.TestSimpleTablereference;
+
+Var
+  T : TSQLSimpleTablereference;
+
+begin
+  T:=CreateSimpleTablereference('A','');
+  AssertSQL(T,'A');
+  T.AliasName:=CreateIdentifier('B');
+  AssertSQL(T,'A B');
+  T.Params:=TSQLElementList.Create(True);
+  T.Params.Add(CreateIdentifierExpression('C'));
+  FToFree:=T;
+  AssertSQL(T,'A(C) B');
+  T.Params.Add(CreateIdentifierExpression('D'));
+  FToFree:=T;
+  AssertSQL(T,'A(C , D) B');
+end;
+
+procedure TTestGenerateSQL.TestSimpleSelect;
+
+Var
+  S : TSQLSelectStatement;
+
+begin
+  S:=CreateSelect(CreateIdentifierExpression('A'),'B');
+  AssertSQL(S,'SELECT A FROM B');
+end;
+
+procedure TTestGenerateSQL.TestAnyExpression;
+Var
+  A : TSQLAnyExpression;
+begin
+  A:=TSQLAnyExpression.Create(Nil);
+  A.Select:=CreateSelect(CreateIdentifierExpression('A'),'B');
+  FTofree:=A;
+  AssertSQL(A,'ANY (SELECT A FROM B)');
+end;
+
+procedure TTestGenerateSQL.TestSomeExpression;
+Var
+  A : TSQLSomeExpression;
+begin
+  A:=TSQLSomeExpression.Create(Nil);
+  A.Select:=CreateSelect(CreateIdentifierExpression('A'),'B');
+  FTofree:=A;
+  AssertSQL(A,'SOME (SELECT A FROM B)');
+end;
+
+procedure TTestGenerateSQL.TestExistsExpression;
+Var
+  A : TSQLExistsExpression;
+begin
+  A:=TSQLExistsExpression.Create(Nil);
+  A.Select:=CreateSelect(CreateIdentifierExpression('A'),'B');
+  FTofree:=A;
+  AssertSQL(A,'EXISTS (SELECT A FROM B)');
+end;
+
+procedure TTestGenerateSQL.TestAllExpression;
+Var
+  A : TSQLAllExpression;
+begin
+  A:=TSQLAllExpression.Create(Nil);
+  A.Select:=CreateSelect(CreateIdentifierExpression('A'),'B');
+  FTofree:=A;
+  AssertSQL(A,'ALL (SELECT A FROM B)');
+end;
+
+procedure TTestGenerateSQL.TestSingularExpression;
+Var
+  A : TSQLSingularExpression;
+begin
+  A:=TSQLSingularExpression.Create(Nil);
+  A.Select:=CreateSelect(CreateIdentifierExpression('A'),'B');
+  FTofree:=A;
+  AssertSQL(A,'SINGULAR (SELECT A FROM B)');
+end;
+
+procedure TTestGenerateSQL.TestUnaryExpression;
+
+Var
+  U : TSQLUnaryExpression;
+
+begin
+  U:=CreateUnaryExpression(CreateLiteralExpression(CreateLiteral(1)));
+  U.Operation:=uoMinus;
+  AssertSQL(U,'-1');
+  U.Operation:=uoNot;
+  AssertSQL(U,'NOT (1)');
+end;
+
+procedure TTestGenerateSQL.TestBinaryExpression;
+
+//                         boIs, boIsNot, boLike, boContaining, boStarting);
+
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=CreateBinaryExpression(CreateLiteralExpression(CreateLiteral(1)),CreateLiteralExpression(CreateLiteral(2)));
+  B.Operation:=boAnd;
+  AssertSQL(B,'1 AND 2');
+  AssertSQL(B,'1'+sLineBreak+'AND 2',[sfoOneLogicalPerLine]);
+  B.Operation:=boOR;
+  AssertSQL(B,'1 OR 2');
+  AssertSQL(B,'1'+sLineBreak+'OR 2',[sfoOneLogicalPerLine]);
+  B.Operation:=boEQ;
+  AssertSQL(B,'1 = 2');
+  B.Operation:=boLT;
+  AssertSQL(B,'1 < 2');
+  B.Operation:=boGT;
+  AssertSQL(B,'1 > 2');
+  B.Operation:=boLE;
+  AssertSQL(B,'1 <= 2');
+  B.Operation:=boGE;
+  AssertSQL(B,'1 >= 2');
+  B.Operation:=boNE;
+  AssertSQL(B,'1 <> 2');
+  B.Operation:=boAdd;
+  AssertSQL(B,'1 + 2');
+  B.Operation:=boSubtract;
+  AssertSQL(B,'1 - 2');
+  B.Operation:=boMultiply;
+  AssertSQL(B,'1 * 2');
+  B.Operation:=boDivide;
+  AssertSQL(B,'1 / 2');
+  B.Right.Free;
+  B.Right:=TSQLSelectExpression.Create(Nil);
+  TSQLSelectExpression(B.Right).Select:=CreateSelect(CreateIdentifierExpression('A'),'B');
+  FTofree:=B;
+  B.Operation:=boIn;
+  AssertSQL(B,'1 IN (SELECT A FROM B)');
+  B.Operation:=boIS;
+  B.Right.Free;
+  B.Right:=CreateLiteralExpression(TSQLNullLiteral.Create(Nil));
+  FTofree:=B;
+  AssertSQL(B,'1 IS NULL');
+  B.Operation:=boISNot;
+  AssertSQL(B,'1 IS NOT NULL');
+  B.Right.Free;
+  B.Right:=CreateLiteralExpression(CreateLiteral('%A%'));
+  FTofree:=B;
+  B.Left.Free;
+  B.Left:=CreateLiteralExpression(CreateLiteral('ADAM'));
+  FTofree:=B;
+  B.Operation:=boLike;
+  AssertSQL(B,'''ADAM'' LIKE ''%A%''');
+  B.Operation:=boContaining;
+  AssertSQL(B,'''ADAM'' CONTAINING ''%A%''');
+  B.Operation:=boStarting;
+  AssertSQL(B,'''ADAM'' STARTING WITH ''%A%''');
+  B.Left.Free;
+  B.Left:=CreateBinaryExpression(CreateLiteralExpression(CreateLiteral(1)),CreateLiteralExpression(CreateLiteral(2)));
+  TSQLBinaryExpression(B.Left).Operation:=boAdd;
+  FTofree:=B;
+  B.Right.Free;
+  B.Right:=CreateBinaryExpression(CreateLiteralExpression(CreateLiteral(3)),CreateLiteralExpression(CreateLiteral(4)));
+  FTofree:=B;
+  TSQLBinaryExpression(B.Right).Operation:=boAdd;
+  B.Operation:=boLT;
+  AssertSQL(B,'(1 + 2) < (3 + 4)');
+end;
+
+procedure TTestGenerateSQL.TestListExpression;
+
+Var
+  L:TSQLListExpression;
+
+begin
+  L:=TSQLListExpression.Create(Nil);
+  FToFree:=L;
+  AssertSQL(L,'()');
+  L.List.Add(CreateLiteralExpression(CreateLiteral(1)));
+  FToFree:=L;
+  AssertSQL(L,'(1)');
+  L.List.Add(CreateLiteralExpression(CreateLiteral(2)));
+  FToFree:=L;
+  AssertSQL(L,'(1 , 2)');
+  AssertSQL(L,'(1, 2)',[sfoListNoSpaceBeforeComma]);
+  AssertSQL(L,'(1 ,2)',[sfoListNoSpaceAfterComma]);
+  AssertSQL(L,'(1,2)',[sfoListNoSpaceBeforeComma,sfoListNoSpaceAfterComma]);
+end;
+
+procedure TTestGenerateSQL.TestTernaryExpression;
+
+Var
+  T : TSQLTernaryExpression;
+
+begin
+  T:=CreateTernaryExpression(CreateLiteralExpression(CreateLiteral(2)),
+                             CreateLiteralExpression(CreateLiteral(1)),
+                             CreateLiteralExpression(CreateLiteral(3)));
+  T.Operation:=toBetween;
+  AssertSQL(T,'2 BETWEEN 1 AND 3');
+  FreeAndNil(FToFree);
+  T:=CreateTernaryExpression(CreateLiteralExpression(CreateLiteral('A')),
+                             CreateLiteralExpression(CreateLiteral('B')),
+                             CreateLiteralExpression(CreateLiteral('C')));
+  T.Operation:=toLikeEscape;
+  AssertSQL(T,'''A'' LIKE ''B'' ESCAPE ''C''');
+end;
+
+procedure TTestGenerateSQL.TestGenIDExpression;
+
+Var
+  G : TSQLGenIDExpression;
+
+begin
+  G:=TSQLGenIDExpression.Create(Nil);
+  G.Generator:=self.CreateIdentifier('A');
+  G.Value:=CreateLiteralExpression(CreateLiteral(1));
+  FTofree:=G;
+  AssertSQL(G,'GEN_ID(A,1)');
+end;
+
+procedure TTestGenerateSQL.TestFunctionCall;
+
+Var
+  F : TSQLFunctionCallExpression;
+begin
+  F:=TSQLFunctionCallExpression.Create(Nil);
+  F.Identifier:='FUNC';
+  FTofree:=F;
+  AssertSQL(F,'FUNC()');
+  F.Arguments:=TSQLElementList.Create(True);
+  F.Arguments.Add(CreateLiteralExpression(CreateLiteral(1)));
+  FTofree:=F;
+  AssertSQL(F,'FUNC(1)');
+  F.Arguments.Add(CreateLiteralExpression(CreateLiteral(2)));
+  FTofree:=F;
+  AssertSQL(F,'FUNC(1 , 2)');
+  AssertSQL(F,'func(1,2)',[sfoLowerCaseKeyWord,sfoListNoSpaceBeforeComma,sfoListNoSpaceAfterComma]);
+end;
+
+procedure TTestGenerateSQL.TestAggregateFunction;
+
+Var
+  A : TSQLAggregateFunctionExpression;
+
+
+begin
+  A:=TSQLAggregateFunctionExpression.Create(Nil);
+  FToFree:=A;
+  A.Aggregate:=afCount;
+  A.Option:=aoAsterisk;
+  AssertSQL(A,'COUNT(*)');
+  AssertSQL(A,'count(*)',[sfoLowercaseKeyword]);
+  A.Option:=aoNone;
+  A.Expression:=CreateIdentifierExpression('A');
+  FTofree:=A;
+  AssertSQL(A,'COUNT(A)');
+  A.Option:=aoDistinct;
+  AssertSQL(A,'COUNT(DISTINCT A)');
+  A.Option:=aoAll;
+  AssertSQL(A,'COUNT(ALL A)');
+  A.Aggregate:=afMax;
+  A.Option:=aoNone;
+  AssertSQL(A,'MAX(A)');
+  A.Aggregate:=afMin;
+  AssertSQL(A,'MIN(A)');
+  A.Aggregate:=afAVG;
+  AssertSQL(A,'AVG(A)');
+  A.Aggregate:=afSUM;
+  AssertSQL(A,'SUM(A)');
+end;
+
+procedure TTestGenerateSQL.TestForeignKey;
+Var
+  K : TSQLForeignKeyDefinition;
+begin
+  K:=CreateForeignKey('A','B','');
+  FTofree:=K;
+  AssertSQL(K,'A (B)') ;
+  K.FieldList.Add(CreateIdentifier('C'));
+  FTofree:=K;
+  AssertSQL(K,'A (B , C)');
+  AssertSQL(K,'A (B,C)',[sfoListNoSpaceBeforeComma,sfoListNoSpaceAfterComma]);
+  K.OnDelete:=fkaNoAction;
+  AssertSQL(K,'A (B , C) ON DELETE NO ACTION');
+  K.OnDelete:=fkaCascade;
+  AssertSQL(K,'A (B , C) ON DELETE CASCADE');
+  K.OnDelete:=fkaSetDefault;
+  AssertSQL(K,'A (B , C) ON DELETE SET DEFAULT');
+  K.OnDelete:=fkaSetNull;
+  AssertSQL(K,'A (B , C) ON DELETE SET NULL');
+  K.OnUpdate:=fkaNoaction;
+  AssertSQL(K,'A (B , C) ON UPDATE NO ACTION ON DELETE SET NULL');
+  K.OnUpdate:=fkaCascade;
+  AssertSQL(K,'A (B , C) ON UPDATE CASCADE ON DELETE SET NULL');
+  K.OnUpdate:=fkaSetDefault;
+  AssertSQL(K,'A (B , C) ON UPDATE SET DEFAULT ON DELETE SET NULL');
+  K.OnUpdate:=fkaSetNull;
+  AssertSQL(K,'A (B , C) ON UPDATE SET NULL ON DELETE SET NULL');
+  K.OnDelete:=fkaNone;
+  AssertSQL(K,'A (B , C) ON UPDATE SET NULL');
+end;
+
+procedure TTestGenerateSQL.TestUniqueFieldConstraint;
+
+Var
+  F : TSQLUniqueFieldConstraint;
+
+begin
+  F:=TSQLUniqueFieldConstraint.Create(Nil);
+  FTofree:=F;
+  AssertSQL(F,'UNIQUE');
+  F.ConstraintName:=CreateIdentifier('A');
+  FTofree:=F;
+  AssertSQL(F,'CONSTRAINT A UNIQUE');
+  AssertSQL(F,'constraint A unique',[sfoLowercaseKeyWord]);
+end;
+
+procedure TTestGenerateSQL.TestPrimaryKeyFieldConstraint;
+
+Var
+  F : TSQLPrimaryKeyFieldConstraint;
+
+begin
+  F:=TSQLPrimaryKeyFieldConstraint.Create(Nil);
+  FTofree:=F;
+  AssertSQL(F,'PRIMARY KEY');
+  F.ConstraintName:=CreateIdentifier('A');
+  FTofree:=F;
+  AssertSQL(F,'CONSTRAINT A PRIMARY KEY');
+  AssertSQL(F,'constraint A primary key',[sfoLowercaseKeyWord]);
+end;
+
+procedure TTestGenerateSQL.TestForeignKeyFieldConstraint;
+
+Var
+  F : TSQLForeignKeyFieldConstraint;
+
+begin
+  F:=TSQLForeignKeyFieldConstraint.Create(Nil);
+  F.Definition:=CreateForeignKey('B','C','');
+  FTofree:=F;
+  AssertSQL(F,'REFERENCES B (C)');
+  F.ConstraintName:=CreateIdentifier('A');
+  FTofree:=F;
+  AssertSQL(F,'CONSTRAINT A REFERENCES B (C)');
+  AssertSQL(F,'constraint A references B (C)',[sfoLowercaseKeyWord]);
+end;
+
+procedure TTestGenerateSQL.TestCheckFieldConstraint;
+
+Var
+  F : TSQLCheckFieldConstraint;
+
+begin
+  F:=TSQLCheckFieldConstraint.Create(Nil);
+  F.Expression:=CreateBinaryExpression(CreateLiteralExpression(TSQLValueLiteral.Create(Nil)),CreateLiteralExpression(CreateLiteral(1)));
+  TSQLBinaryExpression(F.Expression).Operation:=boGT;
+  FTofree:=F;
+  AssertSQL(F,'CHECK (VALUE > 1)');
+  F.ConstraintName:=CreateIdentifier('A');
+  FTofree:=F;
+  AssertSQL(F,'CONSTRAINT A CHECK (VALUE > 1)');
+  AssertSQL(F,'constraint A check (value > 1)',[sfoLowercaseKeyWord]);
+end;
+
+procedure TTestGenerateSQL.TestTableUniqueConstraintDef;
+
+Var
+  U : TSQLTableUniqueConstraintDef;
+
+begin
+  U:=TSQLTableUniqueConstraintDef.Create(Nil);
+  U.FieldList.Add(CreateIdentifier('A'));
+  FToFree:=U;
+  AssertSQL(U,'UNIQUE (A)');
+  U.ConstraintName:=CreateIdentifier('C');
+  FToFree:=U;
+  AssertSQL(U,'CONSTRAINT C UNIQUE (A)');
+  U.FieldList.Add(CreateIdentifier('B'));
+  FToFree:=U;
+  AssertSQL(U,'CONSTRAINT C UNIQUE (A , B)');
+  AssertSQL(U,'constraint C unique (A , B)',[sfoLowercaseKeyWord]);
+end;
+
+procedure TTestGenerateSQL.TestTableprimaryKeyConstraintDef;
+
+Var
+  U : TSQLTablePrimaryKeyConstraintDef;
+
+begin
+  U:=TSQLTablePrimaryKeyConstraintDef.Create(Nil);
+  U.FieldList.Add(CreateIdentifier('A'));
+  FToFree:=U;
+  AssertSQL(U,'PRIMARY KEY (A)');
+  U.ConstraintName:=CreateIdentifier('C');
+  FToFree:=U;
+  AssertSQL(U,'CONSTRAINT C PRIMARY KEY (A)');
+  U.FieldList.Add(CreateIdentifier('B'));
+  FToFree:=U;
+  AssertSQL(U,'CONSTRAINT C PRIMARY KEY (A , B)');
+  AssertSQL(U,'constraint C primary key (A , B)',[sfoLowercaseKeyWord]);
+end;
+
+procedure TTestGenerateSQL.TestTableForeignKeyConstraintDef;
+
+Var
+  U : TSQLTableForeignKeyConstraintDef;
+
+begin
+  U:=TSQLTableForeignKeyConstraintDef.Create(Nil);
+  U.FieldList.Add(CreateIdentifier('A'));
+  U.Definition:=CreateForeignKey('D','E','');
+  FToFree:=U;
+  AssertSQL(U,'FOREIGN KEY (A) REFERENCES D (E)');
+  U.ConstraintName:=CreateIdentifier('C');
+  FToFree:=U;
+  AssertSQL(U,'CONSTRAINT C FOREIGN KEY (A) REFERENCES D (E)');
+  U.FieldList.Add(CreateIdentifier('B'));
+  U.Definition.FieldList.Add(CreateIdentifier('F'));
+  FToFree:=U;
+  AssertSQL(U,'CONSTRAINT C FOREIGN KEY (A , B) REFERENCES D (E , F)');
+  AssertSQL(U,'constraint C foreign key (A,B) references D (E,F)',[sfoLowercaseKeyWord,sfoListNoSpaceBeforeComma,sfoListNoSpaceAfterComma]);
+end;
+
+procedure TTestGenerateSQL.TestTableCheckConstraintDef;
+
+Var
+  F : TSQLTableCheckConstraintDef;
+
+begin
+  F:=TSQLTableCheckConstraintDef.Create(Nil);
+  F.Check:=CreateBinaryExpression(CreateIdentifierExpression('A'),CreateLiteralExpression(CreateLiteral(1)));
+  TSQLBinaryExpression(F.Check).Operation:=boGT;
+  FTofree:=F;
+  AssertSQL(F,'CHECK (A > 1)');
+  F.ConstraintName:=CreateIdentifier('C');
+  FTofree:=F;
+  AssertSQL(F,'CONSTRAINT C CHECK (A > 1)');
+  AssertSQL(F,'constraint C check (A > 1)',[sfoLowercaseKeyWord]);
+end;
+
+procedure TTestGenerateSQL.TestTypeDefinition;
+
+Var
+  T : TSQLTypeDefinition;
+
+begin
+  T:=CreateTypeDefinition(sdtInteger,0);
+  AssertSQl(T,'INT');
+  T.DataType:=sdtSmallInt;
+  AssertSQl(T,'SMALLINT');
+  T.DataType:=sdtDoublePrecision;
+  AssertSQl(T,'DOUBLE PRECISION');
+  T.DataType:=sdtFloat;
+  AssertSQl(T,'FLOAT');
+  T.DataType:=sdtDate;
+  AssertSQl(T,'DATE');
+  T.DataType:=sdtDateTime;
+  AssertSQl(T,'TIMESTAMP');
+  T.DataType:=sdtTime;
+  AssertSQl(T,'TIME');
+  T.DataType:=sdtChar;
+  T.Len:=5;
+  AssertSQl(T,'CHAR(5)');
+  T.DataType:=sdtVarChar;
+  AssertSQl(T,'VARCHAR(5)');
+  T.DataType:=sdtNChar;
+  AssertSQl(T,'NATIONAL CHARACTER(5)');
+  T.DataType:=sdtNVarChar;
+  AssertSQl(T,'NATIONAL CHARACTER VARYING(5)');
+  T.DataType:=sdtDecimal;
+  T.Scale:=2;
+  AssertSQl(T,'DECIMAL(5,2)');
+  T.Scale:=0;
+  AssertSQl(T,'DECIMAL(5)');
+  T.DataType:=sdtNumeric;
+  T.Scale:=2;
+  AssertSQl(T,'NUMERIC(5,2)');
+  T.Scale:=0;
+  AssertSQl(T,'NUMERIC(5)');
+  T.DataType:=sdtBlob;
+  AssertSQL(T,'BLOB SUB_TYPE 0 SEGMENT_SIZE 5');
+  T.Len:=0;
+  AssertSQL(T,'BLOB SUB_TYPE 0');
+  T.DataType:=sdtInteger;
+  T.NotNull:=True;
+  AssertSQL(T,'INT NOT NULL');
+  T.DefaultValue:=CreateLiteral(1);
+  AssertSQL(T,'INT DEFAULT 1 NOT NULL');
+  T.Check:=CreateBinaryExpression(CreateLiteralExpression(TSQLValueLiteral.Create(Nil)),CreateLiteralExpression(CreateLiteral(1)));
+  FToFree:=T;
+  TSQLBinaryExpression(T.Check).Operation:=boGE;
+  AssertSQL(T,'INT DEFAULT 1 NOT NULL CHECK (VALUE >= 1)');
+  T.DefaultValue.Free;
+  T.DefaultValue:=Nil;
+  AssertSQL(T,'INT NOT NULL CHECK (VALUE >= 1)');
+  T.Constraint:=TSQLCheckFieldConstraint.Create(Nil);
+  TSQLCheckFieldConstraint(T.Constraint).Expression:=T.check;
+  T.Check:=Nil;
+  AssertSQL(T,'INT NOT NULL CHECK (VALUE >= 1)');
+  TSQLCheckFieldConstraint(T.Constraint).ConstraintName:=CreateIdentifier('C');
+  FToFree:=T;
+  AssertSQL(T,'INT NOT NULL CONSTRAINT C CHECK (VALUE >= 1)');
+  T.Constraint.Free;
+  T.Constraint:=Nil;
+  T.NotNull:=False;
+  T.DataType:=sdtChar;
+  T.Len:=50;
+  T.CharSet:='UTF-8';
+  AssertSQL(T,'CHAR(50) CHARACTER SET UTF-8');
+  T.Collation:=TSQLCollation.Create(Nil);
+  T.Collation.Name:='MyCol';
+  AssertSQL(T,'CHAR(50) CHARACTER SET UTF-8 COLLATION MYCOL');
+end;
+
+procedure TTestGenerateSQL.TestCastExpression;
+
+Var
+  C : TSQLCastExpression;
+
+begin
+  C:=TSQLCastExpression.Create(Nil);
+  FToFree:=C;
+  C.Value:=CreateLiteralExpression(CreateLiteral(1));
+  C.NewType:=CreateTypeDefinition(sdtNumeric,5);
+  C.NewType.Scale:=2;
+  FToFree:=C;
+  AssertSQL(C,'CAST(1 AS NUMERIC(5,2))');
+
+end;
+
+procedure TTestGenerateSQL.TestJoinTableReference;
+
+var
+  J,J2 : TSQLJoinTableReference;
+
+begin
+  J:=CreateJoinTableReference(CreateSimpleTableReference('A',''),CreateSimpleTableReference('B',''));
+  J.JoinClause:=CreateBinaryExpression(CreateIdentifierExpression('C'),CreateIdentifierExpression('D'));
+  TSQLBinaryExpression(J.JoinClause).Operation:=boEQ;
+  J.JoinType:=jtInner;
+  FToFree:=J;
+  AssertSQL(J,'A INNER JOIN B ON (C = D)');
+  J.JoinType:=jtLeft;
+  AssertSQL(J,'A LEFT JOIN B ON (C = D)');
+  J.JoinType:=jtRight;
+  AssertSQL(J,'A RIGHT JOIN B ON (C = D)');
+  J.JoinType:=jtOuter;
+  AssertSQL(J,'A OUTER JOIN B ON (C = D)');
+  AssertSQL(J,'A'+sLinebreak+'OUTER JOIN B ON (C = D)',[sfoOneTablePerLine]);
+  AssertSQL(J,'A'+sLinebreak+'  OUTER JOIN B ON (C = D)',[sfoOneTablePerLine,sfoIndentTables]);
+  J2:=CreateJoinTableReference(CreateSimpleTableReference('E',''),CreateSimpleTableReference('F',''));
+  J2.JoinClause:=CreateBinaryExpression(CreateIdentifierExpression('G'),CreateIdentifierExpression('H'));
+  TSQLBinaryExpression(J2.JoinClause).Operation:=boEQ;
+  J.Right.Free;
+  J.Right:=J2;
+  FTofree:=J;
+  AssertSQL(J,'A OUTER JOIN (E JOIN F ON (G = H)) ON (C = D)');
+  AssertSQL(J,'A OUTER JOIN E JOIN F ON (G = H) ON (C = D)',[sfoNoBracketRightJoin]);
+  J.Right:=J.Left;
+  J.Left:=J2;
+  AssertSQL(J,'(E JOIN F ON (G = H)) OUTER JOIN A ON (C = D)',[sfoBracketLeftJoin]);
+
+end;
+
+procedure TTestGenerateSQL.TestPlanNatural;
+
+Var
+  N : TSQLSelectNaturalPlan;
+
+begin
+  N:=TSQLSelectNaturalPlan.Create(Nil);
+  N.TableName:=CreateIdentifier('A');
+  FToFree:=N;
+  AssertSQL(N,'A NATURAL');
+  AssertSQL(N,'A natural',[sfoLowercaseKeyword]);
+end;
+
+procedure TTestGenerateSQL.TestPlanIndex;
+
+Var
+  I : TSQLSelectIndexedPlan;
+
+begin
+  I:=TSQLSelectIndexedPlan.Create(Nil);
+  I.TableName:=CreateIdentifier('A');
+  I.Indexes.Add(CreateIdentifier('B'));
+  FToFree:=I;
+  AssertSQL(I,'A INDEX (B)');
+  AssertSQL(I,'A index (B)',[sfoLowercaseKeyword]);
+  I.Indexes.Add(CreateIdentifier('C'));
+  FToFree:=I;
+  AssertSQL(I,'A INDEX (B,C)',[sfoListNoSpacebeforeComma,sfoListNoSpaceAfterComma]);
+end;
+
+procedure TTestGenerateSQL.TestPlanOrder;
+Var
+  I : TSQLSelectOrderedPlan;
+
+begin
+  I:=TSQLSelectOrderedPlan.Create(Nil);
+  I.TableName:=CreateIdentifier('A');
+  I.OrderIndex:=CreateIdentifier('B');
+  FToFree:=I;
+  AssertSQL(I,'A ORDER B');
+  AssertSQL(I,'A order B',[sfoLowercaseKeyword]);
+end;
+
+procedure TTestGenerateSQL.TestPlanExpression;
+
+Var
+  P : TSQLSelectPlanExpr;
+  N : TSQLSelectNaturalPlan;
+  I : TSQLSelectIndexedPlan;
+
+begin
+  P:=TSQLSelectPlanExpr.Create(Nil);
+  P.JoinType:=pjtJoin;
+  N:=TSQLSelectNaturalPlan.Create(Nil);
+  N.TableName:=CreateIdentifier('STATE');
+  P.Items.Add(N);
+  I:=TSQLSelectIndexedPlan.Create(Nil);
+  I.TableName:=CreateIdentifier('CITIES');
+  I.Indexes.Add(CreateIdentifier('DUPE_CITY'));
+  P.Items.Add(I);
+  I:=TSQLSelectIndexedPlan.Create(Nil);
+  I.TableName:=CreateIdentifier('MAYORS');
+  I.Indexes.Add(CreateIdentifier('MAYORS_1'));
+  P.Items.Add(I);
+  FToFree:=P;
+  AssertSQL(P,'JOIN (STATE NATURAL , CITIES INDEX (DUPE_CITY) , MAYORS INDEX (MAYORS_1))');
+end;
+
+procedure TTestGenerateSQL.TestOrderBy;
+
+Var
+  O : TSQLOrderByElement;
+
+begin
+  O:=TSQLOrderByElement.Create(Nil);
+  FToFree:=O;
+  O.Field:=CreateLiteral(1);
+  AssertSQL(O,'1');
+  AssertSQL(O,'1 ASC',[sfoForceAscending]);
+  AssertSQL(O,'1 asc',[sfoForceAscending,sfoLowerCaseKeyword]);
+  O.OrderBy:=obDescending;
+  O.Field.free;
+  O.Field:=CreateIdentifier('A');
+  AssertSQL(O,'A desc',[sfoForceAscending,sfoLowerCaseKeyword]);
+  AssertSQL(O,'A DESC',[sfoForceAscending]);
+  AssertSQL(O,'A DESC');
+  O.Collation:=CreateIdentifier('UTF8');
+  AssertSQL(O,'A DESC UTF8');
+end;
+
+procedure TTestGenerateSQL.TestSelect;
+
+Var
+  S : TSQLSelectStatement;
+
+begin
+  S:=CreateSelect(CreateIdentifierExpression('A'),'B');
+  AssertSQL(S,'SELECT A FROM B');
+  AssertSQL(S,'SELECT'+sLineBreak+'A'+sLineBreak+'FROM B',[sfoOneFieldPerLine]);
+  AssertSQL(S,'SELECT'+sLineBreak+'  A'+sLineBreak+'FROM B',[sfoOneFieldPerLine,sfoIndentFields]);
+  AssertSQL(S,'SELECT A FROM'+SlineBreak+'B',[sfoOneTablePerLine]);
+  AssertSQL(S,'SELECT A FROM'+SlineBreak+'  B',[sfoOneTablePerLine,sfoIndentTables]);
+  AssertSQL(S,'SELECT'+sLineBreak+'A'+sLineBreak+'FROM'+sLineBreak+'B',[sfoOneFieldPerLine,sfoOneTablePerLine]);
+  S.Where:=CreateBinaryExpression(CreateIdentifierExpression('C'),CreateIdentifierExpression('D'));
+  TSQLBinaryExpression(S.Where).Operation:=boEQ;
+  AssertSQL(S,'SELECT A FROM B WHERE C = D');
+  AssertSQL(S,'SELECT A FROM B WHERE'+sLineBreak+'C = D',[sfoWhereOnSeparateLine]);
+  AssertSQL(S,'SELECT A FROM B WHERE'+sLineBreak+'  C = D',[sfoWhereOnSeparateLine,sfoIndentwhere]);
+  AssertSQL(S,'SELECT A FROM'+sLineBreak+'B'+sLineBreak+'WHERE'+sLineBreak+'  C = D',[sfoOneTablePerLine,sfoWhereOnSeparateLine,sfoIndentwhere]);
+  AssertSQL(S,'SELECT A FROM'+sLineBreak+'B'+sLineBreak+'WHERE'+sLineBreak+'  C = D',[sfoOneTablePerLine,sfoWhereOnSeparateLine,sfoIndentwhere]);
+  S.GroupBy.Add(CreateIdentifier('A'));
+  AssertSQL(S,'SELECT A FROM B WHERE C = D GROUP BY A');
+  AssertSQL(S,'SELECT A FROM B WHERE C = D GROUP BY'+sLineBreak+'A',[sfoOneGroupbyFieldPerLine]);
+  AssertSQL(S,'SELECT A FROM B WHERE C = D GROUP BY'+sLineBreak+'  A',[sfoOneGroupbyFieldPerLine,sfoIndentGroupByFields]);
+  AssertSQL(S,'SELECT A FROM B WHERE'+sLineBreak+'C = D'+sLineBreak+'GROUP BY'+sLineBreak+'  A',[sfoWhereOnSeparateLine,sfoOneGroupbyFieldPerLine,sfoIndentGroupByFields]);
+  S.OrderBy.Add(CreateIdentifier('E'));
+  AssertSQL(S,'SELECT A FROM B WHERE C = D GROUP BY A ORDER BY E');
+  AssertSQL(S,'SELECT A FROM B WHERE C = D GROUP BY A ORDER BY'+sLineBreak+'E',[sfoOneOrderbyFieldPerLine]);
+  AssertSQL(S,'SELECT A FROM B WHERE C = D GROUP BY'+sLineBreak+'A'+sLineBreak+'ORDER BY'+sLineBreak+'  E',[sfoOneGroupbyFieldPerLine,sfoOneOrderbyFieldPerLine,sfoIndentOrderByFields]);
+  S.Having:=CreateBinaryExpression(CreateIdentifierExpression('F'),CreateIdentifierExpression('G'));
+  TSQLBinaryExpression(S.Having).Operation:=boGT;
+  AssertSQL(S,'SELECT A FROM B WHERE C = D GROUP BY A HAVING F > G ORDER BY E');
+  AssertSQL(S,'SELECT A FROM B WHERE C = D GROUP BY A HAVING'+sLineBreak+'F > G'+sLineBreak+'ORDER BY E',[sfoHavingOnSeparateLine]);
+  AssertSQL(S,'SELECT A FROM B WHERE C = D GROUP BY A HAVING'+sLineBreak+'  F > G'+sLineBreak+'ORDER BY E',[sfoHavingOnSeparateLine,sfoIndentHaving]);
+  AssertSQL(S,'SELECT A FROM B WHERE C = D GROUP BY'+sLineBreak+'A'+sLineBreak+'HAVING'+sLineBreak+'F > G'+sLineBreak+'ORDER BY E',[sfoOneGroupbyFieldPerLine,sfoHavingOnSeparateLine]);
+  S.Union:=CreateSelect(CreateIdentifierExpression('H'),'I');
+  S.OrderBy.Delete(0);
+  S.OrderBy.Add(CreateLiteral(1));
+  AssertSQL(S,'SELECT A FROM B WHERE C = D GROUP BY A HAVING F > G UNION SELECT H FROM I ORDER BY 1');
+  AssertSQL(S,'SELECT A FROM B WHERE C = D GROUP BY A HAVING F > G'+sLineBreak+'UNION'+sLineBreak+'SELECT H FROM I'+sLineBreak+'ORDER BY 1',[sfoUnionOnSeparateLine]);
+  S.Union.Free;
+  S.Union:=Nil;
+  FToFree:=S;
+  S.Plan:=TSQLSelectNaturalPlan.Create(Nil);
+  TSQLSelectNaturalPlan(S.PLan).TableName:=CreateIdentifier('B');
+  AssertSQL(S,'SELECT A FROM B WHERE C = D GROUP BY A HAVING F > G PLAN B NATURAL ORDER BY 1');
+  AssertSQL(S,'SELECT A FROM B WHERE C = D GROUP BY A HAVING F > G'+sLineBreak+'PLAN'+sLineBreak+'B NATURAL'+sLineBreak+'ORDER BY 1',[sfoPlanOnSeparateLine]);
+end;
+
+procedure TTestGenerateSQL.TestInsert;
+
+Var
+  I : TSQLInsertStatement;
+
+begin
+  I:=TSQLInsertStatement.Create(Nil);
+  I.TableName:=CreateIdentifier('A');
+  FToFree:=I;
+  I.Values:=TSQLelementList.Create(True);
+  I.Values.Add(CreateLiteral('B'));
+  AssertSQL(I,'INSERT INTO A VALUES (''B'')');
+  I.Fields:=TSQLelementList.Create(True);
+  I.Fields.Add(CreateIdentifier('C'));
+  AssertSQL(I,'INSERT INTO A (C) VALUES (''B'')');
+  AssertSQL(I,'INSERT INTO A'+sLineBreak+'(C)'+sLineBreak+'VALUES'+sLineBreak+'(''B'')',[sfoOneFieldPerLine]);
+  I.Fields.Add(CreateIdentifier('D'));
+  I.Values.Add(CreateLiteral('E'));
+  AssertSQL(I,'INSERT INTO A (C, D) VALUES (''B'', ''E'')');
+  AssertSQL(I,'INSERT INTO A'+sLineBreak+'(C,'+sLineBreak+'D)'+sLineBreak+'VALUES'+sLineBreak+'(''B'','+sLineBreak+'''E'')',[sfoOneFieldPerLine]);
+  AssertSQL(I,'INSERT INTO A'+sLineBreak+'  (C,'+sLineBreak+'  D)'+sLineBreak+'VALUES'+sLineBreak+'  (''B'','+sLineBreak+'  ''E'')',[sfoOneFieldPerLine,sfoIndentFields]);
+  I.Select:=CreateSelect(CreateIdentifierExpression('E'),'G');
+  I.Select.Fields.Add(CreateIdentifierExpression('F'));
+  AssertSQL(I,'INSERT INTO A (C, D) SELECT E, F FROM G');
+end;
+
+procedure TTestGenerateSQL.TestUpdatePair;
+
+Var
+  P : TSQLUpdatePair;
+
+begin
+  P:=CreateUpdatePair('A',CreateLiteralExpression(CreateLiteral(1)));
+  AssertSQl(P,'A = 1');
+end;
+
+procedure TTestGenerateSQL.TestUpdate;
+
+Var
+  U : TSQLUpdateStatement;
+  P : TSQLUpdatePair;
+
+begin
+  P:=CreateUpdatePair('A',CreateLiteralExpression(CreateLiteral(1)));
+  U:=TSQLUpdateStatement.Create(Nil);
+  U.TableName:=CreateIdentifier('B');
+  U.Values.Add(P);
+  FTofree:=U;
+  AssertSQL(U,'UPDATE B SET A = 1');
+  AssertSQL(U,'UPDATE B SET'+sLineBreak+'A = 1',[sfoOneFieldPerLine]);
+  AssertSQL(U,'UPDATE B SET'+sLineBreak+'  A = 1',[sfoOneFieldPerLine,sfoIndentFields]);
+  P:=CreateUpdatePair('C',CreateLiteralExpression(CreateLiteral(2)));
+  U.Values.Add(P);
+  FTofree:=U;
+  AssertSQL(U,'UPDATE B SET A = 1, C = 2');
+  AssertSQL(U,'UPDATE B SET'+sLineBreak+'A = 1,'+sLineBreak+'C = 2',[sfoOneFieldPerLine]);
+  AssertSQL(U,'UPDATE B SET'+sLineBreak+'  A = 1,'+sLineBreak+'  C = 2',[sfoOneFieldPerLine,sfoIndentFields]);
+  U.WhereClause:=CreateBinaryExpression(CreateIdentifierExpression('A'),CreateLiteralExpression(CreateLiteral(1)));
+  TSQLBinaryExpression(U.WhereClause).Operation:=boGT;
+  AssertSQL(U,'UPDATE B SET A = 1, C = 2 WHERE A > 1');
+  AssertSQL(U,'UPDATE B SET'+sLineBreak+'  A = 1,'+sLineBreak+'  C = 2'+sLineBreak+'WHERE A > 1',[sfoOneFieldPerLine,sfoIndentFields]);
+  AssertSQL(U,'UPDATE B SET A = 1, C = 2'+sLineBreak+'WHERE'+sLineBreak+'A > 1',[sfoWhereOnSeparateLine]);
+  AssertSQL(U,'UPDATE B SET A = 1, C = 2'+sLineBreak+'WHERE'+sLineBreak+'  A > 1',[sfoWhereOnSeparateLine,sfoIndentWhere]);
+end;
+
+procedure TTestGenerateSQL.TestDelete;
+
+Var
+  D : TSQLDeleteStatement;
+
+begin
+  D:=TSQLDeleteStatement.Create(Nil);
+  D.TableName:=CreateIdentifier('A');
+  FToFree:=D;
+  AssertSQL(D,'DELETE FROM A');
+  D.WhereClause:=CreateBinaryExpression(CreateIdentifierExpression('B'),CreateLiteralExpression(CreateLiteral(1)));
+  TSQLBinaryExpression(D.WhereClause).Operation:=boGT;
+  FToFree:=D;
+  AssertSQL(D,'DELETE FROM A WHERE B > 1');
+  AssertSQL(D,'DELETE FROM A'+sLineBreak+'WHERE'+sLineBreak+'B > 1',[sfoWhereOnSeparateLine]);
+  AssertSQL(D,'DELETE FROM A'+sLineBreak+'WHERE'+sLineBreak+'  B > 1',[sfoWhereOnSeparateLine,sfoIndentWhere]);
+end;
+
+procedure TTestGenerateSQL.TestRollback;
+
+Var
+  R : TSQLRollBackStatement;
+
+begin
+  R:=TSQLRollBackStatement.Create(Nil);
+  FTofree:=R;
+  AssertSQL(R,'ROLLBACK');
+  R.TransactionName:=CreateIdentifier('A');
+  FTofree:=R;
+  AssertSQL(R,'ROLLBACK TRANSACTION A');
+  R.Work:=True;
+  AssertSQL(R,'ROLLBACK TRANSACTION A WORK');
+  R.Release:=True;
+  AssertSQL(R,'ROLLBACK TRANSACTION A WORK RELEASE');
+end;
+
+procedure TTestGenerateSQL.TestCommit;
+Var
+  C : TSQLCommitStatement;
+
+begin
+  C:=TSQLCommitStatement.Create(Nil);
+  FTofree:=C;
+  AssertSQL(C,'COMMIT');
+  C.TransactionName:=CreateIdentifier('A');
+  FTofree:=C;
+  AssertSQL(C,'COMMIT TRANSACTION A');
+  C.Work:=True;
+  AssertSQL(C,'COMMIT TRANSACTION A WORK');
+  C.Release:=True;
+  AssertSQL(C,'COMMIT TRANSACTION A WORK RELEASE');
+  C.Release:=False;
+  C.Retain:=True;
+  AssertSQL(C,'COMMIT TRANSACTION A WORK RETAIN');
+end;
+
+procedure TTestGenerateSQL.TestExecuteProcedure;
+
+Var
+  E : TSQLExecuteProcedureStatement;
+
+begin
+  E:=TSQLExecuteProcedureStatement.Create(Nil);
+  E.ProcedureName:=CreateIdentifier('A');
+  FTofree:=E;
+  AssertSQL(E,'EXECUTE PROCEDURE A');
+  E.Params.Add(CreateLiteralExpression(CreateLiteral(1)));
+  FTofree:=E;
+  AssertSQL(E,'EXECUTE PROCEDURE A(1)');
+  E.Params.Add(CreateLiteralExpression(CreateLiteral(2)));
+  FTofree:=E;
+  AssertSQL(E,'EXECUTE PROCEDURE A(1 , 2)');
+  E.Returning.Add(CreateIdentifier('B'));
+  FTofree:=E;
+  AssertSQL(E,'EXECUTE PROCEDURE A(1 , 2) RETURNING_VALUES :B');
+end;
+
+procedure TTestGenerateSQL.TestCreateGenerator;
+Var
+  G : TSQLCreateGeneratorStatement;
+begin
+  G:=TSQLCreateGeneratorStatement.Create(Nil);
+  G.ObjectName:=CreateIdentifier('A');
+  FToFree:=G;
+  AssertSQL(G,'CREATE GENERATOR A');
+end;
+
+procedure TTestGenerateSQL.TestCreateRole;
+Var
+  R : TSQLCreateRoleStatement;
+begin
+  R:=TSQLCreateRoleStatement.Create(Nil);
+  R.ObjectName:=CreateIdentifier('A');
+  FToFree:=R;
+  AssertSQL(R,'CREATE ROLE A');
+end;
+
+procedure TTestGenerateSQL.TestCreateDomain;
+
+Var
+  D : TSQLCreateDomainStatement;
+
+begin
+  D:=TSQLCreateDomainStatement.Create(Nil);
+  D.ObjectName:=CreateIdentifier('A');
+  D.TypeDefinition:=CreateTypeDefinition(sdtInteger,0);
+  D.TypeDefinition.NotNull:=True;
+  FToFree:=D;
+  AssertSQL(D,'CREATE DOMAIN A INT NOT NULL');
+end;
+
+procedure TTestGenerateSQL.TestAlterDomainDropDefault;
+
+Var
+  A : TSQLAlterDomainDropDefaultStatement;
+
+begin
+  A:=TSQLAlterDomainDropDefaultStatement.Create(Nil);
+  A.Objectname:=CreateIdentifier('A');
+  FToFree:=A;
+  AssertSQL(A,'ALTER DOMAIN A DROP DEFAULT');
+end;
+
+procedure TTestGenerateSQL.TestAlterDomainDropCheck;
+
+Var
+  A : TSQLAlterDomainDropCheckStatement;
+
+begin
+  A:=TSQLAlterDomainDropCheckStatement.Create(Nil);
+  A.Objectname:=CreateIdentifier('A');
+  FToFree:=A;
+  AssertSQL(A,'ALTER DOMAIN A DROP CHECK');
+end;
+
+procedure TTestGenerateSQL.TestAlterDomainSetDefault;
+
+Var
+  A : TSQLAlterDomainSetDefaultStatement;
+
+begin
+  A:=TSQLAlterDomainSetDefaultStatement.Create(Nil);
+  A.Objectname:=CreateIdentifier('A');
+  A.DefaultValue:=TSQLNullLiteral.Create(Nil);
+  FToFree:=A;
+  AssertSQL(A,'ALTER DOMAIN A SET DEFAULT NULL');
+end;
+
+procedure TTestGenerateSQL.TestAlterDomainRename;
+
+Var
+  A : TSQLAlterDomainRenameStatement;
+
+begin
+  A:=TSQLAlterDomainRenameStatement.Create(Nil);
+  A.Objectname:=CreateIdentifier('A');
+  A.NewName:=CreateIdentifier('B');
+  FToFree:=A;
+  AssertSQL(A,'ALTER DOMAIN A B');
+end;
+
+procedure TTestGenerateSQL.TestAlterDomainNewType;
+
+Var
+  A : TSQLAlterDomainTypeStatement;
+
+begin
+  A:=TSQLAlterDomainTypeStatement.Create(Nil);
+  A.Objectname:=CreateIdentifier('A');
+  A.NewType:=CreateTypeDefinition(sdtVarChar,5);
+  FToFree:=A;
+  AssertSQL(A,'ALTER DOMAIN A TYPE VARCHAR(5)');
+end;
+
+procedure TTestGenerateSQL.TestAlterDomainAddCheck;
+
+Var
+  A : TSQLAlterDomainAddCheckStatement;
+
+begin
+  A:=TSQLAlterDomainAddCheckStatement.Create(Nil);
+  A.Objectname:=CreateIdentifier('A');
+  A.Check:=CreateBinaryExpression(CreateLiteralExpression(TSQLValueLiteral.Create(Nil)),CreateLiteralExpression(CreateLiteral(1)));
+  TSQLBinaryExpression(A.Check).Operation:=boGT;
+  FToFree:=A;
+  AssertSQL(A,'ALTER DOMAIN A ADD CHECK VALUE > 1');
+end;
+
+procedure TTestGenerateSQL.TestCreateException;
+
+Var
+  C : TSQLCreateExceptionStatement;
+
+begin
+  C:=TSQLCreateExceptionStatement.Create(Nil);
+  C.ObjectName:=CreateIdentifier('A');
+  C.ExceptionMessage:=CreateLiteral('B');
+  FToFree:=C;
+  AssertSQL(C,'CREATE EXCEPTION A ''B''');
+end;
+
+procedure TTestGenerateSQL.TestAlterException;
+Var
+  C : TSQLAlterExceptionStatement;
+
+begin
+  C:=TSQLAlterExceptionStatement.Create(Nil);
+  C.ObjectName:=CreateIdentifier('A');
+  C.ExceptionMessage:=CreateLiteral('B');
+  FToFree:=C;
+  AssertSQL(C,'ALTER EXCEPTION A ''B''');
+end;
+
+procedure TTestGenerateSQL.TestCreateIndex;
+
+Var
+  I : TSQLCreateIndexStatement;
+
+begin
+  I:=TSQLCreateIndexStatement.Create(Nil);
+  I.ObjectName:=CreateIdentifier('A');
+  I.TableName:=CreateIdentifier('B');
+  I.FieldNames.Add(CreateIdentifier('C'));
+  FTofree:=I;
+  AssertSQL(I,'CREATE INDEX A ON B (C)');
+  I.FieldNames.Add(CreateIdentifier('D'));
+  FTofree:=I;
+  AssertSQL(I,'CREATE INDEX A ON B (C , D)');
+  I.Options:=[ioUnique];
+  AssertSQL(I,'CREATE UNIQUE INDEX A ON B (C , D)');
+  I.Options:=[ioAscending];
+  AssertSQL(I,'CREATE ASCENDING INDEX A ON B (C , D)');
+  I.Options:=[ioUnique,ioDescending];
+  AssertSQL(I,'CREATE UNIQUE DESCENDING INDEX A ON B (C , D)');
+  I.Options:=[ioUnique,ioAscending,ioDescending];
+  AssertSQL(I,'CREATE UNIQUE ASCENDING INDEX A ON B (C , D)');
+  I.Options:=[ioDescending];
+  AssertSQL(I,'CREATE DESCENDING INDEX A ON B (C , D)');
+end;
+
+procedure TTestGenerateSQL.TestAlterIndex;
+
+Var
+  I : TSQLAlterIndexStatement;
+
+begin
+  I:=TSQLAlterIndexStatement.Create(Nil);
+  I.ObjectName:=CreateIdentifier('A');
+  FTofree:=I;
+  AssertSQL(I,'ALTER INDEX A ACTIVE');
+  I.Inactive:=True;
+  AssertSQL(I,'ALTER INDEX A INACTIVE');
+end;
+
+procedure TTestGenerateSQL.TestDeclareExternalFunction;
+
+Var
+  F : TSQLDeclareExternalFunctionStatement;
+
+begin
+  F:=TSQLDeclareExternalFunctionStatement.Create(Nil);
+  F.ObjectName:=CreateIdentifier('A');
+  F.ReturnType:=CreateTypeDefinition(sdtChar,5);
+  F.EntryPoint:='B';
+  F.ModuleName:='C';
+  FToFree:=F;
+  AssertSQL(F,'DECLARE EXTERNAL FUNCTION A RETURNS CHAR(5) ENTRY_POINT ''B'' MODULE_NAME ''C''');
+  F.Arguments.Add(CreateTypeDefinition(sdtChar,10));
+  AssertSQL(F,'DECLARE EXTERNAL FUNCTION A CHAR(10) RETURNS CHAR(5) ENTRY_POINT ''B'' MODULE_NAME ''C''');
+  F.Arguments.Add(CreateTypeDefinition(sdtInteger,0));
+  AssertSQL(F,'DECLARE EXTERNAL FUNCTION A CHAR(10) , INT RETURNS CHAR(5) ENTRY_POINT ''B'' MODULE_NAME ''C''');
+  AssertSQL(F,'DECLARE EXTERNAL FUNCTION A'+sLineBreak+
+              '  CHAR(10) , INT'+sLineBreak+
+              '  RETURNS CHAR(5)'+sLineBreak+
+              '  ENTRY_POINT ''B'''+sLineBreak+
+              '  MODULE_NAME ''C''',[sfoMultilineDeclareFunction]);
+end;
+
+procedure TTestGenerateSQL.TestTableFieldDefinition;
+
+Var
+  F : TSQLTableFieldDef;
+
+begin
+  F:=TSQLTableFieldDef.Create(Nil);
+  F.FieldName:=CreateIdentifier('A');
+  F.FieldType:=CreateTypeDefinition(sdtInteger,0);
+  FTofree:=F;
+  AssertSQL(F,'A INT');
+  F.FieldType.Free;
+  F.FieldType:=Nil;
+  F.ComputedBy:=CreateBinaryExpression(CreateIdentifierExpression('B'),CreateLiteralExpression(CreateLiteral(1)));
+  TSQLBinaryExpression(F.ComputedBy).Operation:=boAdd;
+  FTofree:=F;
+  AssertSQL(F,'A COMPUTED BY B + 1');
+end;
+
+procedure TTestGenerateSQL.TestCreateTable;
+
+Var
+  T : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  U : TSQLTableUniqueConstraintDef;
+
+begin
+  F:=TSQLTableFieldDef.Create(Nil);
+  F.FieldName:=CreateIdentifier('B');
+  F.FieldType:=CreateTypeDefinition(sdtInteger,0);
+  T:=TSQLCreateTableStatement.Create(Nil);
+  T.ObjectName:=CreateIdentifier('A');
+  FTofree:=T;
+  T.FieldDefs.Add(F);
+  AssertSQL(T,'CREATE TABLE A (B INT)');
+  T.ExternalFileName:=CreateLiteral('/my/file');
+  AssertSQL(T,'CREATE TABLE A EXTERNAL FILE ''/my/file'' (B INT)');
+  T.ExternalFileName.Free;
+  T.ExternalFileName:=Nil;
+  F:=TSQLTableFieldDef.Create(Nil);
+  F.FieldName:=CreateIdentifier('C');
+  F.FieldType:=CreateTypeDefinition(sdtChar,5);
+  T.FieldDefs.Add(F);
+  FTofree:=T;
+  AssertSQL(T,'CREATE TABLE A (B INT, C CHAR(5))');
+  AssertSQL(T,'CREATE TABLE A ('+sLineBreak+'B INT,'+sLineBreak+'C CHAR(5))',[sfoOneFieldPerLine]);
+  AssertSQL(T,'CREATE TABLE A ('+sLineBreak+'  B INT,'+sLineBreak+'  C CHAR(5))',[sfoOneFieldPerLine,sfoIndentFields]);
+  U:=TSQLTableUniqueConstraintDef.Create(Nil);
+  U.FieldList.Add(CreateIdentifier('B'));
+  T.Constraints.Add(U);
+  FTofree:=T;
+  AssertSQL(T,'CREATE TABLE A (B INT, C CHAR(5), UNIQUE (B))');
+  AssertSQL(T,'CREATE TABLE A ('+sLineBreak+'B INT,'+sLineBreak+'C CHAR(5),'+sLineBreak+'UNIQUE (B))',[sfoOneFieldPerLine]);
+  AssertSQL(T,'CREATE TABLE A ('+sLineBreak+'  B INT,'+sLineBreak+'  C CHAR(5),'+sLineBreak+'  UNIQUE (B))',[sfoOneFieldPerLine,sfoIndentFields]);
+  U.ConstraintName:=CreateIdentifier('U_A');
+  FTofree:=T;
+  AssertSQL(T,'CREATE TABLE A (B INT, C CHAR(5), CONSTRAINT U_A UNIQUE (B))');
+end;
+
+procedure TTestGenerateSQL.TestDropFieldOperation;
+
+Var
+  O : TSQLDropTableFieldOperation;
+
+begin
+  O:=TSQLDropTableFieldOperation.Create(Nil);
+  O.ObjectName:=CreateIdentifier('A');
+  FTofree:=O;
+  AssertSQL(O,'DROP A');
+end;
+
+procedure TTestGenerateSQL.TestDropConstraintOperation;
+
+Var
+  O : TSQLDropTableConstraintOperation;
+
+begin
+  O:=TSQLDropTableConstraintOperation.Create(Nil);
+  O.ObjectName:=CreateIdentifier('A');
+  FTofree:=O;
+  AssertSQL(O,'DROP CONSTRAINT A');
+end;
+
+procedure TTestGenerateSQL.TestAlterFieldNameOperation;
+
+Var
+  O : TSQLAlterTableFieldNameOperation;
+
+begin
+  O:=TSQLAlterTableFieldNameOperation.Create(Nil);
+  O.ObjectName:=CreateIdentifier('A');
+  O.NewName:=CreateIdentifier('B');
+  FTofree:=O;
+  ASSERTSQl(O,'ALTER COLUMN A TO B');
+end;
+
+procedure TTestGenerateSQL.TestAlterFieldTypeOperation;
+
+Var
+  O : TSQLAlterTableFieldTypeOperation;
+
+begin
+  O:=TSQLAlterTableFieldTypeOperation.Create(Nil);
+  O.ObjectName:=CreateIdentifier('A');
+  O.NewType:=CreateTypeDefinition(sdtInteger,0);
+  FTofree:=O;
+  ASSERTSQl(O,'ALTER COLUMN A TYPE INT');
+end;
+
+procedure TTestGenerateSQL.TestAlterFieldPositionOperation;
+
+Var
+  O : TSQLAlterTableFieldPositionOperation;
+
+begin
+  O:=TSQLAlterTableFieldPositionOperation.Create(Nil);
+  O.ObjectName:=CreateIdentifier('A');
+  O.NewPosition:=2;
+  FTofree:=O;
+  ASSERTSQl(O,'ALTER COLUMN A POSITION 2');
+end;
+
+procedure TTestGenerateSQL.TestAddFieldOperation;
+
+Var
+  O : TSQLAlterTableAddFieldOperation;
+  F : TSQLTableFieldDef;
+
+begin
+  F:=TSQLTableFieldDef.Create(Nil);
+  FTofree:=F;
+  F.FieldName:=CreateIdentifier('C');
+  F.FieldType:=CreateTypeDefinition(sdtChar,5);
+  O:=TSQLAlterTableAddFieldOperation.Create(Nil);
+  FTofree:=O;
+  O.Element:=F;
+  AssertSQL(O,'ADD C CHAR(5)');
+end;
+
+procedure TTestGenerateSQL.TestAddConstraintOperation;
+
+Var
+  O : TSQLAlterTableAddConstraintOperation;
+  C : TSQLTableUniqueConstraintDef;
+
+begin
+  C:=TSQLTableUniqueConstraintDef.Create(Nil);
+  FTofree:=C;
+  C.FieldList.Add(CreateIdentifier('C'));
+  O:=TSQLAlterTableAddConstraintOperation.Create(Nil);
+  FTofree:=O;
+  O.Element:=C;
+  AssertSQL(O,'ADD CONSTRAINT UNIQUE (C)');
+  C.ConstraintName:=CreateIdentifier('D');
+  AssertSQL(O,'ADD CONSTRAINT D UNIQUE (C)');
+end;
+
+procedure TTestGenerateSQL.TestAlterTable;
+
+Var
+  A : TSQLAlterTableStatement;
+  DF : TSQLDropTableFieldOperation;
+  AC : TSQLAlterTableAddConstraintOperation;
+  C : TSQLTableUniqueConstraintDef;
+
+begin
+  A:=TSQLAlterTableStatement.Create(Nil);
+  A.ObjectName:=CreateIdentifier('A');
+  DF:=TSQLDropTableFieldOperation.Create(Nil);
+  DF.ObjectName:=CreateIdentifier('B');
+  A.Operations.Add(DF);
+  FTofree:=A;
+  AssertSQL(A,'ALTER TABLE A DROP B');
+  AssertSQL(A,'ALTER TABLE A'+sLineBreak+'DROP B',[sfoOneFieldPerLine]);
+  AssertSQL(A,'ALTER TABLE A'+sLineBreak+'  DROP B',[sfoOneFieldPerLine,sfoIndentFields]);
+  C:=TSQLTableUniqueConstraintDef.Create(Nil);
+  FTofree:=C;
+  C.FieldList.Add(CreateIdentifier('C'));
+  AC:=TSQLAlterTableAddConstraintOperation.Create(Nil);
+  AC.Element:=C;
+  A.Operations.Add(AC);
+  FTofree:=A;
+  AssertSQL(A,'ALTER TABLE A DROP B, ADD CONSTRAINT UNIQUE (C)');
+end;
+
+procedure TTestGenerateSQL.TestCreateView;
+
+Var
+  V : TSQLCreateViewStatement;
+
+begin
+  V:=TSQLCreateViewStatement.Create(Nil);
+  V.ObjectName:=CreateIdentifier('A');
+  V.Select:=CreateSelect(CreateIdentifierExpression('B'),'C');
+  FToFree:=V;
+  AssertSQL(V,'CREATE VIEW A AS SELECT B FROM C');
+  V.Fields.Add(CreateIdentifier('D'));
+  FToFree:=V;
+  AssertSQL(V,'CREATE VIEW A (D) AS SELECT B FROM C');
+end;
+
+procedure TTestGenerateSQL.TestDatabaseFileInfo;
+
+Var
+  F : TSQLDatabaseFileInfo;
+
+begin
+  F:=TSQLDatabaseFileInfo.Create(Nil);
+  F.FileName:='/my/file';
+  FTofree:=F;
+  AssertSQL(F,'FILE ''/my/file''');
+  F.Length:=2;
+  AssertSQL(F,'FILE ''/my/file'' LENGTH 2 PAGES');
+  F.Length:=0;
+  F.StartPage:=3;
+  AssertSQL(F,'FILE ''/my/file'' STARTING AT 3');
+end;
+
+procedure TTestGenerateSQL.TestCreateDatabase;
+
+Var
+  D : TSQLCreateDatabaseStatement;
+  F : TSQLDatabaseFileInfo;
+
+begin
+  D:=TSQLCreateDatabaseStatement.Create(Nil);
+  D.FileName:='/my/file';
+  FTofree:=D;
+  AssertSQL(D,'CREATE DATABASE ''/my/file''');
+  D.UseSchema:=true;
+  AssertSQL(D,'CREATE SCHEMA ''/my/file''');
+  D.UseSchema:=False;
+  D.Password:='Secret';
+  AssertSQL(D,'CREATE DATABASE ''/my/file''');
+  D.UserName:='me';
+  AssertSQL(D,'CREATE DATABASE ''/my/file'' USER ''me'' PASSWORD ''Secret''');
+  AssertSQL(D,'CREATE DATABASE ''/my/file'''+SlineBreak+'  USER ''me'' PASSWORD ''Secret''',[sfoMultilineCreateDatabase]);
+  D.PageSize:=2048;
+  AssertSQL(D,'CREATE DATABASE ''/my/file'' USER ''me'' PASSWORD ''Secret'' PAGE_SIZE 2048');
+  AssertSQL(D,'CREATE DATABASE ''/my/file'''+SlineBreak+'  USER ''me'' PASSWORD ''Secret'''+SlineBreak+'  PAGE_SIZE 2048',[sfoMultilineCreateDatabase]);
+  D.Length:=1000;
+  AssertSQL(D,'CREATE DATABASE ''/my/file'' USER ''me'' PASSWORD ''Secret'' PAGE_SIZE 2048 LENGTH 1000');
+  AssertSQL(D,'CREATE DATABASE ''/my/file'''+SlineBreak+'  USER ''me'' PASSWORD ''Secret'''+SlineBreak+'  PAGE_SIZE 2048'+SlineBreak+'  LENGTH 1000',[sfoMultilineCreateDatabase]);
+  D.CharSet:=CreateIdentifier('UTF8');
+  FToFree:=D;
+  AssertSQL(D,'CREATE DATABASE ''/my/file'' USER ''me'' PASSWORD ''Secret'' PAGE_SIZE 2048 LENGTH 1000 DEFAULT CHARACTER SET UTF8');
+  AssertSQL(D,'CREATE DATABASE ''/my/file'''+SlineBreak+'  USER ''me'' PASSWORD ''Secret'''+SlineBreak+'  PAGE_SIZE 2048'+SlineBreak+'  LENGTH 1000'+SlineBreak+'  DEFAULT CHARACTER SET UTF8',[sfoMultilineCreateDatabase]);
+  F:=TSQLDatabaseFileInfo.Create(Nil);
+  FToFree:=D;
+  F.FileName:='/my/file2';
+  F.StartPage:=3;
+  D.SecondaryFiles.Add(F);
+  AssertSQL(D,'CREATE DATABASE ''/my/file'' USER ''me'' PASSWORD ''Secret'' PAGE_SIZE 2048 LENGTH 1000 DEFAULT CHARACTER SET UTF8 FILE ''/my/file2'' STARTING AT 3');
+  AssertSQL(D,'CREATE DATABASE ''/my/file'''+SlineBreak+'  USER ''me'' PASSWORD ''Secret'''+SlineBreak+'  PAGE_SIZE 2048'+SlineBreak+'  LENGTH 1000'+SlineBreak+'  DEFAULT CHARACTER SET UTF8'+SlineBreak+'  FILE ''/my/file2'' STARTING AT 3',[sfoMultilineCreateDatabase]);
+  F:=TSQLDatabaseFileInfo.Create(Nil);
+  FToFree:=D;
+  F.FileName:='/my/file3';
+  F.StartPage:=4;
+  D.SecondaryFiles.Add(F);
+  AssertSQL(D,'CREATE DATABASE ''/my/file'' USER ''me'' PASSWORD ''Secret'' PAGE_SIZE 2048 LENGTH 1000 DEFAULT CHARACTER SET UTF8 FILE ''/my/file2'' STARTING AT 3 FILE ''/my/file3'' STARTING AT 4');
+  AssertSQL(D,'CREATE DATABASE ''/my/file'''+SlineBreak+'  USER ''me'' PASSWORD ''Secret'''+SlineBreak+'  PAGE_SIZE 2048'+SlineBreak+'  LENGTH 1000'+SlineBreak+'  DEFAULT CHARACTER SET UTF8'+SlineBreak+'  FILE ''/my/file2'' STARTING AT 3'+SlineBreak+'  FILE ''/my/file3'' STARTING AT 4',[sfoMultilineCreateDatabase]);
+end;
+
+procedure TTestGenerateSQL.TestAlterDatabase;
+
+Var
+  D : TSQLAlterDatabaseStatement;
+  F : TSQLDatabaseFileInfo;
+begin
+  D:=TSQLAlterDatabaseStatement.Create(Nil);
+  F:=TSQLDatabaseFileInfo.Create(Nil);
+  FToFree:=D;
+  F.FileName:='/my/file2';
+  F.StartPage:=3;
+  D.Operations.Add(F);
+  FToFree:=D;
+  AssertSQL(D,'ALTER DATABASE ADD FILE ''/my/file2'' STARTING AT 3');
+  AssertSQL(D,'ALTER DATABASE ADD'+SlineBreak+'  FILE ''/my/file2'' STARTING AT 3',[sfoMultilineCreateDatabase]);
+  D.UseSchema:=True;
+  AssertSQL(D,'ALTER SCHEMA ADD FILE ''/my/file2'' STARTING AT 3');
+  D.UseSchema:=False;
+  F:=TSQLDatabaseFileInfo.Create(Nil);
+  F.FileName:='/my/file3';
+  F.StartPage:=4;
+  D.Operations.Add(F);
+  FToFree:=D;
+  AssertSQL(D,'ALTER DATABASE ADD FILE ''/my/file2'' STARTING AT 3 FILE ''/my/file3'' STARTING AT 4');
+  AssertSQL(D,'ALTER DATABASE ADD'+SlineBreak+'  FILE ''/my/file2'' STARTING AT 3'+SlineBreak+'  FILE ''/my/file3'' STARTING AT 4',[sfoMultilineCreateDatabase]);
+end;
+
+procedure TTestGenerateSQL.TestCreateShadow;
+
+Var
+  S : TSQLCreateShadowStatement;
+  F : TSQLDatabaseFileInfo;
+
+begin
+  S:=TSQLCreateShadowStatement.Create(Nil);
+  S.Number:=1;
+  S.FileName:='/my/file';
+  FTofree:=S;
+  AssertSQL(S,'CREATE SHADOW 1 ''/my/file''');
+  S.Manual:=True;
+  AssertSQL(S,'CREATE SHADOW 1 MANUAL ''/my/file''');
+  S.Conditional:=True;
+  AssertSQL(S,'CREATE SHADOW 1 MANUAL CONDITIONAL ''/my/file''');
+  S.Length:=4;
+  AssertSQL(S,'CREATE SHADOW 1 MANUAL CONDITIONAL ''/my/file'' LENGTH 4 PAGES');
+  F:=TSQLDatabaseFileInfo.Create(Nil);
+  FTofree:=S;
+  F.FileName:='/my/file2';
+  F.StartPage:=4;
+  S.SecondaryFiles.Add(F);
+  AssertSQL(S,'CREATE SHADOW 1 MANUAL CONDITIONAL ''/my/file'' LENGTH 4 PAGES FILE ''/my/file2'' STARTING AT 4');
+  AssertSQL(S,'CREATE SHADOW 1 MANUAL CONDITIONAL ''/my/file'' LENGTH 4 PAGES'+sLineBreak+'  FILE ''/my/file2'' STARTING AT 4',[sfoMultilineCreateShadow]);
+end;
+
+procedure TTestGenerateSQL.TestSuspend;
+Var
+  S : TSQLSuspendStatement;
+
+begin
+  S:=TSQLSuspendStatement.Create(Nil);
+  FToFree:=S;
+  AssertSQL(S,'SUSPEND');
+end;
+
+procedure TTestGenerateSQL.TestExit;
+Var
+  S : TSQLExitStatement;
+
+begin
+  S:=TSQLExitStatement.Create(Nil);
+  FToFree:=S;
+  AssertSQL(S,'EXIT');
+end;
+
+procedure TTestGenerateSQL.TestBlock;
+
+Var
+  B,B2 : TSQLStatementBlock;
+  S : TSQLExitStatement;
+  L : TSQLSelectStatement;
+
+begin
+  B:=TSQLStatementBlock.Create(Nil);
+  FtoFree:=B;
+  B.Statements.Add(TSQLExitStatement.Create(Nil));
+  FtoFree:=B;
+  AssertSQL(B,'BEGIN'+sLineBreak+'  EXIT;'+sLineBreak+'END');
+  B.Statements.Add(TSQLSuspendStatement.Create(Nil));
+  FtoFree:=B;
+  AssertSQL(B,'BEGIN'+sLineBreak+'  EXIT;'+sLineBreak+'  SUSPEND;'+sLineBreak+'END');
+  B.Statements.Clear;
+  L:=CreateSelect(CreateIdentifierExpression('A'),'B');
+  FtoFree:=B;
+  B.Statements.Add(L);
+  AssertSQL(B,'BEGIN'+sLineBreak+'  SELECT'+sLineBreak+'  A'+sLineBreak+'  FROM'+sLineBreak+'  B;'+sLineBreak+'END',[sfoOneFieldPerLine,sfoOneTablePerLine]);
+  AssertSQL(B,'BEGIN'+sLineBreak+'  SELECT'+sLineBreak+'    A'+sLineBreak+'  FROM'+sLineBreak+'    B;'+sLineBreak+'END',[sfoOneFieldPerLine,sfoIndentFields,sfoOneTablePerLine,sfoIndentTables]);
+  B.Statements.Clear;
+  B2:=TSQLStatementBlock.Create(Nil);
+  FtoFree:=B;
+  B2.Statements.Add(TSQLExitStatement.Create(Nil));
+  FtoFree:=B;
+  B.Statements.Add(B2);
+  AssertSQL(B,'BEGIN'+sLineBreak+'  BEGIN'+sLineBreak+'    EXIT;'+sLineBreak+'  END'+sLineBreak+'END');
+end;
+
+procedure TTestGenerateSQL.TestAssignment;
+
+var
+  A : TSQLAssignStatement;
+
+begin
+  A:=TSQLAssignStatement.Create(Nil);
+  A.Variable:=CreateIdentifier('A');
+  A.Expression:=CreateIdentifierExpression('B');
+  FToFree:=A;
+  AssertSQL(A,'A = B');
+end;
+
+procedure TTestGenerateSQL.TestIf;
+
+Var
+  I : TSQLIfStatement;
+  C : TSQLBinaryExpression;
+
+begin
+  I:=TSQLIfStatement.Create(Nil);
+  C:=CreateBinaryExpression(CreateIdentifierExpression('A'),CreateIdentifierExpression('B'));
+  C.Operation:=boEQ;
+  I.Condition:=C;
+  I.TrueBranch:=TSQLSuspendStatement.Create(Nil);
+  FToFree:=I;
+  AssertSQL(I,'IF (A = B) THEN'+sLineBreak+'  SUSPEND');
+  I.FalseBranch:=TSQLExitStatement.Create(Nil);
+  AssertSQL(I,'IF (A = B) THEN'+sLineBreak+'  SUSPEND'+sLineBreak+'ELSE'+sLineBreak+'  EXIT');
+end;
+
+procedure TTestGenerateSQL.TestFor;
+Var
+  F : TSQLForStatement;
+
+begin
+  F:=TSQLForStatement.Create(Nil);
+  F.Select:=CreateSelect(CreateIdentifierExpression('A'),'B');
+  F.FieldList.Add(CreateIdentifier('ID'));
+  F.Statement:=TSQLSuspendStatement.Create(Nil);
+  AssertSQL(F,'FOR SELECT A FROM B'+sLineBreak+'INTO'+sLineBreak+':ID'+sLineBreak+'DO'+sLineBreak+'  SUSPEND',[sfoIndentFields]);
+  F.Select.Fields.Add(CreateIdentifier('C'));
+  F.FieldList.Add(CreateIdentifier('ID2'));
+  AssertSQL(F,'FOR SELECT A, C FROM B'+sLineBreak+'INTO'+sLineBreak+':ID, :ID2'+sLineBreak+'DO'+sLineBreak+'  SUSPEND');
+  AssertSQL(F,'FOR SELECT'+sLineBreak+'A,'+sLineBreak+'C'+sLineBreak+'FROM B'+sLineBreak+'INTO'+sLineBreak+':ID,'+sLineBreak+':ID2'+sLineBreak+'DO'+sLineBreak+'  SUSPEND',[sfoOneFieldPerLine]);
+end;
+
+procedure TTestGenerateSQL.TestWhile;
+
+Var
+  W : TSQLWhileStatement;
+  C : TSQLBinaryExpression;
+  A : TSQLAssignStatement;
+
+begin
+  W:=TSQLWhileStatement.Create(Nil);
+  C:=CreateBinaryExpression(CreateIdentifierExpression('A'),CreateIdentifierExpression('B'));
+  C.Operation:=boLT;
+  W.Condition:=C;
+  FToFree:=W;
+  A:=TSQLAssignStatement.Create(Nil);
+  A.Variable:=CreateIdentifier('A');
+  C:=CreateBinaryExpression(CreateIdentifierExpression('A'),CreateLiteralExpression(CreateLiteral(1)));
+  C.Operation:=boAdd;
+  A.Expression:=C;
+  W.Statement:=A;
+  FToFree:=W;
+  AssertSQL(W,'WHILE (A < B) DO'+slineBreak+'  A = A + 1');
+end;
+
+procedure TTestGenerateSQL.TestWhenSQLError;
+
+Var
+  S : TSQLWhenSQLError;
+
+begin
+  S:=TSQLWhenSQLError.Create(Nil);
+  S.ErrorCode:=2;
+  FToFree:=S;
+  AssertSQL(S,'SQLCODE 2');
+end;
+
+procedure TTestGenerateSQL.TestWhenGDSError;
+
+Var
+  G : TSQLWhenGDSError;
+
+begin
+  G:=TSQLWhenGDSError.Create(Nil);
+  G.GDSErrorNumber:=2;
+  FToFree:=G;
+  AssertSQL(G,'GDSCODE 2');
+end;
+
+procedure TTestGenerateSQL.TestWhenException;
+
+Var
+  E : TSQLWhenException;
+
+begin
+  E:=TSQLWhenException.Create(Nil);
+  E.ExceptionName:=CreateIdentifier('E');
+  FToFree:=E;
+  AssertSQL(E,'EXCEPTION E');
+end;
+
+procedure TTestGenerateSQL.TestWhen;
+
+Var
+  W : TSQLWhenStatement;
+  E : TSQLWhenException;
+  G : TSQLWhenGDSError;
+  S : TSQLWhenSQLError;
+
+begin
+  W:=TSQLWhenStatement.Create(Nil);
+  FToFree:=W;
+  W.Statement:=TSQLExitStatement.Create(Nil);
+  FToFree:=W;
+  W.AnyError:=True;
+  AssertSQL(W,'WHEN ANY DO'+sLineBreak+'  EXIT');
+  W.AnyError:=False;
+  E:=TSQLWhenException.Create(Nil);
+  E.ExceptionName:=CreateIdentifier('E');
+  W.Errors.Add(E);
+  AssertSQL(W,'WHEN EXCEPTION E DO'+sLineBreak+'  EXIT');
+  W.Errors.Extract(E);
+  S:=TSQLWhenSQLError.Create(Nil);
+  S.ErrorCode:=2;
+  W.Errors.Add(S);
+  AssertSQL(W,'WHEN SQLCODE 2 DO'+sLineBreak+'  EXIT');
+  W.Errors.Extract(S);
+  G:=TSQLWhenGDSError.Create(Nil);
+  G.GDSErrorNumber:=3;
+  W.Errors.Add(G);
+  AssertSQL(W,'WHEN GDSCODE 3 DO'+sLineBreak+'  EXIT');
+  W.Errors.Add(S);
+  AssertSQL(W,'WHEN GDSCODE 3 , SQLCODE 2 DO'+sLineBreak+'  EXIT');
+  W.Errors.Add(E);
+  AssertSQL(W,'WHEN GDSCODE 3 , SQLCODE 2 , EXCEPTION E DO'+sLineBreak+'  EXIT');
+end;
+
+procedure TTestGenerateSQL.TestException;
+
+Var
+  E : TSQLExceptionStatement;
+
+begin
+  E:=TSQLExceptionStatement.Create(Nil);
+  E.ExceptionName:=CreateIdentifier('E');
+  FToFree:=E;
+  AssertSQL(E,'EXCEPTION E');
+end;
+
+procedure TTestGenerateSQL.TestPostEvent;
+
+Var
+  P : TSQLPostEventStatement;
+
+begin
+  P:=TSQLPostEventStatement.Create(nil);
+  P.ColName:=CreateIdentifier('E');
+  FTofree:=P;
+  AssertSQL(P,'POST_EVENT E');
+  P.ColName.Free;
+  P.ColName:=Nil;
+  P.EventName:='E';
+  AssertSQL(P,'POST_EVENT ''E''');
+end;
+
+procedure TTestGenerateSQL.TestTriggerProcedure;
+
+Var
+  S : TSQLCreateOrAlterProcedureTriggerStatement;
+  P : TSQLProcedureParamDef;
+
+begin
+  S:=TSQLCreateOrAlterProcedureTriggerStatement.Create(Nil);
+  FToFree:=S;
+  AssertSQL(S,'BEGIN'+sLineBreak+'END');
+  S.Statements.Add(TSQLExitStatement.Create(Nil));
+  AssertSQL(S,'BEGIN'+sLineBreak+'EXIT;'+sLineBreak+'END');
+  AssertSQL(S,'BEGIN'+sLineBreak+'  EXIT;'+sLineBreak+'END',[sfoIndentProcedureBlock]);
+  P:=TSQLProcedureParamDef.Create(Nil);
+  P.ParamName:=CreateIdentifier('A');
+  P.ParamType:=CreatetypeDefinition(sdtInteger,0);
+  FToFree:=S;
+  S.LocalVariables.Add(P);
+  AssertSQL(S,'DECLARE VARIABLE A INT;'+sLineBreak+'BEGIN'+sLineBreak+'EXIT;'+sLineBreak+'END');
+  AssertSQL(S,'DECLARE VARIABLE A INT;'+sLineBreak+'BEGIN'+sLineBreak+'  EXIT;'+sLineBreak+'END',[sfoIndentProcedureBlock]);
+  P:=TSQLProcedureParamDef.Create(Nil);
+  P.ParamName:=CreateIdentifier('B');
+  P.ParamType:=CreatetypeDefinition(sdtChar,5);
+  FToFree:=S;
+  S.LocalVariables.Add(P);
+  AssertSQL(S,'DECLARE VARIABLE A INT;'+sLineBreak+'DECLARE VARIABLE B CHAR(5);'+sLineBreak+'BEGIN'+sLineBreak+'EXIT;'+sLineBreak+'END');
+  AssertSQL(S,'DECLARE VARIABLE A INT;'+sLineBreak+'DECLARE VARIABLE B CHAR(5);'+sLineBreak+'BEGIN'+sLineBreak+'  EXIT;'+sLineBreak+'END',[sfoIndentProcedureBlock]);
+end;
+
+
+procedure TTestGenerateSQL.DoTestAlterCreateProcedure(S : TSQLAlterCreateProcedureStatement; PHEAD : String);
+
+Var
+  P : TSQLProcedureParamDef;
+  H : TSQLStringType;
+
+begin
+  PHead:=PHead+' P';
+  FToFree:=S;
+  S.ObjectName:=CreateIdentifier('P');
+  H:=PHEAD+sLineBreak+'AS'+sLineBreak;
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'END');
+  S.Statements.Add(TSQLExitStatement.Create(Nil));
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'EXIT;'+sLineBreak+'END');
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'  EXIT;'+sLineBreak+'END',[sfoIndentProcedureBlock]);
+  P:=TSQLProcedureParamDef.Create(Nil);
+  P.ParamName:=CreateIdentifier('I');
+  P.ParamType:=CreatetypeDefinition(sdtInteger,0);
+  FToFree:=S;
+  S.InputVariables.Add(P);
+  H:=PHEAD+' (I INT)'+sLineBreak+'AS'+sLineBreak;
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'EXIT;'+sLineBreak+'END');
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'  EXIT;'+sLineBreak+'END',[sfoIndentProcedureBlock]);
+  P:=TSQLProcedureParamDef.Create(Nil);
+  P.ParamName:=CreateIdentifier('J');
+  P.ParamType:=CreatetypeDefinition(sdtChar,5);
+  FToFree:=S;
+  S.InputVariables.Add(P);
+  H:=PHEAD+' (I INT , J CHAR(5))'+sLineBreak+'AS'+sLineBreak;
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'EXIT;'+sLineBreak+'END');
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'  EXIT;'+sLineBreak+'END',[sfoIndentProcedureBlock]);
+  P:=TSQLProcedureParamDef.Create(Nil);
+  P.ParamName:=CreateIdentifier('R');
+  P.ParamType:=CreatetypeDefinition(sdtInteger,0);
+  FToFree:=S;
+  S.OutputVariables.Add(P);
+  H:=PHEAD+' (I INT , J CHAR(5))'+sLineBreak+'RETURNS (R INT)'+sLineBreak+'AS'+sLineBreak;
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'EXIT;'+sLineBreak+'END');
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'  EXIT;'+sLineBreak+'END',[sfoIndentProcedureBlock]);
+  P:=TSQLProcedureParamDef.Create(Nil);
+  P.ParamName:=CreateIdentifier('S');
+  P.ParamType:=CreatetypeDefinition(sdtChar,5);
+  FToFree:=S;
+  S.OutputVariables.Add(P);
+  H:=PHEAD+' (I INT , J CHAR(5))'+sLineBreak+'RETURNS (R INT , S CHAR(5))'+sLineBreak+'AS'+sLineBreak;
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'EXIT;'+sLineBreak+'END');
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'  EXIT;'+sLineBreak+'END',[sfoIndentProcedureBlock]);
+  P:=TSQLProcedureParamDef.Create(Nil);
+  P.ParamName:=CreateIdentifier('A');
+  P.ParamType:=CreatetypeDefinition(sdtInteger,0);
+  FToFree:=S;
+  S.LocalVariables.Add(P);
+  AssertSQL(S,H+'DECLARE VARIABLE A INT;'+sLineBreak+'BEGIN'+sLineBreak+'EXIT;'+sLineBreak+'END');
+  AssertSQL(S,H+'DECLARE VARIABLE A INT;'+sLineBreak+'BEGIN'+sLineBreak+'  EXIT;'+sLineBreak+'END',[sfoIndentProcedureBlock]);
+  P:=TSQLProcedureParamDef.Create(Nil);
+  P.ParamName:=CreateIdentifier('B');
+  P.ParamType:=CreatetypeDefinition(sdtChar,5);
+  FToFree:=S;
+  S.LocalVariables.Add(P);
+  AssertSQL(S,H+'DECLARE VARIABLE A INT;'+sLineBreak+'DECLARE VARIABLE B CHAR(5);'+sLineBreak+'BEGIN'+sLineBreak+'EXIT;'+sLineBreak+'END');
+  AssertSQL(S,H+'DECLARE VARIABLE A INT;'+sLineBreak+'DECLARE VARIABLE B CHAR(5);'+sLineBreak+'BEGIN'+sLineBreak+'  EXIT;'+sLineBreak+'END',[sfoIndentProcedureBlock]);
+end;
+procedure TTestGenerateSQL.TestCreateProcedure;
+begin
+  DoTestAlterCreateProcedure(TSQLCreateProcedureStatement.Create(Nil),'CREATE PROCEDURE');
+end;
+
+procedure TTestGenerateSQL.TestAlterProcedure;
+
+begin
+  DoTestAlterCreateProcedure(TSQLAlterProcedureStatement.Create(Nil),'ALTER PROCEDURE');
+end;
+
+
+procedure TTestGenerateSQL.DoTestAlterCreateTrigger(
+  S: TSQLAlterCreateTriggerStatement; PHEAD: String);
+
+Var
+  P : TSQLProcedureParamDef;
+  H : TSQLStringType;
+
+begin
+  FToFree:=S;
+  S.ObjectName:=CreateIdentifier('TR');
+  S.TableName:=CreateIdentifier('TA');
+  S.Position:=1;
+  S.Moment:=tmBefore;
+  S.Operations:=[toDelete];
+  H:=PHEAD+sLineBreak+'BEFORE DELETE'+sLineBreak+'POSITION 1'+sLineBreak+'AS'+sLineBreak;
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'END');
+  S.Moment:=tmAfter;
+  S.Operations:=[toDelete];
+  H:=PHEAD+sLineBreak+'AFTER DELETE'+sLineBreak+'POSITION 1'+sLineBreak+'AS'+sLineBreak;
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'END');
+  S.Operations:=[toUPDATE];
+  H:=PHEAD+sLineBreak+'AFTER UPDATE'+sLineBreak+'POSITION 1'+sLineBreak+'AS'+sLineBreak;
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'END');
+  S.Operations:=[toUPDATE,toDelete];
+  H:=PHEAD+sLineBreak+'AFTER DELETE OR UPDATE'+sLineBreak+'POSITION 1'+sLineBreak+'AS'+sLineBreak;
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'END');
+  S.Operations:=[toInsert];
+  S.State:=tsActive;
+  H:=PHEAD+sLineBreak+'ACTIVE'+sLineBreak+'AFTER INSERT'+sLineBreak+'POSITION 1'+sLineBreak+'AS'+sLineBreak;
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'END');
+  S.State:=tsInActive;
+  H:=PHEAD+sLineBreak+'INACTIVE'+sLineBreak+'AFTER INSERT'+sLineBreak+'POSITION 1'+sLineBreak+'AS'+sLineBreak;
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'END');
+  S.Statements.Add(TSQLExitStatement.Create(Nil));
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'EXIT;'+sLineBreak+'END');
+  AssertSQL(S,H+'BEGIN'+sLineBreak+'  EXIT;'+sLineBreak+'END',[sfoIndentProcedureBlock]);
+  P:=TSQLProcedureParamDef.Create(Nil);
+  P.ParamName:=CreateIdentifier('A');
+  P.ParamType:=CreatetypeDefinition(sdtInteger,0);
+  FToFree:=S;
+  S.LocalVariables.Add(P);
+  AssertSQL(S,H+'DECLARE VARIABLE A INT;'+sLineBreak+'BEGIN'+sLineBreak+'EXIT;'+sLineBreak+'END');
+  AssertSQL(S,H+'DECLARE VARIABLE A INT;'+sLineBreak+'BEGIN'+sLineBreak+'  EXIT;'+sLineBreak+'END',[sfoIndentProcedureBlock]);
+  P:=TSQLProcedureParamDef.Create(Nil);
+  P.ParamName:=CreateIdentifier('B');
+  P.ParamType:=CreatetypeDefinition(sdtChar,5);
+  FToFree:=S;
+  S.LocalVariables.Add(P);
+  AssertSQL(S,H+'DECLARE VARIABLE A INT;'+sLineBreak+'DECLARE VARIABLE B CHAR(5);'+sLineBreak+'BEGIN'+sLineBreak+'EXIT;'+sLineBreak+'END');
+  AssertSQL(S,H+'DECLARE VARIABLE A INT;'+sLineBreak+'DECLARE VARIABLE B CHAR(5);'+sLineBreak+'BEGIN'+sLineBreak+'  EXIT;'+sLineBreak+'END',[sfoIndentProcedureBlock]);
+end;
+
+procedure TTestGenerateSQL.TestCreateTrigger;
+begin
+  DoTestAlterCreateTrigger(TSQLCreateTriggerStatement.Create(Nil),'CREATE TRIGGER TR FOR TA');
+end;
+
+procedure TTestGenerateSQL.TestAlterTrigger;
+begin
+  DoTestAlterCreateTrigger(TSQLAlterTriggerStatement.Create(Nil),'ALTER TRIGGER TR');
+end;
+
+procedure TTestGenerateSQL.DoTestDropStatement(AClass : TSQLDropStatementClass; Const AObjectName : String);
+
+Var
+  D : TSQLDropStatement;
+
+begin
+  D:=AClass.Create(Nil);
+  D.ObjectName:=CreateIdentifier('D');
+  FToFree:=Nil;
+  Try
+    AssertSQL(D,'DROP '+AObjectName+' D');
+    AssertSQL(D,'drop '+lowercase(AObjectName)+' D',[sfoLowerCaseKeyWord]);
+  Finally
+    D.Free;
+  end;
+end;
+
+procedure TTestGenerateSQL.TestDropStatement;
+begin
+  DoTestDropStatement(TSQLDropTableStatement,'TABLE');
+  DoTestDropStatement(TSQLDropIndexStatement,'INDEX');
+  DoTestDropStatement(TSQLDropViewStatement,'VIEW');
+  DoTestDropStatement(TSQLDropProcedureStatement,'PROCEDURE');
+  DoTestDropStatement(TSQLDropDomainStatement,'DOMAIN');
+  DoTestDropStatement(TSQLDropGeneratorStatement,'GENERATOR');
+  DoTestDropStatement(TSQLDropTriggerStatement,'TRIGGER');
+  DoTestDropStatement(TSQLDropExceptionStatement,'EXCEPTION');
+  DoTestDropStatement(TSQLDropDatabaseStatement,'DATABASE');
+  DoTestDropStatement(TSQLDropRoleStatement,'ROLE');
+  DoTestDropStatement(TSQLDropExternalFunctionStatement,'EXTERNAL FUNCTION');
+  DoTestDropStatement(TSQLDropShadowStatement,'SHADOW');
+end;
+
+procedure TTestGenerateSQL.TestConnect;
+
+Const
+  Base = 'CONNECT ''db''';
+
+Var
+  C : TSQLConnectStatement;
+
+begin
+  C:=TSQLConnectStatement.Create(Nil);
+  FToFree:=C;
+  C.DatabaseName:='db';
+  AssertSQL(C,Base);
+  C.UserName:='u';
+  AssertSQL(C,Base+' USER ''u''');
+  C.Password:='p';
+  AssertSQL(C,Base+' USER ''u'' PASSWORD ''p''');
+  C.UserName:='';
+  AssertSQL(C,Base+' PASSWORD ''p''');
+  C.Password:='';
+  C.Cache:=2048;
+  AssertSQL(C,Base+' CACHE 2048');
+  C.Cache:=0;
+  C.Role:='r';
+  AssertSQL(C,Base+' ROLE ''r''');
+end;
+
+procedure TTestGenerateSQL.TestExtract;
+
+Var
+  C : TSQLExtractExpression;
+
+begin
+  AssertEquals(ExtractElementNames[eeYear],'YEAR');
+  AssertEquals(ExtractElementNames[eeMonth],'MONTH');
+  AssertEquals(ExtractElementNames[eeDay],'DAY');
+  AssertEquals(ExtractElementNames[eeHour],'HOUR');
+  AssertEquals(ExtractElementNames[eeMinute],'MINUTE');
+  AssertEquals(ExtractElementNames[eeSecond],'SECOND');
+  AssertEquals(ExtractElementNames[eeWeekDay],'WEEKDAY');
+  AssertEquals(ExtractElementNames[eeYearDay],'YEARDAY');
+  C:=TSQLExtractExpression.Create(Nil);
+  C.Value:=CreateIdentifierExpression('A');
+  C.Element:=eeYear;
+  AssertSQL(C,'EXTRACT(YEAR FROM A)');
+  C.Element:=eeMonth;
+  AssertSQL(C,'EXTRACT(MONTH FROM A)');
+  C.Element:=eeDay;
+  AssertSQL(C,'EXTRACT(DAY FROM A)');
+  C.Element:=eeHour;
+  AssertSQL(C,'EXTRACT(HOUR FROM A)');
+  C.Element:=eeMinute;
+  AssertSQL(C,'EXTRACT(MINUTE FROM A)');
+  C.Element:=eeSecond;
+  AssertSQL(C,'EXTRACT(SECOND FROM A)');
+  C.Element:=eeWeekday;
+  AssertSQL(C,'EXTRACT(WEEKDAY FROM A)');
+  C.Element:=eeYearday;
+  AssertSQL(C,'EXTRACT(YEARDAY FROM A)');
+end;
+
+procedure TTestGenerateSQL.TestParamExpression;
+
+Var
+  P : TSQLParameterExpression;
+
+begin
+  P:=TSQLParameterExpression.Create(Nil);
+  P.Identifier:=CreateIdentifier('P');
+  FTofree:=P;
+  AssertSQL(P,':P');
+end;
+
+procedure TTestGenerateSQL.TestGrantTable;
+
+Var
+  G : TSQLTableGrantStatement;
+  U : TSQLUserGrantee;
+  PU : TSQLColumnPrivilege;
+  PG : TSQLProcedureGrantee;
+
+begin
+  G:=TSQLTableGrantStatement.Create(Nil);
+  G.TableName:=CreateIdentifier('A');
+  FtoFree:=G;
+  G.Privileges.Add(TSQLSelectPrivilege.Create(Nil));
+  G.Grantees.add(CreateGrantee('B'));
+  FtoFree:=G;
+  AssertSQl(G,'GRANT SELECT ON A TO B');
+  G.Grantees.add(CreateGrantee('C'));
+  FtoFree:=G;
+  AssertSQl(G,'GRANT SELECT ON A TO B , C');
+  G.Privileges.Clear;
+  G.Privileges.Add(TSQLUPdatePrivilege.Create(Nil));
+  FtoFree:=G;
+  AssertSQl(G,'GRANT UPDATE ON A TO B , C');
+  G.Privileges.Clear;
+  G.Privileges.Add(TSQLDeletePrivilege.Create(Nil));
+  FtoFree:=G;
+  AssertSQl(G,'GRANT DELETE ON A TO B , C');
+  G.Privileges.Clear;
+  G.Privileges.Add(TSQLINSERTPrivilege.Create(Nil));
+  FtoFree:=G;
+  AssertSQl(G,'GRANT INSERT ON A TO B , C');
+  G.Privileges.Clear;
+  G.Privileges.Add(TSQLReferencePrivilege.Create(Nil));
+  FtoFree:=G;
+  AssertSQl(G,'GRANT REFERENCES ON A TO B , C');
+  G.Privileges.Clear;
+  G.Privileges.Add(TSQLAllPrivilege.Create(Nil));
+  FtoFree:=G;
+  AssertSQl(G,'GRANT ALL PRIVILEGES ON A TO B , C');
+  G.GrantOption:=True;
+  AssertSQl(G,'GRANT ALL PRIVILEGES ON A TO B , C WITH GRANT OPTION');
+  G.GrantOption:=False;
+  G.Privileges.Clear;
+  G.Privileges.Add(TSQLSelectPrivilege.Create(Nil));
+  G.Grantees.Clear;
+  G.Grantees.Add(TSQLPublicGrantee.Create(Nil));
+  FtoFree:=G;
+  AssertSQl(G,'GRANT SELECT ON A TO PUBLIC');
+  G.Grantees.Clear;
+  G.Grantees.Add(CreateGrantee('B',TSQLProcedureGrantee));
+  AssertSQl(G,'GRANT SELECT ON A TO PROCEDURE B');
+  G.Grantees.Clear;
+  G.Grantees.Add(CreateGrantee('B',TSQLViewGrantee));
+  AssertSQl(G,'GRANT SELECT ON A TO VIEW B');
+  G.Grantees.Clear;
+  G.Grantees.Add(CreateGrantee('B',TSQLTriggerGrantee));
+  AssertSQl(G,'GRANT SELECT ON A TO TRIGGER B');
+  FtoFree:=G;
+  G.Privileges.Clear;
+  Pu:=TSQLUPdatePrivilege.Create(Nil);
+  PU.Columns:=TSQLElementList.Create(True);
+  PU.Columns.Add(CreateIdentifier('C'));
+  G.Privileges.Add(PU);
+  FtoFree:=G;
+  AssertSQl(G,'GRANT UPDATE (C) ON A TO TRIGGER B');
+  PU.Columns.Add(CreateIdentifier('D'));
+  FtoFree:=G;
+  AssertSQl(G,'GRANT UPDATE (C , D) ON A TO TRIGGER B');
+  G.Privileges.Clear;
+  Pu:=TSQLReferencePrivilege.Create(Nil);
+  PU.Columns:=TSQLElementList.Create(True);
+  PU.Columns.Add(CreateIdentifier('C'));
+  G.Privileges.Add(PU);
+  FtoFree:=G;
+  AssertSQl(G,'GRANT REFERENCES (C) ON A TO TRIGGER B');
+  PU.Columns.Add(CreateIdentifier('D'));
+  FtoFree:=G;
+  AssertSQl(G,'GRANT REFERENCES (C , D) ON A TO TRIGGER B');
+end;
+
+procedure TTestGenerateSQL.TestGrantProcedure;
+
+Var
+  G : TSQLProcedureGrantStatement;
+  U : TSQLUserGrantee;
+  PU : TSQLColumnPrivilege;
+  PG : TSQLProcedureGrantee;
+
+begin
+  G:=TSQLProcedureGrantStatement.Create(Nil);
+  G.ProcedureName:=CreateIdentifier('A');
+  FtoFree:=G;
+  G.Grantees.add(CreateGrantee('B'));
+  FtoFree:=G;
+  AssertSQL(G,'GRANT EXECUTE ON PROCEDURE A TO B');
+  G.Grantees.add(CreateGrantee('C'));
+  FtoFree:=G;
+  AssertSQL(G,'GRANT EXECUTE ON PROCEDURE A TO B , C');
+  G.Grantees.Clear;
+  G.Grantees.Add(CreateGrantee('B',TSQLTriggerGrantee));
+  FtoFree:=G;
+  AssertSQL(G,'GRANT EXECUTE ON PROCEDURE A TO TRIGGER B');
+  G.Grantees.Clear;
+  G.Grantees.Add(CreateGrantee('B',TSQLProcedureGrantee));
+  FtoFree:=G;
+  AssertSQL(G,'GRANT EXECUTE ON PROCEDURE A TO PROCEDURE B');
+  G.Grantees.Clear;
+  G.Grantees.Add(CreateGrantee('B',TSQLViewGrantee));
+  FtoFree:=G;
+  AssertSQL(G,'GRANT EXECUTE ON PROCEDURE A TO VIEW B');
+  G.Grantees.Clear;
+  G.Grantees.Add(CreateGrantee('B',TSQLPublicGrantee));
+  FtoFree:=G;
+  AssertSQL(G,'GRANT EXECUTE ON PROCEDURE A TO PUBLIC');
+end;
+
+procedure TTestGenerateSQL.TestGrantRole;
+Var
+  G : TSQLRoleGrantStatement;
+  U : TSQLUserGrantee;
+
+begin
+  G:=TSQLRoleGrantStatement.Create(Nil);
+  G.Roles.Add(CreateIdentifier('A'));
+  FtoFree:=G;
+  G.Grantees.add(CreateGrantee('B'));
+  FtoFree:=G;
+  AssertSQL(G,'GRANT A TO B');
+  G.Roles.Add(CreateIdentifier('C'));
+  FtoFree:=G;
+  AssertSQL(G,'GRANT A , C TO B');
+  G.Grantees.add(CreateGrantee('D'));
+  FtoFree:=G;
+  AssertSQL(G,'GRANT A , C TO B , D');
+  G.AdminOption:=True;
+  AssertSQL(G,'GRANT A , C TO B , D WITH ADMIN OPTION');
+end;
+
+procedure TTestGenerateSQL.TestRevokeTable;
+Var
+  G : TSQLTableRevokeStatement;
+  U : TSQLUserGrantee;
+  PU : TSQLColumnPrivilege;
+  PG : TSQLProcedureGrantee;
+
+begin
+  G:=TSQLTableRevokeStatement.Create(Nil);
+  G.TableName:=CreateIdentifier('A');
+  FtoFree:=G;
+  G.Privileges.Add(TSQLSelectPrivilege.Create(Nil));
+  G.Grantees.add(CreateGrantee('B'));
+  FtoFree:=G;
+  AssertSQl(G,'REVOKE SELECT ON A FROM B');
+  G.Grantees.add(CreateGrantee('C'));
+  FtoFree:=G;
+  AssertSQl(G,'REVOKE SELECT ON A FROM B , C');
+  G.Privileges.Clear;
+  G.Privileges.Add(TSQLUPdatePrivilege.Create(Nil));
+  FtoFree:=G;
+  AssertSQl(G,'REVOKE UPDATE ON A FROM B , C');
+  G.Privileges.Clear;
+  G.Privileges.Add(TSQLDeletePrivilege.Create(Nil));
+  FtoFree:=G;
+  AssertSQl(G,'REVOKE DELETE ON A FROM B , C');
+  G.Privileges.Clear;
+  G.Privileges.Add(TSQLINSERTPrivilege.Create(Nil));
+  FtoFree:=G;
+  AssertSQl(G,'REVOKE INSERT ON A FROM B , C');
+  G.Privileges.Clear;
+  G.Privileges.Add(TSQLReferencePrivilege.Create(Nil));
+  FtoFree:=G;
+  AssertSQl(G,'REVOKE REFERENCES ON A FROM B , C');
+  G.Privileges.Clear;
+  G.Privileges.Add(TSQLAllPrivilege.Create(Nil));
+  FtoFree:=G;
+  AssertSQl(G,'REVOKE ALL PRIVILEGES ON A FROM B , C');
+  G.GrantOption:=True;
+  AssertSQl(G,'REVOKE GRANT OPTION FOR ALL PRIVILEGES ON A FROM B , C');
+  G.GrantOption:=False;
+  G.Privileges.Clear;
+  G.Privileges.Add(TSQLSelectPrivilege.Create(Nil));
+  G.Grantees.Clear;
+  G.Grantees.Add(TSQLPublicGrantee.Create(Nil));
+  FtoFree:=G;
+  AssertSQl(G,'REVOKE SELECT ON A FROM PUBLIC');
+  G.Grantees.Clear;
+  G.Grantees.Add(CreateGrantee('B',TSQLProcedureGrantee));
+  AssertSQl(G,'REVOKE SELECT ON A FROM PROCEDURE B');
+  G.Grantees.Clear;
+  G.Grantees.Add(CreateGrantee('B',TSQLViewGrantee));
+  AssertSQl(G,'REVOKE SELECT ON A FROM VIEW B');
+  G.Grantees.Clear;
+  G.Grantees.Add(CreateGrantee('B',TSQLTriggerGrantee));
+  AssertSQl(G,'REVOKE SELECT ON A FROM TRIGGER B');
+  FtoFree:=G;
+  G.Privileges.Clear;
+  Pu:=TSQLUPdatePrivilege.Create(Nil);
+  PU.Columns:=TSQLElementList.Create(True);
+  PU.Columns.Add(CreateIdentifier('C'));
+  G.Privileges.Add(PU);
+  FtoFree:=G;
+  AssertSQl(G,'REVOKE UPDATE (C) ON A FROM TRIGGER B');
+  PU.Columns.Add(CreateIdentifier('D'));
+  FtoFree:=G;
+  AssertSQl(G,'REVOKE UPDATE (C , D) ON A FROM TRIGGER B');
+  G.Privileges.Clear;
+  Pu:=TSQLReferencePrivilege.Create(Nil);
+  PU.Columns:=TSQLElementList.Create(True);
+  PU.Columns.Add(CreateIdentifier('C'));
+  G.Privileges.Add(PU);
+  FtoFree:=G;
+  AssertSQl(G,'REVOKE REFERENCES (C) ON A FROM TRIGGER B');
+  PU.Columns.Add(CreateIdentifier('D'));
+  FtoFree:=G;
+  AssertSQl(G,'REVOKE REFERENCES (C , D) ON A FROM TRIGGER B');
+end;
+
+procedure TTestGenerateSQL.TestRevokeProcedure;
+Var
+  G : TSQLProcedureRevokeStatement;
+  PG : TSQLProcedureGrantee;
+
+begin
+  G:=TSQLProcedureRevokeStatement.Create(Nil);
+  G.ProcedureName:=CreateIdentifier('A');
+  FtoFree:=G;
+  G.Grantees.add(CreateGrantee('B'));
+  FtoFree:=G;
+  AssertSQL(G,'REVOKE EXECUTE ON PROCEDURE A FROM B');
+  G.Grantees.add(CreateGrantee('C'));
+  FtoFree:=G;
+  AssertSQL(G,'REVOKE EXECUTE ON PROCEDURE A FROM B , C');
+  G.Grantees.Clear;
+  G.Grantees.Add(CreateGrantee('B',TSQLTriggerGrantee));
+  FtoFree:=G;
+  AssertSQL(G,'REVOKE EXECUTE ON PROCEDURE A FROM TRIGGER B');
+  G.Grantees.Clear;
+  G.Grantees.Add(CreateGrantee('B',TSQLProcedureGrantee));
+  FtoFree:=G;
+  AssertSQL(G,'REVOKE EXECUTE ON PROCEDURE A FROM PROCEDURE B');
+  G.Grantees.Clear;
+  G.Grantees.Add(CreateGrantee('B',TSQLViewGrantee));
+  FtoFree:=G;
+  AssertSQL(G,'REVOKE EXECUTE ON PROCEDURE A FROM VIEW B');
+  G.Grantees.Clear;
+  G.Grantees.Add(CreateGrantee('B',TSQLPublicGrantee));
+  FtoFree:=G;
+  AssertSQL(G,'REVOKE EXECUTE ON PROCEDURE A FROM PUBLIC');
+end;
+
+procedure TTestGenerateSQL.TestRevokeRole;
+Var
+  G : TSQLRoleRevokeStatement;
+
+begin
+  G:=TSQLRoleRevokeStatement.Create(Nil);
+  G.Roles.Add(CreateIdentifier('A'));
+  FtoFree:=G;
+  G.Grantees.add(CreateGrantee('B'));
+  FtoFree:=G;
+  AssertSQL(G,'REVOKE A FROM B');
+  G.Roles.Add(CreateIdentifier('C'));
+  FtoFree:=G;
+  AssertSQL(G,'REVOKE A , C FROM B');
+  G.Grantees.add(CreateGrantee('D'));
+  FtoFree:=G;
+  AssertSQL(G,'REVOKE A , C FROM B , D');
+  G.AdminOption:=True;
+  AssertSQL(G,'REVOKE A , C FROM B , D');
+end;
+
+
+initialization
+  RegisterTest(TTestGenerateSQL);
+end.
+

+ 7996 - 0
packages/fcl-db/tests/tcparser.pas

@@ -0,0 +1,7996 @@
+{
+    This file is part of the Free Component Library
+    Copyright (c) 2010 by the Free Pascal development team
+
+    SQL source syntax parser test suite
+
+    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 tcparser;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpcunit, testutils, fpsqltree, fpsqlscanner, fpsqlparser, testregistry;
+
+type
+
+  { TTestParser }
+
+  TTestParser = Class(TSQLparser)
+  public
+    Procedure ParseStringDef(Out DT : TSQLDataType; Out Len : Integer; Out ACharset : TSQLStringtype);
+    Function  ParseType(Flags : TParseTypeFlags) : TSQLTypeDefinition;
+    Function  ParseConstraint : TSQLExpression;
+    Function  ParseProcedureStatements : TSQLStatement;
+  end;
+
+  { TTestSQLParser }
+
+  TTestSQLParser = class(TTestCase)
+  Private
+    FSource : TStringStream;
+    FParser : TTestParser;
+    FToFree: TSQLElement;
+    FErrSource : string;
+  protected
+    procedure AssertTypeDefaults(TD: TSQLTypeDefinition; Len: Integer=0);
+    Procedure TestStringDef(ASource: String; ExpectDT: TSQLDataType; ExpectLen: Integer; ExpectCharset : TSQLStringType='');
+    Function TestType(ASource : string; AFlags : TParseTypeFlags; AExpectedType : TSQLDataType) : TSQLTypeDefinition;
+    Function TestCheck(ASource : string; AExpectedConstraint : TSQLElementClass) : TSQLExpression;
+    Procedure CreateParser(Const ASource : string);
+    Function CheckClass(E : TSQLElement; C : TSQLElementClass) : TSQLElement;
+    procedure TestDropStatement(Const ASource : string;C : TSQLElementClass);
+    Function TestCreateStatement(Const ASource,AName : string;C: TSQLElementClass) : TSQLCreateOrAlterStatement;
+    procedure AssertEquals(const AMessage: String; Expected, Actual: TSQLToken); overload;
+    procedure AssertEquals(const AMessage: String; Expected, Actual: TSQLBinaryoperation); overload;
+    procedure AssertEquals(const AMessage: String; Expected, Actual: TSQLUnaryoperation); overload;
+    procedure AssertEquals(const AMessage: String; Expected, Actual: TSQLternaryoperation); overload;
+    procedure AssertEquals(const AMessage: String; Expected, Actual: TSQLDataType); overload;
+    procedure AssertEquals(const AMessage: String; Expected, Actual: TForeignKeyAction); overload;
+    procedure AssertEquals(const AMessage: String; Expected, Actual: TSQLJoinType); overload;
+    procedure AssertEquals(const AMessage: String; Expected, Actual: TSQLAggregateFunction); overload;
+    procedure AssertEquals(const AMessage: String; Expected, Actual: TSQLAggregateOption); overload;
+    procedure AssertEquals(const AMessage: String; Expected, Actual: TSQLOrderDirection); overload;
+    procedure AssertEquals(const AMessage: String; Expected, Actual: TPlanJoinType); overload;
+    procedure AssertEquals(const AMessage: String; Expected, Actual: TTriggerMoment); overload;
+    procedure AssertEquals(const AMessage: String; Expected, Actual: TTriggerState); overload;
+    procedure AssertEquals(const AMessage: String; Expected, Actual: TTriggerOperations); overload;
+    function AssertLiteralExpr(Const AMessage : String; Element : TSQLExpression; ALiteralClass : TSQLElementClass) : TSQLLiteral;
+    Procedure AssertIdentifierName(Const AMessage : String; Const AExpected : String; Element : TSQLElement);
+    Procedure AssertField(AField : TSQLElement; Const AName : String; Const AAlias : String = '');
+    Procedure AssertAggregate(AField : TSQLElement; AAgregate : TSQLAggregateFunction; Const AFieldName : String; AOption : TSQLAggregateOption; Const AAlias : String = '');
+    Procedure AssertAggregateExpression(E : TSQLElement; AAgregate : TSQLAggregateFunction; Const AFieldName : String; AOption : TSQLAggregateOption);
+    Procedure AssertTable(ATable : TSQLElement; Const AName : String; Const AAlias : String = '');
+    Function AssertJoin(AJoin : TSQLElement; Const AFirst,ASecond : String; Const aJoinType : TSQLJoinType) : TSQLJoinTableReference;
+    Function AssertJoinOn(AJoin : TSQLExpression; Const AFirst,ASecond : String; Const AOperation : TSQLBinaryOperation) : TSQLBinaryExpression;
+    Function AssertOrderBy(AOrderBy : TSQLElement; Const AField : String; Const ANumber : Integer; Const AOrdering : TSQLOrderDirection) : TSQLOrderByElement;
+    Function AssertSecondaryFile(ASecondaryFile : TSQLElement; Const AFile : String; Const ALength,AStart : Integer) : TSQLDatabaseFileInfo;
+    procedure TestTypeError;
+    Procedure TestStringError;
+    Procedure TestCheckError;
+    Procedure TestParseError;
+    procedure SetUp; override;
+    procedure TearDown; override;
+    Property Parser : TTestParser Read FParser;
+    Property ToFree : TSQLElement Read FToFree Write FTofree;
+  end;
+
+  { TTestDropParser }
+
+  TTestDropParser = Class(TTestSQLParser)
+  published
+    procedure TestDropDatabase;
+    procedure TestDropDomain;
+    procedure TestDropException;
+    procedure TestDropGenerator;
+    procedure TestDropIndex;
+    procedure TestDropProcedure;
+    procedure TestDropRole;
+    procedure TestDropTable;
+    procedure TestDropTrigger;
+    procedure TestDropView;
+    procedure TestDropShadow;
+    procedure TestDropExternalFunction;
+  end;
+
+  { TTestGeneratorParser }
+
+  TTestGeneratorParser = Class(TTestSQLParser)
+  Published
+    Procedure TestCreateGenerator;
+    Procedure TestSetGenerator;
+  end;
+
+  { TTestRoleParser }
+
+  TTestRoleParser = Class(TTestSQLParser)
+  Published
+    Procedure TestCreateRole;
+    Procedure TestAlterRole;
+  end;
+
+  { TTestTypeParser }
+
+  TTestTypeParser = Class(TTestSQLParser)
+  private
+  Published
+    Procedure TestStringType1;
+    procedure TestStringType2;
+    procedure TestStringType3;
+    procedure TestStringType4;
+    procedure TestStringType5;
+    procedure TestStringType6;
+    procedure TestStringType7;
+    procedure TestStringType8;
+    procedure TestStringType9;
+    procedure TestStringType10;
+    procedure TestStringType11;
+    procedure TestStringType12;
+    procedure TestStringType13;
+    procedure TestStringType14;
+    Procedure TestStringType15;
+    procedure TestStringType16;
+    procedure TestStringType17;
+    procedure TestStringType18;
+    procedure TestStringType19;
+    Procedure TestStringTypeErrors1;
+    procedure TestStringTypeErrors2;
+    procedure TestStringTypeErrors3;
+    procedure TestTypeInt1;
+    procedure TestTypeInt2;
+    procedure TestTypeInt3;
+    procedure TestTypeInt4;
+    procedure TestTypeInt5;
+    procedure TestNumerical1;
+    procedure TestNumerical2;
+    procedure TestNumerical3;
+    procedure TestNumericalError1;
+    procedure TestNumericalError2;
+    procedure TestNumericalError3;
+    procedure TestNumericalError4;
+    procedure TestNumericalError5;
+    procedure TestNumericalError6;
+    procedure TestNumericalError7;
+    procedure TestBlob1;
+    procedure TestBlob2;
+    procedure TestBlob3;
+    procedure TestBlob4;
+    procedure TestBlob5;
+    procedure TestBlob6;
+    procedure TestBlobError1;
+    procedure TestBlobError2;
+    procedure TestBlobError3;
+    procedure TestBlobError4;
+    procedure TestBlobError5;
+    procedure TestBlobError6;
+    procedure TestBlobError7;
+    procedure TestSmallInt;
+    procedure TestFloat;
+  end;
+
+  { TTestCheckParser }
+
+  TTestCheckParser = Class (TTestSQLParser)
+  private
+  published
+    procedure TestCheckNull;
+    procedure TestCheckNotNull;
+    procedure TestCheckBraces;
+    procedure TestCheckBracesError;
+    Procedure TestCheckParamError;
+    procedure TestCheckIdentifierError;
+    procedure TestIsEqual;
+    procedure TestIsNotEqual1;
+    procedure TestIsNotEqual2;
+    procedure TestGreaterThan;
+    procedure TestGreaterThanEqual1;
+    procedure TestGreaterThanEqual2;
+    procedure TestLessThan;
+    procedure TestLessThanEqual1;
+    procedure TestLessThanEqual2;
+    procedure TestLike;
+    procedure TestNotLike;
+    procedure TestContaining;
+    procedure TestNotContaining;
+    procedure TestStarting;
+    procedure TestNotStarting;
+    procedure TestBetween;
+    procedure TestNotBetween;
+    procedure TestLikeEscape;
+    procedure TestNotLikeEscape;
+    Procedure TestAnd;
+    procedure TestOr;
+    procedure TestNotOr;
+  end;
+
+  { TTestDomainParser }
+
+  // Most relevant tests are in type definition testing.
+  TTestDomainParser = Class(TTestSQLParser)
+  private
+  Published
+    Procedure TestSimpleDomain;
+    Procedure TestSimpleDomainAs;
+    Procedure TestNotNullDomain;
+    procedure TestDefaultNotNullDomain;
+    procedure TestAlterDomainDropDefault;
+    procedure TestAlterDomainDropCheck;
+    procedure TestAlterDomainDropCheckError;
+    procedure TestAlterDomainAddCheck;
+    procedure TestAlterDomainAddConstraintCheck;
+    procedure TestAlterDomainAddConstraintError;
+    procedure TestAlterDomainSetDefault;
+    procedure TestAlterDomainRename;
+    procedure TestAlterDomainNewType;
+    procedure TestAlterDomainNewTypeError1;
+    procedure TestAlterDomainNewTypeError2;
+  end;
+
+  { TTestExceptionParser }
+
+  TTestExceptionParser = Class(TTestSQLParser)
+  Published
+    Procedure TestException;
+    procedure TestAlterException;
+    Procedure TestExceptionError1;
+    procedure TestExceptionError2;
+  end;
+
+  { TTestIndexParser }
+
+  TTestIndexParser = Class(TTestSQLParser)
+  private
+  Published
+    procedure TestAlterindexActive;
+    procedure TestAlterindexInactive;
+    procedure TestCreateIndexSimple;
+    procedure TestIndexIndexDouble;
+    procedure TestCreateIndexAscending;
+    procedure TestCreateIndexDescending;
+    procedure TestCreateIndexUnique;
+    procedure TestCreateIndexUniqueAscending;
+    procedure TestCreateIndexUniqueDescending;
+    procedure TestIndexError1;
+    procedure TestIndexError2;
+    procedure TestIndexError3;
+    procedure TestIndexError4;
+    procedure TestIndexError5;
+    procedure TestIndexError6;
+  end;
+
+  { TTestTableParser }
+
+  TTestTableParser = Class(TTestSQLParser)
+  private
+    procedure DoTestCreateReferencesField(Const ASource : String; AOnUpdate,AOnDelete : TForeignKeyAction);
+  Published
+    Procedure TestCreateOneSimpleField;
+    procedure TestCreateTwoSimpleFields;
+    procedure TestCreateOnePrimaryField;
+    procedure TestCreateOneNamedPrimaryField;
+    procedure TestCreateOneUniqueField;
+    procedure TestCreateOneNamedUniqueField;
+    procedure TestCreateNotNullPrimaryField;
+    procedure TestCreateNotNullDefaultPrimaryField;
+    procedure TestCreateComputedByField;
+    procedure TestCreateCheckField;
+    procedure TestCreateNamedCheckField;
+    procedure TestCreateReferencesField;
+    procedure TestCreateReferencesOnUpdateCascadeField;
+    procedure TestCreateReferencesOnUpdateNoActionField;
+    procedure TestCreateReferencesOnUpdateSetDefaultField;
+    procedure TestCreateReferencesOnUpdateSetNullField;
+    procedure TestCreateReferencesOnDeleteCascadeField;
+    procedure TestCreateReferencesOnDeleteNoActionField;
+    procedure TestCreateReferencesOnDeleteSetDefaultField;
+    procedure TestCreateReferencesOnDeleteSetNullField;
+    procedure TestCreateReferencesOnUpdateAndDeleteSetNullField;
+    procedure TestCreateNamedReferencesField;
+    procedure TestCreatePrimaryKeyConstraint;
+    procedure TestCreateNamedPrimaryKeyConstraint;
+    procedure TestCreateForeignKeyConstraint;
+    procedure TestCreateNamedForeignKeyConstraint;
+    procedure TestCreateUniqueConstraint;
+    procedure TestCreateNamedUniqueConstraint;
+    procedure TestCreateCheckConstraint;
+    procedure TestCreateNamedCheckConstraint;
+    Procedure TestAlterDropField;
+    Procedure TestAlterDropFields;
+    Procedure TestAlterDropConstraint;
+    Procedure TestAlterDropConstraints;
+    Procedure TestAlterRenameField;
+    procedure TestAlterRenameColumnField;
+    Procedure TestAlterFieldType;
+    Procedure TestAlterFieldPosition;
+    Procedure TestAlterAddField;
+    Procedure TestAlterAddFields;
+    Procedure TestAlterAddPrimarykey;
+    Procedure TestAlterAddNamedPrimarykey;
+    Procedure TestAlterAddCheckConstraint;
+    procedure TestAlterAddNamedCheckConstraint;
+    Procedure TestAlterAddForeignkey;
+    Procedure TestAlterAddNamedForeignkey;
+  end;
+
+  { TTestDeleteParser }
+
+  TTestDeleteParser = Class(TTestSQLParser)
+  Private
+    Function TestDelete(Const ASource , ATable: String) : TSQLDeleteStatement;
+  Published
+    Procedure TestSimpleDelete;
+    Procedure TestSimpleDeleteAlias;
+    Procedure TestDeleteWhereNull;
+  end;
+
+  { TTestUpdateParser }
+
+  TTestUpdateParser = Class(TTestSQLParser)
+  Private
+    Function TestUpdate(Const ASource , ATable: String) : TSQLUpdateStatement;
+  Published
+    Procedure TestUpdateOneField;
+    Procedure TestUpdateOneFieldFull;
+    Procedure TestUpdateTwoFields;
+    Procedure TestUpdateOneFieldWhereIsNull;
+  end;
+
+  { TTestInsertParser }
+
+  TTestInsertParser = Class(TTestSQLParser)
+  Private
+    Function TestInsert(Const ASource , ATable: String) : TSQLInsertStatement;
+  Published
+    Procedure TestInsertOneField;
+    procedure TestInsertTwoFields;
+    Procedure TestInsertOneValue;
+    procedure TestInsertTwoValues;
+  end;
+
+  { TTestSelectParser }
+
+  TTestSelectParser = Class(TTestSQLParser)
+  Private
+    FSelect : TSQLSelectStatement;
+    Function TestSelect(Const ASource : String) : TSQLSelectStatement;
+    Procedure TestSelectError(Const ASource : String);
+    Procedure DoExtractSimple(Expected : TSQLExtractElement);
+    Property Select : TSQLSelectStatement Read FSelect;
+  Published
+    Procedure TestSelectOneFieldOneTable;
+    Procedure TestSelectOneFieldOneTableTransaction;
+    Procedure TestSelectOneArrayFieldOneTable;
+    Procedure TestSelectTwoFieldsOneTable;
+    procedure TestSelectOneFieldAliasOneTable;
+    procedure TestSelectTwoFieldAliasesOneTable;
+    Procedure TestSelectOneDistinctFieldOneTable;
+    procedure TestSelectOneAllFieldOneTable;
+    procedure TestSelectAsteriskOneTable;
+    procedure TestSelectDistinctAsteriskOneTable;
+    procedure TestSelectOneFieldOneTableAlias;
+    procedure TestSelectTwoFieldsTwoTables;
+    procedure TestSelectTwoFieldsTwoTablesJoin;
+    procedure TestSelectTwoFieldsTwoInnerTablesJoin;
+    procedure TestSelectTwoFieldsTwoLeftTablesJoin;
+    procedure TestSelectTwoFieldsTwoOuterTablesJoin;
+    procedure TestSelectTwoFieldsTwoRightTablesJoin;
+    procedure TestSelectTwoFieldsThreeTablesJoin;
+    procedure TestSelectTwoFieldsBracketThreeTablesJoin;
+    procedure TestSelectTwoFieldsThreeBracketTablesJoin;
+    Procedure TestAggregateCount;
+    procedure TestAggregateCountAsterisk;
+    procedure TestAggregateCountAll;
+    procedure TestAggregateCountDistinct;
+    procedure TestAggregateMax;
+    procedure TestAggregateMaxAll;
+    procedure TestAggregateMaxAsterisk;
+    procedure TestAggregateMaxDistinct;
+    procedure TestAggregateMin;
+    procedure TestAggregateMinAll;
+    procedure TestAggregateMinAsterisk;
+    procedure TestAggregateMinDistinct;
+    procedure TestAggregateSum;
+    procedure TestAggregateSumAll;
+    procedure TestAggregateSumAsterisk;
+    procedure TestAggregateSumDistinct;
+    procedure TestAggregateAvg;
+    procedure TestAggregateAvgAll;
+    procedure TestAggregateAvgAsterisk;
+    procedure TestAggregateAvgDistinct;
+    Procedure TestUpperConst;
+    procedure TestUpperError;
+    Procedure TestGenID;
+    Procedure TestGenIDError1;
+    Procedure TestGenIDError2;
+    Procedure TestCastSimple;
+    Procedure TestExtractSimple;
+    procedure TestOrderByOneField;
+    procedure TestOrderByTwoFields;
+    procedure TestOrderByThreeFields;
+    procedure TestOrderByOneDescField;
+    procedure TestOrderByTwoDescFields;
+    procedure TestOrderByThreeDescFields;
+    procedure TestOrderByOneColumn;
+    procedure TestOrderByTwoColumns;
+    procedure TestOrderByTwoColumnsDesc;
+    procedure TestOrderByCollate;
+    procedure TestOrderByCollateDesc;
+    procedure TestOrderByCollateDescTwoFields;
+    procedure TestGroupByOne;
+    procedure TestGroupByTwo;
+    procedure TestHavingOne;
+    Procedure TestUnionSimple;
+    procedure TestUnionSimpleAll;
+    procedure TestUnionSimpleOrderBy;
+    Procedure TestUnionDouble;
+    procedure TestUnionError1;
+    procedure TestUnionError2;
+    procedure TestPlanOrderNatural;
+    procedure TestPlanOrderOrder;
+    procedure TestPlanOrderIndex1;
+    procedure TestPlanOrderIndex2;
+    procedure TestPlanJoinNatural;
+    procedure TestPlanDefaultNatural;
+    procedure TestPlanMergeNatural;
+    procedure TestPlanMergeNested;
+    procedure TestSubSelect;
+    procedure TestWhereExists;
+    procedure TestWhereSingular;
+    procedure TestWhereAll;
+    procedure TestWhereAny;
+    procedure TestWhereSome;
+    Procedure TestParam;
+    procedure TestParamExpr;
+  end;
+
+  { TTestRollBackParser }
+
+  TTestRollBackParser = Class(TTestSQLParser)
+  Private
+    FRollback : TSQLRollbackStatement;
+    Function TestRollback(Const ASource : String) : TSQLRollbackStatement;
+    Procedure TestRollbackError(Const ASource : String);
+    Property Rollback : TSQLRollbackStatement Read FRollback;
+  Published
+    Procedure TestRollback;
+    Procedure TestRollbackWork;
+    Procedure TestRollbackRelease;
+    Procedure TestRollbackWorkRelease;
+    Procedure TestRollbackTransaction;
+    Procedure TestRollbackTransactionWork;
+    Procedure TestRollbackTransactionRelease;
+    Procedure TestRollbackTransactionWorkRelease;
+  end;
+
+  { TTestCommitParser }
+
+  TTestCommitParser = Class(TTestSQLParser)
+  Private
+    FCommit : TSQLCommitStatement;
+    Function TestCommit(Const ASource : String) : TSQLCommitStatement;
+    Procedure TestCommitError(Const ASource : String);
+    Property Commit : TSQLCommitStatement Read FCommit;
+  Published
+    Procedure TestCommit;
+    Procedure TestCommitWork;
+    Procedure TestCommitRelease;
+    Procedure TestCommitWorkRelease;
+    Procedure TestCommitTransaction;
+    Procedure TestCommitTransactionWork;
+    Procedure TestCommitTransactionRelease;
+    Procedure TestCommitTransactionWorkRelease;
+    Procedure TestCommitRetain;
+    Procedure TestCommitWorkRetain;
+    Procedure TestCommitReleaseRetain;
+    Procedure TestCommitWorkReleaseRetain;
+    Procedure TestCommitTransactionRetain;
+    Procedure TestCommitTransactionWorkRetain;
+    Procedure TestCommitTransactionReleaseRetain;
+    Procedure TestCommitTransactionWorkReleaseRetain;
+    procedure TestCommitRetainSnapShot;
+  end;
+
+  { TTestExecuteProcedureParser }
+
+  TTestExecuteProcedureParser = Class(TTestSQLParser)
+  Private
+    FExecute : TSQLExecuteProcedureStatement;
+    Function TestExecute(Const ASource : String) : TSQLExecuteProcedureStatement;
+    Procedure TestExecuteError(Const ASource : String);
+    Property Execute: TSQLExecuteProcedureStatement Read FExecute;
+  Published
+    Procedure TestExecuteSimple;
+    Procedure TestExecuteSimpleTransaction;
+    Procedure TestExecuteSimpleReturningValues;
+    procedure TestExecuteSimpleReturning2Values;
+    procedure TestExecuteOneArg;
+    procedure TestExecuteOneArgNB;
+    procedure TestExecuteTwoArgs;
+    procedure TestExecuteTwoArgsNB;
+    procedure TestExecuteOneArgSelect;
+    procedure TestExecuteOneArgSelectNB;
+    procedure TestExecuteTwoArgsSelect;
+    procedure TestExecuteTwoArgsSelectNB;
+    procedure TestExecuteOneArgSelectErr;
+    procedure TestExecuteOneArgSelectErr2;
+    procedure TestExecuteOneArgSelectErr3;
+    procedure TestExecuteOneArgSelectErr4;
+  end;
+
+  { TTestConnectParser }
+
+  TTestConnectParser = Class(TTestSQLParser)
+  Private
+    FConnect : TSQLConnectStatement;
+    Function TestConnect(Const ASource : String) : TSQLConnectStatement;
+    Procedure TestConnectError(Const ASource : String);
+    Property Connect: TSQLConnectStatement Read FConnect;
+  Published
+    Procedure TestConnectSimple;
+    Procedure TestConnectUser;
+    procedure TestConnectPassword;
+    procedure TestConnectUserPassword;
+    procedure TestConnectUserPasswordRole;
+    procedure TestConnectUserPasswordRoleCache;
+    procedure TestConnectSimpleCache;
+  end;
+
+  { TTestCreateDatabaseParser }
+
+  TTestCreateDatabaseParser = Class(TTestSQLParser)
+  Private
+    FCreateDB : TSQLCreateDatabaseStatement;
+    Function TestCreate(Const ASource : String) : TSQLCreateDatabaseStatement;
+    Procedure TestCreateError(Const ASource : String);
+    Property CreateDB : TSQLCreateDatabaseStatement Read FCreateDB;
+  published
+    Procedure TestSimple;
+    procedure TestSimpleSchema;
+    procedure TestSimpleUSer;
+    procedure TestSimpleUSerPassword;
+    procedure TestSimplePassword;
+    procedure TestPageSize;
+    procedure TestPageSize2;
+    procedure TestPageSizeLength;
+    procedure TestPageSizeLength2;
+    procedure TestPageSizeLength3;
+    procedure TestPageSizeLength4;
+    procedure TestCharset;
+    procedure TestSecondaryFile1;
+    procedure TestSecondaryFile2;
+    procedure TestSecondaryFile3;
+    procedure TestSecondaryFile4;
+    procedure TestSecondaryFile5;
+    procedure TestSecondaryFile6;
+    procedure TestSecondaryFile7;
+    procedure TestSecondaryFile8;
+    procedure TestSecondaryFile9;
+    procedure TestSecondaryFile10;
+    procedure TestSecondaryFileS;
+    procedure TestSecondaryFileError1;
+    procedure TestSecondaryFileError2;
+    procedure TestSecondaryFileError3;
+  end;
+
+  { TTestAlterDatabaseParser }
+
+  TTestAlterDatabaseParser = Class(TTestSQLParser)
+  Private
+    FAlterDB : TSQLAlterDatabaseStatement;
+    Function TestAlter(Const ASource : String) : TSQLAlterDatabaseStatement;
+    Procedure TestAlterError(Const ASource : String);
+    Property AlterDB : TSQLAlterDatabaseStatement Read FAlterDB;
+  published
+    Procedure TestSimple;
+    procedure TestLength;
+    procedure TestStarting;
+    procedure TestStartingLength;
+    procedure TestFiles;
+    procedure TestFiles2;
+    procedure TestError;
+    procedure TestFilesError;
+  end;
+
+  { TTestCreateViewParser }
+
+  TTestCreateViewParser = Class(TTestSQLParser)
+  Private
+    FView : TSQLCreateViewStatement;
+    Function TestCreate(Const ASource : String) : TSQLCreateViewStatement;
+    Procedure TestCreateError(Const ASource : String);
+    Property View : TSQLCreateViewStatement Read FView;
+  Published
+    Procedure TestSimple;
+    procedure TestFieldList;
+    procedure TestFieldList2;
+    procedure TestSimpleWithCheckoption;
+  end;
+
+  { TTestCreateShadowParser }
+
+  TTestCreateShadowParser = Class(TTestSQLParser)
+  Private
+    FShadow : TSQLCreateShadowStatement;
+    Function TestCreate(Const ASource : String) : TSQLCreateShadowStatement;
+    Procedure TestCreateError(Const ASource : String);
+    Property Shadow : TSQLCreateShadowStatement Read FShadow;
+  published
+    Procedure TestSimple;
+    procedure TestLength;
+    procedure TestLength2;
+    procedure TestLength3;
+    procedure TestLength4;
+    procedure TestSecondaryFile1;
+    procedure TestSecondaryFile2;
+    procedure TestSecondaryFile3;
+    procedure TestSecondaryFile4;
+    procedure TestSecondaryFile5;
+    procedure TestSecondaryFile6;
+    procedure TestSecondaryFile7;
+    procedure TestSecondaryFile8;
+    procedure TestSecondaryFileS;
+  end;
+
+  { TTestProcedureStatement }
+
+  TTestProcedureStatement = Class(TTestSQLParser)
+  Private
+    FStatement : TSQLStatement;
+    procedure TestParseStatementError;
+    Function TestStatement(Const ASource : String) : TSQLStatement;
+    Procedure TestStatementError(Const ASource : String);
+    Property Statement : TSQLStatement Read FStatement;
+  Published
+    Procedure TestException;
+    Procedure TestExceptionError;
+    Procedure TestExit;
+    procedure TestSuspend;
+    procedure TestEmptyBlock;
+    procedure TestExitBlock;
+    procedure TestExitBlockError;
+    procedure TestPostEvent;
+    procedure TestPostEventColName;
+    procedure TestPostError;
+    procedure TestAssignSimple;
+    procedure TestAssignSimpleNew;
+    procedure TestAssignSelect;
+    procedure TestBlockAssignSimple;
+    procedure TestIf;
+    procedure TestIfBlock;
+    procedure TestIfElse;
+    procedure TestIfBlockElse;
+    procedure TestIfElseError;
+    procedure TestIfBlockElseBlock;
+    procedure TestIfErrorBracketLeft;
+    procedure TestIfErrorBracketRight;
+    procedure TestIfErrorNoThen;
+    procedure TestIfErrorSemicolonElse;
+    procedure TestWhile;
+    procedure TestWhileBlock;
+    procedure TestWhileErrorBracketLeft;
+    procedure TestWhileErrorBracketRight;
+    procedure TestWhileErrorNoDo;
+    procedure TestWhenAny;
+    procedure TestWhenSQLCode;
+    procedure TestWhenGDSCode;
+    procedure TestWhenException;
+    procedure TestWhenExceptionGDS;
+    procedure TestWhenAnyBlock;
+    procedure TestWhenErrorAny;
+    procedure TestWhenErrorNoDo;
+    procedure TestWhenErrorExceptionInt;
+    procedure TestWhenErrorExceptionString;
+    procedure TestWhenErrorSqlCode;
+    procedure TestWhenErrorGDSCode;
+    procedure TestExecuteStatement;
+    procedure TestExecuteStatementReturningValues;
+    procedure TestExecuteStatementReturningValuesColon;
+    procedure TestExecuteStatementReturningValuesBrackets;
+    procedure TestForSimple;
+    procedure TestForSimpleNoColon;
+    procedure TestForSimple2fields;
+    procedure TestForBlock;
+  end;
+
+  { TTestCreateProcedureParser }
+
+  TTestCreateProcedureParser = Class(TTestSQLParser)
+  Private
+    FStatement : TSQLCreateProcedureStatement;
+    Function TestCreate(Const ASource : String) : TSQLCreateProcedureStatement;
+    Procedure TestCreateError(Const ASource : String);
+    Property Statement : TSQLCreateProcedureStatement Read FStatement;
+  Published
+    Procedure TestEmptyProcedure;
+    procedure TestExitProcedure;
+    procedure TestProcedureOneArgument;
+    procedure TestProcedureTwoArguments;
+    procedure TestProcedureOneReturnValue;
+    procedure TestProcedureTwoReturnValues;
+    procedure TestProcedureOneLocalVariable;
+    procedure TestProcedureTwoLocalVariable;
+    procedure TestProcedureInputOutputLocal;
+  end;
+
+  { TTestCreateTriggerParser }
+
+  TTestCreateTriggerParser = Class(TTestSQLParser)
+  Private
+    FStatement : TSQLAlterCreateTriggerStatement;
+    Function TestCreate(Const ASource : String) : TSQLCreateTriggerStatement;
+    Function TestAlter(Const ASource : String) : TSQLAlterTriggerStatement;
+    Procedure TestCreateError(Const ASource : String);
+    Property Statement : TSQLAlterCreateTriggerStatement Read FStatement;
+  Published
+    Procedure TestEmptyTrigger;
+    Procedure TestExitTrigger;
+    procedure TestEmptyTriggerAfterUpdate;
+    procedure TestEmptyTriggerBeforeDelete;
+    procedure TestEmptyTriggerBeforeInsert;
+    procedure TestEmptyTriggerBeforeInsertPosition1;
+    procedure TestEmptyTriggerBeforeInsertPosition1inActive;
+    procedure TestEmptyTriggerBeforeInsertPosition1Active;
+    procedure TestTriggerOneLocalVariable;
+    procedure TestTriggerTwoLocalVariables;
+    procedure TestAlterTrigger;
+  end;
+
+  { TTestDeclareExternalFunctionParser }
+
+  TTestDeclareExternalFunctionParser = Class(TTestSQLParser)
+  Private
+    FStatement : TSQLDeclareExternalFunctionStatement;
+    Function TestCreate(Const ASource : String) : TSQLDeclareExternalFunctionStatement;
+    Procedure TestCreateError(Const ASource : String);
+    Property Statement : TSQLDeclareExternalFunctionStatement Read FStatement;
+  Published
+    Procedure TestEmptyfunction;
+    Procedure TestEmptyfunctionByValue;
+    procedure TestCStringfunction;
+    procedure TestCStringFreeItfunction;
+    procedure TestOneArgumentFunction;
+    procedure TestTwoArgumentsFunction;
+  end;
+
+  { TTestGrantParser }
+
+  TTestGrantParser = Class(TTestSQLParser)
+  Private
+    FStatement : TSQLGrantStatement;
+    Function TestGrant(Const ASource : String) : TSQLGrantStatement;
+    Procedure TestGrantError(Const ASource : String);
+    Property Statement : TSQLGrantStatement Read FStatement;
+  Published
+    Procedure TestSimple;
+    Procedure Test2Operations;
+    Procedure TestDeletePrivilege;
+    Procedure TestUpdatePrivilege;
+    Procedure TestInsertPrivilege;
+    Procedure TestReferencePrivilege;
+    Procedure TestAllPrivileges;
+    Procedure TestAllPrivileges2;
+    Procedure TestUpdateColPrivilege;
+    Procedure TestUpdate2ColsPrivilege;
+    Procedure TestReferenceColPrivilege;
+    Procedure TestReference2ColsPrivilege;
+    Procedure TestUserPrivilege;
+    Procedure TestUserPrivilegeWithGrant;
+    procedure TestGroupPrivilege;
+    procedure TestProcedurePrivilege;
+    procedure TestViewPrivilege;
+    procedure TestTriggerPrivilege;
+    procedure TestPublicPrivilege;
+    Procedure TestExecuteToUser;
+    procedure TestExecuteToProcedure;
+    procedure TestRoleToUser;
+    procedure TestRoleToUserWithAdmin;
+    procedure TestRoleToPublic;
+    procedure Test2RolesToUser;
+  end;
+  { TTestGrantParser }
+
+  TTestRevokeParser = Class(TTestSQLParser)
+  Private
+    FStatement : TSQLRevokeStatement;
+    Function TestRevoke(Const ASource : String) : TSQLRevokeStatement;
+    Procedure TestRevokeError(Const ASource : String);
+    Property Statement : TSQLRevokeStatement Read FStatement;
+  Published
+    Procedure TestSimple;
+    Procedure Test2Operations;
+    Procedure TestDeletePrivilege;
+    Procedure TestUpdatePrivilege;
+    Procedure TestInsertPrivilege;
+    Procedure TestReferencePrivilege;
+    Procedure TestAllPrivileges;
+    Procedure TestAllPrivileges2;
+    Procedure TestUpdateColPrivilege;
+    Procedure TestUpdate2ColsPrivilege;
+    Procedure TestReferenceColPrivilege;
+    Procedure TestReference2ColsPrivilege;
+    Procedure TestUserPrivilege;
+    Procedure TestUserPrivilegeWithRevoke;
+    procedure TestGroupPrivilege;
+    procedure TestProcedurePrivilege;
+    procedure TestViewPrivilege;
+    procedure TestTriggerPrivilege;
+    procedure TestPublicPrivilege;
+    Procedure TestExecuteToUser;
+    procedure TestExecuteToProcedure;
+    procedure TestRoleToUser;
+    procedure TestRoleToPublic;
+    procedure Test2RolesToUser;
+  end;
+
+implementation
+
+uses typinfo;
+
+{ --------------------------------------------------------------------
+  TTestParser
+  --------------------------------------------------------------------}
+
+procedure TTestParser.ParseStringDef(Out DT: TSQLDataType; Out Len: Integer; Out ACharset : TSQLStringtype);
+begin
+  ParseCharTypeDefinition(DT,Len,ACharset);
+end;
+
+function TTestParser.ParseType(Flags: TParseTypeFlags): TSQLTypeDefinition;
+begin
+  Result:=ParseTypeDefinition(Nil,Flags);
+end;
+
+function TTestParser.ParseConstraint: TSQLExpression;
+begin
+//  GetNextToken;
+  Result:=ParseCheckConstraint(Nil);
+end;
+
+function TTestParser.ParseProcedureStatements: TSQLStatement;
+begin
+  Result:=Self.ParseProcedureStatement(Nil);
+end;
+
+{ --------------------------------------------------------------------
+  TTestSQLParser
+  --------------------------------------------------------------------}
+
+procedure TTestSQLParser.SetUp;
+begin
+
+end;
+
+procedure TTestSQLParser.TearDown;
+begin
+  FreeAndNil(FParser);
+  FreeAndNil(FSource);
+  FreeAndNil(FToFree);
+end;
+
+procedure TTestSQLParser.CreateParser(const ASource: string);
+begin
+  FSource:=TStringStream.Create(ASource);
+  FParser:=TTestParser.Create(FSource);
+end;
+
+Function TTestSQLParser.CheckClass(E: TSQLElement; C: TSQLElementClass) : TSQLElement;
+begin
+  AssertEquals(C,E.ClassType);
+  Result:=E;
+end;
+
+procedure TTestSQLParser.AssertEquals(const AMessage: String; Expected, Actual: TSQLToken);
+
+Var
+  NE,NA : String;
+
+begin
+  NE:=GetEnumName(TypeInfo(TSQLToken),Ord(Expected));
+  NA:=GetEnumName(TypeInfo(TSQLToken),Ord(Actual));
+  AssertEquals(AMessage,NE,NA);
+end;
+
+procedure TTestSQLParser.AssertEquals(const AMessage: String; Expected,
+  Actual: TSQLBinaryOperation);
+Var
+  NE,NA : String;
+
+begin
+  NE:=GetEnumName(TypeInfo(TSQLBinaryOperation),Ord(Expected));
+  NA:=GetEnumName(TypeInfo(TSQLBinaryOperation),Ord(Actual));
+  AssertEquals(AMessage,NE,NA);
+end;
+
+procedure TTestSQLParser.AssertEquals(const AMessage: String; Expected,
+  Actual: TSQLUnaryoperation);
+Var
+  NE,NA : String;
+
+begin
+  NE:=GetEnumName(TypeInfo(TSQLUnaryOperation),Ord(Expected));
+  NA:=GetEnumName(TypeInfo(TSQLUnaryOperation),Ord(Actual));
+  AssertEquals(AMessage,NE,NA);
+end;
+
+procedure TTestSQLParser.AssertEquals(const AMessage: String; Expected,
+  Actual: TSQLternaryoperation);
+Var
+  NE,NA : String;
+
+begin
+  NE:=GetEnumName(TypeInfo(TSQLTernaryOperation),Ord(Expected));
+  NA:=GetEnumName(TypeInfo(TSQLTernaryOperation),Ord(Actual));
+  AssertEquals(AMessage,NE,NA);
+end;
+
+procedure TTestSQLParser.AssertEquals(const AMessage: String; Expected, Actual: TSQLDataType);
+
+Var
+  NE,NA : String;
+
+begin
+  NE:=GetEnumName(TypeInfo(TSQLDataType),Ord(Expected));
+  NA:=GetEnumName(TypeInfo(TSQLDataType),Ord(Actual));
+  AssertEquals(AMessage,NE,NA);
+end;
+
+procedure TTestSQLParser.AssertEquals(const AMessage: String; Expected,
+  Actual: TForeignKeyAction);
+Var
+  NE,NA : String;
+
+begin
+  NE:=GetEnumName(TypeInfo(TForeignKeyAction),Ord(Expected));
+  NA:=GetEnumName(TypeInfo(TForeignKeyAction),Ord(Actual));
+  AssertEquals(AMessage,NE,NA);
+end;
+
+procedure TTestSQLParser.AssertEquals(const AMessage: String; Expected,
+  Actual: TSQLJoinType);
+Var
+  NE,NA : String;
+
+begin
+  NE:=GetEnumName(TypeInfo(TSQLJoinType),Ord(Expected));
+  NA:=GetEnumName(TypeInfo(TSQLJoinType),Ord(Actual));
+  AssertEquals(AMessage,NE,NA);
+end;
+
+procedure TTestSQLParser.AssertEquals(const AMessage: String; Expected,
+  Actual: TSQLAggregateFunction);
+Var
+  NE,NA : String;
+
+begin
+  NE:=GetEnumName(TypeInfo(TSQLAggregateFunction),Ord(Expected));
+  NA:=GetEnumName(TypeInfo(TSQLAggregateFunction),Ord(Actual));
+  AssertEquals(AMessage,NE,NA);
+end;
+
+procedure TTestSQLParser.AssertEquals(const AMessage: String; Expected,
+  Actual: TSQLAggregateOption);
+Var
+  NE,NA : String;
+
+begin
+  NE:=GetEnumName(TypeInfo(TSQLAggregateOption),Ord(Expected));
+  NA:=GetEnumName(TypeInfo(TSQLAggregateOption),Ord(Actual));
+  AssertEquals(AMessage,NE,NA);
+end;
+
+procedure TTestSQLParser.AssertEquals(const AMessage: String; Expected,
+  Actual: TSQLOrderDirection);
+
+Var
+  NE,NA : String;
+
+begin
+  NE:=GetEnumName(TypeInfo(TSQLOrderDirection),Ord(Expected));
+  NA:=GetEnumName(TypeInfo(TSQLOrderDirection),Ord(Actual));
+  AssertEquals(AMessage,NE,NA);
+end;
+
+procedure TTestSQLParser.AssertEquals(const AMessage: String; Expected,
+  Actual: TPlanJoinType);
+Var
+  NE,NA : String;
+
+begin
+  NE:=GetEnumName(TypeInfo(TPlanJoinType),Ord(Expected));
+  NA:=GetEnumName(TypeInfo(TPlanJoinType),Ord(Actual));
+  AssertEquals(AMessage,NE,NA);
+end;
+
+procedure TTestSQLParser.AssertEquals(const AMessage: String; Expected,
+  Actual: TTriggerMoment);
+Var
+  NE,NA : String;
+
+begin
+  NE:=GetEnumName(TypeInfo(TTriggerMoment),Ord(Expected));
+  NA:=GetEnumName(TypeInfo(TTriggerMoment),Ord(Actual));
+  AssertEquals(AMessage,NE,NA);
+end;
+
+procedure TTestSQLParser.AssertEquals(const AMessage: String; Expected,
+  Actual: TTriggerState);
+Var
+  NE,NA : String;
+
+begin
+  NE:=GetEnumName(TypeInfo(TTriggerState),Ord(Expected));
+  NA:=GetEnumName(TypeInfo(TTriggerState),Ord(Actual));
+  AssertEquals(AMessage,NE,NA);
+end;
+
+procedure TTestSQLParser.AssertEquals(const AMessage: String; Expected,
+  Actual: TTriggerOperations);
+Var
+  NE,NA : String;
+
+begin
+  If Expected<>Actual then
+    Fail(Amessage)
+end;
+
+Function TTestSQLParser.AssertLiteralExpr(const AMessage: String;
+  Element: TSQLExpression; ALiteralClass: TSQLElementClass) : TSQLLiteral;
+begin
+  CheckClass(Element,TSQLLiteralExpression);
+  Result:=TSQLLiteral(Checkclass(TSQLLiteralExpression(Element).Literal,ALiteralClass));
+end;
+
+procedure TTestSQLParser.AssertIdentifierName(const AMessage : String;
+  const AExpected: String; Element: TSQLElement);
+begin
+  AssertNotNull(AMessage+': Have identifier ',Element);
+  CheckClass(Element,TSQLidentifierName);
+  AssertEquals(AMessage+': Correct identifier name',AExpected,TSQLidentifierName(Element).Name);
+end;
+
+procedure TTestSQLParser.AssertField(AField: TSQLElement; const AName: String;
+  const AAlias: String);
+
+Var
+  F : TSQLSelectField;
+  E : TSQLidentifierExpression;
+
+begin
+  AssertNotNull('Have field',AField);
+  F:=TSQLSelectField(CheckClass(AField,TSQLSelectField));
+  AssertNotNull('Have field expresssion,',F.Expression);
+  E:=TSQLidentifierExpression(CheckClass(F.Expression,TSQLidentifierExpression));
+  AssertIdentifierName('Correct field name',AName,E.Identifier);
+  If (AAlias<>'') then
+    AssertIdentifierName('Correct alias',AALias,F.AliasName);
+end;
+
+procedure TTestSQLParser.AssertAggregate(AField: TSQLElement;
+  AAgregate: TSQLAggregateFunction; const AFieldName: String;
+  AOption: TSQLAggregateOption; const AAlias: String);
+Var
+  F : TSQLSelectField;
+
+begin
+  AssertNotNull('Have field',AField);
+  F:=TSQLSelectField(CheckClass(AField,TSQLSelectField));
+  AssertNotNull('Have field expresssion,',F.Expression);
+  AssertAggregateExpression(F.Expression,AAgregate,AFieldName,AOption);
+  If (AAlias<>'') then
+    AssertIdentifierName('Correct alias',AALias,F.AliasName);
+end;
+
+procedure TTestSQLParser.AssertAggregateExpression(E: TSQLElement;
+  AAgregate: TSQLAggregateFunction; const AFieldName: String;
+  AOption: TSQLAggregateOption);
+
+Var
+  AF : TSQLAggregateFunctionExpression;
+  I : TSQLIdentifierExpression;
+
+begin
+  AF:=TSQLAggregateFunctionExpression(CheckClass(E,TSQLAggregateFunctionExpression));
+  AssertEquals('Correct function',AAgregate,AF.Aggregate);
+  AssertEquals('Correct function',AOption,AF.Option);
+  If (AFieldName<>'') then
+    begin
+    I:=TSQLIdentifierExpression(CheckClass(AF.Expression, TSQLIdentifierExpression));
+    AssertIdentifierName('Correct field name',AFieldName,I.Identifier);
+    end;
+end;
+
+procedure TTestSQLParser.AssertTable(ATable: TSQLElement; const AName: String;
+  const AAlias: String);
+Var
+  T : TSQLSimpleTablereference;
+
+begin
+  AssertNotNull('Have table',ATable);
+  T:=TSQLSimpleTablereference(CheckClass(ATable,TSQLSimpleTablereference));
+  AssertIdentifierName('Correct table name',AName,T.ObjectName);
+  If (AAlias<>'') then
+    AssertIdentifierName('Correct alias',AALias,T.AliasName);
+end;
+
+function TTestSQLParser.AssertJoin(AJoin: TSQLElement; const AFirst,
+  ASecond: String; const ajointype: TSQLJoinType):TSQLJoinTableReference;
+Var
+  J : TSQLJoinTableReference;
+
+begin
+  AssertNotNull('Have join',AJoin);
+  J:=TSQLJoinTableReference(CheckClass(AJoin,TSQLJoinTableReference));
+  if (AFirst<>'') then
+    AssertTable(J.Left,AFirst,'');
+  if (ASecond<>'') then
+    AssertTable(J.Right,ASecond,'');
+  AssertEquals('Correct join type',AJoinType,J.JoinType);
+  Result:=J;
+end;
+
+function TTestSQLParser.AssertJoinOn(AJoin: TSQLExpression; const AFirst,
+  ASecond: String; const AOperation: TSQLBinaryOperation): TSQLBinaryExpression;
+
+Var
+  I : TSQLIdentifierExpression;
+
+begin
+  Result:=TSQLBinaryExpression(CheckClass(AJoin,TSQLBinaryExpression));
+  AssertEquals('Correct ON operation',AOperation,Result.Operation);
+  I:=TSQLIdentifierExpression(CheckClass(Result.Left,TSQLIdentifierExpression));
+  AssertIdentifierName('Left field name',AFirst,I.Identifier);
+  I:=TSQLIdentifierExpression(CheckClass(Result.Right,TSQLIdentifierExpression));
+  AssertIdentifierName('Right field name',ASecond,I.Identifier);
+end;
+
+function TTestSQLParser.AssertOrderBy(AOrderBy: TSQLElement;
+  const AField: String; const ANumber: Integer; const AOrdering: TSQLOrderDirection
+  ): TSQLOrderByElement;
+
+Var
+  I : TSQLIntegerLiteral;
+
+begin
+  Result:=TSQLOrderByElement(CheckClass(AorderBy,TSQLOrderByElement));
+  If (AField<>'') then
+    AssertIdentifierName('Correct order by field',AField,Result.Field)
+  else if (ANumber>0) then
+    begin
+    I:=TSQLIntegerLiteral(CheckClass(Result.Field,TSQLIntegerLiteral));
+    AssertEquals('Correct order by column number',ANumber,I.Value);
+    end;
+  AssertEquals('Correct ordering',AOrdering,Result.OrderBy);
+end;
+
+function TTestSQLParser.AssertSecondaryFile(ASecondaryFile: TSQLElement;
+  const AFile: String; const ALength, AStart: Integer): TSQLDatabaseFileInfo;
+begin
+  Result:=TSQLDatabaseFileInfo(CheckClass(ASecondaryFile,TSQLDatabaseFileInfo));
+  AssertEquals('Secondary file name',AFile,Result.FileName);
+  AssertEquals('Secondary file length',ALength,Result.Length);
+  AssertEquals('Secondary file start',AStart,Result.StartPage);
+end;
+
+procedure TTestSQLParser.TestTypeError;
+
+begin
+  TestType(FErrSource,[],sdtInteger);
+end;
+
+procedure TTestSQLParser.TestStringError;
+
+begin
+  TestStringDef(FErrSource,sdtchar,0);
+end;
+
+procedure TTestSQLParser.TestCheckError;
+begin
+  TestCheck(FErrSource,TSQLExpression);
+end;
+
+procedure TTestSQLParser.TestParseError;
+begin
+  CreateParser(FErrSource);
+  FToFree:=Parser.Parse;
+end;
+
+Procedure TTestSQLParser.TestStringDef(ASource : String; ExpectDT : TSQLDataType; ExpectLen : Integer; ExpectCharset : TSQLStringType='');
+
+Var
+  Dt : TSQLDataType;
+  L : integer;
+  cs : TSQLStringType;
+begin
+  CreateParser(ASOURCE);
+  Parser.GetNextToken;
+  Parser.ParseStringDef(dt,l,cs);
+  AssertEquals('Datatype is CHAR',ExpectDT,Dt);
+  AssertEquals('Length is 1',ExpectLen,l);
+  AssertEquals('End of Stream reached',tsqlEOF,Parser.CurrentToken);
+  AssertEquals('Correct character set',ExpectCharset,CS);
+end;
+
+
+Function TTestSQLParser.TestType(ASource : string; AFlags : TParseTypeFlags; AExpectedType : TSQLDataType) : TSQLTypeDefinition;
+
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.ParseType(AFlags);
+  AssertNotNull('ParseType returns result',FToFree);
+  CheckClass(FTofree,TSQLTypeDefinition);
+  Result:=TSQLTypeDefinition(FToFree);
+  AssertEquals('Type definition has correct data type',AExpectedType,Result.Datatype);
+end;
+
+function TTestSQLParser.TestCheck(ASource: string; AExpectedConstraint: TSQLElementClass
+  ): TSQLExpression;
+begin
+  CreateParser('('+ASource+')');
+  FToFree:=Parser.ParseConstraint();
+  AssertNotNull('ParseType returns result',FToFree);
+  CheckClass(FTofree,AExpectedConstraint);
+  Result:=TSQLExpression(FToFree);
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestSQLParser.AssertTypeDefaults(TD : TSQLTypeDefinition;Len : Integer = 0);
+
+begin
+  AssertNull(TD.DefaultValue);
+  AssertNull(TD.Check);
+  AssertNull(TD.Collation);
+  AssertEquals('Array dim 0',0,TD.ArrayDim);
+  AssertEquals('Blob type 0',0,TD.BlobType);
+  AssertEquals('Not required',False,TD.NotNull);
+  AssertEquals('Length',Len,TD.Len);
+end;
+
+procedure TTestSQLParser.TestDropStatement(const ASource: string;
+  C: TSQLElementClass);
+
+Var
+  D : TSQLDropStatement;
+begin
+  If ASOURCE='SHADOW' then
+    CreateParser('DROP '+ASource+' 1')
+  else
+    CreateParser('DROP '+ASource+' A');
+  FToFree:=Parser.Parse;
+  AssertNotNull('Parse returns result',FTofree);
+  If Not FToFree.InheritsFrom(TSQLDropStatement) then
+    Fail('Drop statement is not of type TSQLDropStatement');
+  CheckClass(FToFree ,C);
+  D:=TSQLDropStatement(FToFree);
+  If ASOURCE='SHADOW' then
+    AssertIdentifierName('object name','1',D.ObjectName)
+  else
+    AssertIdentifierName('object name','A',D.ObjectName);
+end;
+
+function TTestSQLParser.TestCreateStatement(const ASource,AName: string;
+  C: TSQLElementClass): TSQLCreateOrAlterStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  AssertNotNull('Parse returns result',FTofree);
+  If Not FToFree.InheritsFrom(TSQLCreateOrAlterStatement) then
+    Fail('create statement is not of type TSQLCreateOrAlterStatement');
+  CheckClass(FToFree ,C);
+  Result:=TSQLCreateOrAlterStatement(FToFree);
+  AssertIdentifierName('Correct identifier',AName,Result.ObjectName);
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+
+
+{ --------------------------------------------------------------------
+  TTestDropParser
+  --------------------------------------------------------------------}
+
+procedure TTestDropParser.TestDropDatabase;
+
+begin
+  TestDropStatement('DATABASE',TSQLDropDatabaseStatement);
+end;
+
+procedure TTestDropParser.TestDropDomain;
+
+begin
+  TestDropStatement('DOMAIN',TSQLDropDomainStatement);
+end;
+
+procedure TTestDropParser.TestDropException;
+begin
+  TestDropStatement('EXCEPTION',TSQLDropExceptionStatement);
+end;
+
+procedure TTestDropParser.TestDropGenerator;
+
+begin
+  TestDropStatement('GENERATOR',TSQLDropGeneratorStatement);
+end;
+
+procedure TTestDropParser.TestDropIndex;
+
+begin
+  TestDropStatement('INDEX',TSQLDropIndexStatement);
+end;
+
+procedure TTestDropParser.TestDropProcedure;
+
+begin
+  TestDropStatement('PROCEDURE',TSQLDropProcedureStatement);
+end;
+
+procedure TTestDropParser.TestDropRole;
+begin
+  TestDropStatement('ROLE',TSQLDropRoleStatement);
+end;
+
+procedure TTestDropParser.TestDropTable;
+
+begin
+  TestDropStatement('TABLE',TSQLDropTableStatement);
+end;
+
+procedure TTestDropParser.TestDropTrigger;
+
+begin
+  TestDropStatement('TRIGGER',TSQLDropTriggerStatement);
+end;
+
+procedure TTestDropParser.TestDropView;
+
+begin
+  TestDropStatement('VIEW',TSQLDropViewStatement);
+end;
+
+procedure TTestDropParser.TestDropShadow;
+begin
+  TestDropStatement('SHADOW',TSQLDropShadowStatement);
+end;
+
+procedure TTestDropParser.TestDropExternalFunction;
+begin
+  TestDropStatement('EXTERNAL FUNCTION',TSQLDropExternalFunctionStatement);
+
+end;
+
+{ --------------------------------------------------------------------
+  TTestGeneratorParser
+  --------------------------------------------------------------------}
+
+
+procedure TTestGeneratorParser.TestCreateGenerator;
+
+begin
+  TestCreateStatement('CREATE GENERATOR A','A',TSQLCreateGeneratorStatement);
+end;
+
+procedure TTestGeneratorParser.TestSetGenerator;
+
+Var
+  S : TSQLSetGeneratorStatement;
+
+begin
+  CreateParser('SET GENERATOR A TO 1');
+  FToFree:=Parser.Parse;
+  S:=TSQLSetGeneratorStatement(CheckClass(FToFree,TSQLSetGeneratorStatement));
+  AssertIdentifierName('Correct generator name','A',S.Objectname);
+  AssertEquals('New value',1,S.NewValue);
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+{ --------------------------------------------------------------------
+  TTestTypeParser
+  --------------------------------------------------------------------}
+
+procedure TTestTypeParser.TestStringType1;
+
+begin
+  TestStringDef('CHAR(1)',sdtChar,1);
+end;
+
+procedure TTestTypeParser.TestStringType2;
+
+begin
+  TestStringDef('CHAR',sdtChar,0);
+end;
+
+procedure TTestTypeParser.TestStringType3;
+
+begin
+  TestStringDef('CHARACTER',sdtChar,0);
+end;
+
+procedure TTestTypeParser.TestStringType4;
+
+begin
+  TestStringDef('CHARACTER VARYING',sdtVarChar,0);
+end;
+
+procedure TTestTypeParser.TestStringType5;
+
+begin
+  TestStringDef('VARCHAR',sdtVarChar,0);
+end;
+
+procedure TTestTypeParser.TestStringType6;
+
+begin
+  TestStringDef('VARCHAR(2)',sdtVarChar,2);
+end;
+
+procedure TTestTypeParser.TestStringType7;
+
+begin
+  TestStringDef('CHARACTER VARYING (2)',sdtVarChar,2);
+end;
+
+procedure TTestTypeParser.TestStringType8;
+
+begin
+  TestStringDef('NATIONAL CHARACTER VARYING (2)',sdtNVarChar,2);
+end;
+
+procedure TTestTypeParser.TestStringType9;
+
+begin
+  TestStringDef('NATIONAL CHARACTER (2)',sdtNChar,2);
+end;
+
+procedure TTestTypeParser.TestStringType10;
+
+begin
+  TestStringDef('NATIONAL CHARACTER',sdtNChar,0);
+end;
+
+procedure TTestTypeParser.TestStringType11;
+
+begin
+  TestStringDef('NATIONAL CHARACTER VARYING',sdtNVarChar,0);
+end;
+
+procedure TTestTypeParser.TestStringType12;
+
+begin
+  TestStringDef('NCHAR',sdtNChar,0);
+end;
+
+procedure TTestTypeParser.TestStringType13;
+
+begin
+  TestStringDef('NCHAR(2)',sdtNChar,2);
+end;
+
+
+procedure TTestTypeParser.TestStringType14;
+
+begin
+  TestStringDef('NCHAR VARYING(2)',sdtNVarChar,2);
+end;
+
+procedure TTestTypeParser.TestStringType15;
+begin
+  TestStringDef('CHAR (15) CHARACTER SET UTF8',sdtChar,15,'UTF8');
+end;
+
+procedure TTestTypeParser.TestStringType16;
+begin
+  TestStringDef('CHAR VARYING (15) CHARACTER SET UTF8',sdtVarChar,15,'UTF8');
+end;
+
+procedure TTestTypeParser.TestStringType17;
+begin
+  TestStringDef('CHAR VARYING CHARACTER SET UTF8',sdtVarChar,0,'UTF8');
+end;
+
+procedure TTestTypeParser.TestStringType18;
+begin
+  TestStringDef('CHARACTER CHARACTER SET UTF8',sdtChar,0,'UTF8');
+end;
+
+procedure TTestTypeParser.TestStringType19;
+
+Var
+  T : TSQLTypeDefinition;
+
+begin
+  T:=TestType('CHAR(10) COLLATE UTF8',[],sdtChar);
+  AssertNotNull('Have collation',T.Collation);
+  AssertEquals('Correct collation','UTF8',T.Collation.Name);
+end;
+
+procedure TTestTypeParser.TestStringTypeErrors1;
+begin
+  FErrSource:='VARCHAR VARYING';
+  AssertException(ESQLParser,@TestStringError);
+end;
+
+procedure TTestTypeParser.TestStringTypeErrors2;
+begin
+  FErrSource:='CHAR(A)';
+  AssertException(ESQLParser,@TestStringError);
+end;
+
+procedure TTestTypeParser.TestStringTypeErrors3;
+begin
+  FErrSource:='CHAR(1]';
+  AssertException(ESQLParser,@TestStringError);
+end;
+
+
+procedure TTestTypeParser.TestTypeInt1;
+
+Var
+  TD : TSQLTypeDefinition;
+
+begin
+  TD:=TestType('INT',[],sdtInteger);
+  AssertTypeDefaults(TD);
+end;
+
+procedure TTestTypeParser.TestTypeInt2;
+
+Var
+  TD : TSQLTypeDefinition;
+
+begin
+  TD:=TestType('INT DEFAULT NULL',[],sdtInteger);
+  AssertNotNull('Have Default value',TD.DefaultValue);
+  CheckClass(TD.DefaultValue,TSQLNullLiteral);
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestTypeParser.TestTypeInt3;
+
+Var
+  TD : TSQLTypeDefinition;
+
+begin
+  TD:=TestType('INT DEFAULT 1',[],sdtInteger);
+  AssertNotNull('Have Default value',TD.DefaultValue);
+  CheckClass(TD.DefaultValue,TSQLIntegerLiteral);
+  AssertEquals('Correct default value ',1,TSQLIntegerLiteral(TD.DefaultValue).Value);
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestTypeParser.TestTypeInt4;
+
+Var
+  TD : TSQLTypeDefinition;
+
+begin
+  TD:=TestType('INT NOT NULL',[],sdtInteger);
+  AssertNull('No Default value',TD.DefaultValue);
+  AssertEquals('Required field',True,TD.NotNull);
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestTypeParser.TestTypeInt5;
+
+Var
+  TD : TSQLTypeDefinition;
+
+begin
+  TD:=TestType('INT [3]',[],sdtInteger);
+  AssertEquals('Array of length 3',3,TD.ArrayDim);
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestTypeParser.TestNumerical1;
+Var
+  TD : TSQLTypeDefinition;
+
+begin
+  TD:=TestType('NUMERIC (10)',[],sdtNumeric);
+  AssertEquals('Correct length',10,TD.Len);
+end;
+
+procedure TTestTypeParser.TestNumerical2;
+Var
+  TD : TSQLTypeDefinition;
+
+begin
+  TD:=TestType('NUMERIC (10,3)',[],sdtNumeric);
+  AssertEquals('Correct length',10,TD.Len);
+  AssertEquals('Correct scale',3,TD.Scale);
+end;
+
+procedure TTestTypeParser.TestNumerical3;
+Var
+  TD : TSQLTypeDefinition;
+
+begin
+  TD:=TestType('NUMERIC',[],sdtNumeric);
+  AssertEquals('Correct length',0,TD.Len);
+  AssertEquals('Correct scale',0,TD.Scale);
+end;
+
+procedure TTestTypeParser.TestNumericalError1;
+
+begin
+  FErrSource:='NUMERIC ()';
+  AssertException(ESQLParser,@TestTypeError);
+end;
+
+procedure TTestTypeParser.TestNumericalError2;
+
+begin
+  FErrSource:='NUMERIC (A)';
+  AssertException(ESQLParser,@TestTypeError);
+end;
+
+procedure TTestTypeParser.TestNumericalError3;
+
+begin
+  FErrSource:='NUMERIC (,1)';
+  AssertException(ESQLParser,@TestTypeError);
+end;
+
+procedure TTestTypeParser.TestNumericalError4;
+
+begin
+  FErrSource:='NUMERIC (1,)';
+  AssertException(ESQLParser,@TestTypeError);
+end;
+
+procedure TTestTypeParser.TestNumericalError5;
+begin
+  FErrSource:='NUMERIC (1';
+  AssertException(ESQLParser,@TestTypeError);
+end;
+
+procedure TTestTypeParser.TestNumericalError6;
+begin
+  FErrSource:='NUMERIC (1,';
+  AssertException(ESQLParser,@TestTypeError);
+end;
+
+procedure TTestTypeParser.TestNumericalError7;
+begin
+  FErrSource:='NUMERIC (1 NOT';
+  AssertException(ESQLParser,@TestTypeError);
+end;
+
+procedure TTestTypeParser.TestBlob1;
+Var
+  TD : TSQLTypeDefinition;
+
+begin
+  TD:=TestType('BLOB sub_type 1 SEGMENT SIZE 80 CHARACTER SET UTF8',[],sdtBlob);
+  AssertEquals('Blob type 1',1,TD.BlobType);
+  AssertEquals('Blob segment size',80,TD.Len);
+  AssertEquals('Character set','UTF8',TD.Charset);
+
+end;
+
+procedure TTestTypeParser.TestBlob2;
+Var
+  TD : TSQLTypeDefinition;
+
+begin
+  TD:=TestType('BLOB (80,1) CHARACTER SET UTF8',[],sdtBlob);
+  AssertEquals('Blob type 1',1,TD.BlobType);
+  AssertEquals('Blob segment size',80,TD.Len);
+  AssertEquals('Character set','UTF8',TD.Charset);
+end;
+
+procedure TTestTypeParser.TestBlob3;
+Var
+  TD : TSQLTypeDefinition;
+
+begin
+  TD:=TestType('BLOB SEGMENT SIZE 80',[],sdtBlob);
+  AssertEquals('Blob type 0',0,TD.BlobType);
+  AssertEquals('Blob segment size',80,TD.Len);
+  AssertEquals('Character set','',TD.Charset);
+end;
+
+procedure TTestTypeParser.TestBlob4;
+Var
+  TD : TSQLTypeDefinition;
+
+begin
+  TD:=TestType('BLOB SUB_TYPE 1',[],sdtBlob);
+  AssertEquals('Blob type 1',1,TD.BlobType);
+  AssertEquals('Blob segment size',0,TD.Len);
+  AssertEquals('Character set','',TD.Charset);
+end;
+
+procedure TTestTypeParser.TestBlob5;
+Var
+  TD : TSQLTypeDefinition;
+
+begin
+  TD:=TestType('BLOB (80)',[],sdtBlob);
+  AssertEquals('Blob type 0',0,TD.BlobType);
+  AssertEquals('Blob segment size',80,TD.Len);
+  AssertEquals('Character set','',TD.Charset);
+end;
+
+procedure TTestTypeParser.TestBlob6;
+Var
+  TD : TSQLTypeDefinition;
+
+begin
+  TD:=TestType('BLOB',[],sdtBlob);
+  AssertEquals('Blob type 0',0,TD.BlobType);
+  AssertEquals('Blob segment size',0,TD.Len);
+  AssertEquals('Character set','',TD.Charset);
+end;
+procedure TTestTypeParser.TestSmallInt;
+
+Var
+  TD : TSQLTypeDefinition;
+begin
+  TD:=TestType('SMALLINT',[],sdtSmallint);
+end;
+
+procedure TTestTypeParser.TestFloat;
+Var
+  TD : TSQLTypeDefinition;
+begin
+  TD:=TestType('FLOAT',[],sdtFloat);
+end;
+
+procedure TTestTypeParser.TestBlobError1;
+begin
+  FerrSource:='BLOB (1,)';
+  AssertException(ESQLParser,@TestTypeError);
+end;
+
+procedure TTestTypeParser.TestBlobError2;
+begin
+  FerrSource:='BLOB 1,)';
+  // EAssertionfailed, due to not EOF
+  AssertException(EAssertionFailedError,@TestTypeError);
+end;
+
+procedure TTestTypeParser.TestBlobError3;
+begin
+  FerrSource:='BLOB (80) SUB_TYPE 3';
+  AssertException(ESQLParser,@TestTypeError);
+end;
+
+procedure TTestTypeParser.TestBlobError4;
+begin
+  FerrSource:='BLOB CHARACTER UTF8';
+  AssertException(ESQLParser,@TestTypeError);
+end;
+
+procedure TTestTypeParser.TestBlobError5;
+begin
+  FerrSource:='BLOB (80) SEGMENT SIZE 80';
+  AssertException(ESQLParser,@TestTypeError);
+end;
+
+procedure TTestTypeParser.TestBlobError6;
+begin
+  FerrSource:='BLOB (A)';
+  AssertException(ESQLParser,@TestTypeError);
+end;
+
+procedure TTestTypeParser.TestBlobError7;
+begin
+  FerrSource:='BLOB (1';
+  AssertException(ESQLParser,@TestTypeError);
+end;
+
+
+{ --------------------------------------------------------------------
+  TTestCheckParser
+  --------------------------------------------------------------------}
+
+procedure TTestCheckParser.TestCheckNotNull;
+
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=TSQLBinaryExpression(TestCheck('VALUE IS NOT NULL',TSQLBinaryExpression));
+  AssertEquals('IS NOT operator,',boISNot,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is null',B.Right,TSQLNullLiteral);
+end;
+
+procedure TTestCheckParser.TestCheckNull;
+
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=TSQLBinaryExpression(TestCheck('VALUE IS NULL',TSQLBinaryExpression));
+  AssertEquals('IS operator,',boIS,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is null',B.Right,TSQLNullLiteral);
+end;
+
+procedure TTestCheckParser.TestCheckBraces;
+
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=TSQLBinaryExpression(TestCheck('(VALUE IS NULL)',TSQLBinaryExpression));
+  AssertEquals('IS operator,',boIS,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is null',B.Right,TSQLNullLiteral);
+end;
+
+procedure TTestCheckParser.TestCheckBracesError;
+
+begin
+  FErrSource:='(VALUE IS NOT NULL ME )';
+  AssertException('Error in braces.', ESQLParser,@TestCheckError);
+end;
+
+procedure TTestCheckParser.TestCheckParamError;
+begin
+  FErrSource:='VALUE <> :P';
+  AssertException('Parameter.', ESQLParser,@TestCheckError);
+end;
+
+procedure TTestCheckParser.TestCheckIdentifierError;
+
+begin
+  FErrSource:='(X IS NOT NULL)';
+  AssertException('Error in check: identifier.', ESQLParser,@TestCheckError);
+end;
+
+procedure TTestCheckParser.TestIsEqual;
+
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=TSQLBinaryExpression(TestCheck('VALUE = 3',TSQLBinaryExpression));
+  AssertEquals('Equal operator',boEq,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is integer',B.Right,TSQLIntegerLiteral);
+end;
+
+procedure TTestCheckParser.TestIsNotEqual1;
+
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=TSQLBinaryExpression(TestCheck('VALUE <> 3',TSQLBinaryExpression));
+  AssertEquals('Not Equal operator',boNE,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is integer',B.Right,TSQLIntegerLiteral);
+end;
+
+procedure TTestCheckParser.TestIsNotEqual2;
+
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=TSQLBinaryExpression(TestCheck('VALUE != 3',TSQLBinaryExpression));
+  AssertEquals('ENot qual operator',boNE,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is integer',B.Right,TSQLIntegerLiteral);
+end;
+
+procedure TTestCheckParser.TestGreaterThan;
+
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=TSQLBinaryExpression(TestCheck('VALUE > 3',TSQLBinaryExpression));
+  AssertEquals('Greater than operator',boGT,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is integer',B.Right,TSQLIntegerLiteral);
+end;
+
+procedure TTestCheckParser.TestGreaterThanEqual1;
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=TSQLBinaryExpression(TestCheck('VALUE >= 3',TSQLBinaryExpression));
+  AssertEquals('Greater or Equal operator',boGE,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is integer',B.Right,TSQLIntegerLiteral);
+end;
+
+procedure TTestCheckParser.TestGreaterThanEqual2;
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=TSQLBinaryExpression(TestCheck('VALUE !< 3',TSQLBinaryExpression));
+  AssertEquals('Greater or Equal operator',boGE,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is integer',B.Right,TSQLIntegerLiteral);
+end;
+
+procedure TTestCheckParser.TestLessThan;
+
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=TSQLBinaryExpression(TestCheck('VALUE < 3',TSQLBinaryExpression));
+  AssertEquals('Less than operator',boLT,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is integer',B.Right,TSQLIntegerLiteral);
+end;
+
+procedure TTestCheckParser.TestLessThanEqual1;
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=TSQLBinaryExpression(TestCheck('VALUE <= 3',TSQLBinaryExpression));
+  AssertEquals('Less or Equal operator',boLE,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is integer',B.Right,TSQLIntegerLiteral);
+end;
+
+procedure TTestCheckParser.TestLessThanEqual2;
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=TSQLBinaryExpression(TestCheck('VALUE !> 3',TSQLBinaryExpression));
+  AssertEquals('Less or Equal operator',boLE,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is integer',B.Right,TSQLIntegerLiteral);
+end;
+
+procedure TTestCheckParser.TestLike;
+
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=TSQLBinaryExpression(TestCheck('VALUE LIKE ''%3''',TSQLBinaryExpression));
+  AssertEquals('Like operator',boLike,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is string',B.Right,TSQLStringLiteral);
+end;
+
+procedure TTestCheckParser.TestNotLike;
+
+Var
+  B : TSQLBinaryExpression;
+  U : TSQLUnaryExpression;
+begin
+  U:=TSQLUnaryExpression(TestCheck('VALUE NOT LIKE ''%3''',TSQLUnaryExpression));
+  AssertEquals('Like operator',uoNot,U.Operation);
+  CheckClass(U.Operand,TSQLBinaryExpression);
+  B:=TSQLBinaryExpression(U.Operand);
+  AssertEquals('Like operator',boLike,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is string',B.Right,TSQLStringLiteral);
+end;
+
+procedure TTestCheckParser.TestContaining;
+
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=TSQLBinaryExpression(TestCheck('VALUE CONTAINING ''3''',TSQLBinaryExpression));
+  AssertEquals('Like operator',boContaining,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is string',B.Right,TSQLStringLiteral);
+end;
+
+procedure TTestCheckParser.TestNotContaining;
+
+Var
+  B : TSQLBinaryExpression;
+  U : TSQLUnaryExpression;
+begin
+  U:=TSQLUnaryExpression(TestCheck('VALUE NOT CONTAINING ''3''',TSQLUnaryExpression));
+  AssertEquals('Like operator',uoNot,U.Operation);
+  CheckClass(U.Operand,TSQLBinaryExpression);
+  B:=TSQLBinaryExpression(U.Operand);
+  AssertEquals('Like operator',boContaining,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is string',B.Right,TSQLStringLiteral);
+end;
+
+procedure TTestCheckParser.TestStarting;
+
+Var
+  B : TSQLBinaryExpression;
+
+begin
+  B:=TSQLBinaryExpression(TestCheck('VALUE STARTING ''3''',TSQLBinaryExpression));
+  AssertEquals('Like operator',boStarting,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is string',B.Right,TSQLStringLiteral);
+end;
+
+procedure TTestCheckParser.TestNotStarting;
+
+Var
+  B : TSQLBinaryExpression;
+  U : TSQLUnaryExpression;
+begin
+  U:=TSQLUnaryExpression(TestCheck('VALUE NOT STARTING ''3''',TSQLUnaryExpression));
+  AssertEquals('Like operator',uoNot,U.Operation);
+  CheckClass(U.Operand,TSQLBinaryExpression);
+  B:=TSQLBinaryExpression(U.Operand);
+  AssertEquals('Like operator',boStarting,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Right is string',B.Right,TSQLStringLiteral);
+end;
+
+procedure TTestCheckParser.TestBetween;
+
+Var
+  T : TSQLTernaryExpression;
+
+begin
+  T:=TSQLTernaryExpression(TestCheck('VALUE BETWEEN 1 AND 5',TSQLTernaryExpression));
+  AssertEquals('Like operator',tobetween,T.Operation);
+  AssertLiteralExpr('Left is value',T.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Middle is integer',T.Middle,TSQLIntegerLiteral);
+  AssertLiteralExpr('Right is integer',T.Right,TSQLIntegerLiteral);
+end;
+
+procedure TTestCheckParser.TestNotBetween;
+
+Var
+  U : TSQLUnaryExpression;
+  T : TSQLTernaryExpression;
+
+begin
+  U:=TSQLUnaryExpression(TestCheck('VALUE NOT BETWEEN 1 AND 5',TSQLUnaryExpression));
+  AssertEquals('Not operator',uoNot,U.Operation);
+  CheckClass(U.Operand,TSQLTernaryExpression);
+  T:=TSQLTernaryExpression(U.Operand);
+  AssertEquals('Like operator',tobetween,T.Operation);
+  AssertLiteralExpr('Left is value',T.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Middle is integer',T.Middle,TSQLIntegerLiteral);
+  AssertLiteralExpr('Right is integer',T.Right,TSQLIntegerLiteral);
+end;
+
+procedure TTestCheckParser.TestLikeEscape;
+
+Var
+  T : TSQLTernaryExpression;
+
+begin
+  T:=TSQLTernaryExpression(TestCheck('VALUE LIKE ''%2'' ESCAPE ''3''',TSQLTernaryExpression));
+  AssertEquals('Like operator',toLikeEscape,T.Operation);
+  AssertLiteralExpr('Left is value',T.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Middle is string',T.Middle,TSQLStringLiteral);
+  AssertLiteralExpr('Right is string',T.Right,TSQLStringLiteral);
+end;
+
+procedure TTestCheckParser.TestNotLikeEscape;
+Var
+  U : TSQLUnaryExpression;
+  T : TSQLTernaryExpression;
+
+begin
+  U:=TSQLUnaryExpression(TestCheck('VALUE NOT LIKE ''%2'' ESCAPE ''3''',TSQLUnaryExpression));
+  AssertEquals('Not operator',uoNot,U.Operation);
+  CheckClass(U.Operand,TSQLTernaryExpression);
+  T:=TSQLTernaryExpression(U.Operand);
+  AssertEquals('Like operator',toLikeEscape,T.Operation);
+  AssertLiteralExpr('Left is value',T.Left,TSQLValueLiteral);
+  AssertLiteralExpr('Middle is string',T.Middle,TSQLStringLiteral);
+  AssertLiteralExpr('Right is string',T.Right,TSQLStringLiteral);
+end;
+
+procedure TTestCheckParser.TestAnd;
+
+Var
+  T,B : TSQLBinaryExpression;
+
+begin
+  T:=TSQLBinaryExpression(TestCheck('VALUE > 4 AND Value < 11',TSQLBinaryExpression));
+  AssertEquals('And operator',boand,T.Operation);
+  CheckClass(T.Left,TSQLBinaryExpression);
+  CheckClass(T.Right,TSQLBinaryExpression);
+  B:=TSQLBinaryExpression(T.Left);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertEquals('Less than operator',boGT,B.Operation);
+  AssertLiteralExpr('Right is value',B.Right,TSQLIntegerLiteral);
+  B:=TSQLBinaryExpression(T.Right);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertEquals('Less than operator',boLT,B.Operation);
+  AssertLiteralExpr('Right is value',B.Right,TSQLIntegerLiteral);
+end;
+
+procedure TTestCheckParser.TestOr;
+
+Var
+  T,B : TSQLBinaryExpression;
+
+begin
+  T:=TSQLBinaryExpression(TestCheck('VALUE < 4 or Value > 11',TSQLBinaryExpression));
+  AssertEquals('And operator',boor,T.Operation);
+  CheckClass(T.Left,TSQLBinaryExpression);
+  CheckClass(T.Right,TSQLBinaryExpression);
+  B:=TSQLBinaryExpression(T.Left);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertEquals('Less than operator',boLT,B.Operation);
+  AssertLiteralExpr('Right is value',B.Right,TSQLIntegerLiteral);
+  B:=TSQLBinaryExpression(T.Right);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertEquals('Less than operator',boGT,B.Operation);
+  AssertLiteralExpr('Right is value',B.Right,TSQLIntegerLiteral);
+end;
+
+procedure TTestCheckParser.TestNotOr;
+
+Var
+  T,B : TSQLBinaryExpression;
+
+begin
+  T:=TSQLBinaryExpression(TestCheck('VALUE IS NOT NULL or Value > 11',TSQLBinaryExpression));
+  AssertEquals('And operator',boor,T.Operation);
+  CheckClass(T.Left,TSQLBinaryExpression);
+  CheckClass(T.Right,TSQLBinaryExpression);
+  B:=TSQLBinaryExpression(T.Left);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertEquals('Is not null operator',boisNot,B.Operation);
+  AssertLiteralExpr('Right is value',B.Right,TSQLNullLiteral);
+  B:=TSQLBinaryExpression(T.Right);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertEquals('Less than operator',boGT,B.Operation);
+  AssertLiteralExpr('Right is value',B.Right,TSQLIntegerLiteral);
+end;
+
+{ TTestDomainParser }
+
+procedure TTestDomainParser.TestSimpleDomain;
+
+Var
+  P : TSQLCreateOrAlterStatement;
+  D : TSQLCreateDomainStatement;
+  T : TSQLTypeDefinition;
+
+begin
+  P:=TestCreateStatement('CREATE DOMAIN A INT','A',TSQLCreateDomainStatement);
+  CheckClass(P,TSQLCreateDomainStatement);
+  D:=TSQLCreateDomainStatement(P);
+  AssertNotNull('Have type Definition',D.TypeDefinition);
+  T:=D.TypeDefinition;
+  AssertTypeDefaults(T);
+  AssertEquals('Integer data type',sdtInteger,T.DataType);
+end;
+
+procedure TTestDomainParser.TestSimpleDomainAs;
+Var
+  P : TSQLCreateOrAlterStatement;
+  D : TSQLCreateDomainStatement;
+  T : TSQLTypeDefinition;
+
+begin
+  P:=TestCreateStatement('CREATE DOMAIN A AS INT','A',TSQLCreateDomainStatement);
+  CheckClass(P,TSQLCreateDomainStatement);
+  D:=TSQLCreateDomainStatement(P);
+  AssertNotNull('Have type Definition',D.TypeDefinition);
+  T:=D.TypeDefinition;
+  AssertTypeDefaults(T);
+  AssertEquals('Integer data type',sdtInteger,T.DataType);
+end;
+
+procedure TTestDomainParser.TestNotNullDomain;
+Var
+  P : TSQLCreateOrAlterStatement;
+  D : TSQLCreateDomainStatement;
+  T : TSQLTypeDefinition;
+
+begin
+  P:=TestCreateStatement('CREATE DOMAIN A INT NOT NULL','A',TSQLCreateDomainStatement);
+  CheckClass(P,TSQLCreateDomainStatement);
+  D:=TSQLCreateDomainStatement(P);
+  AssertNotNull('Have type Definition',D.TypeDefinition);
+  T:=D.TypeDefinition;
+  AssertEquals('Integer data type',sdtInteger,T.DataType);
+  AssertEquals('Not null',True,T.NotNull);
+end;
+
+procedure TTestDomainParser.TestDefaultNotNullDomain;
+Var
+  P : TSQLCreateOrAlterStatement;
+  D : TSQLCreateDomainStatement;
+  T : TSQLTypeDefinition;
+
+begin
+  P:=TestCreateStatement('CREATE DOMAIN A INT DEFAULT 2 NOT NULL','A',TSQLCreateDomainStatement);
+  CheckClass(P,TSQLCreateDomainStatement);
+  D:=TSQLCreateDomainStatement(P);
+  AssertNotNull('Have type Definition',D.TypeDefinition);
+  T:=D.TypeDefinition;
+  AssertNotNull('Have default value',T.DefaultValue);
+  CheckClass(T.DefaultValue,TSQLINtegerLiteral);
+  AssertEquals('Integer data type',sdtInteger,T.DataType);
+  AssertEquals('Not null',True,T.NotNull);
+end;
+
+procedure TTestDomainParser.TestAlterDomainDropDefault;
+begin
+  TestCreateStatement('ALTER DOMAIN A DROP DEFAULT','A',TSQLAlterDomainDropDefaultStatement);
+end;
+
+procedure TTestDomainParser.TestAlterDomainDropCheck;
+begin
+  TestCreateStatement('ALTER DOMAIN A DROP CONSTRAINT','A',TSQLAlterDomainDropCheckStatement);
+end;
+
+procedure TTestDomainParser.TestAlterDomainAddCheck;
+
+Var
+  P : TSQLCreateOrAlterStatement;
+  D : TSQLAlterDomainAddCheckStatement;
+  B : TSQLBinaryExpression;
+
+begin
+  P:=TestCreateStatement('ALTER DOMAIN A ADD CHECK (VALUE IS NOT NULL)','A',TSQLAlterDomainAddCheckStatement);
+  D:=TSQLAlterDomainAddCheckStatement(P);
+  AssertNotNull('Have check',D.Check);
+  CheckClass(D.Check,TSQLBinaryExpression);
+  B:=TSQLBinaryExpression(D.Check);
+  AssertEquals('Is not null operator',boIsNot,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertEquals('Is not null operator',boisNot,B.Operation);
+  AssertLiteralExpr('Right is value',B.Right,TSQLNullLiteral);
+end;
+procedure TTestDomainParser.TestAlterDomainAddConstraintCheck;
+
+Var
+  P : TSQLCreateOrAlterStatement;
+  D : TSQLAlterDomainAddCheckStatement;
+  B : TSQLBinaryExpression;
+
+begin
+  P:=TestCreateStatement('ALTER DOMAIN A ADD CONSTRAINT CHECK (VALUE IS NOT NULL)','A',TSQLAlterDomainAddCheckStatement);
+  D:=TSQLAlterDomainAddCheckStatement(P);
+  AssertNotNull('Have check',D.Check);
+  CheckClass(D.Check,TSQLBinaryExpression);
+  B:=TSQLBinaryExpression(D.Check);
+  AssertEquals('Is not null operation',boIsNot,B.Operation);
+  AssertLiteralExpr('Left is value',B.Left,TSQLValueLiteral);
+  AssertEquals('Is not null operator',boisNot,B.Operation);
+  AssertLiteralExpr('Right is value',B.Right,TSQLNullLiteral);
+end;
+
+procedure TTestDomainParser.TestAlterDomainAddConstraintError;
+begin
+  FErrSource:='ALTER DOMAIN A ADD CONSTRAINT (VALUE IS NOT NULL)';
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestDomainParser.TestAlterDomainSetDefault;
+Var
+  P : TSQLCreateOrAlterStatement;
+  D : TSQLAlterDomainSetDefaultStatement;
+
+begin
+  P:=TestCreateStatement('ALTER DOMAIN A SET DEFAULT NULL','A',TSQLAlterDomainSetDefaultStatement);
+  D:=TSQLAlterDomainSetDefaultStatement(P);
+  AssertNotNull('Have default',D.DefaultValue);
+  CheckClass(D.DefaultValue,TSQLNullLiteral);
+end;
+
+procedure TTestDomainParser.TestAlterDomainRename;
+Var
+  P : TSQLCreateOrAlterStatement;
+  D : TSQLAlterDomainRenameStatement;
+
+begin
+  P:=TestCreateStatement('ALTER DOMAIN A B','A',TSQLAlterDomainRenameStatement);
+  D:=TSQLAlterDomainRenameStatement(P);
+  AssertIdentifierName('New name','B',D.NewName);
+end;
+
+procedure TTestDomainParser.TestAlterDomainNewType;
+Var
+  P : TSQLCreateOrAlterStatement;
+  D : TSQLAlterDomainTypeStatement;
+
+begin
+  P:=TestCreateStatement('ALTER DOMAIN A TYPE CHAR(10)','A',TSQLAlterDomainTypeStatement);
+  D:=TSQLAlterDomainTypeStatement(P);
+  AssertNotNull('Have type definition',D.NewType);
+  AssertEquals('Char type',sdtChar,D.NewType.DataType);
+  AssertEquals('Char type of len 10',10,D.NewType.Len);
+end;
+
+procedure TTestDomainParser.TestAlterDomainNewTypeError1;
+
+begin
+  FErrSource:='ALTER DOMAIN A TYPE INT NOT NULL';
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestDomainParser.TestAlterDomainNewTypeError2;
+begin
+  FErrSource:='ALTER DOMAIN A TYPE INT DEFAULT 1';
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestDomainParser.TestAlterDomainDropCheckError;
+begin
+  FErrSource:='ALTER DOMAIN A DROP CHECK';
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+
+{ TTestExceptionParser }
+
+procedure TTestExceptionParser.TestException;
+Var
+  P : TSQLCreateOrAlterStatement;
+  E : TSQLCreateExceptionStatement;
+
+begin
+  P:=TestCreateStatement('CREATE EXCEPTION A ''A message''','A',TSQLCreateExceptionStatement);
+  E:=TSQLCreateExceptionStatement(P);
+  AssertNotNull('Have message',E.ExceptionMessage);
+  AssertEquals('Message','A message',E.ExceptionMessage.Value)
+end;
+
+procedure TTestExceptionParser.TestAlterException;
+Var
+  P : TSQLCreateOrAlterStatement;
+  E : TSQLCreateExceptionStatement;
+
+begin
+  P:=TestCreateStatement('ALTER EXCEPTION A ''A massage''','A',TSQLAlterExceptionStatement);
+  E:=TSQLCreateExceptionStatement(P);
+  AssertNotNull('Have message',E.ExceptionMessage);
+  AssertEquals('Message','A massage',E.ExceptionMessage.Value)
+end;
+
+procedure TTestExceptionParser.TestExceptionError1;
+begin
+  FErrSource:='CREATE EXCEPTION NOT';
+  ASsertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestExceptionParser.TestExceptionError2;
+begin
+  FErrSource:='CREATE EXCEPTION A NOT';
+  ASsertException(ESQLParser,@TestParseError);
+end;
+
+{ TTestRoleParser }
+
+procedure TTestRoleParser.TestCreateRole;
+
+begin
+  TestCreateStatement('CREATE ROLE A','A',TSQLCreateROLEStatement);
+end;
+
+procedure TTestRoleParser.TestAlterRole;
+begin
+  FErrSource:='ALTER ROLE A';
+  ASsertException(ESQLParser,@TestParseError);
+end;
+
+{ TTestIndexParser }
+
+procedure TTestIndexParser.TestAlterindexActive;
+
+Var
+  A : TSQLAlterIndexStatement;
+
+begin
+  A:=TSQLAlterIndexStatement(TestCreateStatement('ALTER INDEX A ACTIVE','A',TSQLAlterIndexStatement));
+  AssertEquals('Active',False,A.Inactive);
+end;
+
+procedure TTestIndexParser.TestAlterindexInactive;
+
+Var
+  A : TSQLAlterIndexStatement;
+
+begin
+  A:=TSQLAlterIndexStatement(TestCreateStatement('ALTER INDEX A INACTIVE','A',TSQLAlterIndexStatement));
+  AssertEquals('Inactive',True,A.Inactive);
+end;
+
+procedure TTestIndexParser.TestCreateIndexSimple;
+
+Var
+  C : TSQLCreateIndexStatement;
+
+begin
+  C:=TSQLCreateIndexStatement(TestCreateStatement('CREATE INDEX A ON B (C)','A',TSQLCreateIndexStatement));
+  If Not (C.Options=[]) then
+    Fail('Options empty');
+  AssertIdentifiername('Correct table name','B',C.TableName);
+  AssertNotNull('Have fieldlist',C.FieldNames);
+  AssertEquals('Number of fields',1,C.FieldNames.Count);
+  AssertIdentifiername('Field name','C',C.FieldNames[0]);
+end;
+
+procedure TTestIndexParser.TestIndexIndexDouble;
+
+Var
+  C : TSQLCreateIndexStatement;
+
+begin
+  C:=TSQLCreateIndexStatement(TestCreateStatement('CREATE INDEX A ON B (C,D)','A',TSQLCreateIndexStatement));
+  If Not (C.Options=[]) then
+    Fail('Options empty');
+  AssertIdentifiername('Correct table name','B',C.TableName);
+  AssertNotNull('Have fieldlist',C.FieldNames);
+  AssertEquals('Number of fields',2,C.FieldNames.Count);
+  AssertIdentifiername('Field name 1','C',C.FieldNames[0]);
+  AssertIdentifiername('Field name 2','D',C.FieldNames[1]);
+end;
+
+procedure TTestIndexParser.TestIndexError1;
+begin
+  FErrSource:='ALTER UNIQUE INDEX A ACTIVE';
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestIndexParser.TestIndexError2;
+begin
+  FErrSource:='ALTER ASCENDING INDEX A ACTIVE';
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestIndexParser.TestIndexError3;
+begin
+  FErrSource:='ALTER DESCENDING INDEX A ACTIVE';
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestIndexParser.TestIndexError4;
+begin
+  FErrSource:='CREATE INDEX A ON B';
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestIndexParser.TestIndexError5;
+begin
+  FErrSource:='CREATE INDEX A ON B ()';
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestIndexParser.TestIndexError6;
+begin
+  FErrSource:='CREATE INDEX A ON B (A,)';
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestIndexParser.TestCreateIndexUnique;
+
+Var
+  C : TSQLCreateIndexStatement;
+
+begin
+  C:=TSQLCreateIndexStatement(TestCreateStatement('CREATE UNIQUE INDEX A ON B (C)','A',TSQLCreateIndexStatement));
+  If not ([ioUnique]=C.Options) then
+    Fail('Not Unique index');
+  AssertIdentifierName('Have table name','B',C.TableName);
+  AssertNotNull('Have fieldlist',C.FieldNames);
+  AssertEquals('Number of fields',1,C.FieldNames.Count);
+  AssertIdentifierName('Correct field name','C',C.FieldNames[0]);
+end;
+
+procedure TTestIndexParser.TestCreateIndexUniqueAscending;
+
+Var
+  C : TSQLCreateIndexStatement;
+
+begin
+  C:=TSQLCreateIndexStatement(TestCreateStatement('CREATE UNIQUE ASCENDING INDEX A ON B (C)','A',TSQLCreateIndexStatement));
+  If not ([ioUnique,ioAscending ]=C.Options) then
+    Fail('Not Unique ascending index');
+  AssertIdentifierName('Have table name','B',C.TableName);
+  AssertNotNull('Have fieldlist',C.FieldNames);
+  AssertEquals('Number of fields',1,C.FieldNames.Count);
+  AssertIdentifierName('Correct field name','C',C.FieldNames[0]);
+end;
+
+procedure TTestIndexParser.TestCreateIndexUniqueDescending;
+
+Var
+  C : TSQLCreateIndexStatement;
+
+begin
+  C:=TSQLCreateIndexStatement(TestCreateStatement('CREATE UNIQUE DESCENDING INDEX A ON B (C)','A',TSQLCreateIndexStatement));
+  If not ([ioUnique,ioDescending]=C.Options) then
+    Fail('Not Unique descending index');
+  AssertIdentifierName('Have table name','B',C.TableName);
+  AssertNotNull('Have fieldlist',C.FieldNames);
+  AssertEquals('Number of fields',1,C.FieldNames.Count);
+  AssertIdentifierName('Correct field name','C',C.FieldNames[0]);
+end;
+
+procedure TTestIndexParser.TestCreateIndexAscending;
+
+Var
+  C : TSQLCreateIndexStatement;
+
+begin
+  C:=TSQLCreateIndexStatement(TestCreateStatement('CREATE ASCENDING INDEX A ON B (C)','A',TSQLCreateIndexStatement));
+  If not ([ioAscending]=C.Options) then
+    Fail('Not ascending index');
+  AssertIdentifierName('Have table name','B',C.TableName);
+  AssertNotNull('Have fieldlist',C.FieldNames);
+  AssertEquals('Number of fields',1,C.FieldNames.Count);
+  AssertIdentifierName('Correct field name','C',C.FieldNames[0]);
+end;
+
+procedure TTestIndexParser.TestCreateIndexDescending;
+
+Var
+  C : TSQLCreateIndexStatement;
+
+begin
+  C:=TSQLCreateIndexStatement(TestCreateStatement('CREATE DESCENDING INDEX A ON B (C)','A',TSQLCreateIndexStatement));
+  If not ([ioDescending] = C.Options) then
+    Fail('Not descending index');
+  AssertIdentifierName('Table name','B',C.TableName);
+  AssertNotNull('Have fieldlist',C.FieldNames);
+  AssertEquals('Number of fields',1,C.FieldNames.Count);
+  AssertIdentifierName('Correct field name','C',C.FieldNames[0]);
+end;
+
+{ TTestTableParser }
+
+procedure TTestTableParser.DoTestCreateReferencesField(const ASource: String;
+  AOnUpdate, AOnDelete: TForeignKeyAction);
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  D : TSQLForeignKeyFieldConstraint;
+
+begin
+
+  C:=TSQLCreateTableStatement(TestCreateStatement(ASource,'A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('No constraints',0,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  AssertNotNull('Have field type',F.FieldType);
+  AssertEquals('Correct field type',sdtInteger,F.FieldType.DataType);
+  AssertEquals('Field can be NULL',false,F.FieldType.NotNull);
+  AssertNull('Have default',F.FieldType.DefaultValue);
+  AssertNotNull('Have constraint',F.FieldType.Constraint);
+  D:=TSQLForeignKeyFieldConstraint(CheckClass(F.FieldType.Constraint,TSQLForeignKeyFieldConstraint));
+  AssertNull('No constraint name',D.ConstraintName);
+  AssertIdentifierName('Correct table name','C',D.Definition.TableName);
+  AssertEquals('Correct field list count',1,D.Definition.FieldList.Count);
+  AssertIdentifierName('Correct field name','D',D.Definition.FieldList[0]);
+  AssertEquals('No on update action',AOnUpdate,D.Definition.OnUpdate);
+  AssertEquals('No on delete action',AOnDelete,D.Definition.OnDelete);
+end;
+
+procedure TTestTableParser.TestCreateOneSimpleField;
+
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT)','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('No constraints',0,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  AssertNotNull('Have field type',F.FieldType);
+  AssertEquals('Correct field type',sdtInteger,F.FieldType.DataType);
+end;
+
+procedure TTestTableParser.TestCreateTwoSimpleFields;
+
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT, C CHAR(5))','A',TSQLCreateTableStatement));
+  AssertEquals('Two fields',2,C.FieldDefs.Count);
+  AssertEquals('No constraints',0,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  AssertNotNull('Have field type',F.FieldType);
+  AssertEquals('Correct field type',sdtInteger,F.FieldType.DataType);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[1],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','C',F.FieldName);
+  AssertNotNull('Have field type',F.FieldType);
+  AssertEquals('Correct field type',sdtChar,F.FieldType.DataType);
+end;
+
+procedure TTestTableParser.TestCreateOnePrimaryField;
+
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  P : TSQLPrimaryKeyFieldConstraint;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT PRIMARY KEY)','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('No constraints',0,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  AssertNotNull('Have field type',F.FieldType);
+  AssertEquals('Correct field type',sdtInteger,F.FieldType.DataType);
+  AssertNotNull('Have constraint',F.FieldType.Constraint);
+  P:=TSQLPrimaryKeyFieldConstraint(CheckClass(F.FieldType.Constraint,TSQLPrimaryKeyFieldConstraint));
+  AssertNull('No constraint name',P.ConstraintName);
+end;
+
+procedure TTestTableParser.TestCreateOneNamedPrimaryField;
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  P : TSQLPrimaryKeyFieldConstraint;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT CONSTRAINT C PRIMARY KEY)','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('No constraints',0,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  AssertNotNull('Have field type',F.FieldType);
+  AssertEquals('Correct field type',sdtInteger,F.FieldType.DataType);
+  AssertNotNull('Have constraint',F.FieldType.Constraint);
+  P:=TSQLPrimaryKeyFieldConstraint(CheckClass(F.FieldType.Constraint,TSQLPrimaryKeyFieldConstraint));
+  AssertIdentifierName('Constraint name','C',P.ConstraintName);
+end;
+
+procedure TTestTableParser.TestCreateOneUniqueField;
+
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  U : TSQLUniqueFieldConstraint;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT UNIQUE)','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('No constraints',0,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  AssertNotNull('Have field type',F.FieldType);
+  AssertEquals('Correct field type',sdtInteger,F.FieldType.DataType);
+  AssertNotNull('Have constraint',F.FieldType.Constraint);
+  U:=TSQLUniqueFieldConstraint(CheckClass(F.FieldType.Constraint,TSQLUniqueFieldConstraint));
+  AssertNull('No constraint name',U.ConstraintName);
+end;
+
+procedure TTestTableParser.TestCreateOneNamedUniqueField;
+
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  U : TSQLUniqueFieldConstraint;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT CONSTRAINT C UNIQUE)','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('No constraints',0,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  AssertNotNull('Have field type',F.FieldType);
+  AssertEquals('Correct field type',sdtInteger,F.FieldType.DataType);
+  AssertNotNull('Have constraint',F.FieldType.Constraint);
+  U:=TSQLUniqueFieldConstraint(CheckClass(F.FieldType.Constraint,TSQLUniqueFieldConstraint));
+  AssertIdentifierName('Constraint name','C',U.ConstraintName);
+end;
+
+procedure TTestTableParser.TestCreateNotNullPrimaryField;
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT NOT NULL PRIMARY KEY)','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('No constraints',0,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  AssertNotNull('Have field type',F.FieldType);
+  AssertEquals('Correct field type',sdtInteger,F.FieldType.DataType);
+  AssertEquals('Field is not NULL',true,F.FieldType.NotNull);
+  AssertNotNull('Have constraint',F.FieldType.Constraint);
+  CheckClass(F.FieldType.Constraint,TSQLPrimaryKeyFieldConstraint);
+end;
+
+procedure TTestTableParser.TestCreateNotNullDefaultPrimaryField;
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT DEFAULT 0 NOT NULL PRIMARY KEY)','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('No constraints',0,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  AssertNotNull('Have field type',F.FieldType);
+  AssertEquals('Correct field type',sdtInteger,F.FieldType.DataType);
+  AssertEquals('Field is not NULL',true,F.FieldType.NotNull);
+  AssertNotNull('Have default',F.FieldType.DefaultValue);
+  CheckClass(F.FieldType.DefaultValue,TSQLIntegerLiteral);
+  AssertNotNull('Have constraint',F.FieldType.Constraint);
+  CheckClass(F.FieldType.Constraint,TSQLPrimaryKeyFieldConstraint);
+end;
+
+procedure TTestTableParser.TestCreateCheckField;
+
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  B : TSQLBinaryExpression;
+  CC : TSQLCheckFieldConstraint;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT CHECK (B<>0))','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('No constraints',0,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  AssertNotNull('Have field type',F.FieldType);
+  AssertEquals('Correct field type',sdtInteger,F.FieldType.DataType);
+  AssertNull('Have no default',F.FieldType.DefaultValue);
+  AssertNull('Fieldtype has no check',F.FieldType.Check);
+  AssertNotNull('Field has constraint check',F.FieldType.Constraint);
+  CC:=TSQLCheckFieldConstraint(CheckClass(F.FieldType.Constraint,TSQLCheckFieldConstraint));
+  AssertNull('No constraint name',CC.ConstraintName);
+  B:=TSQLBinaryExpression(CheckClass(CC.Expression,TSQLBinaryExpression));
+  AssertEquals('Unequal check',boNE,B.Operation);
+end;
+
+procedure TTestTableParser.TestCreateNamedCheckField;
+
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  B : TSQLBinaryExpression;
+  CC : TSQLCheckFieldConstraint;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT CONSTRAINT C CHECK (B<>0))','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('No constraints',0,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  AssertNotNull('Have field type',F.FieldType);
+  AssertEquals('Correct field type',sdtInteger,F.FieldType.DataType);
+  AssertNull('Have no default',F.FieldType.DefaultValue);
+  AssertNull('Fieldtype has no check',F.FieldType.Check);
+  AssertNotNull('Field has constraint check',F.FieldType.Constraint);
+  CC:=TSQLCheckFieldConstraint(CheckClass(F.FieldType.Constraint,TSQLCheckFieldConstraint));
+  AssertidentifierName('Constraint name','C',CC.ConstraintName);
+  B:=TSQLBinaryExpression(CheckClass(CC.Expression,TSQLBinaryExpression));
+  AssertEquals('Unequal check',boNE,B.Operation);
+end;
+
+procedure TTestTableParser.TestCreateReferencesField;
+
+begin
+  DoTestCreateReferencesField('CREATE TABLE A (B INT REFERENCES C(D))',fkaNone,fkaNone);
+end;
+
+procedure TTestTableParser.TestCreateReferencesOnUpdateCascadeField;
+
+begin
+  DoTestCreateReferencesField('CREATE TABLE A (B INT REFERENCES C(D) ON UPDATE CASCADE)',fkaCascade,fkaNone);
+end;
+
+procedure TTestTableParser.TestCreateReferencesOnUpdateNoActionField;
+
+begin
+  DoTestCreateReferencesField('CREATE TABLE A (B INT REFERENCES C(D) ON UPDATE NO ACTION)',fkaNoAction,fkaNone);
+end;
+
+procedure TTestTableParser.TestCreateReferencesOnUpdateSetDefaultField;
+begin
+  DoTestCreateReferencesField('CREATE TABLE A (B INT REFERENCES C(D) ON UPDATE SET DEFAULT)',fkaSetDefault,fkaNone);
+end;
+
+procedure TTestTableParser.TestCreateReferencesOnUpdateSetNullField;
+begin
+  DoTestCreateReferencesField('CREATE TABLE A (B INT REFERENCES C(D) ON UPDATE SET NULL)',fkaSetNull,fkaNone);
+end;
+
+procedure TTestTableParser.TestCreateReferencesOnDeleteCascadeField;
+
+begin
+  DoTestCreateReferencesField('CREATE TABLE A (B INT REFERENCES C(D) ON DELETE CASCADE)',fkaNone,fkaCascade);
+end;
+
+procedure TTestTableParser.TestCreateReferencesOnDeleteNoActionField;
+
+begin
+  DoTestCreateReferencesField('CREATE TABLE A (B INT REFERENCES C(D) ON DELETE NO ACTION)',fkaNone,fkaNoAction);
+end;
+
+procedure TTestTableParser.TestCreateReferencesOnDeleteSetDefaultField;
+begin
+  DoTestCreateReferencesField('CREATE TABLE A (B INT REFERENCES C(D) ON DELETE SET DEFAULT)',fkaNone,fkaSetDefault);
+end;
+
+procedure TTestTableParser.TestCreateReferencesOnDeleteSetNullField;
+begin
+  DoTestCreateReferencesField('CREATE TABLE A (B INT REFERENCES C(D) ON DELETE SET NULL)',fkaNone,fkaSetNull);
+end;
+
+procedure TTestTableParser.TestCreateReferencesOnUpdateAndDeleteSetNullField;
+begin
+  DoTestCreateReferencesField('CREATE TABLE A (B INT REFERENCES C(D) ON UPDATE SET NULL ON DELETE SET NULL)',fkaSetNull,fkaSetNull);
+end;
+
+procedure TTestTableParser.TestCreateNamedReferencesField;
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  D : TSQLForeignKeyFieldConstraint;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT CONSTRAINT FK REFERENCES C(D))','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('No constraints',0,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  AssertNotNull('Have field type',F.FieldType);
+  AssertEquals('Correct field type',sdtInteger,F.FieldType.DataType);
+  AssertEquals('Field can be NULL',false,F.FieldType.NotNull);
+  AssertNull('Have default',F.FieldType.DefaultValue);
+  AssertNotNull('Have constraint',F.FieldType.Constraint);
+  D:=TSQLForeignKeyFieldConstraint(CheckClass(F.FieldType.Constraint,TSQLForeignKeyFieldConstraint));
+  AssertIdentifierName('Correct constraint name','FK',D.ConstraintName);
+  AssertIdentifierName('Correct table name','C',D.Definition.TableName);
+  AssertEquals('Correct field list count',1,D.Definition.FieldList.Count);
+  AssertIdentifierName('Correct field name','D',D.Definition.FieldList[0]);
+end;
+
+procedure TTestTableParser.TestCreateComputedByField;
+
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  B : TSQLBinaryExpression;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT, C INT, D COMPUTED BY (B+C))','A',TSQLCreateTableStatement));
+  AssertEquals('Three fields',3,C.FieldDefs.Count);
+  AssertEquals('No constraints',0,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[2],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','D',F.FieldName);
+  AssertNull('No field type',F.FieldType);
+  AssertNotNull('Have computed by expression',F.ComputedBy);
+  B:=TSQLBinaryExpression(CheckClass(F.ComputedBy,TSQLBinaryExpression));
+  AssertEquals('Add operation',boAdd,B.Operation);
+  CheckClass(B.Left,TSQLIdentifierExpression);
+  AssertIdentifierName('Correct identifier','B',TSQLIdentifierExpression(B.Left).Identifier);
+  CheckClass(B.Right,TSQLIdentifierExpression);
+  AssertIdentifierName('Correct identifier','C',TSQLIdentifierExpression(B.Right).Identifier);
+end;
+
+procedure TTestTableParser.TestCreatePrimaryKeyConstraint;
+
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  P: TSQLTablePrimaryKeyConstraintDef;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT, PRIMARY KEY (B))','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('One constraints',1,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  P:=TSQLTablePrimaryKeyConstraintDef(CheckClass(C.Constraints[0],TSQLTablePrimaryKeyConstraintDef));
+  AssertNotNull('Fieldlist assigned',P.FieldList);
+  AssertNull('Constraint name empty',P.ConstraintName);
+  AssertEquals('One field in primary key',1,P.FieldList.Count);
+  AssertIdentifierName('fieldname','B',P.FieldList[0]);
+end;
+
+procedure TTestTableParser.TestCreateNamedPrimaryKeyConstraint;
+
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  P: TSQLTablePrimaryKeyConstraintDef;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT, CONSTRAINT A_PK PRIMARY KEY (B))','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('One constraints',1,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  P:=TSQLTablePrimaryKeyConstraintDef(CheckClass(C.Constraints[0],TSQLTablePrimaryKeyConstraintDef));
+  AssertNotNull('Fieldlist assigned',P.FieldList);
+  AssertIdentifierName('fieldname','A_PK',P.ConstraintName);
+  AssertEquals('One field in primary key',1,P.FieldList.Count);
+  AssertIdentifierName('fieldname','B',P.FieldList[0]);
+end;
+
+procedure TTestTableParser.TestCreateForeignKeyConstraint;
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  P: TSQLTableForeignKeyConstraintDef;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT, FOREIGN KEY (B) REFERENCES C(D))','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('One constraints',1,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  P:=TSQLTableForeignKeyConstraintDef(CheckClass(C.Constraints[0],TSQLTableForeignKeyConstraintDef));
+  AssertNotNull('Fieldlist assigned',P.FieldList);
+  AssertNull('Constraint name',P.ConstraintName);
+  AssertEquals('One field in foreign key',1,P.FieldList.Count);
+  AssertIdentifierName('fieldname','B',P.FieldList[0]);
+  AssertIdentifierName('Target table name','C',P.Definition.TableName);
+  AssertEquals('One field in primary key target',1,P.Definition.FieldList.Count);
+  AssertIdentifierName('target fieldname','D',P.Definition.FieldList[0]);
+end;
+
+procedure TTestTableParser.TestCreateNamedForeignKeyConstraint;
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  P: TSQLTableForeignKeyConstraintDef;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT, CONSTRAINT A_FK FOREIGN KEY (B) REFERENCES C(D))','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('One constraints',1,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  P:=TSQLTableForeignKeyConstraintDef(CheckClass(C.Constraints[0],TSQLTableForeignKeyConstraintDef));
+  AssertNotNull('Fieldlist assigned',P.FieldList);
+  AssertIdentifierName('fieldname','A_FK',P.ConstraintName);
+  AssertEquals('One field in foreign key',1,P.FieldList.Count);
+  AssertIdentifierName('fieldname','B',P.FieldList[0]);
+  AssertIdentifierName('Target table name','C',P.Definition.TableName);
+  AssertEquals('One field in primary key target',1,P.Definition.FieldList.Count);
+  AssertIdentifierName('target fieldname','D',P.Definition.FieldList[0]);
+end;
+
+procedure TTestTableParser.TestCreateUniqueConstraint;
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  P: TSQLTableUniqueConstraintDef;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT, UNIQUE (B))','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('One constraints',1,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  P:=TSQLTableUniqueConstraintDef(CheckClass(C.Constraints[0],TSQLTableUniqueConstraintDef));
+  AssertNotNull('Fieldlist assigned',P.FieldList);
+  AssertNull('Constraint name empty',P.ConstraintName);
+  AssertEquals('One field in primary key',1,P.FieldList.Count);
+  AssertIdentifierName('Name is correct','B',P.FieldList[0]);
+end;
+
+procedure TTestTableParser.TestCreateNamedUniqueConstraint;
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  P: TSQLTableUniqueConstraintDef;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT, CONSTRAINT U_A UNIQUE (B))','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('One constraints',1,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  P:=TSQLTableUniqueConstraintDef(CheckClass(C.Constraints[0],TSQLTableUniqueConstraintDef));
+  AssertNotNull('Fieldlist assigned',P.FieldList);
+  AssertIdentifierName('fieldname','U_A',P.ConstraintName);
+  AssertEquals('One field in primary key',1,P.FieldList.Count);
+  AssertIdentifierName('Name is correct','B',P.FieldList[0]);
+end;
+
+procedure TTestTableParser.TestCreateCheckConstraint;
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  B : TSQLBinaryExpression;
+  P: TSQLTableCheckConstraintDef;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT, CHECK (B<>0))','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('One constraints',1,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  P:=TSQLTableCheckConstraintDef(CheckClass(C.Constraints[0],TSQLTableCheckConstraintDef));
+  AssertNull('Constraint name empty',P.ConstraintName);
+  AssertNotNull('Check expression assigned',P.Check);
+  B:=TSQLBinaryExpression(CheckClass(P.Check,TSQLBinaryExpression));
+  AssertEquals('Unequal',boNE,B.Operation);
+end;
+
+procedure TTestTableParser.TestCreateNamedCheckConstraint;
+Var
+  C : TSQLCreateTableStatement;
+  F : TSQLTableFieldDef;
+  B : TSQLBinaryExpression;
+  P: TSQLTableCheckConstraintDef;
+
+begin
+  C:=TSQLCreateTableStatement(TestCreateStatement('CREATE TABLE A (B INT, CONSTRAINT C_A CHECK (B<>0))','A',TSQLCreateTableStatement));
+  AssertEquals('One field',1,C.FieldDefs.Count);
+  AssertEquals('One constraints',1,C.Constraints.Count);
+  F:=TSQLTableFieldDef(CheckClass(C.FieldDefs[0],TSQLTableFieldDef));
+  AssertIdentifierName('fieldname','B',F.FieldName);
+  P:=TSQLTableCheckConstraintDef(CheckClass(C.Constraints[0],TSQLTableCheckConstraintDef));
+  AssertIdentifierName('Constainrname','C_A',P.ConstraintName);
+  AssertNotNull('Check expression assigned',P.Check);
+  B:=TSQLBinaryExpression(CheckClass(P.Check,TSQLBinaryExpression));
+  AssertEquals('Not equal operation',boNE,B.Operation);
+end;
+
+procedure TTestTableParser.TestAlterDropField;
+Var
+  A : TSQLAlterTableStatement;
+  D : TSQLDropTableFieldOperation;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A DROP B','A',TSQLAlterTableStatement));
+  AssertEquals('One operation',1,A.Operations.Count);
+  D:=TSQLDropTableFieldOperation(CheckClass(A.Operations[0],TSQLDropTableFieldOperation));
+  AssertidentifierName('Drop field name','B',D.ObjectName);
+end;
+
+procedure TTestTableParser.TestAlterDropFields;
+Var
+  A : TSQLAlterTableStatement;
+  D : TSQLDropTableFieldOperation;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A DROP B, DROP C','A',TSQLAlterTableStatement));
+  AssertEquals('Two operations',2,A.Operations.Count);
+  D:=TSQLDropTableFieldOperation(CheckClass(A.Operations[0],TSQLDropTableFieldOperation));
+  AssertidentifierName('Drop field name','B',D.ObjectName);
+  D:=TSQLDropTableFieldOperation(CheckClass(A.Operations[1],TSQLDropTableFieldOperation));
+  AssertidentifierName('Drop field name','C',D.ObjectName);
+end;
+
+procedure TTestTableParser.TestAlterDropConstraint;
+Var
+  A : TSQLAlterTableStatement;
+  D : TSQLDropTableConstraintOperation;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A DROP CONSTRAINT B','A',TSQLAlterTableStatement));
+  AssertEquals('One operation',1,A.Operations.Count);
+  D:=TSQLDropTableConstraintOperation(CheckClass(A.Operations[0],TSQLDropTableConstraintOperation));
+  AssertidentifierName('Drop field name','B',D.ObjectName);
+end;
+
+procedure TTestTableParser.TestAlterDropConstraints;
+Var
+  A : TSQLAlterTableStatement;
+  D : TSQLDropTableConstraintOperation;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A DROP CONSTRAINT B, DROP CONSTRAINT C','A',TSQLAlterTableStatement));
+  AssertEquals('Two operations',2,A.Operations.Count);
+  D:=TSQLDropTableConstraintOperation(CheckClass(A.Operations[0],TSQLDropTableConstraintOperation));
+  AssertidentifierName('Drop Constraint name','B',D.ObjectName);
+  D:=TSQLDropTableConstraintOperation(CheckClass(A.Operations[1],TSQLDropTableConstraintOperation));
+  AssertidentifierName('Drop field name','C',D.ObjectName);
+end;
+
+procedure TTestTableParser.TestAlterRenameField;
+Var
+  A : TSQLAlterTableStatement;
+  R : TSQLAlterTableFieldNameOperation;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A ALTER B TO C','A',TSQLAlterTableStatement));
+  AssertEquals('One operation',1,A.Operations.Count);
+  R:=TSQLAlterTableFieldNameOperation(CheckClass(A.Operations[0],TSQLAlterTableFieldNameOperation));
+  AssertidentifierName('Old field name','B',R.ObjectName);
+  AssertidentifierName('New field name','C',R.NewName);
+end;
+procedure TTestTableParser.TestAlterRenameColumnField;
+Var
+  A : TSQLAlterTableStatement;
+  R : TSQLAlterTableFieldNameOperation;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A ALTER COLUMN B TO C','A',TSQLAlterTableStatement));
+  AssertEquals('One operation',1,A.Operations.Count);
+  R:=TSQLAlterTableFieldNameOperation(CheckClass(A.Operations[0],TSQLAlterTableFieldNameOperation));
+  AssertidentifierName('Old field name','B',R.ObjectName);
+  AssertidentifierName('New field name','C',R.NewName);
+end;
+
+procedure TTestTableParser.TestAlterFieldType;
+Var
+  A : TSQLAlterTableStatement;
+  R : TSQLAlterTableFieldTypeOperation;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A ALTER COLUMN B TYPE INT','A',TSQLAlterTableStatement));
+  AssertEquals('One operation',1,A.Operations.Count);
+  R:=TSQLAlterTableFieldTypeOperation(CheckClass(A.Operations[0],TSQLAlterTableFieldTypeOperation));
+  AssertidentifierName('Old field name','B',R.ObjectName);
+  AssertNotNull('Have field type',R.NewType);
+  Checkclass(R.NewType,TSQLTypeDefinition);
+  AssertEquals('Correct data type',sdtInteger,R.NewType.DataType);
+end;
+
+procedure TTestTableParser.TestAlterFieldPosition;
+Var
+  A : TSQLAlterTableStatement;
+  R : TSQLAlterTableFieldPositionOperation;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A ALTER COLUMN B POSITION 3','A',TSQLAlterTableStatement));
+  AssertEquals('One operation',1,A.Operations.Count);
+  R:=TSQLAlterTableFieldPositionOperation(CheckClass(A.Operations[0],TSQLAlterTableFieldPositionOperation));
+  AssertidentifierName('Old field name','B',R.ObjectName);
+  AssertEquals('Correct position',3,R.NewPosition);
+end;
+
+procedure TTestTableParser.TestAlterAddField;
+Var
+  A : TSQLAlterTableStatement;
+  F : TSQLAlterTableAddFieldOperation;
+  D : TSQLTableFieldDef;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A ADD B INT','A',TSQLAlterTableStatement));
+  AssertEquals('One operation',1,A.Operations.Count);
+  F:=TSQLAlterTableAddFieldOperation(CheckClass(A.Operations[0],TSQLAlterTableAddFieldOperation));
+  AssertNotNull('Have element',F.Element);
+  D:=TSQLTableFieldDef(CheckClass(F.Element,TSQLTableFieldDef));
+  AssertIdentifierName('New field name','B',D.FieldName);
+  AssertNotNull('Have fielddef',D.FieldType);
+  AssertEquals('Correct field type',sdtINteger,D.FieldType.DataType);
+end;
+
+procedure TTestTableParser.TestAlterAddFields;
+
+Var
+  A : TSQLAlterTableStatement;
+  F : TSQLAlterTableAddFieldOperation;
+  D : TSQLTableFieldDef;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A ADD B INT, ADD C CHAR(50)','A',TSQLAlterTableStatement));
+  AssertEquals('Two operations',2,A.Operations.Count);
+  F:=TSQLAlterTableAddFieldOperation(CheckClass(A.Operations[0],TSQLAlterTableAddFieldOperation));
+  AssertNotNull('Have element',F.Element);
+  D:=TSQLTableFieldDef(CheckClass(F.Element,TSQLTableFieldDef));
+  AssertIdentifierName('New field name','B',D.FieldName);
+  AssertNotNull('Have fielddef',D.FieldType);
+  AssertEquals('Correct field type',sdtINteger,D.FieldType.DataType);
+  F:=TSQLAlterTableAddFieldOperation(CheckClass(A.Operations[1],TSQLAlterTableAddFieldOperation));
+  AssertNotNull('Have element',F.Element);
+  D:=TSQLTableFieldDef(CheckClass(F.Element,TSQLTableFieldDef));
+  AssertIdentifierName('New field name','C',D.FieldName);
+  AssertNotNull('Have fielddef',D.FieldType);
+  AssertEquals('Correct field type',sdtChar,D.FieldType.DataType);
+  AssertEquals('Correct field lengthe',50,D.FieldType.Len);
+end;
+
+procedure TTestTableParser.TestAlterAddPrimarykey;
+Var
+  A : TSQLAlterTableStatement;
+  F : TSQLAlterTableAddConstraintOperation;
+  D : TSQLTablePrimaryKeyConstraintDef;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A ADD PRIMARY KEY (B)','A',TSQLAlterTableStatement));
+  AssertEquals('One operation',1,A.Operations.Count);
+  F:=TSQLAlterTableAddConstraintOperation(CheckClass(A.Operations[0],TSQLAlterTableAddConstraintOperation));
+  AssertNotNull('Have element',F.Element);
+  D:=TSQLTablePrimaryKeyConstraintDef(CheckClass(F.Element,TSQLTablePrimaryKeyConstraintDef));
+  AssertNull('No constraint name',D.ConstraintName);
+  AssertEquals('Have 1 field',1,D.FieldList.Count);
+  AssertIdentifierName('fieldname','B',D.FieldList[0]);
+end;
+
+procedure TTestTableParser.TestAlterAddNamedPrimarykey;
+Var
+  A : TSQLAlterTableStatement;
+  F : TSQLAlterTableAddConstraintOperation;
+  D : TSQLTablePrimaryKeyConstraintDef;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A ADD CONSTRAINT U_K PRIMARY KEY (B)','A',TSQLAlterTableStatement));
+  AssertEquals('One operation',1,A.Operations.Count);
+  F:=TSQLAlterTableAddConstraintOperation(CheckClass(A.Operations[0],TSQLAlterTableAddConstraintOperation));
+  AssertNotNull('Have element',F.Element);
+  D:=TSQLTablePrimaryKeyConstraintDef(CheckClass(F.Element,TSQLTablePrimaryKeyConstraintDef));
+  AssertIdentifierName('No constraint name','U_K',D.ConstraintName);
+  AssertEquals('Have 1 field',1,D.FieldList.Count);
+  AssertIdentifierName('fieldname','B',D.FieldList[0]);
+end;
+
+procedure TTestTableParser.TestAlterAddCheckConstraint;
+
+Var
+  A : TSQLAlterTableStatement;
+  F : TSQLAlterTableAddConstraintOperation;
+  D : TSQLTableCheckConstraintDef;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A ADD CHECK (B<>0)','A',TSQLAlterTableStatement));
+  AssertEquals('One operation',1,A.Operations.Count);
+  F:=TSQLAlterTableAddConstraintOperation(CheckClass(A.Operations[0],TSQLAlterTableAddConstraintOperation));
+  AssertNotNull('Have element',F.Element);
+  D:=TSQLTableCheckConstraintDef(CheckClass(F.Element,TSQLTableCheckConstraintDef));
+  AssertNull('Constaintname',D.ConstraintName);
+  AssertNotNull('Check expression assigned',D.Check);
+  CheckClass(D.Check,TSQLBinaryExpression);
+end;
+
+procedure TTestTableParser.TestAlterAddNamedCheckConstraint;
+
+Var
+  A : TSQLAlterTableStatement;
+  F : TSQLAlterTableAddConstraintOperation;
+  D : TSQLTableCheckConstraintDef;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A ADD CONSTRAINT C_A CHECK (B<>0)','A',TSQLAlterTableStatement));
+  AssertEquals('One operation',1,A.Operations.Count);
+  F:=TSQLAlterTableAddConstraintOperation(CheckClass(A.Operations[0],TSQLAlterTableAddConstraintOperation));
+  AssertNotNull('Have element',F.Element);
+  D:=TSQLTableCheckConstraintDef(CheckClass(F.Element,TSQLTableCheckConstraintDef));
+  AssertIdentifierName('Constaintname','C_A',D.ConstraintName);
+  AssertNotNull('Check expression assigned',D.Check);
+  CheckClass(D.Check,TSQLBinaryExpression);
+end;
+
+procedure TTestTableParser.TestAlterAddForeignkey;
+
+Var
+  A : TSQLAlterTableStatement;
+  F : TSQLAlterTableAddConstraintOperation;
+  D : TSQLTableForeignKeyConstraintDef;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A ADD FOREIGN KEY (B) REFERENCES C(D)','A',TSQLAlterTableStatement));
+  AssertEquals('One operation',1,A.Operations.Count);
+  F:=TSQLAlterTableAddConstraintOperation(CheckClass(A.Operations[0],TSQLAlterTableAddConstraintOperation));
+  AssertNotNull('Have element',F.Element);
+  D:=TSQLTableForeignKeyConstraintDef(CheckClass(F.Element,TSQLTableForeignKeyConstraintDef));
+  AssertNull('No constraint name',D.ConstraintName);
+  AssertEquals('Have 1 field',1,D.FieldList.Count);
+  AssertIdentifierName('fieldname','B',D.FieldList[0]);
+  AssertIdentifierName('Target table name','C',D.Definition.TableName);
+  AssertEquals('One field in primary key target',1,D.Definition.FieldList.Count);
+  AssertIdentifierName('target fieldname','D',D.Definition.FieldList[0]);
+end;
+
+procedure TTestTableParser.TestAlterAddNamedForeignkey;
+Var
+  A : TSQLAlterTableStatement;
+  F : TSQLAlterTableAddConstraintOperation;
+  D : TSQLTableForeignKeyConstraintDef;
+
+begin
+  A:=TSQLAlterTableStatement(TestCreateStatement('ALTER TABLE A ADD CONSTRAINT F_A FOREIGN KEY (B) REFERENCES C(D)','A',TSQLAlterTableStatement));
+  AssertEquals('One operation',1,A.Operations.Count);
+  F:=TSQLAlterTableAddConstraintOperation(CheckClass(A.Operations[0],TSQLAlterTableAddConstraintOperation));
+  AssertNotNull('Have element',F.Element);
+  D:=TSQLTableForeignKeyConstraintDef(CheckClass(F.Element,TSQLTableForeignKeyConstraintDef));
+  AssertIdentifierName('constraint name','F_A',D.ConstraintName);
+  AssertEquals('Have 1 field',1,D.FieldList.Count);
+  AssertIdentifierName('fieldname','B',D.FieldList[0]);
+  AssertIdentifierName('Target table name','C',D.Definition.TableName);
+  AssertEquals('One field in primary key target',1,D.Definition.FieldList.Count);
+  AssertIdentifierName('target fieldname','D',D.Definition.FieldList[0]);
+end;
+
+{ TTestDeleteParser }
+
+function TTestDeleteParser.TestDelete(const ASource,ATable: String
+  ): TSQLDeleteStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLDeleteStatement(CheckClass(FToFree,TSQLDeleteStatement));
+  AssertIdentifierName('Correct table name',ATable,Result.TableName);
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestDeleteParser.TestSimpleDelete;
+
+Var
+  D : TSQLDeleteStatement;
+
+begin
+  D:=TestDelete('DELETE FROM A','A');
+  AssertNull('No where',D.WhereClause);
+end;
+
+procedure TTestDeleteParser.TestSimpleDeleteAlias;
+Var
+  D : TSQLDeleteStatement;
+begin
+  D:=TestDelete('DELETE FROM A B','A');
+  AssertIdentifierName('Alias name','B',D.AliasName);
+  AssertNull('No where',D.WhereClause);
+end;
+
+procedure TTestDeleteParser.TestDeleteWhereNull;
+Var
+  D : TSQLDeleteStatement;
+  B : TSQLBinaryExpression;
+  I : TSQLIdentifierExpression;
+  L : TSQLLiteralExpression;
+
+begin
+  D:=TestDelete('DELETE FROM A WHERE B IS NULL','A');
+  AssertNotNull('No where',D.WhereClause);
+  B:=TSQLBinaryExpression(CheckClass(D.WhereClause,TSQLBinaryExpression));
+  AssertEquals('Is null operation',boIs,B.Operation);
+  I:=TSQLIdentifierExpression(CheckClass(B.Left,TSQLIdentifierExpression));
+  AssertIdentifierName('Correct field name','B',I.Identifier);
+  L:=TSQLLiteralExpression(CheckClass(B.Right,TSQLLiteralExpression));
+  CheckClass(L.Literal,TSQLNullLiteral);
+end;
+
+{ TTestUpdateParser }
+
+function TTestUpdateParser.TestUpdate(const ASource, ATable: String
+  ): TSQLUpdateStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLUpdateStatement(CheckClass(FToFree,TSQLUpdateStatement));
+  AssertIdentifierName('Correct table name',ATable,Result.TableName);
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestUpdateParser.TestUpdateOneField;
+
+Var
+  U : TSQLUpdateStatement;
+  P : TSQLUpdatePair;
+  E : TSQLLiteralExpression;
+  I : TSQLIntegerLiteral;
+
+begin
+  U:=TestUpdate('UPDATE A SET B=1','A');
+  AssertEquals('One field updated',1,U.Values.Count);
+  P:=TSQLUpdatePair(CheckClass(U.Values[0],TSQLUpdatePair));
+  AssertIdentifierName('Correct field name','B',P.FieldName);
+  E:=TSQLLiteralExpression(CheckClass(P.Value,TSQLLiteralExpression));
+  I:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Value 1',1,I.Value);
+  AssertNull('No where clause',U.WhereClause);
+end;
+
+procedure TTestUpdateParser.TestUpdateOneFieldFull;
+Var
+  U : TSQLUpdateStatement;
+  P : TSQLUpdatePair;
+  E : TSQLLiteralExpression;
+  I : TSQLIntegerLiteral;
+
+begin
+  U:=TestUpdate('UPDATE A SET A.B=1','A');
+  AssertEquals('One field updated',1,U.Values.Count);
+  P:=TSQLUpdatePair(CheckClass(U.Values[0],TSQLUpdatePair));
+  AssertIdentifierName('Correct field name','A.B',P.FieldName);
+  E:=TSQLLiteralExpression(CheckClass(P.Value,TSQLLiteralExpression));
+  I:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Value 1',1,I.Value);
+  AssertNull('No where clause',U.WhereClause);
+end;
+
+procedure TTestUpdateParser.TestUpdateTwoFields;
+Var
+  U : TSQLUpdateStatement;
+  P : TSQLUpdatePair;
+  E : TSQLLiteralExpression;
+  I : TSQLIntegerLiteral;
+
+begin
+  U:=TestUpdate('UPDATE A SET B=1, C=2','A');
+  AssertEquals('One field updated',2,U.Values.Count);
+  P:=TSQLUpdatePair(CheckClass(U.Values[0],TSQLUpdatePair));
+  AssertIdentifierName('Correct field name','B',P.FieldName);
+  E:=TSQLLiteralExpression(CheckClass(P.Value,TSQLLiteralExpression));
+  I:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Value 1',1,I.Value);
+  P:=TSQLUpdatePair(CheckClass(U.Values[1],TSQLUpdatePair));
+  AssertIdentifierName('Correct field name','C',P.FieldName);
+  E:=TSQLLiteralExpression(CheckClass(P.Value,TSQLLiteralExpression));
+  I:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Value 2',2,I.Value);
+  AssertNull('No where clause',U.WhereClause);
+end;
+
+procedure TTestUpdateParser.TestUpdateOneFieldWhereIsNull;
+Var
+  U : TSQLUpdateStatement;
+  P : TSQLUpdatePair;
+  E : TSQLLiteralExpression;
+  I : TSQLIntegerLiteral;
+  B : TSQLBinaryExpression;
+  IE : TSQLIdentifierExpression;
+  L : TSQLLiteralExpression;
+
+begin
+  U:=TestUpdate('UPDATE A SET B=1 WHERE B IS NULL','A');
+  AssertEquals('One field updated',1,U.Values.Count);
+  P:=TSQLUpdatePair(CheckClass(U.Values[0],TSQLUpdatePair));
+  AssertIdentifierName('Correct field name','B',P.FieldName);
+  E:=TSQLLiteralExpression(CheckClass(P.Value,TSQLLiteralExpression));
+  I:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Value 1',1,I.Value);
+  AssertNotNull('where clause',U.WhereClause);
+  B:=TSQLBinaryExpression(CheckClass(U.WhereClause,TSQLBinaryExpression));
+  AssertEquals('Is null operation',boIs,B.Operation);
+  IE:=TSQLIdentifierExpression(CheckClass(B.Left,TSQLIdentifierExpression));
+  AssertIdentifierName('Correct field name','B',IE.Identifier);
+  L:=TSQLLiteralExpression(CheckClass(B.Right,TSQLLiteralExpression));
+  CheckClass(L.Literal,TSQLNullLiteral);
+end;
+
+{ TTestInsertParser }
+
+function TTestInsertParser.TestInsert(const ASource, ATable: String
+  ): TSQLInsertStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLInsertStatement(CheckClass(FToFree,TSQLInsertStatement));
+  AssertIdentifierName('Correct table name',ATable,Result.TableName);
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestInsertParser.TestInsertOneField;
+
+Var
+  I : TSQLInsertStatement;
+  E : TSQLLiteralExpression;
+  L : TSQLIntegerLiteral;
+
+begin
+  I:=TestInsert('INSERT INTO A (B) VALUES (1)','A');
+  AssertNotNull('Have fields',I.Fields);
+  AssertEquals('1 field',1,I.Fields.Count);
+  AssertIdentifierName('Correct field name','B',I.Fields[0]);
+  AssertNotNull('Have values',I.Values);
+  AssertEquals('Have 1 value',1,I.Values.Count);
+  E:=TSQLLiteralExpression(CheckClass(I.Values[0],TSQLLiteralExpression));
+  L:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',1,L.Value);
+end;
+
+procedure TTestInsertParser.TestInsertTwoFields;
+
+Var
+  I : TSQLInsertStatement;
+  E : TSQLLiteralExpression;
+  L : TSQLIntegerLiteral;
+
+begin
+  I:=TestInsert('INSERT INTO A (B,C) VALUES (1,2)','A');
+  AssertNotNull('Have fields',I.Fields);
+  AssertEquals('2 fields',2,I.Fields.Count);
+  AssertIdentifierName('Correct field 1 name','B',I.Fields[0]);
+  AssertIdentifierName('Correct field 2 name','C',I.Fields[1]);
+  AssertNotNull('Have values',I.Values);
+  AssertEquals('Have 2 values',2,I.Values.Count);
+  E:=TSQLLiteralExpression(CheckClass(I.Values[0],TSQLLiteralExpression));
+  L:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',1,L.Value);
+  E:=TSQLLiteralExpression(CheckClass(I.Values[1],TSQLLiteralExpression));
+  L:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',2,L.Value);
+end;
+
+procedure TTestInsertParser.TestInsertOneValue;
+Var
+  I : TSQLInsertStatement;
+  E : TSQLLiteralExpression;
+  L : TSQLIntegerLiteral;
+
+begin
+  I:=TestInsert('INSERT INTO A VALUES (1)','A');
+  AssertNull('Have no fields',I.Fields);
+  AssertNotNull('Have values',I.Values);
+  AssertEquals('Have 1 value',1,I.Values.Count);
+  E:=TSQLLiteralExpression(CheckClass(I.Values[0],TSQLLiteralExpression));
+  L:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',1,L.Value);
+end;
+
+procedure TTestInsertParser.TestInsertTwoValues;
+Var
+  I : TSQLInsertStatement;
+  E : TSQLLiteralExpression;
+  L : TSQLIntegerLiteral;
+
+begin
+  I:=TestInsert('INSERT INTO A VALUES (1,2)','A');
+  AssertNull('Have no fields',I.Fields);
+  AssertNotNull('Have values',I.Values);
+  AssertEquals('Have 2 values',2,I.Values.Count);
+  E:=TSQLLiteralExpression(CheckClass(I.Values[0],TSQLLiteralExpression));
+  L:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',1,L.Value);
+  E:=TSQLLiteralExpression(CheckClass(I.Values[1],TSQLLiteralExpression));
+  L:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',2,L.Value);
+end;
+
+{ TTestSelectParser }
+
+function TTestSelectParser.TestSelect(const ASource : String): TSQLSelectStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLSelectStatement(CheckClass(FToFree,TSQLSelectStatement));
+  FSelect:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestSelectParser.TestSelectError(const ASource: String);
+begin
+  FErrSource:=ASource;
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestSelectParser.TestSelectOneFieldOneTable;
+begin
+  TestSelect('SELECT B FROM A');
+  AssertNull('No transaction name',Select.TransactionName);
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+end;
+
+procedure TTestSelectParser.TestSelectOneFieldOneTableTransaction;
+begin
+  TestSelect('SELECT TRANSACTION C B FROM A');
+  AssertIdentifierName('Correct transaction name','C',Select.TransactionName);
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+end;
+
+procedure TTestSelectParser.TestSelectOneArrayFieldOneTable;
+Var
+  E : TSQLIdentifierExpression;
+begin
+  TestSelect('SELECT B[1] FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  E:=TSQLIdentifierExpression(CheckClass(TSQLSelectField(Select.Fields[0]).Expression,TSQLIdentifierExpression));
+  AssertEquals('Element 1 in array ',1,E.ElementIndex);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+end;
+
+procedure TTestSelectParser.TestSelectTwoFieldsOneTable;
+begin
+  TestSelect('SELECT B,C FROM A');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+end;
+
+procedure TTestSelectParser.TestSelectOneFieldAliasOneTable;
+
+begin
+  TestSelect('SELECT B AS C FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B','C');
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+end;
+
+procedure TTestSelectParser.TestSelectTwoFieldAliasesOneTable;
+begin
+  TestSelect('SELECT B AS D,C AS E FROM A');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B','D');
+  AssertField(Select.Fields[1],'C','E');
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+end;
+
+procedure TTestSelectParser.TestSelectOneDistinctFieldOneTable;
+begin
+  TestSelect('SELECT DISTINCT B FROM A');
+  AssertEquals('DISTINCT Query',True,Select.Distinct);
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+end;
+
+procedure TTestSelectParser.TestSelectOneAllFieldOneTable;
+begin
+  TestSelect('SELECT ALL B FROM A');
+  AssertEquals('ALL Query',True,Select.All);
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+end;
+
+procedure TTestSelectParser.TestSelectAsteriskOneTable;
+begin
+  TestSelect('SELECT * FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  CheckClass(Select.Fields[0],TSQLSelectAsterisk);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+end;
+
+procedure TTestSelectParser.TestSelectDistinctAsteriskOneTable;
+begin
+  TestSelect('SELECT DISTINCT * FROM A');
+  AssertEquals('DISTINCT Query',True,Select.Distinct);
+  AssertEquals('One field',1,Select.Fields.Count);
+  CheckClass(Select.Fields[0],TSQLSelectAsterisk);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+end;
+
+procedure TTestSelectParser.TestSelectOneFieldOneTableAlias;
+begin
+  TestSelect('SELECT C.B FROM A C');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'C.B');
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+end;
+
+procedure TTestSelectParser.TestSelectTwoFieldsTwoTables;
+begin
+  TestSelect('SELECT B,C FROM A,D');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertEquals('Two table',2,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertTable(Select.Tables[1],'D');
+end;
+
+procedure TTestSelectParser.TestSelectTwoFieldsTwoTablesJoin;
+
+Var
+  J : TSQLJoinTableReference;
+
+begin
+  TestSelect('SELECT B,C FROM A JOIN D ON E=F');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertEquals('One table',1,Select.Tables.Count);
+  J:=AssertJoin(Select.Tables[0],'A','D',jtNone);
+  AssertJoinOn(J.JoinClause,'E','F',boEq);
+end;
+
+procedure TTestSelectParser.TestSelectTwoFieldsTwoInnerTablesJoin;
+Var
+  J : TSQLJoinTableReference;
+
+begin
+  TestSelect('SELECT B,C FROM A INNER JOIN D ON E=F');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertEquals('One table',1,Select.Tables.Count);
+  J:=AssertJoin(Select.Tables[0],'A','D',jtInner);
+  AssertJoinOn(J.JoinClause,'E','F',boEq);
+end;
+
+procedure TTestSelectParser.TestSelectTwoFieldsTwoOuterTablesJoin;
+Var
+  J : TSQLJoinTableReference;
+
+begin
+  TestSelect('SELECT B,C FROM A OUTER JOIN D ON E=F');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertEquals('One table',1,Select.Tables.Count);
+  J:=AssertJoin(Select.Tables[0],'A','D',jtOuter);
+  AssertJoinOn(J.JoinClause,'E','F',boEq);
+end;
+
+procedure TTestSelectParser.TestSelectTwoFieldsTwoLeftTablesJoin;
+Var
+  J : TSQLJoinTableReference;
+
+begin
+  TestSelect('SELECT B,C FROM A LEFT JOIN D ON E=F');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertEquals('One table',1,Select.Tables.Count);
+  J:=AssertJoin(Select.Tables[0],'A','D',jtLeft);
+  AssertJoinOn(J.JoinClause,'E','F',boEq);
+end;
+
+procedure TTestSelectParser.TestSelectTwoFieldsTwoRightTablesJoin;
+Var
+  J : TSQLJoinTableReference;
+
+begin
+  TestSelect('SELECT B,C FROM A RIGHT JOIN D ON E=F');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertEquals('One table',1,Select.Tables.Count);
+  J:=AssertJoin(Select.Tables[0],'A','D',jtRight);
+  AssertJoinOn(J.JoinClause,'E','F',boEq);
+end;
+
+procedure TTestSelectParser.TestSelectTwoFieldsThreeTablesJoin;
+
+Var
+  J : TSQLJoinTableReference;
+
+begin
+  TestSelect('SELECT B,C FROM A JOIN D ON E=F JOIN G ON (H=I)');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertEquals('One table',1,Select.Tables.Count);
+  j:=AssertJoin(Select.Tables[0],'','G',jtNone);
+  AssertJoinOn(J.JoinClause,'H','I',boEq);
+  J:=AssertJoin(J.Left,'A','D',jtNone);
+  AssertJoinOn(J.JoinClause,'E','F',boEq);
+end;
+
+procedure TTestSelectParser.TestSelectTwoFieldsBracketThreeTablesJoin;
+
+Var
+  J : TSQLJoinTableReference;
+
+begin
+  TestSelect('SELECT B,C FROM (A JOIN D ON E=F) JOIN G ON (H=I)');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertEquals('One table',1,Select.Tables.Count);
+  j:=AssertJoin(Select.Tables[0],'','G',jtNone);
+  AssertJoinOn(J.JoinClause,'H','I',boEq);
+  J:=AssertJoin(J.Left,'A','D',jtNone);
+  AssertJoinOn(J.JoinClause,'E','F',boEq);
+end;
+
+procedure TTestSelectParser.TestSelectTwoFieldsThreeBracketTablesJoin;
+Var
+  J : TSQLJoinTableReference;
+
+begin
+  TestSelect('SELECT B,C FROM A JOIN (D JOIN G ON E=F)  ON (H=I)');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertEquals('One table',1,Select.Tables.Count);
+  j:=AssertJoin(Select.Tables[0],'A','',jtNone);
+  AssertJoinOn(J.JoinClause,'H','I',boEq);
+  j:=AssertJoin(J.Right,'D','G',jtNone);
+  AssertJoinOn(J.JoinClause,'E','F',boEq);
+end;
+
+procedure TTestSelectParser.TestAggregateCount;
+
+begin
+  TestSelect('SELECT COUNT(B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afCount,'B',aoNone,'');
+end;
+
+procedure TTestSelectParser.TestAggregateCountAsterisk;
+
+begin
+  TestSelect('SELECT COUNT(*) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afCount,'',aoAsterisk,'');
+end;
+
+procedure TTestSelectParser.TestAggregateCountAll;
+begin
+  TestSelect('SELECT COUNT(ALL B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afCount,'B',aoAll,'');
+end;
+
+procedure TTestSelectParser.TestAggregateCountDistinct;
+begin
+  TestSelect('SELECT COUNT(DISTINCT B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afCount,'B',aoDistinct,'');
+end;
+
+procedure TTestSelectParser.TestAggregateMax;
+
+begin
+  TestSelect('SELECT MAX(B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afMax,'B',aoNone,'');
+end;
+
+procedure TTestSelectParser.TestAggregateMaxAsterisk;
+
+begin
+  TestSelectError('SELECT Max(*) FROM A');
+end;
+
+procedure TTestSelectParser.TestAggregateMaxAll;
+begin
+  TestSelect('SELECT MAX(ALL B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afMax,'B',aoAll,'');
+end;
+
+procedure TTestSelectParser.TestAggregateMaxDistinct;
+begin
+  TestSelect('SELECT MAX(DISTINCT B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afMax,'B',aoDistinct,'');
+end;
+
+procedure TTestSelectParser.TestAggregateMin;
+
+begin
+  TestSelect('SELECT Min(B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afMin,'B',aoNone,'');
+end;
+
+procedure TTestSelectParser.TestAggregateMinAsterisk;
+
+begin
+  TestSelectError('SELECT Min(*) FROM A');
+end;
+
+procedure TTestSelectParser.TestAggregateMinAll;
+begin
+  TestSelect('SELECT Min(ALL B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afMin,'B',aoAll,'');
+end;
+
+procedure TTestSelectParser.TestAggregateMinDistinct;
+begin
+  TestSelect('SELECT Min(DISTINCT B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afMin,'B',aoDistinct,'');
+end;
+
+procedure TTestSelectParser.TestAggregateSum;
+
+begin
+  TestSelect('SELECT Sum(B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afSum,'B',aoNone,'');
+end;
+
+procedure TTestSelectParser.TestAggregateSumAsterisk;
+
+begin
+  TestSelectError('SELECT Sum(*) FROM A');
+end;
+
+procedure TTestSelectParser.TestAggregateSumAll;
+begin
+  TestSelect('SELECT Sum(ALL B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afSum,'B',aoAll,'');
+end;
+
+procedure TTestSelectParser.TestAggregateSumDistinct;
+begin
+  TestSelect('SELECT Sum(DISTINCT B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afSum,'B',aoDistinct,'');
+end;
+
+procedure TTestSelectParser.TestAggregateAvg;
+
+begin
+  TestSelect('SELECT Avg(B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afAvg,'B',aoNone,'');
+end;
+
+procedure TTestSelectParser.TestAggregateAvgAsterisk;
+
+begin
+  TestSelectError('SELECT Avg(*) FROM A');
+end;
+
+procedure TTestSelectParser.TestAggregateAvgAll;
+begin
+  TestSelect('SELECT Avg(ALL B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afAvg,'B',aoAll,'');
+end;
+
+procedure TTestSelectParser.TestAggregateAvgDistinct;
+begin
+  TestSelect('SELECT Avg(DISTINCT B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertAggregate(Select.Fields[0],afAvg,'B',aoDistinct,'');
+end;
+
+procedure TTestSelectParser.TestUpperConst;
+
+Var
+  E : TSQLFunctionCallExpression;
+  L : TSQLLiteralExpression;
+  S : TSQLStringLiteral;
+
+begin
+  TestSelect('SELECT UPPER(''a'') FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  CheckClass(Select.Fields[0],TSQLSelectField);
+  E:=TSQLFunctionCallExpression(CheckClass(TSQLSelectField(Select.Fields[0]).Expression,TSQLFunctionCallExpression));
+  AssertEquals('UPPER function name','UPPER',E.Identifier);
+  AssertEquals('One function element',1,E.Arguments.Count);
+  L:=TSQLLiteralExpression(CheckClass(E.Arguments[0],TSQLLiteralExpression));
+  S:=TSQLStringLiteral(CheckClass(L.Literal,TSQLStringLiteral));
+  AssertEquals('Correct constant','a',S.Value);
+end;
+
+procedure TTestSelectParser.TestUpperError;
+
+begin
+  TestSelectError('SELECT UPPER(''A'',''B'') FROM C');
+end;
+
+procedure TTestSelectParser.TestGenID;
+Var
+  E : TSQLGenIDExpression;
+  L : TSQLLiteralExpression;
+  S : TSQLIntegerLiteral;
+
+begin
+  TestSelect('SELECT GEN_ID(GEN_B,1) FROM RDB$DATABASE');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'RDB$DATABASE');
+  CheckClass(Select.Fields[0],TSQLSelectField);
+  E:=TSQLGenIDExpression(CheckClass(TSQLSelectField(Select.Fields[0]).Expression,TSQLGenIDExpression));
+  AssertIdentifierName('GenID generator function name','GEN_B',E.Generator);
+  L:=TSQLLiteralExpression(CheckClass(E.Value,TSQLLiteralExpression));
+  S:=TSQLIntegerLiteral(CheckClass(L.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct constant',1,S.Value);
+end;
+
+procedure TTestSelectParser.TestGenIDError1;
+begin
+  TestSelectError('SELECT GEN_ID(''GEN_B'',1) FROM RDB$DATABASE');
+end;
+
+procedure TTestSelectParser.TestGenIDError2;
+begin
+  TestSelectError('SELECT GEN_ID(''GEN_B'') FROM RDB$DATABASE');
+end;
+
+procedure TTestSelectParser.TestCastSimple;
+var
+  C : TSQLCastExpression;
+  L : TSQLLiteralExpression;
+  S : TSQLIntegerLiteral;
+
+begin
+  TestSelect('SELECT CAST(1 AS VARCHAR(5)) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  CheckClass(Select.Fields[0],TSQLSelectField);
+  C:=TSQLCastExpression(CheckClass(TSQLSelectField(Select.Fields[0]).Expression,TSQLCastExpression));
+  L:=TSQLLiteralExpression(CheckClass(C.Value,TSQLLiteralExpression));
+  S:=TSQLIntegerLiteral(CheckClass(L.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct constant',1,S.Value);
+  AssertTypeDefaults(C.NewType,5);
+  AssertEquals('Correct type',sdtVarChar,C.NewType.DataType);
+end;
+
+procedure TTestSelectParser.DoExtractSimple(Expected: TSQLExtractElement);
+
+var
+  E : TSQLExtractExpression;
+  I : TSQLIdentifierExpression;
+
+begin
+  TestSelect('SELECT EXTRACT('+ExtractElementNames[Expected]+' FROM B) FROM A');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  CheckClass(Select.Fields[0],TSQLSelectField);
+  E:=TSQLExtractExpression(CheckClass(TSQLSelectField(Select.Fields[0]).Expression,TSQLExtractExpression));
+  I:=TSQLIdentifierExpression(CheckClass(E.Value,TSQLIdentifierExpression));
+  AssertIdentifierName('Correct field','B',I.Identifier);
+  FreeAndNil(FParser);
+  FreeAndNil(FSource);
+  FreeAndNil(FToFree);
+end;
+
+
+procedure TTestSelectParser.TestExtractSimple;
+Var
+  E : TSQLExtractElement;
+begin
+  For E:=Low(TSQLExtractElement) to High(TSQLExtractElement) do
+    DoExtractSimple(E);
+end;
+
+procedure TTestSelectParser.TestOrderByOneField;
+
+begin
+  TestSelect('SELECT B FROM A ORDER BY C');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertTable(Select.Tables[0],'A');
+  AssertEquals('One order by field',1,Select.Orderby.Count);
+  AssertOrderBy(Select.OrderBy[0],'C',0,obAscending);
+end;
+
+procedure TTestSelectParser.TestOrderByTwoFields;
+
+begin
+  TestSelect('SELECT B FROM A ORDER BY C,D');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertTable(Select.Tables[0],'A');
+  AssertEquals('Two order by fields',2,Select.Orderby.Count);
+  AssertOrderBy(Select.OrderBy[0],'C',0,obAscending);
+  AssertOrderBy(Select.OrderBy[1],'D',0,obAscending);
+end;
+
+procedure TTestSelectParser.TestOrderByThreeFields;
+begin
+  TestSelect('SELECT B FROM A ORDER BY C,D,E');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertTable(Select.Tables[0],'A');
+  AssertEquals('Three order by fields',3,Select.Orderby.Count);
+  AssertOrderBy(Select.OrderBy[0],'C',0,obAscending);
+  AssertOrderBy(Select.OrderBy[1],'D',0,obAscending);
+  AssertOrderBy(Select.OrderBy[2],'E',0,obAscending);
+end;
+procedure TTestSelectParser.TestOrderByOneDescField;
+
+begin
+  TestSelect('SELECT B FROM A ORDER BY C DESC');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertTable(Select.Tables[0],'A');
+  AssertEquals('One order by field',1,Select.Orderby.Count);
+  AssertOrderBy(Select.OrderBy[0],'C',0,obDescending);
+end;
+
+procedure TTestSelectParser.TestOrderByTwoDescFields;
+
+begin
+  TestSelect('SELECT B FROM A ORDER BY C DESC, D DESCENDING');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertTable(Select.Tables[0],'A');
+  AssertEquals('Two order by fields',2,Select.Orderby.Count);
+  AssertOrderBy(Select.OrderBy[0],'C',0,obDescending);
+  AssertOrderBy(Select.OrderBy[1],'D',0,obDescending);
+end;
+
+procedure TTestSelectParser.TestOrderByThreeDescFields;
+begin
+  TestSelect('SELECT B FROM A ORDER BY C DESC,D DESCENDING, E DESC');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertTable(Select.Tables[0],'A');
+  AssertEquals('Three order by fields',3,Select.Orderby.Count);
+  AssertOrderBy(Select.OrderBy[0],'C',0,obDescending);
+  AssertOrderBy(Select.OrderBy[1],'D',0,obDescending);
+  AssertOrderBy(Select.OrderBy[2],'E',0,obDescending);
+end;
+
+procedure TTestSelectParser.TestOrderByOneColumn;
+begin
+  TestSelect('SELECT B FROM A ORDER BY 1');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertTable(Select.Tables[0],'A');
+  AssertEquals('One order by field',1,Select.Orderby.Count);
+  AssertOrderBy(Select.OrderBy[0],'',1,obAscending);
+end;
+
+procedure TTestSelectParser.TestOrderByTwoColumns;
+
+begin
+  TestSelect('SELECT B,C FROM A ORDER BY 1,2');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertTable(Select.Tables[0],'A');
+  AssertEquals('Two order by fields',2,Select.Orderby.Count);
+  AssertOrderBy(Select.OrderBy[0],'',1,obAscending);
+  AssertOrderBy(Select.OrderBy[1],'',2,obAscending);
+end;
+
+procedure TTestSelectParser.TestOrderByTwoColumnsDesc;
+
+begin
+  TestSelect('SELECT B,C FROM A ORDER BY 1 DESC,2');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertTable(Select.Tables[0],'A');
+  AssertEquals('Two order by fields',2,Select.Orderby.Count);
+  AssertOrderBy(Select.OrderBy[0],'',1,obDescending);
+  AssertOrderBy(Select.OrderBy[1],'',2,obAscending);
+end;
+
+procedure TTestSelectParser.TestOrderByCollate;
+
+Var
+  O : TSQLOrderByElement;
+
+begin
+  TestSelect('SELECT B,C FROM A ORDER BY D COLLATE E');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertTable(Select.Tables[0],'A');
+  AssertEquals('One order by fields',1,Select.Orderby.Count);
+  O:=AssertOrderBy(Select.OrderBy[0],'D',0,obAscending);
+  AssertIdentifierName('Correct collation','E',O.Collation);
+end;
+
+procedure TTestSelectParser.TestOrderByCollateDesc;
+
+Var
+  O : TSQLOrderByElement;
+
+begin
+  TestSelect('SELECT B,C FROM A ORDER BY D COLLATE E');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertTable(Select.Tables[0],'A');
+  AssertEquals('One order by fields',1,Select.Orderby.Count);
+  O:=AssertOrderBy(Select.OrderBy[0],'D',0,obAscending);
+  AssertIdentifierName('Correct collation','E',O.Collation);
+end;
+
+procedure TTestSelectParser.TestOrderByCollateDescTwoFields;
+
+Var
+  O : TSQLOrderByElement;
+
+begin
+  TestSelect('SELECT B,C FROM A ORDER BY D COLLATE E DESC,F COLLATE E');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertTable(Select.Tables[0],'A');
+  AssertEquals('Two order by fields',2,Select.Orderby.Count);
+  O:=AssertOrderBy(Select.OrderBy[0],'D',0,obDescending);
+  AssertIdentifierName('Correct collation','E',O.Collation);
+  O:=AssertOrderBy(Select.OrderBy[1],'F',0,obAscending);
+  AssertIdentifierName('Correct collation','E',O.Collation);
+end;
+
+procedure TTestSelectParser.TestGroupByOne;
+begin
+  TestSelect('SELECT B,COUNT(C) AS THECOUNT FROM A GROUP BY B');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertEquals('One group by field',1,Select.GroupBy.Count);
+  AssertIdentifierName('Correct group by field','B',Select.GroupBy[0]);
+  AssertField(Select.Fields[0],'B');
+  AssertAggregate(Select.Fields[1],afCount,'C',aoNone,'THECOUNT');
+end;
+
+procedure TTestSelectParser.TestGroupByTwo;
+begin
+  TestSelect('SELECT B,C,SUM(D) AS THESUM FROM A GROUP BY B,C');
+  AssertEquals('Three fields',3,Select.Fields.Count);
+  AssertEquals('One group two fields',2,Select.GroupBy.Count);
+  AssertIdentifierName('Correct first group by field','B',Select.GroupBy[0]);
+  AssertIdentifierName('Correct second group by field','C',Select.GroupBy[1]);
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertAggregate(Select.Fields[2],afSum,'D',aoNone,'THESUM');
+end;
+
+procedure TTestSelectParser.TestHavingOne;
+
+Var
+  H : TSQLBinaryExpression;
+  L : TSQLLiteralExpression;
+  S : TSQLIntegerLiteral;
+
+begin
+  TestSelect('SELECT B,COUNT(C) AS THECOUNT FROM A GROUP BY B HAVING COUNT(C)>1');
+  AssertEquals('Two fields',2,Select.Fields.Count);
+  AssertEquals('One group by field',1,Select.GroupBy.Count);
+  AssertIdentifierName('Correct group by field','B',Select.GroupBy[0]);
+  AssertField(Select.Fields[0],'B');
+  AssertAggregate(Select.Fields[1],afCount,'C',aoNone,'THECOUNT');
+  AssertNotNull('Have having',Select.Having);
+  H:=TSQLBinaryExpression(CheckClass(Select.Having,TSQLBinaryExpression));
+  AssertEquals('Larger than',boGT,H.Operation);
+  L:=TSQLLiteralExpression(CheckClass(H.Right,TSQLLiteralExpression));
+  S:=TSQLIntegerLiteral(CheckClass(L.Literal,TSQLIntegerLiteral));
+  AssertEquals('One',1,S.Value);
+  AssertAggregateExpression(H.Left,afCount,'C',aoNone);
+end;
+
+procedure TTestSelectParser.TestUnionSimple;
+
+Var
+  S : TSQLSelectStatement;
+
+begin
+  TestSelect('SELECT B FROM A UNION SELECT C FROM D');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  S:=TSQLSelectStatement(CheckClass(Select.Union,TSQLSelectStatement));
+  AssertEquals('One field',1,S.Fields.Count);
+  AssertField(S.Fields[0],'C');
+  AssertEquals('One table',1,S.Tables.Count);
+  AssertTable(S.Tables[0],'D');
+  AssertEquals('No UNION ALL : ',False,Select.UnionAll)
+end;
+
+procedure TTestSelectParser.TestUnionSimpleAll;
+
+Var
+  S : TSQLSelectStatement;
+
+begin
+  TestSelect('SELECT B FROM A UNION ALL SELECT C FROM D');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  S:=TSQLSelectStatement(CheckClass(Select.Union,TSQLSelectStatement));
+  AssertEquals('One field',1,S.Fields.Count);
+  AssertField(S.Fields[0],'C');
+  AssertEquals('One table',1,S.Tables.Count);
+  AssertTable(S.Tables[0],'D');
+  AssertEquals('UNION ALL : ',True,Select.UnionAll)
+end;
+
+procedure TTestSelectParser.TestUnionSimpleOrderBy;
+Var
+  S : TSQLSelectStatement;
+
+begin
+  TestSelect('SELECT B FROM A UNION SELECT C FROM D ORDER BY 1');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertOrderBy(Select.OrderBy[0],'',1,obAscending);
+  S:=TSQLSelectStatement(CheckClass(Select.Union,TSQLSelectStatement));
+  AssertEquals('One field',1,S.Fields.Count);
+  AssertField(S.Fields[0],'C');
+  AssertEquals('One table',1,S.Tables.Count);
+  AssertTable(S.Tables[0],'D');
+end;
+
+procedure TTestSelectParser.TestUnionDouble;
+Var
+  S : TSQLSelectStatement;
+
+begin
+  TestSelect('SELECT B FROM A UNION SELECT C FROM D UNION SELECT E FROM F ORDER BY 1');
+  AssertEquals('One field',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'B');
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A');
+  AssertOrderBy(Select.OrderBy[0],'',1,obAscending);
+  S:=TSQLSelectStatement(CheckClass(Select.Union,TSQLSelectStatement));
+  AssertEquals('One field',1,S.Fields.Count);
+  AssertField(S.Fields[0],'C');
+  AssertEquals('One table',1,S.Tables.Count);
+  AssertTable(S.Tables[0],'D');
+  S:=TSQLSelectStatement(CheckClass(S.Union,TSQLSelectStatement));
+  AssertEquals('One field',1,S.Fields.Count);
+  AssertField(S.Fields[0],'E');
+  AssertEquals('One table',1,S.Tables.Count);
+  AssertTable(S.Tables[0],'F');
+end;
+
+procedure TTestSelectParser.TestUnionError1;
+
+begin
+  TestSelectError('SELECT B FROM A ORDER BY B UNION SELECT C FROM D');
+end;
+
+procedure TTestSelectParser.TestUnionError2;
+begin
+  TestSelectError('SELECT B FROM A UNION SELECT C,E FROM D');
+end;
+
+procedure TTestSelectParser.TestPlanOrderNatural;
+
+Var
+  E : TSQLSelectPlanExpr;
+  N : TSQLSelectNaturalPLan;
+
+begin
+  TestSelect('SELECT A FROM B PLAN SORT (B NATURAL)');
+  E:=TSQLSelectPlanExpr(CheckClass(Select.Plan,TSQLSelectPlanExpr));
+  AssertEquals('One plan item',1,E.Items.Count);
+  AssertEquals('Correct plan type',pjtSort,E.JoinType);
+  N:=TSQLSelectNaturalPLan(CheckClass(E.Items[0],TSQLSelectNaturalPLan));
+  AssertIdentifierName('Correct table','B',N.TableName);
+end;
+
+procedure TTestSelectParser.TestPlanOrderOrder;
+
+Var
+  E : TSQLSelectPlanExpr;
+  O : TSQLSelectOrderedPLan;
+
+begin
+  TestSelect('SELECT A FROM B PLAN SORT (B ORDER C)');
+  E:=TSQLSelectPlanExpr(CheckClass(Select.Plan,TSQLSelectPlanExpr));
+  AssertEquals('One plan item',1,E.Items.Count);
+  AssertEquals('Correct plan type',pjtSort,E.JoinType);
+  O:=TSQLSelectOrderedPLan(CheckClass(E.Items[0],TSQLSelectOrderedPLan));
+  AssertIdentifierName('Correct table','B',O.TableName);
+  AssertIdentifierName('Correct table','C',O.OrderIndex);
+end;
+
+procedure TTestSelectParser.TestPlanOrderIndex1;
+
+Var
+  E : TSQLSelectPlanExpr;
+  O : TSQLSelectIndexedPLan;
+
+begin
+  TestSelect('SELECT A FROM B PLAN SORT (B INDEX (C))');
+  E:=TSQLSelectPlanExpr(CheckClass(Select.Plan,TSQLSelectPlanExpr));
+  AssertEquals('One plan item',1,E.Items.Count);
+  AssertEquals('Correct plan type',pjtSort,E.JoinType);
+  O:=TSQLSelectIndexedPLan(CheckClass(E.Items[0],TSQLSelectIndexedPlan));
+  AssertIdentifierName('Correct table','B',O.TableName);
+  AssertEquals('Correct index count',1,O.Indexes.Count);
+  AssertIdentifierName('Correct table','C',O.Indexes[0]);
+end;
+
+procedure TTestSelectParser.TestPlanOrderIndex2;
+Var
+  E : TSQLSelectPlanExpr;
+  O : TSQLSelectIndexedPLan;
+
+begin
+  TestSelect('SELECT A FROM B PLAN SORT (B INDEX (C,D))');
+  E:=TSQLSelectPlanExpr(CheckClass(Select.Plan,TSQLSelectPlanExpr));
+  AssertEquals('One plan item',1,E.Items.Count);
+  AssertEquals('Correct plan type',pjtSort,E.JoinType);
+  O:=TSQLSelectIndexedPLan(CheckClass(E.Items[0],TSQLSelectIndexedPlan));
+  AssertIdentifierName('Correct table','B',O.TableName);
+  AssertEquals('Correct index count',2,O.Indexes.Count);
+  AssertIdentifierName('Correct table','C',O.Indexes[0]);
+  AssertIdentifierName('Correct table','D',O.Indexes[1]);
+end;
+
+procedure TTestSelectParser.TestPlanJoinNatural;
+Var
+  E : TSQLSelectPlanExpr;
+  N : TSQLSelectNaturalPLan;
+  O : TSQLSelectOrderedPLan;
+
+begin
+  TestSelect('SELECT A FROM B PLAN JOIN (B NATURAL, C ORDER D)');
+  E:=TSQLSelectPlanExpr(CheckClass(Select.Plan,TSQLSelectPlanExpr));
+  AssertEquals('One plan item',2,E.Items.Count);
+  AssertEquals('Correct plan type',pjtJoin,E.JoinType);
+  N:=TSQLSelectNaturalPLan(CheckClass(E.Items[0],TSQLSelectNaturalPlan));
+  AssertIdentifierName('Correct table','B',N.TableName);
+  O:=TSQLSelectOrderedPLan(CheckClass(E.Items[1],TSQLSelectOrderedPlan));
+  AssertIdentifierName('Correct table','C',O.TableName);
+  AssertIdentifierName('Correct index','D',O.OrderIndex);
+end;
+
+procedure TTestSelectParser.TestPlanDefaultNatural;
+Var
+  E : TSQLSelectPlanExpr;
+  N : TSQLSelectNaturalPLan;
+  O : TSQLSelectOrderedPLan;
+
+begin
+  TestSelect('SELECT A FROM B PLAN  (B NATURAL, C ORDER D)');
+  E:=TSQLSelectPlanExpr(CheckClass(Select.Plan,TSQLSelectPlanExpr));
+  AssertEquals('One plan item',2,E.Items.Count);
+  AssertEquals('Correct plan type',pjtJoin,E.JoinType);
+  N:=TSQLSelectNaturalPLan(CheckClass(E.Items[0],TSQLSelectNaturalPlan));
+  AssertIdentifierName('Correct table','B',N.TableName);
+  O:=TSQLSelectOrderedPLan(CheckClass(E.Items[1],TSQLSelectOrderedPlan));
+  AssertIdentifierName('Correct table','C',O.TableName);
+  AssertIdentifierName('Correct index','D',O.OrderIndex);
+end;
+
+procedure TTestSelectParser.TestPlanMergeNatural;
+Var
+  E : TSQLSelectPlanExpr;
+  N : TSQLSelectNaturalPLan;
+  O : TSQLSelectOrderedPLan;
+
+begin
+  TestSelect('SELECT A FROM B PLAN MERGE (B NATURAL, C ORDER D)');
+  E:=TSQLSelectPlanExpr(CheckClass(Select.Plan,TSQLSelectPlanExpr));
+  AssertEquals('One plan item',2,E.Items.Count);
+  AssertEquals('Correct plan type',pjtMerge,E.JoinType);
+  N:=TSQLSelectNaturalPLan(CheckClass(E.Items[0],TSQLSelectNaturalPlan));
+  AssertIdentifierName('Correct table','B',N.TableName);
+  O:=TSQLSelectOrderedPLan(CheckClass(E.Items[1],TSQLSelectOrderedPlan));
+  AssertIdentifierName('Correct table','C',O.TableName);
+  AssertIdentifierName('Correct index','D',O.OrderIndex);
+end;
+
+procedure TTestSelectParser.TestPlanMergeNested;
+Var
+  E,EN : TSQLSelectPlanExpr;
+  N : TSQLSelectNaturalPLan;
+  I : TSQLSelectIndexedPLan;
+
+begin
+  TestSelect('SELECT A FROM B PLAN MERGE (SORT (B NATURAL), SORT (JOIN (D NATURAL, E INDEX (F))))');
+  E:=TSQLSelectPlanExpr(CheckClass(Select.Plan,TSQLSelectPlanExpr));
+  AssertEquals('Two plan items',2,E.Items.Count);
+  AssertEquals('Correct overall plan type',pjtMerge,E.JoinType);
+  // SORT (B NATURAL)
+  EN:=TSQLSelectPlanExpr(CheckClass(E.Items[0],TSQLSelectPlanExpr));
+  AssertEquals('Correct plan type Item 1',pjtSort,EN.JoinType);
+  AssertEquals('On plan item in item 1',1,EN.Items.Count);
+  N:=TSQLSelectNaturalPLan(CheckClass(EN.Items[0],TSQLSelectNaturalPlan));
+  AssertIdentifierName('Correct table','B',N.TableName);
+  // SORT (JOIN (D...
+  EN:=TSQLSelectPlanExpr(CheckClass(E.Items[1],TSQLSelectPlanExpr));
+  AssertEquals('Correct plan type item 2',pjtSort,EN.JoinType);
+  AssertEquals('One plan item in item 2',1,EN.Items.Count);
+  // JOIN (D NATURAL, E
+  E:=TSQLSelectPlanExpr(CheckClass(EN.Items[0],TSQLSelectPlanExpr));
+  AssertEquals('Correct plan type',pjtJoin,E.JoinType);
+  AssertEquals('Two plan items in item 2',2,E.Items.Count);
+  N:=TSQLSelectNaturalPLan(CheckClass(E.Items[0],TSQLSelectNaturalPlan));
+  AssertIdentifierName('Correct table','D',N.TableName);
+  // E INDEX (F)
+  I:=TSQLSelectIndexedPLan(CheckClass(E.Items[1],TSQLSelectIndexedPlan));
+  AssertIdentifierName('Correct table','E',I.TableName);
+  AssertEquals('Correct index count for table E',1,I.Indexes.Count);
+  AssertIdentifierName('Correct index for table E','F',I.Indexes[0]);
+end;
+
+procedure TTestSelectParser.TestSubSelect;
+
+Var
+  F : TSQLSelectField;
+  E : TSQLSelectExpression;
+  S : TSQLSelectStatement;
+
+begin
+  TestSelect('SELECT A,(SELECT C FROM D WHERE E=A) AS THECOUNT FROM B');
+  AssertEquals('1 table in select',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'B','');
+  AssertEquals('2 fields in select',2,Select.Fields.Count);
+  AssertField(Select.Fields[0],'A','');
+  F:=TSQLSelectField(CheckClass(Select.fields[1],TSQLSelectField));
+  AssertIdentifierName('Correct alias name for subselect','THECOUNT',F.AliasName);
+  E:=TSQLSelectExpression(CheckClass(F.Expression,TSQLSelectExpression));
+  S:=TSQLSelectStatement(CheckClass(E.Select,TSQLSelectStatement));
+  AssertEquals('1 field in subselect',1,S.Fields.Count);
+  AssertField(S.Fields[0],'C','');
+  AssertEquals('1 table in subselect',1,S.Tables.Count);
+  AssertTable(S.Tables[0],'D','');
+end;
+
+procedure TTestSelectParser.TestWhereExists;
+
+Var
+  F : TSQLSelectField;
+  E : TSQLExistsExpression;
+  S : TSQLSelectStatement;
+
+begin
+  TestSelect('SELECT A FROM B WHERE EXISTS (SELECT C FROM D WHERE E=A)');
+  AssertEquals('1 table in select',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'B','');
+  AssertEquals('1 fields in select',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'A','');
+  E:=TSQLExistsExpression(CheckClass(Select.Where,TSQLExistsExpression));
+  S:=TSQLSelectStatement(CheckClass(E.Select,TSQLSelectStatement));
+  AssertEquals('1 field in subselect',1,S.Fields.Count);
+  AssertField(S.Fields[0],'C','');
+  AssertEquals('1 table in subselect',1,S.Tables.Count);
+  AssertTable(S.Tables[0],'D','');
+end;
+
+procedure TTestSelectParser.TestWhereSingular;
+
+Var
+  E : TSQLSingularExpression;
+  S : TSQLSelectStatement;
+
+begin
+  TestSelect('SELECT A FROM B WHERE SINGULAR (SELECT C FROM D WHERE E=A)');
+  AssertEquals('1 table in select',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'B','');
+  AssertEquals('1 fields in select',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'A','');
+  E:=TSQLSingularExpression(CheckClass(Select.Where,TSQLSingularExpression));
+  S:=TSQLSelectStatement(CheckClass(E.Select,TSQLSelectStatement));
+  AssertEquals('1 field in subselect',1,S.Fields.Count);
+  AssertField(S.Fields[0],'C','');
+  AssertEquals('1 table in subselect',1,S.Tables.Count);
+  AssertTable(S.Tables[0],'D','');
+end;
+
+procedure TTestSelectParser.TestWhereAll;
+
+Var
+  E : TSQLAllExpression;
+  S : TSQLSelectStatement;
+  B : TSQLBinaryExpression;
+
+begin
+  TestSelect('SELECT A FROM B WHERE A > ALL (SELECT C FROM D WHERE E=F)');
+  AssertEquals('1 table in select',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'B','');
+  AssertEquals('1 fields in select',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'A','');
+  B:=TSQLBinaryExpression(CheckClass(Select.Where,TSQLBinaryExpression));
+  AssertEquals('Correct operation',boGT,B.Operation);
+  E:=TSQLAllExpression(CheckClass(B.right,TSQLAllExpression));
+  S:=TSQLSelectStatement(CheckClass(E.Select,TSQLSelectStatement));
+  AssertEquals('1 field in subselect',1,S.Fields.Count);
+  AssertField(S.Fields[0],'C','');
+  AssertEquals('1 table in subselect',1,S.Tables.Count);
+  AssertTable(S.Tables[0],'D','');
+end;
+
+procedure TTestSelectParser.TestWhereAny;
+
+Var
+  E : TSQLANyExpression;
+  S : TSQLSelectStatement;
+  B : TSQLBinaryExpression;
+
+begin
+  TestSelect('SELECT A FROM B WHERE A > ANY (SELECT C FROM D WHERE E=F)');
+  AssertEquals('1 table in select',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'B','');
+  AssertEquals('1 fields in select',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'A','');
+  B:=TSQLBinaryExpression(CheckClass(Select.Where,TSQLBinaryExpression));
+  AssertEquals('Correct operation',boGT,B.Operation);
+  E:=TSQLAnyExpression(CheckClass(B.right,TSQLANyExpression));
+  S:=TSQLSelectStatement(CheckClass(E.Select,TSQLSelectStatement));
+  AssertEquals('1 field in subselect',1,S.Fields.Count);
+  AssertField(S.Fields[0],'C','');
+  AssertEquals('1 table in subselect',1,S.Tables.Count);
+  AssertTable(S.Tables[0],'D','');
+end;
+
+procedure TTestSelectParser.TestWhereSome;
+
+Var
+  E : TSQLSomeExpression;
+  S : TSQLSelectStatement;
+  B : TSQLBinaryExpression;
+
+begin
+  TestSelect('SELECT A FROM B WHERE A > SOME (SELECT C FROM D WHERE E=F)');
+  AssertEquals('1 table in select',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'B','');
+  AssertEquals('1 fields in select',1,Select.Fields.Count);
+  AssertField(Select.Fields[0],'A','');
+  B:=TSQLBinaryExpression(CheckClass(Select.Where,TSQLBinaryExpression));
+  AssertEquals('Correct operation',boGT,B.Operation);
+  E:=TSQLSomeExpression(CheckClass(B.right,TSQLSomeExpression));
+  S:=TSQLSelectStatement(CheckClass(E.Select,TSQLSelectStatement));
+  AssertEquals('1 field in subselect',1,S.Fields.Count);
+  AssertField(S.Fields[0],'C','');
+  AssertEquals('1 table in subselect',1,S.Tables.Count);
+  AssertTable(S.Tables[0],'D','');
+end;
+
+
+procedure TTestSelectParser.TestParam;
+
+Var
+  F : TSQLSelectField;
+  P : TSQLParameterExpression;
+
+begin
+  TestSelect('SELECT :A FROM B');
+  AssertEquals('1 table in select',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'B','');
+  AssertEquals('1 fields in select',1,Select.Fields.Count);
+  AssertNotNull('Have field',Select.Fields[0]);
+  F:=TSQLSelectField(CheckClass(Select.Fields[0],TSQLSelectField));
+  AssertNotNull('Have field expresssion,',F.Expression);
+  P:=TSQLParameterExpression(CheckClass(F.Expression,TSQLParameterExpression));
+  AssertIdentifierName('Correct parameter name','A',P.Identifier);
+end;
+
+procedure TTestSelectParser.TestParamExpr;
+
+Var
+  F : TSQLSelectField;
+  P : TSQLParameterExpression;
+  B : TSQLBinaryExpression;
+
+begin
+  TestSelect('SELECT :A + 1 FROM B');
+  AssertEquals('1 table in select',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'B','');
+  AssertEquals('1 fields in select',1,Select.Fields.Count);
+  AssertNotNull('Have field',Select.Fields[0]);
+  F:=TSQLSelectField(CheckClass(Select.Fields[0],TSQLSelectField));
+  AssertNotNull('Have field expresssion,',F.Expression);
+  B:=TSQLBinaryExpression(CheckClass(F.Expression,TSQLBinaryExpression));
+  P:=TSQLParameterExpression(CheckClass(B.Left,TSQLParameterExpression));
+  AssertIdentifierName('Correct parameter name','A',P.Identifier);
+end;
+
+{ TTestRollBackParser }
+
+function TTestRollBackParser.TestRollback(const ASource: String
+  ): TSQLRollbackStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLRollbackStatement(CheckClass(FToFree,TSQLRollbackStatement));
+  FRollback:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestRollBackParser.TestRollbackError(const ASource: String);
+begin
+  FErrSource:=ASource;
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestRollBackParser.TestRollback;
+begin
+  TestRollBack('ROLLBACK');
+  AssertNull('No transaction name',Rollback.TransactionName);
+  AssertEquals('No work',False,Rollback.Work);
+  AssertEquals('No release',False,Rollback.Release);
+end;
+
+procedure TTestRollBackParser.TestRollbackWork;
+begin
+  TestRollBack('ROLLBACK WORK');
+  AssertNull('No transaction name',Rollback.TransactionName);
+  AssertEquals('work',True,Rollback.Work);
+  AssertEquals('No release',False,Rollback.Release);
+end;
+
+procedure TTestRollBackParser.TestRollbackRelease;
+begin
+  TestRollBack('ROLLBACK RELEASE');
+  AssertNull('No transaction name',Rollback.TransactionName);
+  AssertEquals('no work',False,Rollback.Work);
+  AssertEquals('release',True,Rollback.Release);
+end;
+
+procedure TTestRollBackParser.TestRollbackWorkRelease;
+begin
+  TestRollBack('ROLLBACK WORK RELEASE');
+  AssertNull('No transaction name',Rollback.TransactionName);
+  AssertEquals('work',True,Rollback.Work);
+  AssertEquals('release',True,Rollback.Release);
+end;
+
+procedure TTestRollBackParser.TestRollbackTransaction;
+begin
+  TestRollBack('ROLLBACK TRANSACTION T');
+  AssertIdentifierName('Transaction name','T',Rollback.TransactionName);
+  AssertEquals('No work',False,Rollback.Work);
+  AssertEquals('No release',False,Rollback.Release);
+end;
+
+procedure TTestRollBackParser.TestRollbackTransactionWork;
+begin
+  TestRollBack('ROLLBACK TRANSACTION T WORK');
+  AssertIdentifierName('Transaction name','T',Rollback.TransactionName);
+  AssertEquals('work',True,Rollback.Work);
+  AssertEquals('No release',False,Rollback.Release);
+end;
+
+procedure TTestRollBackParser.TestRollbackTransactionRelease;
+begin
+  TestRollBack('ROLLBACK TRANSACTION T RELEASE');
+  AssertIdentifierName('Transaction name','T',Rollback.TransactionName);
+  AssertEquals('no work',False,Rollback.Work);
+  AssertEquals('release',True,Rollback.Release);
+end;
+
+procedure TTestRollBackParser.TestRollbackTransactionWorkRelease;
+begin
+  TestRollBack('ROLLBACK TRANSACTION T WORK RELEASE');
+  AssertIdentifierName('Transaction name','T',Rollback.TransactionName);
+  AssertEquals('work',True,Rollback.Work);
+  AssertEquals('release',True,Rollback.Release);
+end;
+{ TTestCommitParser }
+
+function TTestCommitParser.TestCommit(const ASource: String
+  ): TSQLCommitStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLCommitStatement(CheckClass(FToFree,TSQLCommitStatement));
+  FCommit:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestCommitParser.TestCommitError(const ASource: String);
+begin
+  FErrSource:=ASource;
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestCommitParser.TestCommit;
+begin
+  TestCommit('Commit');
+  AssertNull('No transaction name',Commit.TransactionName);
+  AssertEquals('No work',False,Commit.Work);
+  AssertEquals('No release',False,Commit.Release);
+  AssertEquals('No Retain',False,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitWork;
+begin
+  TestCommit('Commit WORK');
+  AssertNull('No transaction name',Commit.TransactionName);
+  AssertEquals('work',True,Commit.Work);
+  AssertEquals('No release',False,Commit.Release);
+  AssertEquals('No Retain',False,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitRelease;
+begin
+  TestCommit('Commit RELEASE');
+  AssertNull('No transaction name',Commit.TransactionName);
+  AssertEquals('no work',False,Commit.Work);
+  AssertEquals('release',True,Commit.Release);
+  AssertEquals('No Retain',False,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitWorkRelease;
+begin
+  TestCommit('Commit WORK RELEASE');
+  AssertNull('No transaction name',Commit.TransactionName);
+  AssertEquals('work',True,Commit.Work);
+  AssertEquals('release',True,Commit.Release);
+  AssertEquals('No Retain',False,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitTransaction;
+begin
+  TestCommit('Commit TRANSACTION T');
+  AssertIdentifierName('Transaction name','T',Commit.TransactionName);
+  AssertEquals('No work',False,Commit.Work);
+  AssertEquals('No release',False,Commit.Release);
+  AssertEquals('No Retain',False,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitTransactionWork;
+begin
+  TestCommit('Commit WORK TRANSACTION T ');
+  AssertIdentifierName('Transaction name','T',Commit.TransactionName);
+  AssertEquals('work',True,Commit.Work);
+  AssertEquals('No release',False,Commit.Release);
+  AssertEquals('No Retain',False,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitTransactionRelease;
+begin
+  TestCommit('Commit TRANSACTION T RELEASE');
+  AssertIdentifierName('Transaction name','T',Commit.TransactionName);
+  AssertEquals('no work',False,Commit.Work);
+  AssertEquals('release',True,Commit.Release);
+  AssertEquals('No Retain',False,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitTransactionWorkRelease;
+begin
+  TestCommit('Commit WORK TRANSACTION T  RELEASE');
+  AssertIdentifierName('Transaction name','T',Commit.TransactionName);
+  AssertEquals('work',True,Commit.Work);
+  AssertEquals('release',True,Commit.Release);
+  AssertEquals('No Retain',False,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitRetain;
+begin
+  TestCommit('Commit RETAIN');
+  AssertNull('No transaction name',Commit.TransactionName);
+  AssertEquals('No work',False,Commit.Work);
+  AssertEquals('No release',False,Commit.Release);
+  AssertEquals('Retain',True,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitRetainSnapShot;
+begin
+  TestCommit('Commit RETAIN SNAPSHOT');
+  AssertNull('No transaction name',Commit.TransactionName);
+  AssertEquals('No work',False,Commit.Work);
+  AssertEquals('No release',False,Commit.Release);
+  AssertEquals('Retain',True,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitWorkRetain;
+begin
+  TestCommit('Commit WORK  RETAIN');
+  AssertNull('No transaction name',Commit.TransactionName);
+  AssertEquals('work',True,Commit.Work);
+  AssertEquals('No release',False,Commit.Release);
+  AssertEquals('Retain',True,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitReleaseRetain;
+begin
+  TestCommit('Commit RELEASE  RETAIN');
+  AssertNull('No transaction name',Commit.TransactionName);
+  AssertEquals('no work',False,Commit.Work);
+  AssertEquals('release',True,Commit.Release);
+  AssertEquals('Retain',True,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitWorkReleaseRetain;
+begin
+  TestCommit('Commit WORK RELEASE  RETAIN');
+  AssertNull('No transaction name',Commit.TransactionName);
+  AssertEquals('work',True,Commit.Work);
+  AssertEquals('release',True,Commit.Release);
+  AssertEquals('Retain',True,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitTransactionRetain;
+begin
+  TestCommit('Commit TRANSACTION T  RETAIN');
+  AssertIdentifierName('Transaction name','T',Commit.TransactionName);
+  AssertEquals('No work',False,Commit.Work);
+  AssertEquals('No release',False,Commit.Release);
+  AssertEquals('Retain',True,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitTransactionWorkRetain;
+begin
+  TestCommit('Commit WORK TRANSACTION T  RETAIN');
+  AssertIdentifierName('Transaction name','T',Commit.TransactionName);
+  AssertEquals('work',True,Commit.Work);
+  AssertEquals('No release',False,Commit.Release);
+  AssertEquals('Retain',True,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitTransactionReleaseRetain;
+begin
+  TestCommit('Commit TRANSACTION T RELEASE  RETAIN');
+  AssertIdentifierName('Transaction name','T',Commit.TransactionName);
+  AssertEquals('no work',False,Commit.Work);
+  AssertEquals('release',True,Commit.Release);
+  AssertEquals('Retain',True,Commit.Retain);
+end;
+
+procedure TTestCommitParser.TestCommitTransactionWorkReleaseRetain;
+begin
+  TestCommit('Commit WORK TRANSACTION T  RELEASE RETAIN');
+  AssertIdentifierName('Transaction name','T',Commit.TransactionName);
+  AssertEquals('work',True,Commit.Work);
+  AssertEquals('release',True,Commit.Release);
+  AssertEquals('Retain',True,Commit.Retain);
+end;
+
+{ TTestExecuteProcedureParser }
+
+function TTestExecuteProcedureParser.TestExecute(const ASource: String
+  ): TSQLExecuteProcedureStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLExecuteProcedureStatement(CheckClass(FToFree,TSQLExecuteProcedureStatement));
+  FExecute:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteError(const ASource: String);
+begin
+  FErrSource:=ASource;
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteSimple;
+begin
+  TestExecute('EXECUTE PROCEDURE A');
+  AssertIdentifierName('Correct procedure name','A',Execute.ProcedureName);
+  AssertNull('No transaction name',Execute.TransactionName);
+  AssertEquals('No arguments',0,Execute.Params.Count);
+  AssertEquals('No return values',0,Execute.Returning.Count);
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteSimpleTransaction;
+begin
+  TestExecute('EXECUTE PROCEDURE TRANSACTION B A');
+  AssertIdentifierName('Correct procedure name','A',Execute.ProcedureName);
+  AssertIdentifierName('Correct transaction name','B',Execute.TransactionName);
+  AssertEquals('No arguments',0,Execute.Params.Count);
+  AssertEquals('No return values',0,Execute.Returning.Count);
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteSimpleReturningValues;
+begin
+  TestExecute('EXECUTE PROCEDURE A RETURNING_VALUES :B');
+  AssertIdentifierName('Correct procedure name','A',Execute.ProcedureName);
+  AssertNull('No transaction name',Execute.TransactionName);
+  AssertEquals('No arguments',0,Execute.Params.Count);
+  AssertEquals('1 return value',1,Execute.Returning.Count);
+  AssertIdentifierName('return value','B',Execute.Returning[0]);
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteSimpleReturning2Values;
+begin
+  TestExecute('EXECUTE PROCEDURE A RETURNING_VALUES :B,:C');
+  AssertIdentifierName('Correct procedure name','A',Execute.ProcedureName);
+  AssertNull('No transaction name',Execute.TransactionName);
+  AssertEquals('No arguments',0,Execute.Params.Count);
+  AssertEquals('2 return values',2,Execute.Returning.Count);
+  AssertIdentifierName('return value','B',Execute.Returning[0]);
+  AssertIdentifierName('return value','C',Execute.Returning[1]);
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteOneArg;
+
+Var
+  I : TSQLIdentifierExpression;
+
+begin
+  TestExecute('EXECUTE PROCEDURE A (B)');
+  AssertIdentifierName('Correct procedure name','A',Execute.ProcedureName);
+  AssertNull('No transaction name',Execute.TransactionName);
+  AssertEquals('One argument',1,Execute.Params.Count);
+  I:=TSQLIdentifierExpression(CheckClass(Execute.Params[0],TSQLIdentifierExpression));
+  AssertIdentifierName('Correct argument','B',I.Identifier);
+  AssertEquals('No return values',0,Execute.Returning.Count);
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteOneArgNB;
+
+Var
+  I : TSQLIdentifierExpression;
+
+begin
+  TestExecute('EXECUTE PROCEDURE A B');
+  AssertIdentifierName('Correct procedure name','A',Execute.ProcedureName);
+  AssertNull('No transaction name',Execute.TransactionName);
+  AssertEquals('One argument',1,Execute.Params.Count);
+  I:=TSQLIdentifierExpression(CheckClass(Execute.Params[0],TSQLIdentifierExpression));
+  AssertIdentifierName('Correct argument','B',I.Identifier);
+  AssertEquals('No return values',0,Execute.Returning.Count);
+end;
+
+
+procedure TTestExecuteProcedureParser.TestExecuteTwoArgs;
+Var
+  I : TSQLIdentifierExpression;
+
+begin
+  TestExecute('EXECUTE PROCEDURE A (B,C)');
+  AssertIdentifierName('Correct procedure name','A',Execute.ProcedureName);
+  AssertNull('No transaction name',Execute.TransactionName);
+  AssertEquals('Two arguments',2,Execute.Params.Count);
+  I:=TSQLIdentifierExpression(CheckClass(Execute.Params[0],TSQLIdentifierExpression));
+  AssertIdentifierName('Correct argument','B',I.Identifier);
+  I:=TSQLIdentifierExpression(CheckClass(Execute.Params[1],TSQLIdentifierExpression));
+  AssertIdentifierName('Correct argument','C',I.Identifier);
+  AssertEquals('No return values',0,Execute.Returning.Count);
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteTwoArgsNB;
+Var
+  I : TSQLIdentifierExpression;
+
+begin
+  TestExecute('EXECUTE PROCEDURE A B, C');
+  AssertIdentifierName('Correct procedure name','A',Execute.ProcedureName);
+  AssertNull('No transaction name',Execute.TransactionName);
+  AssertEquals('Two arguments',2,Execute.Params.Count);
+  I:=TSQLIdentifierExpression(CheckClass(Execute.Params[0],TSQLIdentifierExpression));
+  AssertIdentifierName('Correct argument','B',I.Identifier);
+  I:=TSQLIdentifierExpression(CheckClass(Execute.Params[1],TSQLIdentifierExpression));
+  AssertIdentifierName('Correct argument','C',I.Identifier);
+  AssertEquals('No return values',0,Execute.Returning.Count);
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteOneArgSelect;
+
+Var
+  S : TSQLSelectExpression;
+
+begin
+  TestExecute('EXECUTE PROCEDURE A ((SELECT B FROM C))');
+  AssertIdentifierName('Correct procedure name','A',Execute.ProcedureName);
+  AssertNull('No transaction name',Execute.TransactionName);
+  AssertEquals('One argument',1,Execute.Params.Count);
+  S:=TSQLSelectExpression(CheckClass(Execute.Params[0],TSQLSelectExpression));
+  AssertField(S.Select.Fields[0],'B','');
+  AssertTable(S.Select.Tables[0],'C','');
+  AssertEquals('No return values',0,Execute.Returning.Count);
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteOneArgSelectNB;
+
+Var
+  S : TSQLSelectExpression;
+
+begin
+  TestExecute('EXECUTE PROCEDURE A (SELECT B FROM C)');
+  AssertIdentifierName('Correct procedure name','A',Execute.ProcedureName);
+  AssertNull('No transaction name',Execute.TransactionName);
+  AssertEquals('One argument',1,Execute.Params.Count);
+  S:=TSQLSelectExpression(CheckClass(Execute.Params[0],TSQLSelectExpression));
+  AssertField(S.Select.Fields[0],'B','');
+  AssertTable(S.Select.Tables[0],'C','');
+  AssertEquals('No return values',0,Execute.Returning.Count);
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteTwoArgsSelect;
+
+Var
+  S : TSQLSelectExpression;
+  I : TSQLIdentifierExpression;
+
+begin
+  TestExecute('EXECUTE PROCEDURE A ((SELECT B FROM C),D)');
+  AssertIdentifierName('Correct procedure name','A',Execute.ProcedureName);
+  AssertNull('No transaction name',Execute.TransactionName);
+  AssertEquals('Two arguments',2,Execute.Params.Count);
+  S:=TSQLSelectExpression(CheckClass(Execute.Params[0],TSQLSelectExpression));
+  AssertField(S.Select.Fields[0],'B','');
+  AssertTable(S.Select.Tables[0],'C','');
+  I:=TSQLIdentifierExpression(CheckClass(Execute.Params[1],TSQLIdentifierExpression));
+  AssertIdentifierName('Correct argument','D',I.Identifier);
+  AssertEquals('No return values',0,Execute.Returning.Count);
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteTwoArgsSelectNB;
+
+Var
+  S : TSQLSelectExpression;
+  I : TSQLIdentifierExpression;
+
+begin
+  TestExecute('EXECUTE PROCEDURE A (SELECT B FROM C),D');
+  AssertIdentifierName('Correct procedure name','A',Execute.ProcedureName);
+  AssertNull('No transaction name',Execute.TransactionName);
+  AssertEquals('Two arguments',2,Execute.Params.Count);
+  S:=TSQLSelectExpression(CheckClass(Execute.Params[0],TSQLSelectExpression));
+  AssertField(S.Select.Fields[0],'B','');
+  AssertTable(S.Select.Tables[0],'C','');
+  I:=TSQLIdentifierExpression(CheckClass(Execute.Params[1],TSQLIdentifierExpression));
+  AssertIdentifierName('Correct argument','D',I.Identifier);
+  AssertEquals('No return values',0,Execute.Returning.Count);
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteOneArgSelectErr;
+begin
+  TestExecuteError('EXECUTE PROCEDURE A ((SELECT B FROM C), 2')
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteOneArgSelectErr2;
+begin
+  TestExecuteError('EXECUTE PROCEDURE A (SELECT B FROM C), 2)')
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteOneArgSelectErr3;
+begin
+  TestExecuteError('EXECUTE PROCEDURE A B)')
+end;
+
+procedure TTestExecuteProcedureParser.TestExecuteOneArgSelectErr4;
+begin
+  TestExecuteError('EXECUTE PROCEDURE A B,C)')
+end;
+
+{ EXECUTE PROCEDURE DELETE_EMPLOYEE2 1, 2;
+  EXECUTE PROCEDURE DELETE_EMPLOYEE2 (1, 2);
+  EXECUTE PROCEDURE DELETE_EMPLOYEE2 ((SELECT A FROM A), 2);
+  EXECUTE PROCEDURE DELETE_EMPLOYEE2 (SELECT A FROM A), 2;
+}
+
+{ TTestConnectParser }
+
+function TTestConnectParser.TestConnect(const ASource: String
+  ): TSQLConnectStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLConnectStatement(CheckClass(FToFree,TSQLConnectStatement));
+  FConnect:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestConnectParser.TestConnectError(const ASource: String);
+begin
+  FErrSource:=ASource;
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestConnectParser.TestConnectSimple;
+begin
+  TestConnect('CONNECT ''/my/database/file''');
+  AssertEquals('Database name','/my/database/file',Connect.DatabaseName);
+  AssertEquals('User name','',Connect.UserName);
+  AssertEquals('Password','',Connect.Password);
+  AssertEquals('Role','',Connect.Role);
+  AssertEquals('Cache',0,Connect.Cache);
+end;
+
+procedure TTestConnectParser.TestConnectUser;
+begin
+  TestConnect('CONNECT ''/my/database/file'' USER ''me''');
+  AssertEquals('Database name','/my/database/file',Connect.DatabaseName);
+  AssertEquals('User name','me',Connect.UserName);
+  AssertEquals('Password','',Connect.Password);
+  AssertEquals('Role','',Connect.Role);
+  AssertEquals('Cache',0,Connect.Cache);
+end;
+
+procedure TTestConnectParser.TestConnectPassword;
+begin
+  TestConnect('CONNECT ''/my/database/file'' PASSWORD ''secret''');
+  AssertEquals('Database name','/my/database/file',Connect.DatabaseName);
+  AssertEquals('User name','',Connect.UserName);
+  AssertEquals('Password','secret',Connect.Password);
+  AssertEquals('Role','',Connect.Role);
+  AssertEquals('Cache',0,Connect.Cache);
+end;
+
+procedure TTestConnectParser.TestConnectUserPassword;
+begin
+  TestConnect('CONNECT ''/my/database/file'' USER ''me'' PASSWORD ''secret''');
+  AssertEquals('Database name','/my/database/file',Connect.DatabaseName);
+  AssertEquals('User name','me',Connect.UserName);
+  AssertEquals('Password','secret',Connect.Password);
+  AssertEquals('Role','',Connect.Role);
+  AssertEquals('Cache',0,Connect.Cache);
+end;
+procedure TTestConnectParser.TestConnectUserPasswordRole;
+begin
+  TestConnect('CONNECT ''/my/database/file'' USER ''me'' PASSWORD ''secret'' ROLE ''admin''');
+  AssertEquals('Database name','/my/database/file',Connect.DatabaseName);
+  AssertEquals('User name','me',Connect.UserName);
+  AssertEquals('Password','secret',Connect.Password);
+  AssertEquals('Role','admin',Connect.Role);
+  AssertEquals('Cache',0,Connect.Cache);
+end;
+
+procedure TTestConnectParser.TestConnectUserPasswordRoleCache;
+begin
+  TestConnect('CONNECT ''/my/database/file'' USER ''me'' PASSWORD ''secret'' ROLE ''admin'' CACHE 2048');
+  AssertEquals('Database name','/my/database/file',Connect.DatabaseName);
+  AssertEquals('User name','me',Connect.UserName);
+  AssertEquals('Password','secret',Connect.Password);
+  AssertEquals('Role','admin',Connect.Role);
+  AssertEquals('Cache',2048,Connect.Cache);
+end;
+
+procedure TTestConnectParser.TestConnectSimpleCache;
+begin
+  TestConnect('CONNECT ''/my/database/file'' CACHE 2048');
+  AssertEquals('Database name','/my/database/file',Connect.DatabaseName);
+  AssertEquals('User name','',Connect.UserName);
+  AssertEquals('Password','',Connect.Password);
+  AssertEquals('Role','',Connect.Role);
+  AssertEquals('Cache',2048,Connect.Cache);
+end;
+
+{ TTestCreateDatabaseParser }
+
+function TTestCreateDatabaseParser.TestCreate(const ASource: String
+  ): TSQLCreateDatabaseStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLCreateDatabaseStatement(CheckClass(FToFree,TSQLCreateDatabaseStatement));
+  FCreateDB:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestCreateDatabaseParser.TestCreateError(const ASource: String);
+begin
+  FerrSource:=ASource;
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestCreateDatabaseParser.TestSimple;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file''');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',0,CreateDB.PageSize);
+  AssertEquals('Length',0,CreateDB.Length);
+  AssertEquals('Secondary files',0,CreateDB.SecondaryFiles.Count);
+end;
+
+procedure TTestCreateDatabaseParser.TestSimpleSchema;
+begin
+  TestCreate('CREATE SCHEMA ''/my/database/file''');
+  AssertEquals('schema',True,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',0,CreateDB.PageSize);
+  AssertEquals('Length',0,CreateDB.Length);
+  AssertEquals('Secondary files',0,CreateDB.SecondaryFiles.Count);
+end;
+
+procedure TTestCreateDatabaseParser.TestSimpleUSer;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' USER ''me''');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','me',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',0,CreateDB.PageSize);
+  AssertEquals('Length',0,CreateDB.Length);
+  AssertEquals('Secondary files',0,CreateDB.SecondaryFiles.Count);
+end;
+
+procedure TTestCreateDatabaseParser.TestSimpleUSerPassword;
+
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' USER ''me'' PASSWORD ''SECRET''');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','me',CreateDB.UserName);
+  AssertEquals('Password','SECRET',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',0,CreateDB.PageSize);
+  AssertEquals('Length',0,CreateDB.Length);
+  AssertEquals('Secondary files',0,CreateDB.SecondaryFiles.Count);
+end;
+
+procedure TTestCreateDatabaseParser.TestSimplePassword;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PASSWORD ''SECRET''');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','SECRET',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',0,CreateDB.PageSize);
+  AssertEquals('Length',0,CreateDB.Length);
+  AssertEquals('Secondary files',0,CreateDB.SecondaryFiles.Count);
+end;
+
+procedure TTestCreateDatabaseParser.TestPageSize;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE = 2048');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',0,CreateDB.Length);
+  AssertEquals('Secondary files',0,CreateDB.SecondaryFiles.Count);
+end;
+
+procedure TTestCreateDatabaseParser.TestPageSize2;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',0,CreateDB.Length);
+  AssertEquals('Secondary files',0,CreateDB.SecondaryFiles.Count);
+end;
+
+procedure TTestCreateDatabaseParser.TestPageSizeLength;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH = 2000');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',2000,CreateDB.Length);
+  AssertEquals('Secondary files',0,CreateDB.SecondaryFiles.Count);
+end;
+
+procedure TTestCreateDatabaseParser.TestPageSizeLength2;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',2000,CreateDB.Length);
+  AssertEquals('Secondary files',0,CreateDB.SecondaryFiles.Count);
+end;
+
+procedure TTestCreateDatabaseParser.TestPageSizeLength3;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 PAGES');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',2000,CreateDB.Length);
+  AssertEquals('Secondary files',0,CreateDB.SecondaryFiles.Count);
+end;
+
+procedure TTestCreateDatabaseParser.TestPageSizeLength4;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 PAGE');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',2000,CreateDB.Length);
+  AssertEquals('Secondary files',0,CreateDB.SecondaryFiles.Count);
+end;
+
+procedure TTestCreateDatabaseParser.TestCharset;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' DEFAULT CHARACTER SET UTF8');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertIDentifierName('Character set','UTF8',CreateDB.CharSet);
+  AssertEquals('Page size',0,CreateDB.PageSize);
+  AssertEquals('Length',0,CreateDB.Length);
+  AssertEquals('Secondary files',0,CreateDB.SecondaryFiles.Count);
+end;
+
+procedure TTestCreateDatabaseParser.TestSecondaryFile1;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 FILE ''/my/database/file2''');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',2000,CreateDB.Length);
+  AssertEquals('Secondary files',1,CreateDB.SecondaryFiles.Count);
+  AssertSecondaryFile(CreateDB.SecondaryFiles[0],'/my/database/file2',0,0);
+end;
+procedure TTestCreateDatabaseParser.TestSecondaryFile2;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 FILE ''/my/database/file2'' LENGTH 1000');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',2000,CreateDB.Length);
+  AssertEquals('Secondary files',1,CreateDB.SecondaryFiles.Count);
+  AssertSecondaryFile(CreateDB.SecondaryFiles[0],'/my/database/file2',1000,0);
+end;
+
+procedure TTestCreateDatabaseParser.TestSecondaryFile3;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 FILE ''/my/database/file2'' LENGTH = 1000');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',2000,CreateDB.Length);
+  AssertEquals('Secondary files',1,CreateDB.SecondaryFiles.Count);
+  AssertSecondaryFile(CreateDB.SecondaryFiles[0],'/my/database/file2',1000,0);
+end;
+
+procedure TTestCreateDatabaseParser.TestSecondaryFile4;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 FILE ''/my/database/file2'' LENGTH = 1000 PAGE');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',2000,CreateDB.Length);
+  AssertEquals('Secondary files',1,CreateDB.SecondaryFiles.Count);
+  AssertSecondaryFile(CreateDB.SecondaryFiles[0],'/my/database/file2',1000,0);
+end;
+
+procedure TTestCreateDatabaseParser.TestSecondaryFile5;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 FILE ''/my/database/file2'' LENGTH = 1000 PAGES');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',2000,CreateDB.Length);
+  AssertEquals('Secondary files',1,CreateDB.SecondaryFiles.Count);
+  AssertSecondaryFile(CreateDB.SecondaryFiles[0],'/my/database/file2',1000,0);
+end;
+
+procedure TTestCreateDatabaseParser.TestSecondaryFile6;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 FILE ''/my/database/file2'' STARTING 3000 ');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',2000,CreateDB.Length);
+  AssertEquals('Secondary files',1,CreateDB.SecondaryFiles.Count);
+  AssertSecondaryFile(CreateDB.SecondaryFiles[0],'/my/database/file2',0,3000);
+end;
+
+procedure TTestCreateDatabaseParser.TestSecondaryFile7;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 FILE ''/my/database/file2'' STARTING AT 3000 ');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',2000,CreateDB.Length);
+  AssertEquals('Secondary files',1,CreateDB.SecondaryFiles.Count);
+  AssertSecondaryFile(CreateDB.SecondaryFiles[0],'/my/database/file2',0,3000);
+end;
+
+procedure TTestCreateDatabaseParser.TestSecondaryFile9;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 FILE ''/my/database/file2'' LENGTH 201 STARTING AT PAGE 3000 ');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',2000,CreateDB.Length);
+  AssertEquals('Secondary files',1,CreateDB.SecondaryFiles.Count);
+  AssertSecondaryFile(CreateDB.SecondaryFiles[0],'/my/database/file2',201,3000);
+end;
+
+procedure TTestCreateDatabaseParser.TestSecondaryFile10;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 FILE ''/my/database/file2''  STARTING AT PAGE 3000 LENGTH 201');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',2000,CreateDB.Length);
+  AssertEquals('Secondary files',1,CreateDB.SecondaryFiles.Count);
+  AssertSecondaryFile(CreateDB.SecondaryFiles[0],'/my/database/file2',201,3000);
+end;
+procedure TTestCreateDatabaseParser.TestSecondaryFile8;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 FILE ''/my/database/file2'' STARTING AT PAGE 3000 ');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',2000,CreateDB.Length);
+  AssertEquals('Secondary files',1,CreateDB.SecondaryFiles.Count);
+  AssertSecondaryFile(CreateDB.SecondaryFiles[0],'/my/database/file2',0,3000);
+end;
+
+procedure TTestCreateDatabaseParser.TestSecondaryFileS;
+begin
+  TestCreate('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 FILE ''/my/database/file2'' FILE ''/my/database/file3'' ');
+  AssertEquals('Not schema',False,CreateDB.UseSchema);
+  AssertEquals('Database file','/my/database/file',CreateDB.FileName);
+  AssertEquals('Username','',CreateDB.UserName);
+  AssertEquals('Password','',CreateDB.Password);
+  AssertNull('Character set',CreateDB.CharSet);
+  AssertEquals('Page size',2048,CreateDB.PageSize);
+  AssertEquals('Length',2000,CreateDB.Length);
+  AssertEquals('Secondary files',2,CreateDB.SecondaryFiles.Count);
+  AssertSecondaryFile(CreateDB.SecondaryFiles[0],'/my/database/file2',0,0);
+  AssertSecondaryFile(CreateDB.SecondaryFiles[1],'/my/database/file3',0,0);
+end;
+
+procedure TTestCreateDatabaseParser.TestSecondaryFileError1;
+begin
+  TestCreateError('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 FILE ''/my/database/file2'' LENGTH 3 LENGTH 2');
+end;
+
+procedure TTestCreateDatabaseParser.TestSecondaryFileError2;
+begin
+  TestCreateError('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 FILE ''/my/database/file2'' STARTING 3 STARTING 2');
+end;
+
+procedure TTestCreateDatabaseParser.TestSecondaryFileError3;
+begin
+  TestCreateError('CREATE DATABASE ''/my/database/file'' PAGE_SIZE 2048 LENGTH 2000 FILE ''/my/database/file2'' STARTING 3 LENGTH 2 STARTING 2');
+end;
+
+{ TTestAlterDatabaseParser }
+
+function TTestAlterDatabaseParser.TestAlter(const ASource: String
+  ): TSQLAlterDatabaseStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLAlterDatabaseStatement(CheckClass(FToFree,TSQLAlterDatabaseStatement));
+  FAlterDB:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestAlterDatabaseParser.TestAlterError(const ASource: String);
+begin
+  FerrSource:=ASource;
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestAlterDatabaseParser.TestSimple;
+begin
+  TestAlter('ALTER DATABASE ADD FILE ''/my/file''');
+  AssertEquals('Operation count',1,AlterDB.Operations.Count);
+  AssertSecondaryFile(AlterDB.Operations[0],'/my/file',0,0);
+end;
+
+procedure TTestAlterDatabaseParser.TestStarting;
+begin
+  TestAlter('ALTER DATABASE ADD FILE ''/my/file'' STARTING AT 100');
+  AssertEquals('Operation count',1,AlterDB.Operations.Count);
+  AssertSecondaryFile(AlterDB.Operations[0],'/my/file',0,100);
+end;
+
+procedure TTestAlterDatabaseParser.TestStartingLength;
+begin
+  TestAlter('ALTER DATABASE ADD FILE ''/my/file'' STARTING AT 100 LENGTH 200');
+  AssertEquals('Operation count',1,AlterDB.Operations.Count);
+  AssertSecondaryFile(AlterDB.Operations[0],'/my/file',200,100);
+end;
+
+procedure TTestAlterDatabaseParser.TestFiles;
+begin
+  TestAlter('ALTER DATABASE ADD FILE ''/my/file2'' ADD FILE ''/my/file3'' ');
+  AssertEquals('Operation count',2,AlterDB.Operations.Count);
+  AssertSecondaryFile(AlterDB.Operations[0],'/my/file2',0,0);
+  AssertSecondaryFile(AlterDB.Operations[1],'/my/file3',0,0);
+end;
+
+procedure TTestAlterDatabaseParser.TestFiles2;
+begin
+  TestAlter('ALTER DATABASE ADD FILE ''/my/file2'' FILE ''/my/file3'' ');
+  AssertEquals('Operation count',2,AlterDB.Operations.Count);
+  AssertSecondaryFile(AlterDB.Operations[0],'/my/file2',0,0);
+  AssertSecondaryFile(AlterDB.Operations[1],'/my/file3',0,0);
+end;
+
+procedure TTestAlterDatabaseParser.TestFilesError;
+begin
+  TestAlterError('ALTER DATABASE FILE ''/my/file2'' FILE ''/my/file3'' ');
+end;
+
+procedure TTestAlterDatabaseParser.TestError;
+begin
+  TestAlterError('ALTER DATABASE ');
+end;
+
+procedure TTestAlterDatabaseParser.TestLength;
+begin
+  TestAlter('ALTER DATABASE ADD FILE ''/my/file'' LENGTH 200');
+  AssertEquals('Operation count',1,AlterDB.Operations.Count);
+  AssertSecondaryFile(AlterDB.Operations[0],'/my/file',200,0);
+end;
+
+{ TTestCreateViewParser }
+
+function TTestCreateViewParser.TestCreate(const ASource: String
+  ): TSQLCreateViewStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLCreateViewStatement(CheckClass(FToFree,TSQLCreateViewStatement));
+  FView:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestCreateViewParser.TestCreateError(const ASource: String);
+begin
+  FerrSource:=ASource;
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestCreateViewParser.TestSimple;
+
+Var
+  S : TSQLSelectStatement;
+
+begin
+  TestCreate('CREATE VIEW A AS SELECT B FROM C');
+  AssertIdentifierName('View name','A',View.ObjectName);
+  AssertNotNull('field list created',View.Fields);
+  AssertEquals('No fields in list',0,View.Fields.Count);
+  S:=TSQLSelectStatement(CheckClass(View.select,TSQLSelectStatement));
+  AssertEquals('1 Field',1,S.Fields.Count);
+  AssertField(S.Fields[0],'B','');
+  AssertEquals('1 table',1,S.Tables.Count);
+  AssertTable(S.Tables[0],'C','');
+  AssertEquals('No with check option',False,View.WithCheckOption);
+end;
+
+procedure TTestCreateViewParser.TestFieldList;
+
+Var
+  S : TSQLSelectStatement;
+
+begin
+  TestCreate('CREATE VIEW A (D) AS SELECT B FROM C');
+  AssertIdentifierName('View name','A',View.ObjectName);
+  AssertNotNull('field list created',View.Fields);
+  AssertEquals('1 field in list',1,View.Fields.Count);
+  AssertIdentifierName('Field name','D',View.Fields[0]);
+  S:=TSQLSelectStatement(CheckClass(View.select,TSQLSelectStatement));
+  AssertEquals('1 Field',1,S.Fields.Count);
+  AssertField(S.Fields[0],'B','');
+  AssertEquals('1 table',1,S.Tables.Count);
+  AssertTable(S.Tables[0],'C','');
+  AssertEquals('No with check option',False,View.WithCheckOption);
+end;
+
+procedure TTestCreateViewParser.TestFieldList2;
+
+Var
+  S : TSQLSelectStatement;
+
+begin
+  TestCreate('CREATE VIEW A (B,C) AS SELECT D,E FROM F');
+  AssertIdentifierName('View name','A',View.ObjectName);
+  AssertNotNull('field list created',View.Fields);
+  AssertEquals('2 fields in list',2,View.Fields.Count);
+  AssertIdentifierName('Field name','B',View.Fields[0]);
+  AssertIdentifierName('Field name','C',View.Fields[1]);
+  S:=TSQLSelectStatement(CheckClass(View.select,TSQLSelectStatement));
+  AssertEquals('2 Fields in select',2,S.Fields.Count);
+  AssertField(S.Fields[0],'D','');
+  AssertField(S.Fields[1],'E','');
+  AssertEquals('1 table',1,S.Tables.Count);
+  AssertTable(S.Tables[0],'F','');
+  AssertEquals('No with check option',False,View.WithCheckOption);
+end;
+
+procedure TTestCreateViewParser.TestSimpleWithCheckoption;
+
+Var
+  S : TSQLSelectStatement;
+
+begin
+  TestCreate('CREATE VIEW A AS SELECT B FROM C WITH CHECK OPTION');
+  AssertIdentifierName('View name','A',View.ObjectName);
+  AssertNotNull('field list created',View.Fields);
+  AssertEquals('No fields in list',0,View.Fields.Count);
+  S:=TSQLSelectStatement(CheckClass(View.select,TSQLSelectStatement));
+  AssertEquals('1 Field',1,S.Fields.Count);
+  AssertField(S.Fields[0],'B','');
+  AssertEquals('1 table',1,S.Tables.Count);
+  AssertTable(S.Tables[0],'C','');
+  AssertEquals('With check option',True,View.WithCheckOption);
+end;
+
+{ TTestCreateShadowParser }
+
+function TTestCreateShadowParser.TestCreate(const ASource: String
+  ): TSQLCreateShadowStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLCreateShadowStatement(CheckClass(FToFree,TSQLCreateShadowStatement));
+  FShadow:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestCreateShadowParser.TestCreateError(const ASource: String);
+begin
+  FerrSource:=ASource;
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestCreateShadowParser.TestSimple;
+begin
+  TestCreate('CREATE SHADOW 1 ''/my/file''');
+  AssertEquals('Not manual',False,Shadow.Manual);
+  AssertEquals('Not conditional',False,Shadow.COnditional);
+  AssertEquals('Filename','/my/file',Shadow.FileName);
+  AssertEquals('No length',0,Shadow.Length);
+  AssertEquals('No secondary files',0,Shadow.SecondaryFiles.Count);
+end;
+
+
+procedure TTestCreateShadowParser.TestLength;
+begin
+  TestCreate('CREATE SHADOW 1 ''/my/file'' LENGTH 2');
+  AssertEquals('Not manual',False,Shadow.Manual);
+  AssertEquals('Not conditional',False,Shadow.COnditional);
+  AssertEquals('Filename','/my/file',Shadow.FileName);
+  AssertEquals('No length',2,Shadow.Length);
+  AssertEquals('No secondary files',0,Shadow.SecondaryFiles.Count);
+end;
+
+procedure TTestCreateShadowParser.TestLength2;
+begin
+  TestCreate('CREATE SHADOW 1 ''/my/file'' LENGTH = 2');
+  AssertEquals('Not manual',False,Shadow.Manual);
+  AssertEquals('Not conditional',False,Shadow.COnditional);
+  AssertEquals('Filename','/my/file',Shadow.FileName);
+  AssertEquals('No length',2,Shadow.Length);
+  AssertEquals('No secondary files',0,Shadow.SecondaryFiles.Count);
+end;
+
+procedure TTestCreateShadowParser.TestLength3;
+begin
+  TestCreate('CREATE SHADOW 1 ''/my/file'' LENGTH = 2 PAGE');
+  AssertEquals('Not manual',False,Shadow.Manual);
+  AssertEquals('Not conditional',False,Shadow.COnditional);
+  AssertEquals('Filename','/my/file',Shadow.FileName);
+  AssertEquals('No length',2,Shadow.Length);
+  AssertEquals('No secondary files',0,Shadow.SecondaryFiles.Count);
+end;
+
+procedure TTestCreateShadowParser.TestLength4;
+begin
+  TestCreate('CREATE SHADOW 1 ''/my/file'' LENGTH = 2 PAGES');
+  AssertEquals('Not manual',False,Shadow.Manual);
+  AssertEquals('Not conditional',False,Shadow.COnditional);
+  AssertEquals('Filename','/my/file',Shadow.FileName);
+  AssertEquals('No length',2,Shadow.Length);
+  AssertEquals('No secondary files',0,Shadow.SecondaryFiles.Count);
+end;
+
+
+procedure TTestCreateShadowParser.TestSecondaryFile1;
+begin
+  TestCreate('CREATE SHADOW 1 ''/my/file'' LENGTH 2 FILE ''/my/file2''');
+  AssertEquals('Not manual',False,Shadow.Manual);
+  AssertEquals('Not conditional',False,Shadow.COnditional);
+  AssertEquals('Filename','/my/file',Shadow.FileName);
+  AssertEquals('No length',2,Shadow.Length);
+  AssertEquals('1 secondary file',1,Shadow.SecondaryFiles.Count);
+  AssertSecondaryFile(Shadow.SecondaryFiles[0],'/my/file2',0,0);
+end;
+
+procedure TTestCreateShadowParser.TestSecondaryFile2;
+begin
+  TestCreate('CREATE SHADOW 1 ''/my/file'' LENGTH 2 FILE ''/my/file2'' LENGTH 1000');
+  AssertEquals('Not manual',False,Shadow.Manual);
+  AssertEquals('Not conditional',False,Shadow.COnditional);
+  AssertEquals('Filename','/my/file',Shadow.FileName);
+  AssertEquals('No length',2,Shadow.Length);
+  AssertEquals('1 secondary file',1,Shadow.SecondaryFiles.Count);
+  AssertSecondaryFile(Shadow.SecondaryFiles[0],'/my/file2',1000,0);
+
+end;
+
+procedure TTestCreateShadowParser.TestSecondaryFile3;
+begin
+  TestCreate('CREATE SHADOW 1 ''/my/file'' LENGTH 2 FILE ''/my/file2'' LENGTH = 1000');
+  AssertEquals('Not manual',False,Shadow.Manual);
+  AssertEquals('Not conditional',False,Shadow.COnditional);
+  AssertEquals('Filename','/my/file',Shadow.FileName);
+  AssertEquals('No length',2,Shadow.Length);
+  AssertEquals('1 secondary file',1,Shadow.SecondaryFiles.Count);
+  AssertSecondaryFile(Shadow.SecondaryFiles[0],'/my/file2',1000,0);
+end;
+
+procedure TTestCreateShadowParser.TestSecondaryFile4;
+begin
+  TestCreate('CREATE SHADOW 1 ''/my/file'' LENGTH 2 FILE ''/my/file2'' LENGTH = 1000 PAGE');
+  AssertEquals('Not manual',False,Shadow.Manual);
+  AssertEquals('Not conditional',False,Shadow.COnditional);
+  AssertEquals('Filename','/my/file',Shadow.FileName);
+  AssertEquals('No length',2,Shadow.Length);
+  AssertEquals('1 secondary file',1,Shadow.SecondaryFiles.Count);
+  AssertSecondaryFile(Shadow.SecondaryFiles[0],'/my/file2',1000,0);
+end;
+
+procedure TTestCreateShadowParser.TestSecondaryFile5;
+begin
+  TestCreate('CREATE SHADOW 1 ''/my/file'' LENGTH 2 FILE ''/my/file2'' LENGTH = 1000 PAGES');
+  AssertEquals('Not manual',False,Shadow.Manual);
+  AssertEquals('Not conditional',False,Shadow.COnditional);
+  AssertEquals('Filename','/my/file',Shadow.FileName);
+  AssertEquals('No length',2,Shadow.Length);
+  AssertEquals('1 secondary file',1,Shadow.SecondaryFiles.Count);
+  AssertSecondaryFile(Shadow.SecondaryFiles[0],'/my/file2',1000,0);
+end;
+
+procedure TTestCreateShadowParser.TestSecondaryFile6;
+begin
+  TestCreate('CREATE SHADOW 1 ''/my/file'' LENGTH 2 FILE ''/my/file2'' STARTING 3000');
+  AssertEquals('Not manual',False,Shadow.Manual);
+  AssertEquals('Not conditional',False,Shadow.COnditional);
+  AssertEquals('Filename','/my/file',Shadow.FileName);
+  AssertEquals('No length',2,Shadow.Length);
+  AssertEquals('1 secondary file',1,Shadow.SecondaryFiles.Count);
+  AssertSecondaryFile(Shadow.SecondaryFiles[0],'/my/file2',0,3000);
+end;
+
+procedure TTestCreateShadowParser.TestSecondaryFile7;
+begin
+  TestCreate('CREATE SHADOW 1 ''/my/file'' LENGTH 2 FILE ''/my/file2'' STARTING AT 3000');
+  AssertEquals('Not manual',False,Shadow.Manual);
+  AssertEquals('Not conditional',False,Shadow.COnditional);
+  AssertEquals('Filename','/my/file',Shadow.FileName);
+  AssertEquals('No length',2,Shadow.Length);
+  AssertEquals('1 secondary file',1,Shadow.SecondaryFiles.Count);
+  AssertSecondaryFile(Shadow.SecondaryFiles[0],'/my/file2',0,3000);
+end;
+
+procedure TTestCreateShadowParser.TestSecondaryFile8;
+begin
+  TestCreate('CREATE SHADOW 1 ''/my/file'' LENGTH 2 FILE ''/my/file2'' STARTING AT PAGE 3000');
+  AssertEquals('Not manual',False,Shadow.Manual);
+  AssertEquals('Not conditional',False,Shadow.COnditional);
+  AssertEquals('Filename','/my/file',Shadow.FileName);
+  AssertEquals('No length',2,Shadow.Length);
+  AssertEquals('1 secondary file',1,Shadow.SecondaryFiles.Count);
+  AssertSecondaryFile(Shadow.SecondaryFiles[0],'/my/file2',0,3000);
+end;
+
+
+procedure TTestCreateShadowParser.TestSecondaryFileS;
+begin
+  TestCreate('CREATE SHADOW 1 ''/my/file'' LENGTH 2 FILE ''/my/file2'' FILE ''/my/file3''');
+  AssertEquals('Not manual',False,Shadow.Manual);
+  AssertEquals('Not conditional',False,Shadow.COnditional);
+  AssertEquals('Filename','/my/file',Shadow.FileName);
+  AssertEquals('No length',2,Shadow.Length);
+  AssertEquals('2 secondary file',2,Shadow.SecondaryFiles.Count);
+  AssertSecondaryFile(Shadow.SecondaryFiles[0],'/my/file2',0,0);
+  AssertSecondaryFile(Shadow.SecondaryFiles[1],'/my/file3',0,0);
+end;
+
+
+{ TTestProcedureStatement }
+
+function TTestProcedureStatement.TestStatement(const ASource: String
+  ): TSQLStatement;
+begin
+  CreateParser(ASource);
+  Parser.GetNextToken;
+  FToFree:=Parser.ParseProcedureStatements;
+  If not (FToFree is TSQLStatement) then
+    Fail('Not a TSQLStatement');
+  Result:=TSQLStatement(FToFree);
+  FSTatement:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestProcedureStatement.TestParseStatementError;
+
+begin
+  CreateParser(FErrSource);
+  FToFree:=Parser.ParseProcedureStatements;
+end;
+
+procedure TTestProcedureStatement.TestStatementError(const ASource: String);
+begin
+  FerrSource:=ASource;
+  AssertException(ESQLParser,@TestParseStatementError);
+end;
+
+procedure TTestProcedureStatement.TestException;
+
+Var
+  E : TSQLExceptionStatement;
+begin
+  E:=TSQLExceptionStatement(CheckClass(TestStatement('EXCEPTION MYE'),TSQLExceptionStatement));
+  AssertIdentifierName('Exception name','MYE',E.ExceptionName);
+end;
+
+procedure TTestProcedureStatement.TestExceptionError;
+begin
+  TestStatementError('EXCEPTION ''MYE''');
+end;
+
+procedure TTestProcedureStatement.TestExit;
+
+Var
+  E : TSQLExitStatement;
+begin
+  E:=TSQLExitStatement(CheckClass(TestStatement('EXIT'),TSQLExitStatement));
+end;
+
+procedure TTestProcedureStatement.TestSuspend;
+
+Var
+  E : TSQLSuspendStatement;
+
+begin
+  E:=TSQLSuspendStatement(CheckClass(TestStatement('Suspend'),TSQLSuspendStatement));
+end;
+
+procedure TTestProcedureStatement.TestEmptyBlock;
+
+Var
+  B : TSQLStatementBlock;
+
+begin
+  B:=TSQLStatementBlock(CheckClass(TestStatement('BEGIN END'),TSQLStatementBlock));
+  AssertEquals('No statements',0,B.Statements.Count)
+end;
+
+procedure TTestProcedureStatement.TestExitBlock;
+
+Var
+  B : TSQLStatementBlock;
+
+begin
+  B:=TSQLStatementBlock(CheckClass(TestStatement('BEGIN EXIT; END'),TSQLStatementBlock));
+  AssertEquals('1 statement',1,B.Statements.Count);
+  CheckClass(B.Statements[0],TSQLExitStatement);
+end;
+
+procedure TTestProcedureStatement.TestExitBlockError;
+
+begin
+  TestStatementError('BEGIN EXIT END')
+end;
+
+procedure TTestProcedureStatement.TestPostEvent;
+Var
+  P : TSQLPostEventStatement;
+
+begin
+  P:=TSQLPostEventStatement(CheckClass(TestStatement('POST_EVENT ''MYEVENT'''),TSQLPostEventStatement));
+  AssertEquals('Correct event name','MYEVENT' , P.EventName);
+  AssertNull('No event column',P.ColName);
+end;
+
+procedure TTestProcedureStatement.TestPostEventColName;
+
+Var
+  P : TSQLPostEventStatement;
+
+begin
+  P:=TSQLPostEventStatement(CheckClass(TestStatement('POST_EVENT MyColName'),TSQLPostEventStatement));
+  AssertEquals('Correct event name','' , P.EventName);
+  AssertIdentifierName('event column','MyColName',P.ColName);
+end;
+
+procedure TTestProcedureStatement.TestPostError;
+
+begin
+  TestStatementError('POST_EVENT 1');
+end;
+
+procedure TTestProcedureStatement.TestAssignSimple;
+Var
+  A : TSQLAssignStatement;
+  E : TSQLLiteralExpression;
+  I : TSQLIntegerLiteral;
+begin
+  A:=TSQLAssignStatement(CheckClass(TestStatement('A=1'),TSQLAssignStatement));
+  AssertIdentifierName('Variable name','A',A.Variable);
+  E:=TSQLLiteralExpression(CheckClass(A.Expression,TSQLLiteralExpression));
+  I:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',1,I.Value);
+end;
+
+procedure TTestProcedureStatement.TestAssignSimpleNew;
+Var
+  A : TSQLAssignStatement;
+  E : TSQLLiteralExpression;
+  I : TSQLIntegerLiteral;
+begin
+  A:=TSQLAssignStatement(CheckClass(TestStatement('NEW.A=1'),TSQLAssignStatement));
+  AssertIdentifierName('Variable name','NEW.A',A.Variable);
+  E:=TSQLLiteralExpression(CheckClass(A.Expression,TSQLLiteralExpression));
+  I:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',1,I.Value);
+end;
+
+procedure TTestProcedureStatement.TestAssignSelect;
+Var
+  A : TSQLAssignStatement;
+  S : TSQLSelectExpression;
+
+begin
+  A:=TSQLAssignStatement(CheckClass(TestStatement('A=(SELECT B FROM C)'),TSQLAssignStatement));
+  AssertIdentifierName('Variable name','A',A.Variable);
+  S:=TSQLSelectExpression(CheckClass(A.Expression,TSQLSelectExpression));
+  AssertEquals('Field count',1,S.Select.Fields.Count);
+  AssertEquals('Table count',1,S.Select.Tables.Count);
+  AssertField(S.Select.Fields[0],'B','');
+  AssertTable(S.Select.Tables[0],'C','');
+end;
+
+procedure TTestProcedureStatement.TestBlockAssignSimple;
+Var
+  A : TSQLAssignStatement;
+  E : TSQLLiteralExpression;
+  I : TSQLIntegerLiteral;
+  B : TSQLStatementBlock;
+
+begin
+  B:=TSQLStatementBlock(CheckClass(TestStatement('BEGIN A=1; EXIT; END'),TSQLStatementBlock));
+  AssertEquals('2 statements',2,B.Statements.Count);
+  CheckClass(B.Statements[1],TSQLExitStatement);
+  A:=TSQLAssignStatement(CheckClass(B.Statements[0],TSQLAssignStatement));
+  AssertIdentifierName('Variable name','A',A.Variable);
+  E:=TSQLLiteralExpression(CheckClass(A.Expression,TSQLLiteralExpression));
+  I:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',1,I.Value);
+end;
+
+procedure TTestProcedureStatement.TestIf;
+Var
+  I : TSQLIfStatement;
+  C : TSQLBinaryExpression;
+  E : TSQLLiteralExpression;
+  A : TSQLIdentifierExpression;
+  LI : TSQLIntegerLiteral;
+
+begin
+  I:=TSQLIfStatement(CheckClass(TestStatement('IF (A=1) THEN EXIT'),TSQLIfStatement));
+  C:=TSQLBinaryExpression(CheckClass(I.Condition,TSQLBinaryExpression));
+  AssertEquals('Equals',boEq,C.Operation);
+  E:=TSQLLiteralExpression(CheckClass(C.Right,TSQLLiteralExpression));
+  LI:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',1,LI.Value);
+  A:=TSQLIdentifierExpression(CheckClass(C.Left,TSQLIdentifierExpression));
+  AssertIdentifierName('Variable name','A',A.Identifier);
+  CheckClass(I.TrueBranch,TSQLExitStatement);
+end;
+
+procedure TTestProcedureStatement.TestIfBlock;
+
+Var
+  I : TSQLIfStatement;
+  C : TSQLBinaryExpression;
+  E : TSQLLiteralExpression;
+  A : TSQLIdentifierExpression;
+  LI : TSQLIntegerLiteral;
+  B : TSQLStatementBlock;
+
+begin
+  I:=TSQLIfStatement(CheckClass(TestStatement('IF (A=1) THEN BEGIN EXIT; END'),TSQLIfStatement));
+  C:=TSQLBinaryExpression(CheckClass(I.Condition,TSQLBinaryExpression));
+  AssertEquals('Equals',boEq,C.Operation);
+  E:=TSQLLiteralExpression(CheckClass(C.Right,TSQLLiteralExpression));
+  LI:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',1,LI.Value);
+  A:=TSQLIdentifierExpression(CheckClass(C.Left,TSQLIdentifierExpression));
+  AssertIdentifierName('Variable name','A',A.Identifier);
+  B:=TSQLStatementBlock(CheckClass(I.TrueBranch,TSQLStatementBlock));
+  AssertEquals('1 statement',1,B.Statements.Count);
+  CheckClass(B.Statements[0],TSQLExitStatement);
+end;
+
+procedure TTestProcedureStatement.TestIfElse;
+Var
+  I : TSQLIfStatement;
+  C : TSQLBinaryExpression;
+  E : TSQLLiteralExpression;
+  A : TSQLIdentifierExpression;
+  LI : TSQLIntegerLiteral;
+begin
+  I:=TSQLIfStatement(CheckClass(TestStatement('IF (A=1) THEN EXIT; ELSE SUSPEND'),TSQLIfStatement));
+  C:=TSQLBinaryExpression(CheckClass(I.Condition,TSQLBinaryExpression));
+  AssertEquals('Equals',boEq,C.Operation);
+  E:=TSQLLiteralExpression(CheckClass(C.Right,TSQLLiteralExpression));
+  LI:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',1,LI.Value);
+  A:=TSQLIdentifierExpression(CheckClass(C.Left,TSQLIdentifierExpression));
+  AssertIdentifierName('Variable name','A',A.Identifier);
+  CheckClass(I.TrueBranch,TSQLExitStatement);
+  CheckClass(I.FalseBranch,TSQLSuspendStatement);
+end;
+
+procedure TTestProcedureStatement.TestIfBlockElse;
+
+Var
+  I : TSQLIfStatement;
+  C : TSQLBinaryExpression;
+  E : TSQLLiteralExpression;
+  A : TSQLIdentifierExpression;
+  LI : TSQLIntegerLiteral;
+  B : TSQLStatementBlock;
+
+begin
+  I:=TSQLIfStatement(CheckClass(TestStatement('IF (A=1) THEN BEGIN EXIT; END ELSE SUSPEND'),TSQLIfStatement));
+  C:=TSQLBinaryExpression(CheckClass(I.Condition,TSQLBinaryExpression));
+  AssertEquals('Equals',boEq,C.Operation);
+  E:=TSQLLiteralExpression(CheckClass(C.Right,TSQLLiteralExpression));
+  LI:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',1,LI.Value);
+  A:=TSQLIdentifierExpression(CheckClass(C.Left,TSQLIdentifierExpression));
+  AssertIdentifierName('Variable name','A',A.Identifier);
+  B:=TSQLStatementBlock(CheckClass(I.TrueBranch,TSQLStatementBlock));
+  AssertEquals('1 statement',1,B.Statements.Count);
+  CheckClass(B.Statements[0],TSQLExitStatement);
+  CheckClass(I.FalseBranch,TSQLSuspendStatement);
+end;
+
+procedure TTestProcedureStatement.TestIfElseError;
+begin
+  TestStatementError('IF (A=B) THEN EXIT ELSE SUSPEND');
+  TestStatementError('IF (A=B) THEN BEGIN EXIT; END; ELSE SUSPEND');
+end;
+
+procedure TTestProcedureStatement.TestIfBlockElseBlock;
+
+Var
+  I : TSQLIfStatement;
+  C : TSQLBinaryExpression;
+  E : TSQLLiteralExpression;
+  A : TSQLIdentifierExpression;
+  LI : TSQLIntegerLiteral;
+  B : TSQLStatementBlock;
+
+begin
+  I:=TSQLIfStatement(CheckClass(TestStatement('IF (A=1) THEN BEGIN EXIT; END ELSE BEGIN SUSPEND; END'),TSQLIfStatement));
+  C:=TSQLBinaryExpression(CheckClass(I.Condition,TSQLBinaryExpression));
+  AssertEquals('Equals',boEq,C.Operation);
+  E:=TSQLLiteralExpression(CheckClass(C.Right,TSQLLiteralExpression));
+  LI:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',1,LI.Value);
+  A:=TSQLIdentifierExpression(CheckClass(C.Left,TSQLIdentifierExpression));
+  AssertIdentifierName('Variable name','A',A.Identifier);
+  B:=TSQLStatementBlock(CheckClass(I.TrueBranch,TSQLStatementBlock));
+  AssertEquals('1 statement',1,B.Statements.Count);
+  CheckClass(B.Statements[0],TSQLExitStatement);
+  B:=TSQLStatementBlock(CheckClass(I.FalseBranch,TSQLStatementBlock));
+  AssertEquals('1 statement',1,B.Statements.Count);
+  CheckClass(B.Statements[0],TSQLSuspendStatement);
+end;
+
+procedure TTestProcedureStatement.TestIfErrorBracketLeft;
+begin
+  TestStatementError('IF A=1) THEN EXIT');
+end;
+
+procedure TTestProcedureStatement.TestIfErrorBracketRight;
+begin
+  TestStatementError('IF (A=1 THEN EXIT');
+end;
+
+procedure TTestProcedureStatement.TestIfErrorNoThen;
+begin
+  TestStatementError('IF (A=1) EXIT');
+end;
+
+procedure TTestProcedureStatement.TestIfErrorSemicolonElse;
+begin
+  TestStatementError('IF (A=1) THEN EXIT; ELSE SUSPEND');
+end;
+
+procedure TTestProcedureStatement.TestWhile;
+
+Var
+  W : TSQLWhileStatement;
+  C : TSQLBinaryExpression;
+  E : TSQLLiteralExpression;
+  A : TSQLIdentifierExpression;
+  LI : TSQLIntegerLiteral;
+  SA : TSQLAssignStatement;
+
+begin
+  W:=TSQLWhileStatement(CheckClass(TestStatement('WHILE (A>1) DO A=A-1'),TSQLWhileStatement));
+  C:=TSQLBinaryExpression(CheckClass(W.Condition,TSQLBinaryExpression));
+  AssertEquals('Equals',boGT,C.Operation);
+  E:=TSQLLiteralExpression(CheckClass(C.Right,TSQLLiteralExpression));
+  LI:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',1,LI.Value);
+  A:=TSQLIdentifierExpression(CheckClass(C.Left,TSQLIdentifierExpression));
+  AssertIdentifierName('Variable name','A',A.Identifier);
+  SA:=TSQLAssignStatement(CheckClass(W.Statement,TSQLAssignStatement));
+  AssertIdentifierName('Variable name','A',SA.Variable);
+  // Check assignment expression
+  C:=TSQLBinaryExpression(CheckClass(SA.Expression,TSQLBinaryExpression));
+  AssertEquals('Equals',boAdd,C.Operation);
+  // Left operand
+  A:=TSQLIdentifierExpression(CheckClass(C.Left,TSQLIdentifierExpression));
+  AssertIdentifierName('Variable name','A',A.Identifier);
+  // Right operand
+  E:=TSQLLiteralExpression(CheckClass(C.Right,TSQLLiteralExpression));
+  LI:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',-1,LI.Value);
+end;
+
+procedure TTestProcedureStatement.TestWhileBlock;
+
+Var
+  W  : TSQLWhileStatement;
+  C  : TSQLBinaryExpression;
+  E  : TSQLLiteralExpression;
+  A  : TSQLIdentifierExpression;
+  LI : TSQLIntegerLiteral;
+  SA : TSQLAssignStatement;
+  B  : TSQLStatementBlock;
+
+begin
+  W:=TSQLWhileStatement(CheckClass(TestStatement('WHILE (A>1) DO BEGIN A=A-1; END'),TSQLWhileStatement));
+  C:=TSQLBinaryExpression(CheckClass(W.Condition,TSQLBinaryExpression));
+  AssertEquals('Equals',boGT,C.Operation);
+  E:=TSQLLiteralExpression(CheckClass(C.Right,TSQLLiteralExpression));
+  LI:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',1,LI.Value);
+  A:=TSQLIdentifierExpression(CheckClass(C.Left,TSQLIdentifierExpression));
+  AssertIdentifierName('Variable name','A',A.Identifier);
+  B:=TSQLStatementBlock(CheckClass(W.Statement,TSQLStatementBlock));
+  AssertEquals('One statement',1,B.Statements.Count);
+  SA:=TSQLAssignStatement(CheckClass(B.Statements[0],TSQLAssignStatement));
+  AssertIdentifierName('Variable name','A',SA.Variable);
+  // Check assignment expression
+  C:=TSQLBinaryExpression(CheckClass(SA.Expression,TSQLBinaryExpression));
+  AssertEquals('Equals',boAdd,C.Operation);
+  // Left operand
+  A:=TSQLIdentifierExpression(CheckClass(C.Left,TSQLIdentifierExpression));
+  AssertIdentifierName('Variable name','A',A.Identifier);
+  // Right operand
+  E:=TSQLLiteralExpression(CheckClass(C.Right,TSQLLiteralExpression));
+  LI:=TSQLIntegerLiteral(CheckClass(E.Literal,TSQLIntegerLiteral));
+  AssertEquals('Correct value',-1,LI.Value);
+end;
+
+procedure TTestProcedureStatement.TestWhileErrorBracketLeft;
+begin
+  TestStatementError('WHILE A>1) DO A=A-1');
+end;
+
+procedure TTestProcedureStatement.TestWhileErrorBracketRight;
+begin
+  TestStatementError('WHILE (A>1 DO A=A-1');
+end;
+
+procedure TTestProcedureStatement.TestWhileErrorNoDo;
+begin
+  TestStatementError('WHILE (A>1) A=A-1');
+end;
+
+procedure TTestProcedureStatement.TestWhenAny;
+Var
+  W : TSQLWhenStatement;
+begin
+  W:=TSQLWhenStatement(CheckClass(TestStatement('WHEN ANY DO EXIT'),TSQLWhenStatement));
+  AssertEquals('No error codes',0,W.Errors.Count);
+  AssertEquals('Any error',True,W.AnyError);
+  CheckClass(W.Statement,TSQLExitStatement);
+end;
+
+procedure TTestProcedureStatement.TestWhenSQLCode;
+Var
+  W : TSQLWhenStatement;
+  E : TSQLWhenSQLError;
+
+begin
+  W:=TSQLWhenStatement(CheckClass(TestStatement('WHEN SQLCODE 1 DO EXIT'),TSQLWhenStatement));
+  AssertEquals('Not Any error',False,W.AnyError);
+  AssertEquals('1 error code',1,W.Errors.Count);
+  CheckClass(W.Statement,TSQLExitStatement);
+  E:=TSQLWhenSQLError(CheckClass(W.Errors[0],TSQLWhenSQLError));
+  AssertEquals('Correct SQL Code',1,E.ErrorCode);
+end;
+
+procedure TTestProcedureStatement.TestWhenGDSCode;
+Var
+  W : TSQLWhenStatement;
+  E : TSQLWhenGDSError;
+
+begin
+  W:=TSQLWhenStatement(CheckClass(TestStatement('WHEN GDSCODE 1 DO EXIT'),TSQLWhenStatement));
+  AssertEquals('Not Any error',False,W.AnyError);
+  AssertEquals('1 error code',1,W.Errors.Count);
+  CheckClass(W.Statement,TSQLExitStatement);
+  E:=TSQLWhenGDSError(CheckClass(W.Errors[0],TSQLWhenGDSError));
+  AssertEquals('Correct SQL Code',1,E.GDSErrorNumber);
+end;
+
+procedure TTestProcedureStatement.TestWhenException;
+Var
+  W : TSQLWhenStatement;
+  E : TSQLWhenException;
+
+begin
+  W:=TSQLWhenStatement(CheckClass(TestStatement('WHEN EXCEPTION MYE DO EXIT'),TSQLWhenStatement));
+  AssertEquals('Not Any error',False,W.AnyError);
+  AssertEquals('1 error code',1,W.Errors.Count);
+  CheckClass(W.Statement,TSQLExitStatement);
+  E:=TSQLWhenException(CheckClass(W.Errors[0],TSQLWhenException));
+  AssertIdentifierName('Correct SQL Code','MYE',E.ExceptionName);
+end;
+
+procedure TTestProcedureStatement.TestWhenExceptionGDS;
+Var
+  W : TSQLWhenStatement;
+  E : TSQLWhenException;
+  G : TSQLWhenGDSError;
+
+begin
+  W:=TSQLWhenStatement(CheckClass(TestStatement('WHEN EXCEPTION MYE, GDSCODE 1 DO EXIT'),TSQLWhenStatement));
+  AssertEquals('Not Any error',False,W.AnyError);
+  AssertEquals('2 error code',2,W.Errors.Count);
+  CheckClass(W.Statement,TSQLExitStatement);
+  E:=TSQLWhenException(CheckClass(W.Errors[0],TSQLWhenException));
+  AssertIdentifierName('Correct SQL Code','MYE',E.ExceptionName);
+  G:=TSQLWhenGDSError(CheckClass(W.Errors[1],TSQLWhenGDSError));
+  AssertEquals('Correct SQL Code',1,G.GDSErrorNumber);
+end;
+
+procedure TTestProcedureStatement.TestWhenAnyBlock;
+
+Var
+  W : TSQLWhenStatement;
+  B : TSQLStatementBlock;
+
+begin
+  W:=TSQLWhenStatement(CheckClass(TestStatement('WHEN ANY DO BEGIN EXIT; END'),TSQLWhenStatement));
+  AssertEquals('No error codes',0,W.Errors.Count);
+  AssertEquals('Any error',True,W.AnyError);
+  B:=TSQLStatementBlock(CheckClass(W.Statement,TSQLStatementBlock));
+  AssertEquals('One statement',1,B.Statements.Count);
+  CheckClass(B.Statements[0],TSQLExitStatement);
+end;
+
+procedure TTestProcedureStatement.TestWhenErrorAny;
+begin
+  TestStatementError('WHEN ANY, EXCEPTION MY DO EXIT');
+end;
+
+procedure TTestProcedureStatement.TestWhenErrorNoDo;
+
+begin
+  TestStatementError('WHEN ANY EXIT');
+end;
+
+procedure TTestProcedureStatement.TestWhenErrorExceptionInt;
+begin
+  TestStatementError('WHEN EXCEPTION 1 DO EXIT');
+end;
+
+procedure TTestProcedureStatement.TestWhenErrorExceptionString;
+begin
+  TestStatementError('WHEN EXCEPTION ''1'' DO EXIT');
+end;
+
+procedure TTestProcedureStatement.TestWhenErrorSqlCode;
+begin
+  TestStatementError('WHEN SQLCODE A DO EXIT');
+end;
+
+procedure TTestProcedureStatement.TestWhenErrorGDSCode;
+begin
+  TestStatementError('WHEN GDSCODE A DO EXIT');
+end;
+
+procedure TTestProcedureStatement.TestExecuteStatement;
+
+Var
+  E : TSQLExecuteProcedureStatement;
+
+begin
+  E:=TSQLExecuteProcedureStatement(CheckClass(TestStatement('EXECUTE PROCEDURE A'),TSQLExecuteProcedureStatement));
+  AssertIDentifierName('Correct procedure','A',E.ProcedureName);
+end;
+
+procedure TTestProcedureStatement.TestExecuteStatementReturningValues;
+
+Var
+  E : TSQLExecuteProcedureStatement;
+
+begin
+  E:=TSQLExecuteProcedureStatement(CheckClass(TestStatement('EXECUTE PROCEDURE A RETURNING_VALUES B'),TSQLExecuteProcedureStatement));
+  AssertIDentifierName('Correct procedure','A',E.ProcedureName);
+  AssertEquals('Returning 1 value',1,E.Returning.Count);
+  AssertIDentifierName('Correct return value','B',E.Returning[0]);
+end;
+procedure TTestProcedureStatement.TestExecuteStatementReturningValuesColon;
+
+Var
+  E : TSQLExecuteProcedureStatement;
+
+begin
+  E:=TSQLExecuteProcedureStatement(CheckClass(TestStatement('EXECUTE PROCEDURE A RETURNING_VALUES :B'),TSQLExecuteProcedureStatement));
+  AssertIDentifierName('Correct procedure','A',E.ProcedureName);
+  AssertEquals('Returning 1 value',1,E.Returning.Count);
+  AssertIDentifierName('Correct return value','B',E.Returning[0]);
+end;
+
+procedure TTestProcedureStatement.TestExecuteStatementReturningValuesBrackets;
+
+Var
+  E : TSQLExecuteProcedureStatement;
+
+begin
+  E:=TSQLExecuteProcedureStatement(CheckClass(TestStatement('EXECUTE PROCEDURE A RETURNING_VALUES (:B)'),TSQLExecuteProcedureStatement));
+  AssertIDentifierName('Correct procedure','A',E.ProcedureName);
+  AssertEquals('Returning 1 value',1,E.Returning.Count);
+  AssertIDentifierName('Correct return value','B',E.Returning[0]);
+end;
+
+procedure TTestProcedureStatement.TestForSimple;
+Var
+  F : TSQLForStatement;
+  P : TSQLPostEventStatement;
+
+begin
+  F:=TSQLForStatement(CheckClass(TestStatement('FOR SELECT A FROM B INTO :C DO POST_EVENT C'),TSQLForStatement));
+  AssertEquals('Field count',1,F.Select.Fields.Count);
+  AssertEquals('Table count',1,F.Select.Tables.Count);
+  AssertField(F.Select.Fields[0],'A','');
+  AssertTable(F.Select.Tables[0],'B','');
+  AssertEquals('Into Fieldlist count',1,F.FieldList.Count);
+  AssertIdentifierName('Correct field name','C',F.FieldList[0]);
+  P:=TSQLPostEventStatement(CheckClass(F.Statement,TSQLPostEventStatement));
+  AssertIdentifierName('Event name','C',P.ColName);
+end;
+
+procedure TTestProcedureStatement.TestForSimpleNoColon;
+Var
+  F : TSQLForStatement;
+  P : TSQLPostEventStatement;
+
+begin
+  F:=TSQLForStatement(CheckClass(TestStatement('FOR SELECT A FROM B INTO C DO POST_EVENT C'),TSQLForStatement));
+  AssertEquals('Field count',1,F.Select.Fields.Count);
+  AssertEquals('Table count',1,F.Select.Tables.Count);
+  AssertField(F.Select.Fields[0],'A','');
+  AssertTable(F.Select.Tables[0],'B','');
+  AssertEquals('Into Fieldlist count',1,F.FieldList.Count);
+  AssertIdentifierName('Correct field name','C',F.FieldList[0]);
+  P:=TSQLPostEventStatement(CheckClass(F.Statement,TSQLPostEventStatement));
+  AssertIdentifierName('Event name','C',P.ColName);
+end;
+
+procedure TTestProcedureStatement.TestForSimple2fields;
+Var
+  F : TSQLForStatement;
+  P : TSQLPostEventStatement;
+
+begin
+  F:=TSQLForStatement(CheckClass(TestStatement('FOR SELECT A,B FROM C INTO :D,:E DO POST_EVENT D'),TSQLForStatement));
+  AssertEquals('Field count',2,F.Select.Fields.Count);
+  AssertEquals('Table count',1,F.Select.Tables.Count);
+  AssertField(F.Select.Fields[0],'A','');
+  AssertField(F.Select.Fields[1],'B','');
+  AssertTable(F.Select.Tables[0],'C','');
+  AssertEquals('Into Fieldlist count',2,F.FieldList.Count);
+  AssertIdentifierName('Correct field name','D',F.FieldList[0]);
+  AssertIdentifierName('Correct field name','E',F.FieldList[1]);
+  P:=TSQLPostEventStatement(CheckClass(F.Statement,TSQLPostEventStatement));
+  AssertIdentifierName('Event name','D',P.ColName);
+end;
+
+procedure TTestProcedureStatement.TestForBlock;
+Var
+  F : TSQLForStatement;
+  P : TSQLPostEventStatement;
+  B : TSQLStatementBlock;
+
+begin
+  F:=TSQLForStatement(CheckClass(TestStatement('FOR SELECT A FROM B INTO :C DO BEGIN POST_EVENT C; END'),TSQLForStatement));
+  AssertEquals('Field count',1,F.Select.Fields.Count);
+  AssertEquals('Table count',1,F.Select.Tables.Count);
+  AssertField(F.Select.Fields[0],'A','');
+  AssertTable(F.Select.Tables[0],'B','');
+  AssertEquals('Into Fieldlist count',1,F.FieldList.Count);
+  AssertIdentifierName('Correct field name','C',F.FieldList[0]);
+  B:=TSQLStatementBlock(CheckClass(F.Statement,TSQLStatementBlock));
+  AssertEquals('One statement',1,B.Statements.Count);
+  P:=TSQLPostEventStatement(CheckClass(B.Statements[0],TSQLPostEventStatement));
+  AssertIdentifierName('Event name','C',P.ColName);
+end;
+
+{ TTestCreateProcedureParser }
+
+function TTestCreateProcedureParser.TestCreate(const ASource: String
+  ): TSQLCreateProcedureStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLCreateProcedureStatement(CheckClass(FToFree,TSQLCreateProcedureStatement));
+  FSTatement:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestCreateProcedureParser.TestCreateError(const ASource: String
+  );
+begin
+  FErrSource:=ASource;
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestCreateProcedureParser.TestEmptyProcedure;
+
+begin
+  TestCreate('CREATE PROCEDURE A AS BEGIN END');
+  AssertIdentifierName('Correcte procedure naam','A',Statement.ObjectName);
+  AssertEquals('No arguments',0,Statement.InputVariables.Count);
+  AssertEquals('No return values',0,Statement.OutputVariables.Count);
+  AssertEquals('No local variables',0,Statement.LocalVariables.Count);
+  AssertEquals('No statements',0,Statement.Statements.Count);
+end;
+
+procedure TTestCreateProcedureParser.TestExitProcedure;
+
+begin
+  TestCreate('CREATE PROCEDURE A AS BEGIN EXIT; END');
+  AssertIdentifierName('Correcte procedure naam','A',Statement.ObjectName);
+  AssertEquals('No arguments',0,Statement.InputVariables.Count);
+  AssertEquals('No return values',0,Statement.OutputVariables.Count);
+  AssertEquals('No local variables',0,Statement.LocalVariables.Count);
+  AssertEquals('One statement',1,Statement.Statements.Count);
+  CheckClass(Statement.Statements[0],TSQLExitStatement);
+end;
+
+procedure TTestCreateProcedureParser.TestProcedureOneArgument;
+
+Var
+  P : TSQLProcedureParamDef;
+
+begin
+  TestCreate('CREATE PROCEDURE A (P INT) AS BEGIN END');
+  AssertIdentifierName('Correcte procedure naam','A',Statement.ObjectName);
+  AssertEquals('1 arguments',1,Statement.InputVariables.Count);
+  P:=TSQLProcedureParamDef(CheckClass(Statement.InputVariables[0],TSQLProcedureParamDef));
+  AssertIdentifierName('Correct parameter name','P',P.ParamName);
+  AssertNotNull('Have type definition',P.ParamType);
+  AssertEquals('Correct type',sdtInteger,P.ParamType.DataType);
+  AssertEquals('No return values',0,Statement.OutputVariables.Count);
+  AssertEquals('No local variables',0,Statement.LocalVariables.Count);
+  AssertEquals('No statements',0,Statement.Statements.Count);
+end;
+
+procedure TTestCreateProcedureParser.TestProcedureTwoArguments;
+Var
+  P : TSQLProcedureParamDef;
+
+begin
+  TestCreate('CREATE PROCEDURE A (P INT,Q CHAR(4)) AS BEGIN END');
+  AssertIdentifierName('Correcte procedure naam','A',Statement.ObjectName);
+  AssertEquals('Two arguments',2,Statement.InputVariables.Count);
+  P:=TSQLProcedureParamDef(CheckClass(Statement.InputVariables[0],TSQLProcedureParamDef));
+  AssertIdentifierName('Correct parameter name','P',P.ParamName);
+  AssertNotNull('Have type definition',P.ParamType);
+  AssertEquals('Correct type',sdtInteger,P.ParamType.DataType);
+  AssertEquals('No return values',0,Statement.OutputVariables.Count);
+  P:=TSQLProcedureParamDef(CheckClass(Statement.InputVariables[1],TSQLProcedureParamDef));
+  AssertIdentifierName('Correct parameter name','Q',P.ParamName);
+  AssertNotNull('Have type definition',P.ParamType);
+  AssertEquals('Correct type',sdtChar,P.ParamType.DataType);
+  AssertEquals('Correct length',4,P.ParamType.Len);
+  //
+  AssertEquals('No local variables',0,Statement.LocalVariables.Count);
+  AssertEquals('No statements',0,Statement.Statements.Count);
+end;
+
+procedure TTestCreateProcedureParser.TestProcedureOneReturnValue;
+Var
+  P : TSQLProcedureParamDef;
+
+begin
+  TestCreate('CREATE PROCEDURE A RETURNS (P INT) AS BEGIN END');
+  AssertIdentifierName('Correcte procedure naam','A',Statement.ObjectName);
+  AssertEquals('1 return value',1,Statement.OutputVariables.Count);
+  P:=TSQLProcedureParamDef(CheckClass(Statement.OutputVariables[0],TSQLProcedureParamDef));
+  AssertIdentifierName('Correct parameter name','P',P.ParamName);
+  AssertNotNull('Have type definition',P.ParamType);
+  AssertEquals('Correct type',sdtInteger,P.ParamType.DataType);
+  AssertEquals('No input values',0,Statement.InputVariables.Count);
+  AssertEquals('No local variables',0,Statement.LocalVariables.Count);
+  AssertEquals('No statements',0,Statement.Statements.Count);
+end;
+
+procedure TTestCreateProcedureParser.TestProcedureTwoReturnValues;
+Var
+  P : TSQLProcedureParamDef;
+
+begin
+  TestCreate('CREATE PROCEDURE A RETURNS (P INT, Q CHAR(5)) AS BEGIN END');
+  AssertIdentifierName('Correcte procedure naam','A',Statement.ObjectName);
+  AssertEquals('2 return values',2,Statement.OutputVariables.Count);
+  P:=TSQLProcedureParamDef(CheckClass(Statement.OutputVariables[0],TSQLProcedureParamDef));
+  AssertIdentifierName('Correct parameter name','P',P.ParamName);
+  AssertNotNull('Have type definition',P.ParamType);
+  AssertEquals('Correct type',sdtInteger,P.ParamType.DataType);
+  P:=TSQLProcedureParamDef(CheckClass(Statement.OutputVariables[1],TSQLProcedureParamDef));
+  AssertIdentifierName('Correct parameter name','Q',P.ParamName);
+  AssertNotNull('Have type definition',P.ParamType);
+  AssertEquals('Correct type',sdtChar,P.ParamType.DataType);
+  AssertEquals('Correct length',5,P.ParamType.Len);
+  AssertEquals('No input values',0,Statement.InputVariables.Count);
+  AssertEquals('No local variables',0,Statement.LocalVariables.Count);
+  AssertEquals('No statements',0,Statement.Statements.Count);
+end;
+
+procedure TTestCreateProcedureParser.TestProcedureOneLocalVariable;
+Var
+  P : TSQLProcedureParamDef;
+
+begin
+  TestCreate('CREATE PROCEDURE A AS DECLARE VARIABLE P INT; BEGIN END');
+  AssertIdentifierName('Correcte procedure naam','A',Statement.ObjectName);
+  AssertEquals('0 return values',0,Statement.OutputVariables.Count);
+  AssertEquals('1 local variable',1,Statement.LocalVariables.Count);
+  P:=TSQLProcedureParamDef(CheckClass(Statement.LocalVariables[0],TSQLProcedureParamDef));
+  AssertIdentifierName('Correct parameter name','P',P.ParamName);
+  AssertNotNull('Have type definition',P.ParamType);
+  AssertEquals('Correct type',sdtInteger,P.ParamType.DataType);
+  AssertEquals('No input values',0,Statement.InputVariables.Count);
+  AssertEquals('No statements',0,Statement.Statements.Count);
+end;
+
+procedure TTestCreateProcedureParser.TestProcedureTwoLocalVariable;
+Var
+  P : TSQLProcedureParamDef;
+
+begin
+  TestCreate('CREATE PROCEDURE A AS DECLARE VARIABLE P INT; DECLARE VARIABLE Q CHAR(5); BEGIN END');
+  AssertIdentifierName('Correcte procedure naam','A',Statement.ObjectName);
+  AssertEquals('0 return values',0,Statement.OutputVariables.Count);
+  AssertEquals('2 local variable',2,Statement.LocalVariables.Count);
+  P:=TSQLProcedureParamDef(CheckClass(Statement.LocalVariables[0],TSQLProcedureParamDef));
+  AssertIdentifierName('Correct parameter name','P',P.ParamName);
+  AssertNotNull('Have type definition',P.ParamType);
+  AssertEquals('Correct type',sdtInteger,P.ParamType.DataType);
+  P:=TSQLProcedureParamDef(CheckClass(Statement.LocalVariables[1],TSQLProcedureParamDef));
+  AssertIdentifierName('Correct parameter name','Q',P.ParamName);
+  AssertNotNull('Have type definition',P.ParamType);
+  AssertEquals('Correct type',sdtChar,P.ParamType.DataType);
+  AssertEquals('Correct length',5,P.ParamType.Len);
+  AssertEquals('No input values',0,Statement.InputVariables.Count);
+  AssertEquals('No statements',0,Statement.Statements.Count);
+end;
+
+procedure TTestCreateProcedureParser.TestProcedureInputOutputLocal;
+
+Var
+  P : TSQLProcedureParamDef;
+
+begin
+  TestCreate('CREATE PROCEDURE A (P INT) RETURNS (Q CHAR(5)) AS DECLARE VARIABLE R VARCHAR(5); BEGIN END');
+  AssertIdentifierName('Correcte procedure naam','A',Statement.ObjectName);
+  // Input
+  AssertEquals('1 input value',1,Statement.InputVariables.Count);
+  P:=TSQLProcedureParamDef(CheckClass(Statement.InputVariables[0],TSQLProcedureParamDef));
+  AssertIdentifierName('Correct parameter name','P',P.ParamName);
+  AssertNotNull('Have type definition',P.ParamType);
+  AssertEquals('Correct type',sdtInteger,P.ParamType.DataType);
+  // Output
+  AssertEquals('1 return values',1,Statement.OutputVariables.Count);
+  P:=TSQLProcedureParamDef(CheckClass(Statement.OutputVariables[0],TSQLProcedureParamDef));
+  AssertIdentifierName('Correct parameter name','Q',P.ParamName);
+  AssertNotNull('Have type definition',P.ParamType);
+  AssertEquals('Correct type',sdtChar,P.ParamType.DataType);
+  AssertEquals('Correct length',5,P.ParamType.Len);
+  // Local
+  AssertEquals('1 local variable',1,Statement.LocalVariables.Count);
+  P:=TSQLProcedureParamDef(CheckClass(Statement.LocalVariables[0],TSQLProcedureParamDef));
+  AssertIdentifierName('Correct parameter name','R',P.ParamName);
+  AssertNotNull('Have type definition',P.ParamType);
+  AssertEquals('Correct type',sdtvarChar,P.ParamType.DataType);
+  AssertEquals('Correct length',5,P.ParamType.Len);
+  AssertEquals('No statements',0,Statement.Statements.Count);
+end;
+
+{ TTestCreateTriggerParser }
+
+function TTestCreateTriggerParser.TestCreate(const ASource: String
+  ): TSQLCreateTriggerStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLCreateTriggerStatement(CheckClass(FToFree,TSQLCreateTriggerStatement));
+  FSTatement:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+function TTestCreateTriggerParser.TestAlter(const ASource: String
+  ): TSQLAlterTriggerStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLAlterTriggerStatement(CheckClass(FToFree,TSQLAlterTriggerStatement));
+  FSTatement:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestCreateTriggerParser.TestCreateError(const ASource: String);
+begin
+  FErrSource:=ASource;
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestCreateTriggerParser.TestEmptyTrigger;
+begin
+  TestCreate('CREATE TRIGGER A FOR B BEFORE UPDATE AS BEGIN END');
+  AssertIdentifierName('Correct trigger name','A',Statement.ObjectName);
+  AssertIdentifierName('Correct table','B',Statement.TableName);
+  AssertEquals('No variables',0,Statement.LocalVariables.Count);
+  AssertEquals('No Statements',0,Statement.Statements.Count);
+  AssertEquals('No position',0,Statement.Position);
+  AssertEquals('No active/inactive',tsNone,Statement.State);
+  AssertEquals('Before moment',tmBefore,Statement.Moment);
+  AssertEquals('Update operation',[toUpdate],Statement.Operations);
+end;
+
+procedure TTestCreateTriggerParser.TestExitTrigger;
+begin
+  TestCreate('CREATE TRIGGER A FOR B BEFORE UPDATE AS BEGIN EXIT; END');
+  AssertIdentifierName('Correct trigger name','A',Statement.ObjectName);
+  AssertIdentifierName('Correct table','B',Statement.TableName);
+  AssertEquals('No variables',0,Statement.LocalVariables.Count);
+  AssertEquals('1 Statements',1,Statement.Statements.Count);
+  AssertEquals('No position',0,Statement.Position);
+  AssertEquals('No active/inactive',tsNone,Statement.State);
+  AssertEquals('Before moment',tmBefore,Statement.Moment);
+  AssertEquals('Update operation',[toUpdate],Statement.Operations);
+  CheckClass(Statement.Statements[0],TSQLExitStatement);
+end;
+
+procedure TTestCreateTriggerParser.TestEmptyTriggerAfterUpdate;
+begin
+  TestCreate('CREATE TRIGGER A FOR B AFTER UPDATE AS BEGIN END');
+  AssertIdentifierName('Correct trigger name','A',Statement.ObjectName);
+  AssertIdentifierName('Correct table','B',Statement.TableName);
+  AssertEquals('No variables',0,Statement.LocalVariables.Count);
+  AssertEquals('No Statements',0,Statement.Statements.Count);
+  AssertEquals('No position',0,Statement.Position);
+  AssertEquals('No active/inactive',tsNone,Statement.State);
+  AssertEquals('Before moment',tmAfter,Statement.Moment);
+  AssertEquals('Update operation',[toUpdate],Statement.Operations);
+end;
+
+procedure TTestCreateTriggerParser.TestEmptyTriggerBeforeDelete;
+begin
+  TestCreate('CREATE TRIGGER A FOR B BEFORE DELETE AS BEGIN END');
+  AssertIdentifierName('Correct trigger name','A',Statement.ObjectName);
+  AssertIdentifierName('Correct table','B',Statement.TableName);
+  AssertEquals('No variables',0,Statement.LocalVariables.Count);
+  AssertEquals('No Statements',0,Statement.Statements.Count);
+  AssertEquals('No position',0,Statement.Position);
+  AssertEquals('No active/inactive',tsNone,Statement.State);
+  AssertEquals('Before moment',tmBefore,Statement.Moment);
+  AssertEquals('Delete operation',[toDelete],Statement.Operations);
+end;
+
+procedure TTestCreateTriggerParser.TestEmptyTriggerBeforeInsert;
+begin
+  TestCreate('CREATE TRIGGER A FOR B BEFORE INSERT AS BEGIN END');
+  AssertIdentifierName('Correct trigger name','A',Statement.ObjectName);
+  AssertIdentifierName('Correct table','B',Statement.TableName);
+  AssertEquals('No variables',0,Statement.LocalVariables.Count);
+  AssertEquals('No Statements',0,Statement.Statements.Count);
+  AssertEquals('No position',0,Statement.Position);
+  AssertEquals('No active/inactive',tsNone,Statement.State);
+  AssertEquals('Before moment',tmBefore,Statement.Moment);
+  AssertEquals('Insert operation',[toInsert],Statement.Operations);
+end;
+
+procedure TTestCreateTriggerParser.TestEmptyTriggerBeforeInsertPosition1;
+begin
+  TestCreate('CREATE TRIGGER A FOR B BEFORE INSERT POSITION 1 AS BEGIN END');
+  AssertIdentifierName('Correct trigger name','A',Statement.ObjectName);
+  AssertIdentifierName('Correct table','B',Statement.TableName);
+  AssertEquals('No variables',0,Statement.LocalVariables.Count);
+  AssertEquals('No Statements',0,Statement.Statements.Count);
+  AssertEquals('position 1',1,Statement.Position);
+  AssertEquals('No active/inactive',tsNone,Statement.State);
+  AssertEquals('Before moment',tmBefore,Statement.Moment);
+  AssertEquals('Insert operation',[toInsert],Statement.Operations);
+end;
+
+procedure TTestCreateTriggerParser.TestEmptyTriggerBeforeInsertPosition1inActive;
+begin
+  TestCreate('CREATE TRIGGER A FOR B INACTIVE BEFORE INSERT POSITION 1 AS BEGIN END');
+  AssertIdentifierName('Correct trigger name','A',Statement.ObjectName);
+  AssertIdentifierName('Correct table','B',Statement.TableName);
+  AssertEquals('No variables',0,Statement.LocalVariables.Count);
+  AssertEquals('No Statements',0,Statement.Statements.Count);
+  AssertEquals('position 1',1,Statement.Position);
+  AssertEquals('inactive',tsInactive,Statement.State);
+  AssertEquals('Before moment',tmBefore,Statement.Moment);
+  AssertEquals('Insert operation',[toInsert],Statement.Operations);
+end;
+
+procedure TTestCreateTriggerParser.TestEmptyTriggerBeforeInsertPosition1Active;
+begin
+  TestCreate('CREATE TRIGGER A FOR B ACTIVE BEFORE INSERT POSITION 1 AS BEGIN END');
+  AssertIdentifierName('Correct trigger name','A',Statement.ObjectName);
+  AssertIdentifierName('Correct table','B',Statement.TableName);
+  AssertEquals('No variables',0,Statement.LocalVariables.Count);
+  AssertEquals('No Statements',0,Statement.Statements.Count);
+  AssertEquals('position 1',1,Statement.Position);
+  AssertEquals('Active',tsActive,Statement.State);
+  AssertEquals('Before moment',tmBefore,Statement.Moment);
+  AssertEquals('Insert operation',[toInsert],Statement.Operations);
+end;
+
+procedure TTestCreateTriggerParser.TestTriggerOneLocalVariable;
+
+Var
+  P : TSQLProcedureParamDef;
+
+begin
+  TestCreate('CREATE TRIGGER A FOR B ACTIVE BEFORE INSERT POSITION 1 AS DECLARE VARIABLE P INT; BEGIN END');
+  AssertIdentifierName('Correcte procedure naam','A',Statement.ObjectName);
+  AssertIdentifierName('Correct table','B',Statement.TableName);
+  AssertEquals('No Statements',0,Statement.Statements.Count);
+  AssertEquals('position 1',1,Statement.Position);
+  AssertEquals('Active',tsActive,Statement.State);
+  AssertEquals('Before moment',tmBefore,Statement.Moment);
+  AssertEquals('Insert operation',[toInsert],Statement.Operations);
+  AssertEquals('1 local variable',1,Statement.LocalVariables.Count);
+  P:=TSQLProcedureParamDef(CheckClass(Statement.LocalVariables[0],TSQLProcedureParamDef));
+  AssertIdentifierName('Correct parameter name','P',P.ParamName);
+  AssertNotNull('Have type definition',P.ParamType);
+  AssertEquals('Correct type',sdtInteger,P.ParamType.DataType);
+end;
+
+procedure TTestCreateTriggerParser.TestTriggerTwoLocalVariables;
+Var
+  P : TSQLProcedureParamDef;
+
+begin
+  TestCreate('CREATE TRIGGER A FOR B ACTIVE BEFORE INSERT POSITION 1 AS DECLARE VARIABLE P INT; DECLARE VARIABLE Q INT; BEGIN END');
+  AssertIdentifierName('Correcte procedure naam','A',Statement.ObjectName);
+  AssertIdentifierName('Correct table','B',Statement.TableName);
+  AssertEquals('No Statements',0,Statement.Statements.Count);
+  AssertEquals('position 1',1,Statement.Position);
+  AssertEquals('Active',tsActive,Statement.State);
+  AssertEquals('Before moment',tmBefore,Statement.Moment);
+  AssertEquals('Insert operation',[toInsert],Statement.Operations);
+  AssertEquals('2 local variables',2,Statement.LocalVariables.Count);
+  P:=TSQLProcedureParamDef(CheckClass(Statement.LocalVariables[0],TSQLProcedureParamDef));
+  AssertIdentifierName('Correct parameter name','P',P.ParamName);
+  AssertNotNull('Have type definition',P.ParamType);
+  AssertEquals('Correct type',sdtInteger,P.ParamType.DataType);
+  P:=TSQLProcedureParamDef(CheckClass(Statement.LocalVariables[1],TSQLProcedureParamDef));
+  AssertIdentifierName('Correct parameter name','Q',P.ParamName);
+  AssertNotNull('Have type definition',P.ParamType);
+  AssertEquals('Correct type',sdtInteger,P.ParamType.DataType);
+end;
+
+procedure TTestCreateTriggerParser.TestAlterTrigger;
+begin
+  TestAlter('ALTER TRIGGER A BEFORE UPDATE AS BEGIN END');
+  AssertIdentifierName('Correct trigger name','A',Statement.ObjectName);
+  AssertNull('Correct table',Statement.TableName);
+  AssertEquals('No variables',0,Statement.LocalVariables.Count);
+  AssertEquals('No Statements',0,Statement.Statements.Count);
+  AssertEquals('No position',0,Statement.Position);
+  AssertEquals('No active/inactive',tsNone,Statement.State);
+  AssertEquals('Before moment',tmBefore,Statement.Moment);
+  AssertEquals('Update operation',[toUpdate],Statement.Operations);
+
+end;
+
+{ TTestDeclareExternalFunctionParser }
+
+function TTestDeclareExternalFunctionParser.TestCreate(const ASource: String
+  ): TSQLDeclareExternalFunctionStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  Result:=TSQLDeclareExternalFunctionStatement(CheckClass(FToFree,TSQLDeclareExternalFunctionStatement));
+  FSTatement:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestDeclareExternalFunctionParser.TestCreateError(
+  const ASource: String);
+begin
+  FErrSource:=ASource;
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestDeclareExternalFunctionParser.TestEmptyfunction;
+begin
+  TestCreate('DECLARE EXTERNAL FUNCTION A RETURNS INT ENTRY_POINT ''A'' MODULE_NAME ''B''');
+  AssertIdentifierName('Correct function','A',Statement.ObjectName);
+  AssertEquals('Correct entry point','A',Statement.EntryPoint);
+  AssertEquals('Correct module name','B',Statement.ModuleName);
+  AssertEquals('No arguments',0,Statement.Arguments.Count);
+  AssertNotNull('Have return type',Statement.ReturnType);
+  AssertEquals('No FreeIt',False,Statement.FreeIt);
+  AssertEquals('Correct return type',sdtInteger,Statement.ReturnType.DataType);
+end;
+
+procedure TTestDeclareExternalFunctionParser.TestEmptyfunctionByValue;
+begin
+  TestCreate('DECLARE EXTERNAL FUNCTION A RETURNS INT BY VALUE ENTRY_POINT ''A'' MODULE_NAME ''B''');
+  AssertIdentifierName('Correct function','A',Statement.ObjectName);
+  AssertEquals('Correct entry point','A',Statement.EntryPoint);
+  AssertEquals('Correct module name','B',Statement.ModuleName);
+  AssertEquals('No arguments',0,Statement.Arguments.Count);
+  AssertNotNull('Have return type',Statement.ReturnType);
+  AssertEquals('No FreeIt',False,Statement.FreeIt);
+  AssertEquals('Correct return type',sdtInteger,Statement.ReturnType.DataType);
+  AssertEquals('By Value',True,Statement.ReturnType.ByValue);
+end;
+
+procedure TTestDeclareExternalFunctionParser.TestCStringfunction;
+
+begin
+  TestCreate('DECLARE EXTERNAL FUNCTION A RETURNS CSTRING (50) ENTRY_POINT ''A'' MODULE_NAME ''B''');
+  AssertIdentifierName('Correct function','A',Statement.ObjectName);
+  AssertEquals('Correct entry point','A',Statement.EntryPoint);
+  AssertEquals('Correct module name','B',Statement.ModuleName);
+  AssertEquals('No arguments',0,Statement.Arguments.Count);
+  AssertNotNull('Have return type',Statement.ReturnType);
+  AssertEquals('No FreeIt',False,Statement.FreeIt);
+  AssertEquals('Correct return type',sdtCstring,Statement.ReturnType.DataType);
+  AssertEquals('Correct return length',50,Statement.ReturnType.Len);
+end;
+
+procedure TTestDeclareExternalFunctionParser.TestCStringFreeItfunction;
+begin
+  TestCreate('DECLARE EXTERNAL FUNCTION A RETURNS CSTRING (50) FREE_IT ENTRY_POINT ''A'' MODULE_NAME ''B''');
+  AssertIdentifierName('Correct function','A',Statement.ObjectName);
+  AssertEquals('Correct entry point','A',Statement.EntryPoint);
+  AssertEquals('Correct module name','B',Statement.ModuleName);
+  AssertEquals('No arguments',0,Statement.Arguments.Count);
+  AssertNotNull('Have return type',Statement.ReturnType);
+  AssertEquals('FreeIt',True,Statement.FreeIt);
+  AssertEquals('Correct return type',sdtCstring,Statement.ReturnType.DataType);
+  AssertEquals('Correct return length',50,Statement.ReturnType.Len);
+end;
+
+procedure TTestDeclareExternalFunctionParser.TestOneArgumentFunction;
+
+Var
+  T : TSQLTypeDefinition;
+
+begin
+  TestCreate('DECLARE EXTERNAL FUNCTION A INT RETURNS INT ENTRY_POINT ''A'' MODULE_NAME ''B''');
+  AssertIdentifierName('Correct function','A',Statement.ObjectName);
+  AssertEquals('Correct entry point','A',Statement.EntryPoint);
+  AssertEquals('Correct module name','B',Statement.ModuleName);
+  AssertEquals('1 argument',1,Statement.Arguments.Count);
+  T:=TSQLTypeDefinition(CheckClass(Statement.Arguments[0],TSQLTypeDefinition));
+  AssertEquals('Correct return type',sdtInteger,T.DataType);
+  AssertNotNull('Have return type',Statement.ReturnType);
+  AssertEquals('No FreeIt',False,Statement.FreeIt);
+  AssertEquals('Correct return type',sdtInteger,Statement.ReturnType.DataType);
+end;
+
+procedure TTestDeclareExternalFunctionParser.TestTwoArgumentsFunction;
+
+Var
+  T : TSQLTypeDefinition;
+
+begin
+  TestCreate('DECLARE EXTERNAL FUNCTION A INT, CSTRING(10) RETURNS INT ENTRY_POINT ''A'' MODULE_NAME ''B''');
+  AssertIdentifierName('Correct function','A',Statement.ObjectName);
+  AssertEquals('Correct entry point','A',Statement.EntryPoint);
+  AssertEquals('Correct module name','B',Statement.ModuleName);
+  AssertEquals('2 arguments',2,Statement.Arguments.Count);
+  T:=TSQLTypeDefinition(CheckClass(Statement.Arguments[0],TSQLTypeDefinition));
+  AssertEquals('Correct argument type',sdtInteger,T.DataType);
+  T:=TSQLTypeDefinition(CheckClass(Statement.Arguments[1],TSQLTypeDefinition));
+  AssertEquals('Correct return type',sdtCstring,T.DataType);
+  AssertEquals('Correct argument length',10,T.Len);
+  AssertNotNull('Have return type',Statement.ReturnType);
+  AssertEquals('No FreeIt',False,Statement.FreeIt);
+  AssertEquals('Correct return type',sdtInteger,Statement.ReturnType.DataType);
+end;
+
+{ TTestGrantParser }
+
+function TTestGrantParser.TestGrant(const ASource: String): TSQLGrantStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  If not (FToFree is  TSQLGrantStatement) then
+    Fail(Format('Wrong parse result class. Expected TSQLGrantStatement, got %s',[FTofree.ClassName]));
+  Result:=TSQLGrantStatement(Ftofree);
+  FSTatement:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestGrantParser.TestGrantError(const ASource: String);
+begin
+  FErrSource:=ASource;
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestGrantParser.TestSimple;
+
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestGrant('GRANT SELECT ON A TO B');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.Test2Operations;
+
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestGrant('GRANT SELECT,INSERT ON A TO B');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('Two permissions',2,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+  CheckClass(T.Privileges[1],TSQLINSERTPrivilege);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestDeletePrivilege;
+
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestGrant('GRANT DELETE ON A TO B');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLDeletePrivilege);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestUpdatePrivilege;
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestGrant('GRANT UPDATE ON A TO B');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLUPDATEPrivilege);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestInsertPrivilege;
+
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestGrant('GRANT INSERT ON A TO B');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLInsertPrivilege);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestReferencePrivilege;
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestGrant('GRANT REFERENCES ON A TO B');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLReferencePrivilege);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestAllPrivileges;
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestGrant('GRANT ALL ON A TO B');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLAllPrivilege);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestAllPrivileges2;
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestGrant('GRANT ALL PRIVILEGES ON A TO B');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLAllPrivilege);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestUpdateColPrivilege;
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLUSerGrantee;
+  U : TSQLUPDATEPrivilege;
+
+begin
+  TestGrant('GRANT UPDATE (C) ON A TO B');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  U:=TSQLUPDATEPrivilege(CheckClass(T.Privileges[0],TSQLUPDATEPrivilege));
+  AssertEquals('1 column',1,U.Columns.Count);
+  AssertIdentifierName('Column C','C',U.Columns[0]);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestUpdate2ColsPrivilege;
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLUSerGrantee;
+  U : TSQLUPDATEPrivilege;
+
+begin
+  TestGrant('GRANT UPDATE (C,D) ON A TO B');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  U:=TSQLUPDATEPrivilege(CheckClass(T.Privileges[0],TSQLUPDATEPrivilege));
+  AssertEquals('2 column',2,U.Columns.Count);
+  AssertIdentifierName('Column C','C',U.Columns[0]);
+  AssertIdentifierName('Column D','D',U.Columns[1]);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestReferenceColPrivilege;
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLUSerGrantee;
+  U : TSQLReferencePrivilege;
+
+begin
+  TestGrant('GRANT REFERENCES (C) ON A TO B');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  U:=TSQLReferencePrivilege(CheckClass(T.Privileges[0],TSQLReferencePrivilege));
+  AssertEquals('1 column',1,U.Columns.Count);
+  AssertIdentifierName('Column C','C',U.Columns[0]);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestReference2ColsPrivilege;
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLUSerGrantee;
+  U : TSQLReferencePrivilege;
+
+begin
+  TestGrant('GRANT REFERENCES (C,D) ON A TO B');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  U:=TSQLReferencePrivilege(CheckClass(T.Privileges[0],TSQLReferencePrivilege));
+  AssertEquals('2 column',2,U.Columns.Count);
+  AssertIdentifierName('Column C','C',U.Columns[0]);
+  AssertIdentifierName('Column D','D',U.Columns[1]);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestUserPrivilege;
+
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLUSerGrantee;
+
+begin
+    TestGrant('GRANT SELECT ON A TO USER B');
+    T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+    AssertIdentifierName('Table name','A',T.TableName);
+    AssertEquals('One grantee', 1,T.Grantees.Count);
+    G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+    AssertEquals('Grantee B','B',G.Name);
+    AssertEquals('One permission',1,T.Privileges.Count);
+    CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+    AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestUserPrivilegeWithGrant;
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLUSerGrantee;
+
+begin
+    TestGrant('GRANT SELECT ON A TO USER B WITH GRANT OPTION');
+    T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+    AssertIdentifierName('Table name','A',T.TableName);
+    AssertEquals('One grantee', 1,T.Grantees.Count);
+    G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+    AssertEquals('Grantee B','B',G.Name);
+    AssertEquals('One permission',1,T.Privileges.Count);
+    CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+    AssertEquals('With grant option',True,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestGroupPrivilege;
+
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLGroupGrantee;
+
+begin
+    TestGrant('GRANT SELECT ON A TO GROUP B');
+    T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+    AssertIdentifierName('Table name','A',T.TableName);
+    AssertEquals('One grantee', 1,T.Grantees.Count);
+    G:=TSQLGroupGrantee(CheckClass(T.Grantees[0],TSQLGroupGrantee));
+    AssertEquals('Grantee B','B',G.Name);
+    AssertEquals('One permission',1,T.Privileges.Count);
+    CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+    AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestProcedurePrivilege;
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLProcedureGrantee;
+
+begin
+  TestGrant('GRANT SELECT ON A TO PROCEDURE B');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  G:=TSQLProcedureGrantee(CheckClass(T.Grantees[0],TSQLProcedureGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestViewPrivilege;
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLViewGrantee;
+
+begin
+  TestGrant('GRANT SELECT ON A TO VIEW B');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  G:=TSQLViewGrantee(CheckClass(T.Grantees[0],TSQLViewGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestTriggerPrivilege;
+
+Var
+  t : TSQLTableGrantStatement;
+  G : TSQLTriggerGrantee;
+
+begin
+  TestGrant('GRANT SELECT ON A TO TRIGGER B');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  G:=TSQLTriggerGrantee(CheckClass(T.Grantees[0],TSQLTriggerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestPublicPrivilege;
+Var
+  t : TSQLTableGrantStatement;
+  P : TSQLPublicGrantee;
+
+begin
+  TestGrant('GRANT SELECT ON A TO PUBLIC');
+  T:=TSQLTableGrantStatement(CheckClass(Statement,TSQLTableGrantStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One grantee', 1,T.Grantees.Count);
+  (CheckClass(T.Grantees[0],TSQLPublicGrantee));
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+  AssertEquals('No grant option',False,T.GrantOption);
+end;
+
+procedure TTestGrantParser.TestExecuteToUser;
+Var
+  P : TSQLProcedureGrantStatement;
+  U : TSQLUserGrantee;
+
+begin
+  TestGrant('GRANT EXECUTE ON PROCEDURE A TO B');
+  P:=TSQLProcedureGrantStatement(CheckClass(Statement,TSQLProcedureGrantStatement));
+  AssertIdentifierName('Procedure name','A',P.ProcedureName);
+  AssertEquals('One grantee', 1,P.Grantees.Count);
+  U:=TSQLUserGrantee(CheckClass(P.Grantees[0],TSQLUserGrantee));
+  AssertEquals('User name','B',U.Name);
+  AssertEquals('No grant option',False,P.GrantOption);
+end;
+
+procedure TTestGrantParser.TestExecuteToProcedure;
+Var
+  P : TSQLProcedureGrantStatement;
+  U : TSQLProcedureGrantee;
+
+begin
+  TestGrant('GRANT EXECUTE ON PROCEDURE A TO PROCEDURE B');
+  P:=TSQLProcedureGrantStatement(CheckClass(Statement,TSQLProcedureGrantStatement));
+  AssertIdentifierName('Procedure name','A',P.ProcedureName);
+  AssertEquals('One grantee', 1,P.Grantees.Count);
+  U:=TSQLProcedureGrantee(CheckClass(P.Grantees[0],TSQLProcedureGrantee));
+  AssertEquals('Procedure grantee name','B',U.Name);
+  AssertEquals('No grant option',False,P.GrantOption);
+end;
+
+procedure TTestGrantParser.TestRoleToUser;
+Var
+  R : TSQLRoleGrantStatement;
+  U : TSQLUserGrantee;
+
+begin
+  TestGrant('GRANT A TO B');
+  R:=TSQLRoleGrantStatement(CheckClass(Statement,TSQLRoleGrantStatement));
+  AssertEquals('One role', 1,R.Roles.Count);
+  AssertIdentifierName('Role name','A',R.Roles[0]);
+  AssertEquals('One grantee', 1,R.Grantees.Count);
+  U:=TSQLUserGrantee(CheckClass(R.Grantees[0],TSQLUserGrantee));
+  AssertEquals('Procedure grantee name','B',U.Name);
+  AssertEquals('No admin option',False,R.AdminOption);
+end;
+
+procedure TTestGrantParser.TestRoleToUserWithAdmin;
+Var
+  R : TSQLRoleGrantStatement;
+  U : TSQLUserGrantee;
+
+begin
+  TestGrant('GRANT A TO B WITH ADMIN OPTION');
+  R:=TSQLRoleGrantStatement(CheckClass(Statement,TSQLRoleGrantStatement));
+  AssertEquals('One role', 1,R.Roles.Count);
+  AssertIdentifierName('Role name','A',R.Roles[0]);
+  AssertEquals('One grantee', 1,R.Grantees.Count);
+  U:=TSQLUserGrantee(CheckClass(R.Grantees[0],TSQLUserGrantee));
+  AssertEquals('Procedure grantee name','B',U.Name);
+  AssertEquals('Admin option',True,R.AdminOption);
+end;
+
+procedure TTestGrantParser.TestRoleToPublic;
+Var
+  R : TSQLRoleGrantStatement;
+
+begin
+  TestGrant('GRANT A TO PUBLIC');
+  R:=TSQLRoleGrantStatement(CheckClass(Statement,TSQLRoleGrantStatement));
+  AssertEquals('One role', 1,R.Roles.Count);
+  AssertIdentifierName('Role name','A',R.Roles[0]);
+  AssertEquals('One grantee', 1,R.Grantees.Count);
+  CheckClass(R.Grantees[0],TSQLPublicGrantee);
+  AssertEquals('No admin option',False,R.AdminOption);
+end;
+
+procedure TTestGrantParser.Test2RolesToUser;
+
+Var
+  R : TSQLRoleGrantStatement;
+  U : TSQLUserGrantee;
+
+begin
+  TestGrant('GRANT A,C TO B');
+  R:=TSQLRoleGrantStatement(CheckClass(Statement,TSQLRoleGrantStatement));
+  AssertEquals('2 roles', 2,R.Roles.Count);
+  AssertIdentifierName('Role name','A',R.Roles[0]);
+  AssertIdentifierName('Role name','C',R.Roles[1]);
+  AssertEquals('One grantee', 1,R.Grantees.Count);
+  U:=TSQLUserGrantee(CheckClass(R.Grantees[0],TSQLUserGrantee));
+  AssertEquals('Procedure grantee name','B',U.Name);
+  AssertEquals('No admin option',False,R.AdminOption);
+end;
+
+{ TTestRevokeParser }
+
+function TTestRevokeParser.TestRevoke(const ASource: String): TSQLRevokeStatement;
+begin
+  CreateParser(ASource);
+  FToFree:=Parser.Parse;
+  If not (FToFree is  TSQLRevokeStatement) then
+    Fail(Format('Wrong parse result class. Expected TSQLRevokeStatement, got %s',[FTofree.ClassName]));
+  Result:=TSQLRevokeStatement(Ftofree);
+  FSTatement:=Result;
+  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
+end;
+
+procedure TTestRevokeParser.TestRevokeError(const ASource: String);
+begin
+  FErrSource:=ASource;
+  AssertException(ESQLParser,@TestParseError);
+end;
+
+procedure TTestRevokeParser.TestSimple;
+
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestRevoke('Revoke SELECT ON A FROM B');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.Test2Operations;
+
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestRevoke('Revoke SELECT,INSERT ON A FROM B');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('Two permissions',2,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+  CheckClass(T.Privileges[1],TSQLINSERTPrivilege);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestDeletePrivilege;
+
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestRevoke('Revoke DELETE ON A FROM B');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLDeletePrivilege);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestUpdatePrivilege;
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestRevoke('Revoke UPDATE ON A FROM B');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLUPDATEPrivilege);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestInsertPrivilege;
+
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestRevoke('Revoke INSERT ON A FROM B');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLInsertPrivilege);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestReferencePrivilege;
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestRevoke('Revoke REFERENCES ON A FROM B');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLReferencePrivilege);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestAllPrivileges;
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestRevoke('Revoke ALL ON A FROM B');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLAllPrivilege);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestAllPrivileges2;
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLUSerGrantee;
+
+begin
+  TestRevoke('Revoke ALL PRIVILEGES ON A FROM B');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLAllPrivilege);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestUpdateColPrivilege;
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLUSerGrantee;
+  U : TSQLUPDATEPrivilege;
+
+begin
+  TestRevoke('Revoke UPDATE (C) ON A FROM B');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  U:=TSQLUPDATEPrivilege(CheckClass(T.Privileges[0],TSQLUPDATEPrivilege));
+  AssertEquals('1 column',1,U.Columns.Count);
+  AssertIdentifierName('Column C','C',U.Columns[0]);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestUpdate2ColsPrivilege;
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLUSerGrantee;
+  U : TSQLUPDATEPrivilege;
+
+begin
+  TestRevoke('Revoke UPDATE (C,D) ON A FROM B');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  U:=TSQLUPDATEPrivilege(CheckClass(T.Privileges[0],TSQLUPDATEPrivilege));
+  AssertEquals('2 column',2,U.Columns.Count);
+  AssertIdentifierName('Column C','C',U.Columns[0]);
+  AssertIdentifierName('Column D','D',U.Columns[1]);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestReferenceColPrivilege;
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLUSerGrantee;
+  U : TSQLReferencePrivilege;
+
+begin
+  TestRevoke('Revoke REFERENCES (C) ON A FROM B');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  U:=TSQLReferencePrivilege(CheckClass(T.Privileges[0],TSQLReferencePrivilege));
+  AssertEquals('1 column',1,U.Columns.Count);
+  AssertIdentifierName('Column C','C',U.Columns[0]);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestReference2ColsPrivilege;
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLUSerGrantee;
+  U : TSQLReferencePrivilege;
+
+begin
+  TestRevoke('Revoke REFERENCES (C,D) ON A FROM B');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  U:=TSQLReferencePrivilege(CheckClass(T.Privileges[0],TSQLReferencePrivilege));
+  AssertEquals('2 column',2,U.Columns.Count);
+  AssertIdentifierName('Column C','C',U.Columns[0]);
+  AssertIdentifierName('Column D','D',U.Columns[1]);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestUserPrivilege;
+
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLUSerGrantee;
+
+begin
+    TestRevoke('Revoke SELECT ON A FROM USER B');
+    T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+    AssertIdentifierName('Table name','A',T.TableName);
+    AssertEquals('One Grantee', 1,T.Grantees.Count);
+    G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+    AssertEquals('Grantee B','B',G.Name);
+    AssertEquals('One permission',1,T.Privileges.Count);
+    CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+    AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestUserPrivilegeWithRevoke;
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLUSerGrantee;
+
+begin
+    TestRevoke('Revoke GRANT OPTION FOR SELECT ON A FROM USER B');
+    T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+    AssertIdentifierName('Table name','A',T.TableName);
+    AssertEquals('One Grantee', 1,T.Grantees.Count);
+    G:=TSQLUSerGrantee(CheckClass(T.Grantees[0],TSQLUSerGrantee));
+    AssertEquals('Grantee B','B',G.Name);
+    AssertEquals('One permission',1,T.Privileges.Count);
+    CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+    AssertEquals('With Revoke option',True,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestGroupPrivilege;
+
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLGroupGrantee;
+
+begin
+    TestRevoke('Revoke SELECT ON A FROM GROUP B');
+    T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+    AssertIdentifierName('Table name','A',T.TableName);
+    AssertEquals('One Grantee', 1,T.Grantees.Count);
+    G:=TSQLGroupGrantee(CheckClass(T.Grantees[0],TSQLGroupGrantee));
+    AssertEquals('Grantee B','B',G.Name);
+    AssertEquals('One permission',1,T.Privileges.Count);
+    CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+    AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestProcedurePrivilege;
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLProcedureGrantee;
+
+begin
+  TestRevoke('Revoke SELECT ON A FROM PROCEDURE B');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  G:=TSQLProcedureGrantee(CheckClass(T.Grantees[0],TSQLProcedureGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestViewPrivilege;
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLViewGrantee;
+
+begin
+  TestRevoke('Revoke SELECT ON A FROM VIEW B');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  G:=TSQLViewGrantee(CheckClass(T.Grantees[0],TSQLViewGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestTriggerPrivilege;
+
+Var
+  t : TSQLTableRevokeStatement;
+  G : TSQLTriggerGrantee;
+
+begin
+  TestRevoke('Revoke SELECT ON A FROM TRIGGER B');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  G:=TSQLTriggerGrantee(CheckClass(T.Grantees[0],TSQLTriggerGrantee));
+  AssertEquals('Grantee B','B',G.Name);
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestPublicPrivilege;
+Var
+  t : TSQLTableRevokeStatement;
+  P : TSQLPublicGrantee;
+
+begin
+  TestRevoke('Revoke SELECT ON A FROM PUBLIC');
+  T:=TSQLTableRevokeStatement(CheckClass(Statement,TSQLTableRevokeStatement));
+  AssertIdentifierName('Table name','A',T.TableName);
+  AssertEquals('One Grantee', 1,T.Grantees.Count);
+  (CheckClass(T.Grantees[0],TSQLPublicGrantee));
+  AssertEquals('One permission',1,T.Privileges.Count);
+  CheckClass(T.Privileges[0],TSQLSelectPrivilege);
+  AssertEquals('No Revoke option',False,T.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestExecuteToUser;
+Var
+  P : TSQLProcedureRevokeStatement;
+  U : TSQLUserGrantee;
+
+begin
+  TestRevoke('Revoke EXECUTE ON PROCEDURE A FROM B');
+  P:=TSQLProcedureRevokeStatement(CheckClass(Statement,TSQLProcedureRevokeStatement));
+  AssertIdentifierName('Procedure name','A',P.ProcedureName);
+  AssertEquals('One Grantee', 1,P.Grantees.Count);
+  U:=TSQLUserGrantee(CheckClass(P.Grantees[0],TSQLUserGrantee));
+  AssertEquals('User name','B',U.Name);
+  AssertEquals('No Revoke option',False,P.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestExecuteToProcedure;
+Var
+  P : TSQLProcedureRevokeStatement;
+  U : TSQLProcedureGrantee;
+
+begin
+  TestRevoke('Revoke EXECUTE ON PROCEDURE A FROM PROCEDURE B');
+  P:=TSQLProcedureRevokeStatement(CheckClass(Statement,TSQLProcedureRevokeStatement));
+  AssertIdentifierName('Procedure name','A',P.ProcedureName);
+  AssertEquals('One Grantee', 1,P.Grantees.Count);
+  U:=TSQLProcedureGrantee(CheckClass(P.Grantees[0],TSQLProcedureGrantee));
+  AssertEquals('Procedure Grantee name','B',U.Name);
+  AssertEquals('No Revoke option',False,P.GrantOption);
+end;
+
+procedure TTestRevokeParser.TestRoleToUser;
+Var
+  R : TSQLRoleRevokeStatement;
+  U : TSQLUserGrantee;
+
+begin
+  TestRevoke('Revoke A FROM B');
+  R:=TSQLRoleRevokeStatement(CheckClass(Statement,TSQLRoleRevokeStatement));
+  AssertEquals('One role', 1,R.Roles.Count);
+  AssertIdentifierName('Role name','A',R.Roles[0]);
+  AssertEquals('One Grantee', 1,R.Grantees.Count);
+  U:=TSQLUserGrantee(CheckClass(R.Grantees[0],TSQLUserGrantee));
+  AssertEquals('Procedure Grantee name','B',U.Name);
+  AssertEquals('No admin option',False,R.AdminOption);
+end;
+
+procedure TTestRevokeParser.TestRoleToPublic;
+Var
+  R : TSQLRoleRevokeStatement;
+
+begin
+  TestRevoke('Revoke A FROM PUBLIC');
+  R:=TSQLRoleRevokeStatement(CheckClass(Statement,TSQLRoleRevokeStatement));
+  AssertEquals('One role', 1,R.Roles.Count);
+  AssertIdentifierName('Role name','A',R.Roles[0]);
+  AssertEquals('One Grantee', 1,R.Grantees.Count);
+  CheckClass(R.Grantees[0],TSQLPublicGrantee);
+  AssertEquals('No admin option',False,R.AdminOption);
+end;
+
+procedure TTestRevokeParser.Test2RolesToUser;
+
+Var
+  R : TSQLRoleRevokeStatement;
+  U : TSQLUserGrantee;
+
+begin
+  TestRevoke('Revoke A,C FROM B');
+  R:=TSQLRoleRevokeStatement(CheckClass(Statement,TSQLRoleRevokeStatement));
+  AssertEquals('2 roles', 2,R.Roles.Count);
+  AssertIdentifierName('Role name','A',R.Roles[0]);
+  AssertIdentifierName('Role name','C',R.Roles[1]);
+  AssertEquals('One Grantee', 1,R.Grantees.Count);
+  U:=TSQLUserGrantee(CheckClass(R.Grantees[0],TSQLUserGrantee));
+  AssertEquals('Procedure Grantee name','B',U.Name);
+  AssertEquals('No admin option',False,R.AdminOption);
+end;
+
+
+initialization
+  RegisterTests([TTestDropParser,
+                 TTestGeneratorParser,
+                 TTestRoleParser,
+                 TTestTypeParser,
+                 TTestCheckParser,
+                 TTestDomainParser,
+                 TTestExceptionParser,
+                 TTestIndexParser,
+                 TTestTableParser,
+                 TTestDeleteParser,
+                 TTestUpdateParser,
+                 TTestInsertParser,
+                 TTestSelectParser,
+                 TTestRollbackParser,
+                 TTestCommitParser,
+                 TTestExecuteProcedureParser,
+                 TTestConnectParser,
+                 TTestCreateDatabaseParser,
+                 TTestAlterDatabaseParser,
+                 TTestCreateViewParser,
+                 TTestCreateShadowParser,
+                 TTestProcedureStatement,
+                 TTestCreateProcedureParser,
+                 TTestCreateTriggerParser,
+                 TTestDeclareExternalFunctionParser,
+                 TTestGrantParser,
+                 TTestRevokeParser]);
+end.
+

+ 1626 - 0
packages/fcl-db/tests/tcsqlscanner.pas

@@ -0,0 +1,1626 @@
+{
+    This file is part of the Free Component Library
+    Copyright (c) 2010 by the Free Pascal development team
+
+    SQL source lexical scanner test suite
+
+    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 tcsqlscanner;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpcunit, testutils, testregistry, fpsqlscanner;
+
+type
+
+  { TTestSQLScanner }
+
+  TTestSQLScanner= class(TTestCase)
+  Private
+    FStream : TStream;
+    FLineReader : TLineReader;
+    FScanner : TSQLScanner;
+    FErrorSource : String;
+    FErrorOptions : TSQLScannerOptions;
+    procedure AssertEquals(AMessage: String; AExpected, AActual : TSQLToken); overload;
+    procedure CheckToken(AToken: TSQLToken; ASource: String);
+    procedure CheckTokens(ASource: String; ATokens: array of TSQLToken);
+    procedure DoTestFloat(F: Double);
+    procedure DoTestFloat(F: Double; S: String);
+    procedure DoTestString(S: String; DoubleDelim : Boolean = False);
+    procedure TestErrorSource;
+  protected
+    Function CreateScanner(AInput : String; AOptions : TSQLScannerOptions = []) : TSQLScanner;
+    procedure FreeScanner;
+    procedure SetUp; override;
+    procedure TearDown; override;
+    Property Scanner : TSQLScanner Read FScanner;
+  published
+    procedure TestAction;
+    procedure TestAdd;
+    procedure TestAdmin;
+    procedure TestAfter;
+    procedure TestALTER;
+    procedure TestAnd;
+    procedure TestAny;
+    procedure TestAs;
+    procedure TestASC;
+    procedure TestASCENDING;
+    Procedure TestAt;
+    procedure TestAuto;
+    procedure TestAVG;
+    procedure TestAssign;
+    procedure TestBefore;
+    Procedure TestBegin;
+    procedure TestBetween;
+    procedure TestBlob;
+    procedure TestBraceClose;
+    procedure TestBraceOpen;
+    procedure TestBy;
+    Procedure TestCache;
+    procedure TestCascade;
+    procedure TestChar;
+    procedure TestCharacter;
+    procedure TestCheck;
+    procedure TestCollate;
+    procedure TestColon;
+    procedure TestColumn;
+    procedure TestComma;
+    procedure TestCommit;
+    procedure TestComputed;
+    procedure TestConcatenate;
+    Procedure TestConditional;
+    Procedure TestConnect;
+    procedure TestConstraint;
+    procedure TestContaining;
+    procedure TestCount;
+    procedure TestCreate;
+    procedure TestCString;
+    Procedure TestDatabase;
+    Procedure TestDate;
+    Procedure TestDecimal;
+    procedure TestDeclare;
+    procedure TestDefault;
+    procedure TestDelete;
+    procedure TestDesc;
+    procedure TestDescending;
+    procedure TestDistinct;
+    procedure TestDiv;
+    procedure TestDO;
+    procedure TestDomain;
+    procedure TestDot;
+    procedure TestDrop;
+    procedure TestElse;
+    procedure TestEmpty;
+    procedure TestEnd;
+    Procedure TestEntryPoint;
+    procedure TestEq;
+    procedure TestEscape;
+    procedure TestException;
+    procedure TestExists;
+    procedure TestExit;
+    Procedure TestExternal;
+    Procedure TestExtract;
+    procedure TestFile;
+    Procedure TestFloat;
+    procedure TestFor;
+    procedure TestForeign;
+    procedure TestFreeIt;
+    procedure TestFunction;
+    Procedure TestGDSError;
+    procedure TestGE;
+    procedure TestGenerator;
+    procedure TestGrant;
+    procedure TestGreaterThan;
+    procedure TestGroup;
+    Procedure TestHaving;
+    procedure TestIf;
+    procedure TestIn;
+    procedure TestIndex;
+    procedure TestInner;
+    procedure TestInsert;
+    procedure TestInt;
+    procedure TestInteger;
+    procedure TestInto;
+    procedure TestIs;
+    procedure TestJoin;
+    procedure TestKey;
+    procedure TestLeft;
+    Procedure TestLength;
+    procedure TestLike;
+    procedure TestLE;
+    procedure TestLessThan;
+    Procedure TestManual;
+    Procedure TestModuleName;
+    procedure TestMax;
+    procedure TestMerge;
+    procedure TestMin;
+    procedure TestMinus;
+    procedure TestMul;
+    procedure TestNational;
+    procedure TestNatural;
+    procedure TestNE;
+    procedure TestNo;
+    procedure TestNot;
+    procedure TestNull;
+    procedure TestNumeric;
+    Procedure TestOn;
+    Procedure TestOption;
+    Procedure TestOr;
+    Procedure TestOrder;
+    Procedure TestOuter;
+    Procedure TestPage;
+    Procedure TestPages;
+    Procedure TestPageSize;
+    Procedure TestPassword;
+    procedure TestPlus;
+    procedure TestPosition;
+    Procedure TestPostEvent;
+    procedure TestPrimary;
+    procedure TestPrivileges;
+    procedure TestProcedure;
+    procedure TestPublic;
+    Procedure TestReferences;
+    Procedure TestRelease;
+    Procedure TestReturningValues;
+    Procedure TestReturns;
+    Procedure TestRetain;
+    Procedure TestRevoke;
+    Procedure TestRight;
+    Procedure TestRole;
+    Procedure TestRollback;
+    Procedure TestSegment;
+    Procedure TestSelect;
+    procedure TestSemicolon;
+    Procedure TestSet;
+    Procedure TestSchema;
+    Procedure TestShadow;
+    Procedure TestSingular;
+    Procedure TestSize;
+    Procedure TestSkip;
+    Procedure TestSome;
+    Procedure TestSort;
+    Procedure TestSnapshot;
+    Procedure TestSQLCode;
+    procedure TestSquareBraceClose;
+    procedure TestSquareBraceOpen;
+    Procedure TestStarting;
+    procedure TestString;
+    procedure TestSubtype;
+    Procedure TestSum;
+    Procedure TestSuspend;
+    Procedure TestTable;
+    Procedure TestThen;
+    Procedure TestTime;
+    Procedure TestTimeStamp;
+    Procedure TestTo;
+    Procedure TestTransaction;
+    Procedure TestTrigger;
+    Procedure TestType;
+    Procedure TestUnion;
+    Procedure TestUnique;
+    Procedure TestUpdate;
+    Procedure TestUpper;
+    Procedure TestUser;
+    procedure TestValue;
+    procedure TestValues;
+    procedure TestVariable;
+    procedure TestVarChar;
+    Procedure TestVarying;
+    Procedure TestView;
+    Procedure TestWhen;
+    Procedure TestWhere;
+    procedure TestWhile;
+    procedure TestWith;
+    procedure TestWork;
+    Procedure Test2Words;
+    procedure Test3Words;
+    procedure TestIdentifier;
+    procedure TestIdentifier2;
+    procedure TestIdentifier3;
+    procedure TestIdentifier4;
+    procedure TestIdentifier5;
+    procedure TestIdentifierDotIdentifier;
+    procedure TestEOLN;
+    procedure TestEOLN2;
+    procedure TestEOLN3;
+    procedure TestEOLN4;
+    procedure TestComment1;
+    procedure TestComment2;
+    procedure TestComment3;
+    procedure TestComment4;
+    procedure TestComment5;
+    procedure TestComment6;
+    procedure TestFloatLiteral;
+    procedure TestStringLiteral1;
+    procedure TestStringLiteral2;
+    procedure TestStringError;
+    procedure TestFloatError;
+    Procedure TestOptionsoDoubleQuoteStringLiteral;
+    Procedure TestOptionsoSingleQuoteIdentifier;
+    procedure TestOptionsoBackQuoteIdentifier;
+    procedure TestOptionNosoBackQuoteIdentifier;
+    procedure TestOptionNosoBackslashEscapes;
+    procedure TestOptionsoBackslashEscapesTab;
+    procedure TestOptionsoBackslashEscapesNewLine;
+    procedure TestOptionsoBackslashEscapesBackSlash;
+    procedure TestOptionsoBackslashEscapesBackspace;
+    procedure TestOptionsoBackslashEscapesLineFeed;
+    procedure TestOptionsoBackslashEscapesNewPage;
+    procedure TestOptionsoBackslashEscapesSlash;
+    procedure TestOptionsoBackslashEscapesQuote;
+    procedure TestOptionsoBackslashEscapesDoubleQuote;
+  end;
+
+implementation
+
+uses typinfo;
+
+procedure TTestSQLScanner.AssertEquals(AMessage: String; AExpected,
+  AActual: TSQLToken);
+
+Var
+  S,EN1,EN2 : String;
+
+begin
+  If (AActual<>AExpected) then
+    begin
+    EN1:=GetEnumName(TypeINfo(TSQLToken),Ord(AExpected));
+    EN2:=GetEnumName(TypeINfo(TSQLToken),Ord(AActual));
+    S:=Format('%s : %s <> %s',[AMessage,EN1,EN2]);
+    Fail(S);
+    end;
+end;
+
+procedure TTestSQLScanner.CheckToken(AToken: TSQLToken; ASource: String);
+
+Var
+  J : TSqlToken;
+  EN2 : String;
+
+begin
+  CreateScanner(ASource);
+  J:=Scanner.FetchToken;
+  EN2:=GetEnumName(TypeINfo(TSQLToken),Ord(AToken));
+  AssertEquals(Format('Source %s should result in %s.',[ASource,EN2]),AToken,J);
+end;
+
+
+procedure TTestSQLScanner.DoTestFloat(F: Double);
+Var
+  S : String;
+
+begin
+  Str(F,S);
+  DoTestFloat(F,S);
+end;
+
+procedure TTestSQLScanner.DoTestFloat(F: Double; S: String);
+Var
+  J : TSQLToken;
+  C : Double;
+  I : integer;
+  V : String;
+
+begin
+  CreateScanner(S);
+  try
+    J:=FScanner.FetchToken;
+    AssertEquals(S+' is a number',tsqlFloatNumber,J);
+    V:=FScanner.CurTokenString;
+    Val(V,C,I);
+    If (I<>0) then
+      Fail(FScanner.CurTokenString+' does not contain a float value');
+    AssertEquals('Parsed float equals original float',F,C);
+  finally
+    FreeScanner;
+  end;
+end;
+
+procedure TTestSQLScanner.DoTestString(S: String; DoubleDelim : Boolean = False);
+Var
+  J : TSQLToken;
+  C : Char;
+
+begin
+  CreateScanner(S);
+  try
+    J:=FScanner.FetchToken;
+    AssertEquals(S+' is a string',tsqlString,J);
+    If (Length(S)>0) and (S[1] in ['"','''']) then
+      begin
+      C:=S[1];
+      S:=Copy(S,2,Length(S)-2);
+      end;
+    If DoubleDelim then
+      S:=StringReplace(S,C+C,C,[rfReplaceAll]);
+    AssertEquals('Correct string is returned',S,FScanner.CurTokenString);
+  finally
+    FreeScanner;
+  end;
+end;
+
+procedure TTestSQLScanner.TestErrorSource;
+begin
+  CreateScanner(FErrorSource,FErrorOptions);
+  While (FScanner.FetchToken<>tsqlEOF) do ;
+end;
+
+function TTestSQLScanner.CreateScanner(AInput: String; AOptions : TSQLScannerOptions = []): TSQLScanner;
+begin
+  FStream:=TStringStream.Create(AInput);
+  FLineReader:=TStreamLineReader.Create(Fstream);
+  FScanner:=TSQLScanner.Create(FLineReader);
+  FScanner.Options:=AOptions;
+  Result:=FSCanner;
+end;
+
+procedure TTestSQLScanner.FreeScanner;
+begin
+  FreeAndNil(FScanner);
+  FreeAndNil(FLineReader);
+  FreeAndNil(FStream);
+end;
+
+procedure TTestSQLScanner.SetUp;
+begin
+  inherited SetUp;
+  FErrorSource:='';
+  FErrorOptions:=[];
+end;
+
+procedure TTestSQLScanner.TearDown;
+begin
+  FreeScanner;
+  iNHERITED;
+end;
+
+procedure TTestSQLScanner.TestAction;
+begin
+  CheckToken(tsqlAction,'ACTION');
+end;
+
+procedure TTestSQLScanner.TestAdd;
+begin
+  CheckToken(tsqlAdd,'ADD');
+end;
+
+procedure TTestSQLScanner.TestAdmin;
+begin
+  CheckToken(tsqlAdmin,'ADMIN');
+end;
+
+procedure TTestSQLScanner.TestAfter;
+begin
+  CheckToken(tsqlAfter,'AFTER');
+end;
+
+procedure TTestSQLScanner.TestEmpty;
+
+Var
+  J : TSQLToken;
+begin
+  CreateScanner('');
+  J:=Scanner.FetchToken;
+  If (J<>tsqlEOF) then
+    Fail('Empty returns EOF');
+end;
+
+procedure TTestSQLScanner.TestEnd;
+begin
+  CheckToken(tsqlEnd,'END');
+end;
+
+procedure TTestSQLScanner.TestEntryPoint;
+begin
+  CheckToken(tsqlEntryPoint,'ENTRY_POINT');
+end;
+
+procedure TTestSQLScanner.TestEscape;
+begin
+  CheckToken(tsqlEscape,'ESCAPE');
+end;
+
+procedure TTestSQLScanner.TestException;
+begin
+  CheckToken(tsqlException,'EXCEPTION');
+end;
+
+procedure TTestSQLScanner.TestExists;
+begin
+  CheckToken(tsqlExists,'EXISTS');
+end;
+
+procedure TTestSQLScanner.TestExit;
+begin
+  CheckToken(tsqlExit,'EXIT');
+end;
+
+procedure TTestSQLScanner.TestExternal;
+begin
+  CheckToken(tsqlExternal,'external');
+end;
+
+procedure TTestSQLScanner.TestExtract;
+begin
+  CheckToken(tsqlExtract,'EXTRACT');
+end;
+
+procedure TTestSQLScanner.TestAnd;
+
+begin
+  CheckToken(tsqlAnd,'and');
+end;
+
+procedure TTestSQLScanner.TestAny;
+begin
+  CheckToken(tsqlAny,'any');
+end;
+
+procedure TTestSQLScanner.TestAs;
+begin
+  CheckToken(tsqlAs,'as');
+end;
+
+procedure TTestSQLScanner.TestAt;
+begin
+  CheckToken(tsqlAt,'at');
+end;
+
+procedure TTestSQLScanner.TestAuto;
+begin
+  CheckToken(tsqlAUTO,'auto');
+end;
+
+procedure TTestSQLScanner.TestASC;
+begin
+  CheckToken(tsqlASC,'asc');
+end;
+
+procedure TTestSQLScanner.TestASCENDING;
+begin
+  CheckToken(tsqlASCENDING,'ascending');
+end;
+
+procedure TTestSQLScanner.TestAVG;
+begin
+  CheckToken(tsqlAVG,'avg');
+end;
+
+procedure TTestSQLScanner.TestALTER;
+begin
+  CheckToken(tsqlALTER,'alter');
+end;
+
+procedure TTestSQLScanner.TestBraceOpen;
+
+begin
+  CheckToken(tsqlBraceOpen,'(');
+end;
+
+procedure TTestSQLScanner.TestBraceClose;
+
+begin
+  CheckToken(tsqlBraceClose,')');
+end;
+
+
+procedure TTestSQLScanner.TestComma;
+
+begin
+  CheckToken(tsqlComma,',');
+end;
+
+procedure TTestSQLScanner.TestCommit;
+begin
+  CheckToken(tsqlCommit,'COMMIT');
+end;
+
+procedure TTestSQLScanner.TestComputed;
+begin
+  CheckToken(tsqlComputed,'COMPUTED');
+end;
+
+procedure TTestSQLScanner.TestConditional;
+begin
+  CheckToken(tsqlConditional,'CONDITIONAL');
+end;
+
+procedure TTestSQLScanner.TestConnect;
+begin
+  CheckToken(tsqlConnect,'CONNECT');
+end;
+
+procedure TTestSQLScanner.TestConstraint;
+begin
+  CheckToken(tsqlConstraint,'CONSTRAINT');
+end;
+
+procedure TTestSQLScanner.TestColon;
+
+begin
+  CheckToken(tsqlColon,':');
+end;
+
+procedure TTestSQLScanner.TestColumn;
+begin
+  CheckToken(tsqlColumn,'COLUMN');
+end;
+
+procedure TTestSQLScanner.TestDot;
+
+begin
+  CheckToken(tsqlDot,'.');
+end;
+
+procedure TTestSQLScanner.TestDrop;
+begin
+  CheckToken(tsqldrop,'DROP');
+end;
+
+procedure TTestSQLScanner.TestSemicolon;
+
+begin
+  CheckToken(tsqlSemicolon,';');
+end;
+
+procedure TTestSQLScanner.TestSet;
+begin
+  CheckToken(tsqlSet,'SET');
+end;
+
+procedure TTestSQLScanner.TestSchema;
+begin
+  CheckToken(tsqlSchema,'SCHEMA');
+end;
+
+procedure TTestSQLScanner.TestShadow;
+begin
+  CheckToken(tsqlShadow,'SHADOW');
+end;
+
+procedure TTestSQLScanner.TestSingular;
+begin
+  CheckToken(tsqlSINGULAR,'SINGULAR');
+end;
+
+procedure TTestSQLScanner.TestSize;
+begin
+  CheckToken(tsqlSize,'size');
+end;
+
+procedure TTestSQLScanner.TestSkip;
+begin
+  CheckToken(tsqlSkip,'skip');
+end;
+
+procedure TTestSQLScanner.TestSome;
+begin
+  CheckToken(tsqlSome,'some');
+end;
+
+procedure TTestSQLScanner.TestSort;
+begin
+  CheckToken(tsqlSort,'sort');
+end;
+
+procedure TTestSQLScanner.TestSnapshot;
+begin
+  CheckToken(tsqlSnapshot,'snapshot');
+end;
+
+procedure TTestSQLScanner.TestSQLCode;
+begin
+  CheckToken(tsqlSQLCOde,'SQLCODE');
+end;
+
+procedure TTestSQLScanner.TestSquareBraceClose;
+begin
+  CheckToken(tsqlSquareBraceClose,']');
+end;
+
+procedure TTestSQLScanner.TestSquareBraceOpen;
+begin
+  CheckToken(tsqlSquareBraceOpen,'[');
+end;
+
+procedure TTestSQLScanner.TestSubtype;
+begin
+  CheckToken(tsqlSubtype,'sub_type');
+end;
+
+procedure TTestSQLScanner.TestSuspend;
+begin
+  CheckToken(tsqlSuspend,'Suspend');
+end;
+
+procedure TTestSQLScanner.TestStarting;
+begin
+  CheckToken(tsqlStarting,'starting');
+end;
+
+procedure TTestSQLScanner.TestSum;
+begin
+  CheckToken(tsqlSum,'sum');
+end;
+
+procedure TTestSQLScanner.TestString;
+begin
+  DoTestString('''A string''');
+  DoTestString('''''');
+  DoTestString(''' " ''');
+  DoTestString('''A string''');
+  DoTestString(''' '''' ''',True);
+  DoTestString('''12345'#10'67890''');
+  DoTestString('''12345'#13'67890''');
+  DoTestString('''12345'#13#10'67890''');
+end;
+
+procedure TTestSQLScanner.TestTable;
+begin
+  CheckToken(tsqltable,'TABLE');
+end;
+
+procedure TTestSQLScanner.TestThen;
+begin
+  CheckToken(tsqlThen,'THEN');
+end;
+
+procedure TTestSQLScanner.TestTime;
+begin
+  CheckToken(tsqlTime,'TIME');
+end;
+
+procedure TTestSQLScanner.TestTimeStamp;
+begin
+  CheckToken(tsqlTimeStamp,'TIMESTAMP');
+end;
+
+procedure TTestSQLScanner.TestTo;
+begin
+  CheckToken(tsqlTo,'TO');
+end;
+
+procedure TTestSQLScanner.TestTransaction;
+begin
+  CheckToken(tsqlTransaction,'TRANSACTION');
+end;
+
+procedure TTestSQLScanner.TestTrigger;
+begin
+  CheckToken(tsqlTrigger,'TRIGGER');
+end;
+
+procedure TTestSQLScanner.TestType;
+begin
+  CheckToken(tsqltype,'TYPE');
+end;
+
+procedure TTestSQLScanner.TestUnion;
+begin
+  CheckToken(tsqlUnion,'UNION');
+end;
+
+procedure TTestSQLScanner.TestUnique;
+begin
+  CheckToken(tsqlUnique,'UNIQUE');
+end;
+
+procedure TTestSQLScanner.TestUpdate;
+begin
+  CheckToken(tsqlUPDATE,'UPDATE');
+end;
+
+procedure TTestSQLScanner.TestUpper;
+begin
+  CheckToken(tsqlUPPER,'UPPER');
+end;
+
+procedure TTestSQLScanner.TestUser;
+begin
+  CheckToken(tsqlUSER,'USER');
+end;
+
+procedure TTestSQLScanner.TestValues;
+begin
+  CheckToken(tsqlVALUES,'VALUES');
+end;
+
+procedure TTestSQLScanner.TestValue;
+begin
+  CheckToken(tsqlVALUE,'VALUE');
+end;
+
+procedure TTestSQLScanner.TestAssign;
+
+begin
+  CheckToken(tsqlEq,'=');
+end;
+
+procedure TTestSQLScanner.TestBefore;
+begin
+  CheckToken(tsqlbefore,'BEFORE');
+end;
+
+procedure TTestSQLScanner.TestBegin;
+begin
+  CheckToken(tsqlbegin,'BEGIN');
+end;
+
+procedure TTestSQLScanner.TestBetween;
+begin
+  CheckToken(tsqlBetween,'BETWEEN');
+end;
+
+procedure TTestSQLScanner.TestGreaterThan;
+
+begin
+  CheckToken(tsqlGT,'>');
+end;
+
+procedure TTestSQLScanner.TestGroup;
+begin
+  CheckToken(tsqlGroup,'group');
+end;
+
+procedure TTestSQLScanner.TestHaving;
+begin
+  CheckToken(tsqlHaving,'HAVING');
+end;
+
+procedure TTestSQLScanner.TestLessThan;
+
+begin
+  CheckToken(tsqlLT,'<');
+end;
+
+procedure TTestSQLScanner.TestManual;
+begin
+  Checktoken(tsqlManual,'manual');
+end;
+
+procedure TTestSQLScanner.TestModuleName;
+begin
+  Checktoken(tsqlModuleName,'module_name');
+end;
+
+procedure TTestSQLScanner.TestMax;
+begin
+  Checktoken(tsqlMax,'max');
+end;
+
+procedure TTestSQLScanner.TestMerge;
+begin
+  Checktoken(tsqlMerge,'merge');
+end;
+
+procedure TTestSQLScanner.TestMin;
+begin
+  Checktoken(tsqlMin,'min');
+end;
+
+procedure TTestSQLScanner.TestPlus;
+
+begin
+  CheckToken(tsqlPlus,'+');
+end;
+
+procedure TTestSQLScanner.TestPosition;
+begin
+  Checktoken(tsqlposition,'position');
+end;
+
+procedure TTestSQLScanner.TestPostEvent;
+begin
+  Checktoken(tsqlpostevent,'post_event');
+end;
+
+procedure TTestSQLScanner.TestPrimary;
+begin
+  Checktoken(tsqlprimary,'primary');
+end;
+
+procedure TTestSQLScanner.TestPrivileges;
+begin
+  Checktoken(tsqlprivileges,'privileges');
+end;
+
+procedure TTestSQLScanner.TestProcedure;
+begin
+  Checktoken(tsqlprocedure,'procedure');
+end;
+
+procedure TTestSQLScanner.TestPublic;
+begin
+  CheckToken(tsqlPublic,'PUBLIC');
+end;
+
+procedure TTestSQLScanner.TestReferences;
+begin
+  CheckToken(tsqlReferences,'REFERENCES');
+end;
+
+procedure TTestSQLScanner.TestRelease;
+begin
+  CheckToken(tsqlrelease,'release');
+end;
+
+procedure TTestSQLScanner.TestReturningValues;
+begin
+  CheckToken(tsqlreturningvalues,'returning_values');
+end;
+
+procedure TTestSQLScanner.TestReturns;
+begin
+  CheckToken(tsqlreturns,'returns');
+end;
+
+procedure TTestSQLScanner.TestRetain;
+begin
+  Checktoken(tsqlRetain,'retain');
+end;
+
+procedure TTestSQLScanner.TestRevoke;
+begin
+  Checktoken(tsqlRevoke,'revoke');
+end;
+
+procedure TTestSQLScanner.TestRight;
+begin
+  Checktoken(tsqlright,'right');
+end;
+
+procedure TTestSQLScanner.TestRole;
+begin
+  Checktoken(tsqlrole,'role');
+end;
+
+procedure TTestSQLScanner.TestRollback;
+begin
+  Checktoken(tsqlrollback,'rollback');
+end;
+
+procedure TTestSQLScanner.TestSegment;
+begin
+  CheckToken(tsqlSegment,'SEGMENT');
+end;
+
+procedure TTestSQLScanner.TestSelect;
+begin
+  CheckToken(tsqlSelect,'SELECT');
+end;
+
+procedure TTestSQLScanner.TestMinus;
+
+begin
+  CheckToken(tsqlMinus,'-');
+end;
+
+procedure TTestSQLScanner.TestMul;
+
+begin
+  CheckToken(tsqlMul,'*');
+end;
+
+procedure TTestSQLScanner.TestNational;
+begin
+  CheckToken(tsqlNational,'NATIONAL');
+end;
+
+procedure TTestSQLScanner.TestNatural;
+begin
+  CheckToken(tsqlNatural,'NATURAL');
+end;
+
+procedure TTestSQLScanner.TestDiv;
+
+begin
+  CheckToken(tsqlDiv,'/');
+end;
+
+procedure TTestSQLScanner.TestEq;
+
+begin
+  CheckToken(tsqlEq,'==');
+end;
+
+procedure TTestSQLScanner.TestFloat;
+begin
+  CheckToken(tsqlFloat,'FLOAT');
+end;
+
+procedure TTestSQLScanner.TestGE;
+
+begin
+  CheckToken(tsqlGE,'>=');
+end;
+
+procedure TTestSQLScanner.TestGenerator;
+begin
+  CheckToken(tsqlGenerator,'generator');
+end;
+
+procedure TTestSQLScanner.TestGrant;
+begin
+  CheckToken(tsqlGrant,'grant');
+end;
+
+procedure TTestSQLScanner.TestLE;
+
+begin
+  CheckToken(tsqlLE,'<=');
+end;
+
+
+procedure TTestSQLScanner.TestNE;
+
+begin
+  CheckToken(tsqlNE,'<>');
+end;
+
+procedure TTestSQLScanner.TestNo;
+begin
+  CheckToken(tsqlNo,'no');
+end;
+
+procedure TTestSQLScanner.TestNot;
+
+begin
+  CheckToken(tsqlNot,'not');
+end;
+
+procedure TTestSQLScanner.TestNull;
+begin
+  CheckToken(tsqlnull,'null');
+end;
+
+procedure TTestSQLScanner.TestNumeric;
+begin
+  CheckToken(tsqlNumeric,'NUMERIC');
+end;
+
+procedure TTestSQLScanner.TestOn;
+begin
+  CheckToken(tsqlON,'on');
+end;
+
+procedure TTestSQLScanner.TestOption;
+begin
+  CheckToken(tsqlOption,'option');
+end;
+
+procedure TTestSQLScanner.TestOr;
+begin
+  CheckToken(tsqlOR,'or');
+end;
+
+procedure TTestSQLScanner.TestOrder;
+begin
+  CheckToken(tsqlORDER,'order');
+end;
+
+procedure TTestSQLScanner.TestOuter;
+begin
+  CheckToken(tsqlOUTER,'outer');
+end;
+
+procedure TTestSQLScanner.TestPage;
+begin
+  CheckToken(tsqlPage,'PAGE');
+end;
+
+procedure TTestSQLScanner.TestPages;
+begin
+  CheckToken(tsqlPages,'PAGES');
+end;
+
+procedure TTestSQLScanner.TestPageSize;
+begin
+  CheckToken(tsqlPageSize,'PAGE_SIZE');
+end;
+
+procedure TTestSQLScanner.TestPassword;
+begin
+  CheckToken(tsqlPassword,'PASSWORD');
+end;
+
+{
+procedure TTestSQLScanner.TestTrue;
+
+begin
+  CheckToken(tsqlTrue,'true');
+end;
+
+procedure TTestSQLScanner.TestFalse;
+
+begin
+  CheckToken(tsqlFalse,'false');
+end;
+}
+
+procedure TTestSQLScanner.TestBy;
+
+begin
+  CheckToken(tsqlBy,'by');
+end;
+
+procedure TTestSQLScanner.TestCache;
+begin
+  CheckToken(tsqlCache,'CACHE');
+end;
+
+procedure TTestSQLScanner.TestCascade;
+begin
+  CheckToken(tsqlCascade,'cascade');
+end;
+
+procedure TTestSQLScanner.TestBlob;
+
+begin
+  CheckToken(tsqlBlob,'blob');
+end;
+
+procedure TTestSQLScanner.TestChar;
+begin
+  CheckToken(tsqlChar,'char');
+end;
+
+procedure TTestSQLScanner.TestCharacter;
+begin
+  CheckToken(tsqlCharacter,'character');
+end;
+
+procedure TTestSQLScanner.TestCheck;
+begin
+  CheckToken(tsqlCHECK,'check');
+end;
+
+procedure TTestSQLScanner.TestCollate;
+
+begin
+  CheckToken(tsqlCollate,'collate');
+end;
+
+procedure TTestSQLScanner.TestConcatenate;
+begin
+  CheckToken(tsqlConcatenate,'||');
+end;
+
+procedure TTestSQLScanner.TestContaining;
+
+begin
+  CheckToken(tsqlContaining,'containing');
+end;
+
+procedure TTestSQLScanner.TestCount;
+
+begin
+  CheckToken(tsqlCount,'count');
+end;
+
+procedure TTestSQLScanner.TestCreate;
+begin
+  CheckToken(tsqlCreate,'create');
+end;
+
+procedure TTestSQLScanner.TestCString;
+begin
+  CheckToken(tsqlCString,'CSTRING');
+end;
+
+procedure TTestSQLScanner.TestDatabase;
+begin
+  CheckToken(tsqlDatabase,'database');
+end;
+
+procedure TTestSQLScanner.TestDate;
+begin
+  CheckToken(tsqlDate,'date');
+end;
+
+procedure TTestSQLScanner.TestDecimal;
+begin
+  CheckToken(tsqlDecimal,'decimal');
+end;
+
+procedure TTestSQLScanner.TestDefault;
+
+begin
+  CheckToken(tsqldefault,'default');
+end;
+
+procedure TTestSQLScanner.TestDelete;
+
+begin
+  CheckToken(tsqldelete,'delete');
+end;
+
+procedure TTestSQLScanner.TestDeclare;
+begin
+  CheckToken(tsqlDeclare,'DECLARE');
+end;
+
+procedure TTestSQLScanner.TestDesc;
+begin
+  CheckToken(tsqlDESC,'DESC');
+end;
+
+procedure TTestSQLScanner.TestDescending;
+begin
+ CheckToken(tsqlDescending,'DESCENDING');
+end;
+
+procedure TTestSQLScanner.TestDistinct;
+begin
+ CheckToken(tsqlDistinct,'DISTINCT');
+end;
+
+procedure TTestSQLScanner.TestDO;
+
+begin
+  CheckToken(tsqldo,'do');
+end;
+
+procedure TTestSQLScanner.TestDomain;
+begin
+  CheckToken(tsqlDomain,'domain');
+end;
+
+procedure TTestSQLScanner.TestElse;
+
+begin
+  CheckToken(tsqlelse,'else');
+end;
+
+procedure TTestSQLScanner.TestFor;
+
+begin
+  CheckToken(tsqlfor,'for');
+end;
+
+procedure TTestSQLScanner.TestForeign;
+begin
+  CheckToken(tsqlForeign,'foreign');
+end;
+
+procedure TTestSQLScanner.TestFreeIt;
+begin
+  CheckToken(tsqlFreeIt,'FREE_IT');
+end;
+
+procedure TTestSQLScanner.TestFile;
+begin
+  CheckToken(tsqlFile,'FILE');
+end;
+
+procedure TTestSQLScanner.TestFunction;
+
+begin
+  CheckToken(tsqlfunction,'function');
+end;
+
+procedure TTestSQLScanner.TestGDSError;
+begin
+  CheckToken(tsqlGDSCODE,'GDSCODE');
+end;
+
+procedure TTestSQLScanner.TestIf;
+
+begin
+  CheckToken(tsqlif,'if');
+end;
+
+procedure TTestSQLScanner.TestIn;
+
+begin
+  CheckToken(tsqlin,'in');
+end;
+
+procedure TTestSQLScanner.TestInner;
+
+begin
+  CheckToken(tsqlInner,'inner');
+end;
+
+procedure TTestSQLScanner.TestInsert;
+
+begin
+  CheckToken(tsqlInsert,'insert');
+end;
+
+procedure TTestSQLScanner.TestInt;
+
+begin
+  CheckToken(tsqlInt,'int');
+end;
+
+procedure TTestSQLScanner.TestInteger;
+
+begin
+  CheckToken(tsqlInteger,'integer');
+end;
+
+procedure TTestSQLScanner.TestInto;
+begin
+  CheckToken(tsqlInto,'into');
+end;
+
+procedure TTestSQLScanner.TestIs;
+begin
+  CheckToken(tsqlis,'is');
+end;
+
+procedure TTestSQLScanner.TestJoin;
+begin
+  CheckToken(tsqlJoin,'JOIN');
+end;
+
+procedure TTestSQLScanner.TestKey;
+begin
+  CheckToken(tsqlKey,'KEY');
+end;
+
+procedure TTestSQLScanner.TestLeft;
+begin
+  CheckToken(tsqlLEFT,'LEFT');
+end;
+
+procedure TTestSQLScanner.TestLength;
+begin
+  CheckToken(tsqlLength,'LENGTH');
+end;
+
+procedure TTestSQLScanner.TestLike;
+begin
+  CheckToken(tsqlLIKE,'LIKE');
+end;
+
+procedure TTestSQLScanner.TestIndex;
+begin
+  CheckToken(tsqlindex,'index');
+end;
+
+procedure TTestSQLScanner.TestVariable;
+
+begin
+  CheckToken(tsqlvariable,'variable');
+end;
+
+procedure TTestSQLScanner.TestVarChar;
+begin
+  CheckToken(tsqlvarchar,'varchar');
+end;
+
+procedure TTestSQLScanner.TestVarying;
+begin
+  CheckToken(tsqlvarying,'varying');
+end;
+
+procedure TTestSQLScanner.TestView;
+begin
+  CheckToken(tsqlview,'view');
+end;
+
+procedure TTestSQLScanner.TestWhen;
+begin
+  CheckToken(tsqlWhen,'when');
+end;
+
+procedure TTestSQLScanner.TestWhere;
+begin
+  CheckToken(tsqlwhere,'where');
+end;
+
+procedure TTestSQLScanner.TestWhile;
+
+begin
+  CheckToken(tsqlwhile,'while');
+end;
+
+procedure TTestSQLScanner.TestWith;
+
+begin
+  CheckToken(tsqlwith,'with');
+end;
+
+procedure TTestSQLScanner.TestWork;
+begin
+  CheckToken(tsqlWork,'work');
+end;
+
+procedure TTestSQLScanner.CheckTokens(ASource : String; ATokens : Array of TSQLToken);
+
+Var
+  I : Integer;
+  J : TSQLToken;
+  S : String;
+
+begin
+  CreateScanner(ASource);
+  For I:=Low(ATokens) to High(ATokens) do
+    begin
+    J:=FScanner.FetchToken;
+    S:=GetEnumName(TypeINfo(TSQLToken),Ord(ATokens[i]));
+    S:=Format('Source "%s", token %d (%s): expected %s',[ASource,I,FScanner.CurTokenString,S]);
+    AssertEquals(S,ATokens[i],J);
+    end;
+end;
+
+procedure TTestSQLScanner.Test2Words;
+begin
+  CheckTokens('with do',[tsqlWith,tsqlDo]);
+end;
+
+procedure TTestSQLScanner.Test3Words;
+begin
+  CheckTokens('with do for',[tsqlWith,tsqlDo,tsqlFor]);
+end;
+
+procedure TTestSQLScanner.TestIdentifier;
+begin
+  CheckToken(tsqlIdentifier,'something');
+  AssertEquals('Correct identifier','something',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestIdentifier2;
+begin
+  CheckToken(tsqlIdentifier,'"_something"');
+  AssertEquals('Correct identifier','_something',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestIdentifier3;
+begin
+  CheckToken(tsqlIdentifier,'RDB$');
+  AssertEquals('Correct identifier','RDB$',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestIdentifier4;
+begin
+  CheckToken(tsqlIdentifier,'A_0');
+  AssertEquals('Correct identifier','A_0',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestIdentifier5;
+begin
+  FErrorSource:='$0';
+  AssertException('Identifier cannot start with _',ESQLScannerError,@TestErrorSource);
+end;
+
+procedure TTestSQLScanner.TestIdentifierDotIdentifier;
+begin
+  CheckTokens('something.different',[tsqlIdentifier,tsqldot,tsqlIdentifier]);
+//  AssertEquals('Correct identifier','something',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestEOLN;
+begin
+  CreateScanner('something');
+  FScanner.FetchToken;
+  AssertEquals('Got to end of line after reading single token at EOF',True,FScanner.IsEndOfLine);
+//  AssertEquals('Correct identifier','something',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestEOLN2;
+begin
+  CreateScanner('something different');
+  FScanner.FetchToken;
+  AssertEquals('Not yet end of line after reading single token at EOF',False,FScanner.IsEndOfLine);
+end;
+
+procedure TTestSQLScanner.TestEOLN3;
+begin
+  CreateScanner('something'#13#10'different');
+  FScanner.FetchToken;
+  AssertEquals('End of line after reading single token',True,FScanner.IsEndOfLine);
+end;
+
+procedure TTestSQLScanner.TestEOLN4;
+begin
+  CreateScanner('something'#10'different');
+  FScanner.FetchToken;
+  AssertEquals('End of line after reading first token',True,FScanner.IsEndOfLine);
+  FScanner.FetchToken;
+  AssertEquals('End of line after reading second token',True,FScanner.IsEndOfLine);
+end;
+
+procedure TTestSQLScanner.TestComment1;
+begin
+  CreateScanner('-- some comment string');
+  AssertEquals('Comment line is skipped',tsqlEOF,FScanner.FetchToken);
+end;
+
+procedure TTestSQLScanner.TestComment2;
+begin
+  CreateScanner('--  some comment string');
+  FScanner.Options:=[soReturnComments];
+  AssertEquals('Comment line is returned',tsqlComment,FScanner.FetchToken);
+  AssertEquals('Comment contents is returned',' some comment string',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestComment3;
+begin
+  CreateScanner('/* some comment string */');
+  AssertEquals('Comment line is skipped',tsqlEOF,FScanner.FetchToken);
+end;
+
+procedure TTestSQLScanner.TestComment4;
+begin
+  CreateScanner('/* some comment string */');
+  FScanner.Options:=[soReturnComments];
+  AssertEquals('Comment line is returned',tsqlComment,FScanner.FetchToken);
+  AssertEquals('Comment contents is returned',' some comment string ',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestComment5;
+begin
+  CreateScanner('/* some nested comment -- string */');
+  FScanner.Options:=[soReturnComments];
+  AssertEquals('Comment line is returned',tsqlComment,FScanner.FetchToken);
+  AssertEquals('Comment contents is returned',' some nested comment -- string ',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestComment6;
+begin
+  CreateScanner('-- /* some nested comment string */');
+  FScanner.Options:=[soReturnComments];
+  AssertEquals('Comment line is returned',tsqlComment,FScanner.FetchToken);
+  AssertEquals('Comment contents is returned','/* some nested comment string */',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestFloatLiteral;
+begin
+  DoTestFloat(1.2);
+  DoTestFloat(-1.2);
+  DoTestFloat(1.2e1);
+  DoTestFloat(-1.2e1);
+  DoTestFloat(1.2,'1.2');
+  DoTestFloat(-1.2,'-1.2');
+  DoTestFloat(0,'0.0');
+end;
+
+procedure TTestSQLScanner.TestStringLiteral1;
+begin
+  CreateScanner('''A''');
+  FScanner.Options:=[];
+  AssertEquals('String is returned',tsqlString,FScanner.FetchToken);
+  AssertEquals('Correct string','A',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestStringLiteral2;
+begin
+  CreateScanner('"A"',[soDoubleQuoteStringLiteral]);
+  AssertEquals('String is returned',tsqlString,FScanner.FetchToken);
+  AssertEquals('Correct string','A',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestStringError;
+begin
+
+end;
+
+procedure TTestSQLScanner.TestFloatError;
+begin
+  FErrorSource:='1xz';
+  AssertException('Wrong float',ESQLScannerError,@TestErrorSource);
+end;
+
+procedure TTestSQLScanner.TestOptionsoDoubleQuoteStringLiteral;
+begin
+  CreateScanner('"A"',[soDoubleQuoteStringLiteral]);
+  AssertEquals('String is returned',tsqlString,FScanner.FetchToken);
+  AssertEquals('Correct string','A',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestOptionsoSingleQuoteIdentifier;
+begin
+  CreateScanner('''A''',[soSingleQuoteIdentifier,soDoubleQuoteStringLiteral]);
+  If (Scanner.Options<>[soSingleQuoteIdentifier,soDoubleQuoteStringLiteral]) then
+    Fail('Options not correctly set');
+  AssertEquals('Identifier is returned',tsqlIdentifier,FScanner.FetchToken);
+  AssertEquals('Correct string','A',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestOptionsoBackQuoteIdentifier;
+begin
+  CreateScanner('`A`',[soBackQuoteIdentifier]);
+  AssertEquals('String is returned',tsqlIdentifier,FScanner.FetchToken);
+  AssertEquals('Correct string','A',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestOptionNosoBackQuoteIdentifier;
+begin
+  FErrorSource:='`A`';
+  AssertException('Wrong token',ESQLScannerError,@TestErrorSource);
+end;
+
+procedure TTestSQLScanner.TestOptionsoBackslashEscapesTab;
+begin
+  CreateScanner('''\t''',[soBackslashEscapes]);
+  AssertEquals('String is returned',tsqlString,FScanner.FetchToken);
+  AssertEquals('Correct string',#9,FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestOptionsoBackslashEscapesNewLine;
+begin
+  CreateScanner('''\n''',[soBackslashEscapes]);
+  AssertEquals('String is returned',tsqlString,FScanner.FetchToken);
+  AssertEquals('Correct string',#10,FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestOptionsoBackslashEscapesLineFeed;
+
+begin
+  CreateScanner('''\r''',[soBackslashEscapes]);
+  AssertEquals('String is returned',tsqlString,FScanner.FetchToken);
+  AssertEquals('Correct string',#13,FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestOptionsoBackslashEscapesBackSlash;
+
+begin
+  CreateScanner('''\\''',[soBackslashEscapes]);
+  AssertEquals('String is returned',tsqlString,FScanner.FetchToken);
+  AssertEquals('Correct string','\',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestOptionsoBackslashEscapesNewPage;
+
+begin
+  CreateScanner('''\f''',[soBackslashEscapes]);
+  AssertEquals('String is returned',tsqlString,FScanner.FetchToken);
+  AssertEquals('Correct string',#12,FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestOptionsoBackslashEscapesSlash;
+begin
+  CreateScanner('''\/''',[soBackslashEscapes]);
+  AssertEquals('String is returned',tsqlString,FScanner.FetchToken);
+  AssertEquals('Correct string','/',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestOptionsoBackslashEscapesBackspace;
+
+begin
+  CreateScanner('''\f''',[soBackslashEscapes]);
+  AssertEquals('String is returned',tsqlString,FScanner.FetchToken);
+  AssertEquals('Correct string',#12,FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestOptionsoBackslashEscapesQuote;
+
+begin
+  CreateScanner('''\''''',[soBackslashEscapes]);
+  AssertEquals('String is returned',tsqlString,FScanner.FetchToken);
+  AssertEquals('Correct string','''',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestOptionsoBackslashEscapesDoubleQuote;
+begin
+  CreateScanner('''\"''',[soBackslashEscapes]);
+  AssertEquals('String is returned',tsqlString,FScanner.FetchToken);
+  AssertEquals('Correct string','"',FScanner.CurTokenString);
+end;
+
+procedure TTestSQLScanner.TestOptionNosoBackslashEscapes;
+begin
+  CreateScanner('''\"''',[]);
+  AssertEquals('String is returned',tsqlString,FScanner.FetchToken);
+  AssertEquals('Correct string','\"',FScanner.CurTokenString);
+end;
+
+
+initialization
+
+  RegisterTest(TTestSQLScanner);
+end.
+

+ 266 - 0
packages/fcl-db/tests/testsqlfiles.lpi

@@ -0,0 +1,266 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="8"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+        <UseDefaultCompilerOptions Value="True"/>
+      </Flags>
+      <MainUnit Value="0"/>
+      <TargetFileExt Value=""/>
+      <Title Value="testsqlfiles"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <Icon Value="0"/>
+      <ActiveWindowIndexAtStart Value="0"/>
+    </General>
+    <i18n>
+      <EnableI18N LFM="False"/>
+    </i18n>
+    <VersionInfo>
+      <Language Value=""/>
+      <CharSet Value=""/>
+      <StringTable Comments="" CompanyName="" FileDescription="" FileVersion="" InternalName="" LegalCopyright="" LegalTrademarks="" OriginalFilename="" ProductName="" ProductVersion=""/>
+    </VersionInfo>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IgnoreBinaries Value="False"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <LaunchingApplication PathPlusParams="/usr/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <Units Count="6">
+      <Unit0>
+        <Filename Value="testsqlfiles.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="testsqlfiles"/>
+        <IsVisibleTab Value="True"/>
+        <EditorIndex Value="0"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="32"/>
+        <CursorPos X="1" Y="47"/>
+        <UsageCount Value="64"/>
+        <Loaded Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="../../../../FPC/trunk/packages/fcl-db/src/base/sqlscript.pp"/>
+        <UnitName Value="sqlscript"/>
+        <EditorIndex Value="2"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="1"/>
+        <CursorPos X="1" Y="4"/>
+        <UsageCount Value="32"/>
+        <Loaded Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="../src/sql/fpsqlscanner.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="fpsqlscanner"/>
+        <EditorIndex Value="3"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="1"/>
+        <CursorPos X="1" Y="4"/>
+        <UsageCount Value="64"/>
+        <Loaded Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="fpsqlparser"/>
+        <EditorIndex Value="4"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="1"/>
+        <CursorPos X="1" Y="15"/>
+        <UsageCount Value="64"/>
+        <Loaded Value="True"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="fpsqltree"/>
+        <EditorIndex Value="5"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="1"/>
+        <CursorPos X="1" Y="15"/>
+        <UsageCount Value="64"/>
+        <Loaded Value="True"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="../../../../FPC/trunk/rtl/inc/heaptrc.pp"/>
+        <UnitName Value="heaptrc"/>
+        <EditorIndex Value="1"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="34"/>
+        <CursorPos X="3" Y="84"/>
+        <UsageCount Value="32"/>
+        <Loaded Value="True"/>
+      </Unit5>
+    </Units>
+    <JumpHistory Count="30" HistoryIndex="29">
+      <Position1>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="1" Column="1" TopLine="1"/>
+      </Position1>
+      <Position2>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="129" Column="63" TopLine="114"/>
+      </Position2>
+      <Position3>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="2017" Column="1" TopLine="1993"/>
+      </Position3>
+      <Position4>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="2794" Column="20" TopLine="2791"/>
+      </Position4>
+      <Position5>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="1" Column="1" TopLine="1"/>
+      </Position5>
+      <Position6>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="2233" Column="35" TopLine="2229"/>
+      </Position6>
+      <Position7>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="54" Column="14" TopLine="39"/>
+      </Position7>
+      <Position8>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="1" Column="1" TopLine="1"/>
+      </Position8>
+      <Position9>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="95" Column="30" TopLine="80"/>
+      </Position9>
+      <Position10>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="3215" Column="30" TopLine="3190"/>
+      </Position10>
+      <Position11>
+        <Filename Value="testsqlfiles.lpr"/>
+        <Caret Line="40" Column="20" TopLine="31"/>
+      </Position11>
+      <Position12>
+        <Filename Value="../src/sql/fpsqlscanner.pp"/>
+        <Caret Line="473" Column="1" TopLine="471"/>
+      </Position12>
+      <Position13>
+        <Filename Value="../src/sql/fpsqlscanner.pp"/>
+        <Caret Line="1" Column="1" TopLine="1"/>
+      </Position13>
+      <Position14>
+        <Filename Value="../src/sql/fpsqlscanner.pp"/>
+        <Caret Line="301" Column="1" TopLine="285"/>
+      </Position14>
+      <Position15>
+        <Filename Value="../src/sql/fpsqlscanner.pp"/>
+        <Caret Line="386" Column="1" TopLine="364"/>
+      </Position15>
+      <Position16>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="3198" Column="36" TopLine="3189"/>
+      </Position16>
+      <Position17>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="1" Column="1" TopLine="1"/>
+      </Position17>
+      <Position18>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="214" Column="32" TopLine="199"/>
+      </Position18>
+      <Position19>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="2099" Column="30" TopLine="2084"/>
+      </Position19>
+      <Position20>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="2219" Column="28" TopLine="2204"/>
+      </Position20>
+      <Position21>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="2222" Column="32" TopLine="2204"/>
+      </Position21>
+      <Position22>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="2260" Column="28" TopLine="2245"/>
+      </Position22>
+      <Position23>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="2289" Column="28" TopLine="2274"/>
+      </Position23>
+      <Position24>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="2320" Column="28" TopLine="2305"/>
+      </Position24>
+      <Position25>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="2475" Column="30" TopLine="2460"/>
+      </Position25>
+      <Position26>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="3670" Column="30" TopLine="3655"/>
+      </Position26>
+      <Position27>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="3651" Column="45" TopLine="3651"/>
+      </Position27>
+      <Position28>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="261" Column="73" TopLine="261"/>
+      </Position28>
+      <Position29>
+        <Filename Value="../../../../FPC/trunk/packages/fcl-db/src/base/sqlscript.pp"/>
+        <Caret Line="46" Column="23" TopLine="46"/>
+      </Position29>
+      <Position30>
+        <Filename Value="testsqlfiles.lpr"/>
+        <Caret Line="43" Column="15" TopLine="28"/>
+      </Position30>
+    </JumpHistory>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="9"/>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)/"/>
+      <OtherUnitFiles Value="/home/michael/fpc/packages/fcl-db/src/sql/"/>
+    </SearchPaths>
+    <Parsing>
+      <SyntaxOptions>
+        <UseAnsiStrings Value="False"/>
+      </SyntaxOptions>
+    </Parsing>
+    <Linking>
+      <Debugging>
+        <UseHeaptrc Value="True"/>
+        <UseValgrind Value="True"/>
+      </Debugging>
+    </Linking>
+    <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>

+ 163 - 0
packages/fcl-db/tests/testsqlfiles.lpr

@@ -0,0 +1,163 @@
+{
+    This file is part of the Free Component Library
+    Copyright (c) 2010 by the Free Pascal development team
+
+    SQL source syntax parser test program
+
+    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.
+
+ **********************************************************************}
+program testsqlfiles;
+
+{$mode objfpc}{$H+}
+
+uses
+  {$IFDEF UNIX}{$IFDEF UseCThreads}
+  cthreads,
+  {$ENDIF}{$ENDIF}
+  Classes,
+  SysUtils, fpsqltree, fpsqlparser, fpsqlscanner, sqlscript,
+  CustApp;
+  { you can add units after this }
+
+type
+
+  { TTestSQLFilesApplication }
+
+  TTestSQLFilesApplication = class(TCustomApplication)
+  private
+    procedure ParseStatement(Sender: TObject; Statement: TStrings;
+      var StopExecution: Boolean);
+    procedure ProcessFile(const AFileName: String);
+  protected
+    FStatementCount : integer;
+    FFileCount : Integer;
+    FErrorCount : Integer;
+    FCurrentFile : String;
+    FWriteSQL : Boolean; // Set to true to write SQL to screen.
+    procedure DoRun; override;
+  public
+    constructor Create(TheOwner: TComponent); override;
+    destructor Destroy; override;
+  end;
+
+{ TTestSQLFilesApplication }
+Procedure TTestSQLFilesApplication.ParseStatement(Sender: TObject; Statement: TStrings; var StopExecution: Boolean);
+
+Var
+  P : TSQLParser;
+  D : TStringStream;
+  S : TSQLElement;
+  I : Integer;
+
+begin
+  Inc(FStatementCount);
+  D:=TStringStream.Create(Statement.Text);
+  try
+    P:=TSQLParser.Create(D);
+    try
+      try
+        S:=P.Parse;
+        If FWriteSQL then
+          writeln(S.GetasSql([],0));
+        S.Free;
+      except
+        On E : Exception do
+          begin
+          Inc(FErrorCount);
+          Writeln('Error ',FErrorCount,' processing: ',FCurrentFile,' statement after line : ',(Sender as TEventSQLScript).Line);
+          for I:=0 to Statement.Count-1 do
+            begin
+            Writeln(I+1:5,':',Statement[i]);
+            end;
+          Writeln('Exception message: ',E.Message);
+          If (Sender as TEventSQLScript).Terminator<>';' then
+            begin
+            Statement.Insert(0,'SET TERM ^ ;');
+            Statement.Add('^');
+            end
+          else
+            Statement.Add(';');
+          Statement.SaveToFile(Format('error-%d.sql',[FErrorCount]));
+          end;
+      end;
+    finally
+      P.Free;
+    end;
+  finally
+    D.Free;
+  end;
+end;
+
+
+
+
+Procedure TTestSQLFilesApplication.ProcessFile(Const AFileName : String);
+
+Var
+  I : TEventSQLScript;
+
+begin
+  try
+    Inc(FFileCount);
+    FCurrentFile:=AFileName;
+    I:=TEventSQLScript.Create(Nil);
+    try
+      I.Script.LoadFromFile(AFileName);;
+      I.OnSQLStatement:=@ParseStatement;
+      I.UseSetTerm:=True;
+      I.UseCommit:=True;
+      I.Directives.Add('DISPLAY');
+      I.Directives.Add('SET SQL DIALECT');
+      I.Directives.Add('TRAP');
+      I.Execute;
+    finally
+      I.Free;
+    end;
+  except
+    On E : Exception do
+      Writeln('Error processing ',AFIleName,' : ',E.Message);
+  end;
+end;
+
+procedure TTestSQLFilesApplication.DoRun;
+var
+  ErrorMsg: String;
+  I : Integer;
+
+begin
+  For I:=1 to ParamCount do
+    ProcessFile(Paramstr(i));
+  Writeln('Processed ',FFileCount,' files.');
+  Writeln('Processed ',FStatementCount,' statements.');
+  Writeln(FErrorCount,' statements had errors');
+  Writeln(FStatementCount-FErrorCount,' statements processed correctly');
+  // stop program loop
+  Terminate;
+end;
+
+constructor TTestSQLFilesApplication.Create(TheOwner: TComponent);
+begin
+  inherited Create(TheOwner);
+  StopOnException:=True;
+end;
+
+destructor TTestSQLFilesApplication.Destroy;
+begin
+  inherited Destroy;
+end;
+var
+  Application: TTestSQLFilesApplication;
+
+begin
+  Application:=TTestSQLFilesApplication.Create(nil);
+  Application.Title:='Test SQL Files';
+  Application.Run;
+  Application.Free;
+end.
+

+ 288 - 0
packages/fcl-db/tests/testsqlscanner.lpi

@@ -0,0 +1,288 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="8"/>
+    <General>
+      <MainUnit Value="0"/>
+      <TargetFileExt Value=""/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <ActiveWindowIndexAtStart Value="0"/>
+    </General>
+    <VersionInfo>
+      <Language Value=""/>
+      <CharSet Value=""/>
+      <StringTable Comments="" CompanyName="" FileDescription="" FileVersion="" InternalName="" LegalCopyright="" LegalTrademarks="" OriginalFilename="" ProductName="" ProductVersion=""/>
+    </VersionInfo>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IgnoreBinaries Value="False"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <LaunchingApplication PathPlusParams="/usr/X11R6/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="9">
+      <Unit0>
+        <Filename Value="testsqlscanner.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="testsqlscanner"/>
+        <EditorIndex Value="1"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="1"/>
+        <CursorPos X="3" Y="12"/>
+        <UsageCount Value="208"/>
+        <Loaded Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="tcsqlscanner.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="tcsqlscanner"/>
+        <EditorIndex Value="0"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="873"/>
+        <CursorPos X="3" Y="875"/>
+        <UsageCount Value="208"/>
+        <Loaded Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="fpsqltree"/>
+        <IsVisibleTab Value="True"/>
+        <EditorIndex Value="6"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="4751"/>
+        <CursorPos X="49" Y="4767"/>
+        <UsageCount Value="208"/>
+        <Loaded Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="../src/sql/fpsqlscanner.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="fpsqlscanner"/>
+        <EditorIndex Value="4"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="43"/>
+        <CursorPos X="126" Y="62"/>
+        <UsageCount Value="208"/>
+        <Loaded Value="True"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="fpsqlparser"/>
+        <EditorIndex Value="7"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="3562"/>
+        <CursorPos X="12" Y="3588"/>
+        <UsageCount Value="208"/>
+        <Loaded Value="True"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="tcparser.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="tcparser"/>
+        <EditorIndex Value="5"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="7911"/>
+        <CursorPos X="30" Y="7924"/>
+        <UsageCount Value="220"/>
+        <Loaded Value="True"/>
+      </Unit5>
+      <Unit6>
+        <Filename Value="tcgensql.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="tcgensql"/>
+        <EditorIndex Value="3"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="2449"/>
+        <CursorPos X="13" Y="2452"/>
+        <UsageCount Value="371"/>
+        <Loaded Value="True"/>
+      </Unit6>
+      <Unit7>
+        <Filename Value="../../../../FPC/fpc/packages/fcl-fpcunit/src/fpcunit.pp"/>
+        <UnitName Value="fpcunit"/>
+        <EditorIndex Value="2"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="113"/>
+        <CursorPos X="10" Y="120"/>
+        <UsageCount Value="156"/>
+        <Loaded Value="True"/>
+      </Unit7>
+      <Unit8>
+        <Filename Value="../../../../FPC/trunk/rtl/inc/systemh.inc"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="438"/>
+        <CursorPos X="3" Y="453"/>
+        <UsageCount Value="0"/>
+      </Unit8>
+    </Units>
+    <JumpHistory Count="30" HistoryIndex="29">
+      <Position1>
+        <Filename Value="tcgensql.pas"/>
+        <Caret Line="2286" Column="1" TopLine="2258"/>
+      </Position1>
+      <Position2>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="4607" Column="32" TopLine="4586"/>
+      </Position2>
+      <Position3>
+        <Filename Value="tcgensql.pas"/>
+        <Caret Line="2327" Column="1" TopLine="2315"/>
+      </Position3>
+      <Position4>
+        <Filename Value="tcgensql.pas"/>
+        <Caret Line="159" Column="28" TopLine="143"/>
+      </Position4>
+      <Position5>
+        <Filename Value="tcgensql.pas"/>
+        <Caret Line="2394" Column="14" TopLine="2372"/>
+      </Position5>
+      <Position6>
+        <Filename Value="tcgensql.pas"/>
+        <Caret Line="2395" Column="9" TopLine="2376"/>
+      </Position6>
+      <Position7>
+        <Filename Value="tcgensql.pas"/>
+        <Caret Line="2390" Column="22" TopLine="2376"/>
+      </Position7>
+      <Position8>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="1781" Column="1" TopLine="1759"/>
+      </Position8>
+      <Position9>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="4632" Column="4" TopLine="4625"/>
+      </Position9>
+      <Position10>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="4625" Column="16" TopLine="4625"/>
+      </Position10>
+      <Position11>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="1774" Column="42" TopLine="1759"/>
+      </Position11>
+      <Position12>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="1726" Column="3" TopLine="1707"/>
+      </Position12>
+      <Position13>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="4640" Column="52" TopLine="4625"/>
+      </Position13>
+      <Position14>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="4534" Column="3" TopLine="4527"/>
+      </Position14>
+      <Position15>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="4640" Column="46" TopLine="4625"/>
+      </Position15>
+      <Position16>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="1781" Column="20" TopLine="1760"/>
+      </Position16>
+      <Position17>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="82" Column="14" TopLine="67"/>
+      </Position17>
+      <Position18>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="1789" Column="3" TopLine="1772"/>
+      </Position18>
+      <Position19>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="4594" Column="31" TopLine="4576"/>
+      </Position19>
+      <Position20>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="1726" Column="74" TopLine="1711"/>
+      </Position20>
+      <Position21>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="4549" Column="3" TopLine="4531"/>
+      </Position21>
+      <Position22>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="4765" Column="32" TopLine="4742"/>
+      </Position22>
+      <Position23>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <Caret Line="4771" Column="57" TopLine="4749"/>
+      </Position23>
+      <Position24>
+        <Filename Value="tcgensql.pas"/>
+        <Caret Line="160" Column="25" TopLine="144"/>
+      </Position24>
+      <Position25>
+        <Filename Value="tcgensql.pas"/>
+        <Caret Line="2443" Column="1" TopLine="2413"/>
+      </Position25>
+      <Position26>
+        <Filename Value="tcgensql.pas"/>
+        <Caret Line="2426" Column="1" TopLine="2413"/>
+      </Position26>
+      <Position27>
+        <Filename Value="tcgensql.pas"/>
+        <Caret Line="2451" Column="1" TopLine="2421"/>
+      </Position27>
+      <Position28>
+        <Filename Value="tcgensql.pas"/>
+        <Caret Line="2419" Column="1" TopLine="2406"/>
+      </Position28>
+      <Position29>
+        <Filename Value="tcgensql.pas"/>
+        <Caret Line="2490" Column="1" TopLine="2475"/>
+      </Position29>
+      <Position30>
+        <Filename Value="tcgensql.pas"/>
+        <Caret Line="2414" Column="1" TopLine="2400"/>
+      </Position30>
+    </JumpHistory>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="9"/>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)/"/>
+      <OtherUnitFiles Value="/home/michael/fpc/packages/fcl-db/src/sql/"/>
+    </SearchPaths>
+    <Parsing>
+      <SyntaxOptions>
+        <UseAnsiStrings Value="False"/>
+      </SyntaxOptions>
+    </Parsing>
+    <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/testsqlscanner.lpr

@@ -0,0 +1,28 @@
+program testsqlscanner;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes, consoletestrunner, tcsqlscanner, 
+  fpsqltree, fpsqlscanner, fpsqlparser,
+  tcparser, tcgensql;
+
+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.

+ 1 - 1
packages/fcl-image/src/fpreadpng.pp

@@ -196,7 +196,7 @@ procedure TFPReaderPNG.HandleAlpha;
           begin
           begin
           c := ThePalette[r];
           c := ThePalette[r];
           a := data^[r];
           a := data^[r];
-          c.alpha := (a shl 16) + a;
+          c.alpha := (a shl 8) + a;
           ThePalette[r] := c;
           ThePalette[r] := c;
           end;
           end;
         end;
         end;

+ 163 - 0
packages/fcl-json/src/README.txt

@@ -0,0 +1,163 @@
+This package implements JSON support for FPC.
+
+JSON support consists of 3 parts:
+
+unit fpJSON contains the data representation. Basically, it defines a set of
+classes:
+
+TJSONData
++- TJSONNumber
+   +- TJSONIntegerNumber
+   +- TJSONFloatNumber
+   +- TJSONInt64Number
++- TJSONString
++- TJSONBoolean
++- TJSONNull
++- TJSONObject
++- TJSONArray
+
+The TJSONData.JSONType property is an enumerated:
+TJSONtype = (jtUnknown, jtNumber, jtString, jtBoolean, jtNull, jtArray, jtObject);
+
+Which allows to determine the type of a value.
+
+The following methods exist:
+
+Procedure Clear;
+  Clears the value. For arrays and objects, removes all elements/members
+Function Clone : TJSONData;
+  Creates an exact replica of the valye
+property Count: Integer;
+  For simple values this is zero, for complex values this is the number of
+  elements/members. Read only.
+property Items[Index: Integer]: TJSONData
+  For simple values, reading this will result in an error. For complex
+  values, this gives access to the members.
+property Value: variant;
+  The value as a variant. Only for simple values.
+Property AsString : TJSONStringType:
+   The value as a string. Only for simple values.
+Property AsFloat : TJSONFloat;
+  The value as a float (double). only for simple values.
+Property AsInteger : Integer ;
+  The value as an integer. only for simple values.
+Property AsInt64 : Int64;
+  The value as an 64-bit integer. only for simple values.
+Property AsBoolean : Boolean ;
+  The value as a boolean.
+Property IsNull : Boolean ;
+  Is the value Null ?
+Property AsJSON : TJSONStringType 
+  Return the value in JSON notation. For simple and complex values.
+
+The TJSONArray type provides access to the elements in the array in the
+following ways:
+
+Property Types[Index : Integer] : TJSONType;
+ Indexed access to the types of the elements in the array.
+Property Nulls[Index : Integer] : Boolean 
+ Checks if the Index-the element is NULL.
+Property Integers[Index : Integer] : Integer
+  Read/Write element values as integers.
+Property Int64s[Index : Integer] : Int64 
+  Read/Write element values as 64-bit integers.
+Property Strings[Index : Integer] : TJSONStringType;
+  Read/Write element values as strings.
+Property Floats[Index : Integer] : TJSONFloat ;
+  Read/Write element values as floats (doubles).
+Property Booleans[Index : Integer] : Boolean;
+  Read/Write element values as booleans.
+Property Arrays[Index : Integer] : TJSONArray;
+  Read/Write element values as arrays.
+Property Objects[Index : Integer] : TJSONObject;
+  Read/Write element values a strings
+
+Reading an element as a type which is incompatible, will result in an
+exception. For instance if element 5 is an object value, then the following
+will result in an exception:
+  i:=i+Array.Integers[5]
+
+The TJSONObject type similarly provides access to the elements in the array
+using the member names:
+property Names[Index : Integer] : TJSONStringType;
+  Indexed access to the member names.
+property Elements[AName: string] : TJSONData;
+  Read/Write a member as a raw TJSONData value.
+Property Types[AName : String] : TJSONType Read GetTypes;
+  Read/Write the type of a member.
+Property Nulls[AName : String] : Boolean;
+  Read/Write a member as a NULL value.
+Property Floats[AName : String] : TJSONFloat;
+  Read/Write a member as a float value (double)
+Property Integers[AName : String] : Integer;
+  Read/Write a member as an integer value
+Property Int64s[AName : String] : Int64;
+  Read/Write a member as an 64-bit integer value
+Property Strings[AName : String] : TJSONStringType;
+  Read/Write a member as a string value.
+Property Booleans[AName : String] : Boolean;
+  Read/Write a member as a boolean value.
+Property Arrays[AName : String] : TJSONArray;
+  Read/Write a member as an array value.
+Property Objects[AName : String] : TJSONObject
+  Read/Write a member as an object value.
+
+Members can be added with the Add() call, which exists in various overloaded
+forms:
+   function Add(const AName: TJSONStringType; Const AValue): Integer;
+Where the type of AVAlue is one of the supported types: 
+integer, int64, double, string, TJSONArray or TJSONObject.
+
+The Delete() call deletes an element from an array or object.
+
+Important remark:
+The array and object classes own their members: the members are destroyed as
+they are deleted. For this, the Extract() call exists: it removes an
+element/member from the array/object, without destroying it.
+
+The JSONSCanner unit contains a scanner for JSON data: TJSONScanner. 
+Currently it does not support full unicode, only UTF-8 is supported.
+
+The JSONParser unit contains the parser for JSON data: TJSONParser. 
+It uses to scanner to read the tokens. The scanner is created automatically.
+
+
+The Parse method will parse the data that was passed to the parser and will
+return the JSON value.
+
+Sample use:
+
+Var
+  P : TJSONParser;
+  S : String;
+  D : TJSONObject;
+
+begin
+  P:=TJSONParser.Create('{ "top": 10, "left": 20}');
+  try
+    D:=P.Parse as TJSONObject;
+    Writeln('Top : ',D.Integers['top']);
+    Writeln('Left : ',D.Integers['left']);
+    D.free;
+  Finally
+    P.free;
+  end;
+end;
+
+Note that the member names are case sensitive. 
+
+As an alternative, a stream may be passed to the constructor of TJSONParser.
+
+The scanner and parser support the 'Strict' property. 
+Strict JSON syntax requires the member names of an object to be strings:
+{ "top": 10, "left": 20}
+However, due to the sloppy definition of Javascript (and hence JSON), 
+the following type of JSON notation is frequently encountered:
+{ top: 10, left: 20}
+By default, this sloppy notation is accepted. Setting 'Strict' to true will
+reject this.
+
+A second effect of the Strict property is the requirement of " as a string
+delimiter. A single quote is also often found in Javascript and JSON:
+{ title: 'A nice title' }
+By default, this is accepted. Setting 'Strict' to true will reject this.

+ 15 - 2
packages/fcl-json/src/jsonparser.pp

@@ -28,7 +28,9 @@ Type
   TJSONParser = Class(TObject)
   TJSONParser = Class(TObject)
   Private
   Private
     FScanner : TJSONScanner;
     FScanner : TJSONScanner;
+    FStrict: Boolean;
     function ParseNumber: TJSONNumber;
     function ParseNumber: TJSONNumber;
+    procedure SetStrict(const AValue: Boolean);
   Protected
   Protected
     procedure DoError(const Msg: String);
     procedure DoError(const Msg: String);
     function DoParse(AtCurrent,AllowEOF: Boolean): TJSONData;
     function DoParse(AtCurrent,AllowEOF: Boolean): TJSONData;
@@ -42,6 +44,8 @@ Type
     Constructor Create(Source : TStream); overload;
     Constructor Create(Source : TStream); overload;
     Constructor Create(Source : TJSONStringType); overload;
     Constructor Create(Source : TJSONStringType); overload;
     destructor Destroy();override;
     destructor Destroy();override;
+    // Use strict JSON: " for strings, object members are strings, not identifiers
+    Property Strict : Boolean Read FStrict Write SetStrict;
   end;
   end;
   
   
   EJSONScanner = Class(Exception);
   EJSONScanner = Class(Exception);
@@ -82,7 +86,7 @@ end;
 Function TJSONParser.CurrentTokenString : String;
 Function TJSONParser.CurrentTokenString : String;
 
 
 begin
 begin
-  If CurrentToken in [tkString,tkNumber] then
+  If CurrentToken in [tkString,tkIdentifier,tkNumber] then
     Result:=FScanner.CurTokenString
     Result:=FScanner.CurTokenString
   else
   else
     Result:=TokenInfos[CurrentToken];
     Result:=TokenInfos[CurrentToken];
@@ -147,6 +151,15 @@ begin
     end;
     end;
 end;
 end;
 
 
+procedure TJSONParser.SetStrict(const AValue: Boolean);
+begin
+  if (FStrict=AValue) then
+     exit;
+  FStrict:=AValue;
+  If Assigned(FScanner) then
+    FScanner.Strict:=Fstrict;
+end;
+
 // Current token is {, on exit current token is }
 // Current token is {, on exit current token is }
 Function TJSONParser.ParseObject : TJSONObject;
 Function TJSONParser.ParseObject : TJSONObject;
 
 
@@ -161,7 +174,7 @@ begin
     T:=GetNextToken;
     T:=GetNextToken;
     While T<>tkCurlyBraceClose do
     While T<>tkCurlyBraceClose do
       begin
       begin
-      If T<>tkString then
+      If (T<>tkString) and (T<>tkIdentifier) then
         DoError(SErrExpectedElementName);
         DoError(SErrExpectedElementName);
       N:=CurrentTokenString;
       N:=CurrentTokenString;
       T:=GetNextToken;
       T:=GetNextToken;

+ 26 - 10
packages/fcl-json/src/jsonscanner.pp

@@ -22,7 +22,7 @@ interface
 uses SysUtils, Classes;
 uses SysUtils, Classes;
 
 
 resourcestring
 resourcestring
-  SErrInvalidCharacter = 'Invalid character ''%s''';
+  SErrInvalidCharacter = 'Invalid character at line %d, pos %d: ''%s''';
   SErrOpenString = 'string exceeds end of line';
   SErrOpenString = 'string exceeds end of line';
 
 
 type
 type
@@ -42,12 +42,15 @@ type
     tkCurlyBraceClose,       // '}'
     tkCurlyBraceClose,       // '}'
     tkSquaredBraceOpen,       // '['
     tkSquaredBraceOpen,       // '['
     tkSquaredBraceClose,      // ']'
     tkSquaredBraceClose,      // ']'
+    tkIdentifier,            // Any Javascript identifier
     tkUnknown
     tkUnknown
     );
     );
 
 
   EScannerError       = class(Exception);
   EScannerError       = class(Exception);
 
 
 
 
+  { TJSONScanner }
+
   TJSONScanner = class
   TJSONScanner = class
   private
   private
     FSource : TStringList;
     FSource : TStringList;
@@ -55,6 +58,7 @@ type
     FCurToken: TJSONToken;
     FCurToken: TJSONToken;
     FCurTokenString: string;
     FCurTokenString: string;
     FCurLine: string;
     FCurLine: string;
+    FStrict: Boolean;
     TokenStr: PChar;
     TokenStr: PChar;
     function GetCurColumn: Integer;
     function GetCurColumn: Integer;
   protected
   protected
@@ -74,6 +78,8 @@ type
 
 
     property CurToken: TJSONToken read FCurToken;
     property CurToken: TJSONToken read FCurToken;
     property CurTokenString: string read FCurTokenString;
     property CurTokenString: string read FCurTokenString;
+    // Use strict JSON: " for strings, object members are strings, not identifiers
+    Property Strict : Boolean Read FStrict Write FStrict;
   end;
   end;
 
 
 const
 const
@@ -91,6 +97,7 @@ const
     '}',
     '}',
     '[',
     '[',
     ']',
     ']',
+    'identifier',
     ''
     ''
   );
   );
 
 
@@ -156,6 +163,7 @@ var
   it : TJSONToken;
   it : TJSONToken;
   I : Integer;
   I : Integer;
   OldLength, SectionLength, Index: Integer;
   OldLength, SectionLength, Index: Integer;
+  C : char;
   S : String;
   S : String;
   
   
 begin
 begin
@@ -188,14 +196,16 @@ begin
           end;
           end;
       until not (TokenStr[0] in [#9, ' ']);
       until not (TokenStr[0] in [#9, ' ']);
       end;
       end;
-    '"':
+    '"','''':
       begin
       begin
+        C:=TokenStr[0];
+        If (C='''') and Strict then
+          Error(SErrInvalidCharacter, [CurRow,CurColumn,TokenStr[0]]);
         Inc(TokenStr);
         Inc(TokenStr);
         TokenStart := TokenStr;
         TokenStart := TokenStr;
         OldLength := 0;
         OldLength := 0;
         FCurTokenString := '';
         FCurTokenString := '';
-
-        while not (TokenStr[0] in [#0,'"']) do
+        while not (TokenStr[0] in [#0,C]) do
           begin
           begin
           if (TokenStr[0]='\') then
           if (TokenStr[0]='\') then
             begin
             begin
@@ -205,6 +215,7 @@ begin
             // Read escaped token
             // Read escaped token
             Case TokenStr[0] of
             Case TokenStr[0] of
               '"' : S:='"';
               '"' : S:='"';
+              '''' : S:='''';
               't' : S:=#9;
               't' : S:=#9;
               'b' : S:=#8;
               'b' : S:=#8;
               'n' : S:=#10;
               'n' : S:=#10;
@@ -221,7 +232,7 @@ begin
                         '0'..'9','A'..'F','a'..'f' :
                         '0'..'9','A'..'F','a'..'f' :
                           S[i]:=Upcase(TokenStr[0]);
                           S[i]:=Upcase(TokenStr[0]);
                       else
                       else
-                        Error(SErrInvalidCharacter, [TokenStr[0]]);
+                        Error(SErrInvalidCharacter, [CurRow,CurColumn,TokenStr[0]]);
                       end;
                       end;
                       end;
                       end;
                     // Takes care of conversion...  
                     // Takes care of conversion...  
@@ -229,7 +240,7 @@ begin
                     end;
                     end;
               #0  : Error(SErrOpenString);
               #0  : Error(SErrOpenString);
             else
             else
-              Error(SErrInvalidCharacter, [TokenStr[0]]);  
+              Error(SErrInvalidCharacter, [CurRow,CurColumn,TokenStr[0]]);
             end;
             end;
             SetLength(FCurTokenString, OldLength + SectionLength+1+Length(S));
             SetLength(FCurTokenString, OldLength + SectionLength+1+Length(S));
             if SectionLength > 0 then
             if SectionLength > 0 then
@@ -258,7 +269,7 @@ begin
         Inc(TokenStr);
         Inc(TokenStr);
         Result := tkComma;
         Result := tkComma;
       end;
       end;
-    '0'..'9','-':
+    '0'..'9','.','-':
       begin
       begin
         TokenStart := TokenStr;
         TokenStart := TokenStr;
         while true do
         while true do
@@ -294,6 +305,8 @@ begin
         SetLength(FCurTokenString, SectionLength);
         SetLength(FCurTokenString, SectionLength);
         if SectionLength > 0 then
         if SectionLength > 0 then
           Move(TokenStart^, FCurTokenString[1], SectionLength);
           Move(TokenStart^, FCurTokenString[1], SectionLength);
+        If (FCurTokenString[1]='.') then
+          FCurTokenString:='0'+FCurTokenString;
         Result := tkNumber;
         Result := tkNumber;
       end;
       end;
     ':':
     ':':
@@ -321,7 +334,7 @@ begin
         Inc(TokenStr);
         Inc(TokenStr);
         Result := tkSquaredBraceClose;
         Result := tkSquaredBraceClose;
       end;
       end;
-    'T','t','F','f','N','n' :
+    'a'..'z','_':
       begin
       begin
         TokenStart := TokenStr;
         TokenStart := TokenStr;
         repeat
         repeat
@@ -338,10 +351,13 @@ begin
             FCurToken := Result;
             FCurToken := Result;
             exit;
             exit;
             end;
             end;
-        Error(SErrInvalidCharacter, [TokenStart[0]]);
+        if Strict then
+          Error(SErrInvalidCharacter, [CurRow,CurColumn,TokenStr[0]])
+        else
+          Result:=tkIdentifier;
       end;
       end;
   else
   else
-    Error(SErrInvalidCharacter, [TokenStr[0]]);
+    Error(SErrInvalidCharacter, [CurRow,CurCOlumn,TokenStr[0]]);
   end;
   end;
 
 
   FCurToken := Result;
   FCurToken := Result;

+ 72 - 0
packages/fpvectorial/examples/fpvwritetest.lpi

@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <PathDelim Value="\"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="fpvwritetest"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <Icon Value="0"/>
+    </General>
+    <i18n>
+      <EnableI18N LFM="False"/>
+    </i18n>
+    <VersionInfo>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+      </local>
+    </RunParams>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="fpvwritetest.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="fpvwritetest"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="9"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="fpvwritetest"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)\"/>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </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>

+ 46 - 5
packages/fpvectorial/examples/fpvwritetest.pas

@@ -29,23 +29,43 @@ const
   cExtension = '.svg';
   cExtension = '.svg';
 var
 var
   Vec: TvVectorialDocument;
   Vec: TvVectorialDocument;
+
+{$R *.res}
+
 begin
 begin
   Vec := TvVectorialDocument.Create;
   Vec := TvVectorialDocument.Create;
   try
   try
+    // All documents are 10cm x 10cm
+    Vec.Width := 100;
+    Vec.Height := 100;
+
     // single_line_1    One line from (0, 20) to (30, 30)
     // single_line_1    One line from (0, 20) to (30, 30)
     Vec.StartPath(0, 20);
     Vec.StartPath(0, 20);
     Vec.AddLineToPath(30, 30);
     Vec.AddLineToPath(30, 30);
     Vec.EndPath();
     Vec.EndPath();
     Vec.WriteToFile('single_line_1' + cExtension, cFormat);
     Vec.WriteToFile('single_line_1' + cExtension, cFormat);
 
 
-    //    single_line_2    One line from (20, 30) to (30, 20)
+    // single_line_2    One line from (20, 30) to (30, 20)
     Vec.Clear;
     Vec.Clear;
     Vec.StartPath(20, 30);
     Vec.StartPath(20, 30);
     Vec.AddLineToPath(30, 20);
     Vec.AddLineToPath(30, 20);
     Vec.EndPath();
     Vec.EndPath();
     Vec.WriteToFile('single_line_2' + cExtension, cFormat);
     Vec.WriteToFile('single_line_2' + cExtension, cFormat);
 
 
-    //    polyline_1       One line from (0, 0) to (10, 10) to (20, 30) to (30, 20)
+    // single_line_3    One line from (0, 20) to (30, 30) + frame
+    Vec.Clear;
+    Vec.StartPath(0, 20);
+    Vec.AddLineToPath(30, 30);
+    Vec.EndPath();
+    Vec.StartPath(0, 0);
+    Vec.AddLineToPath(100, 0);
+    Vec.AddLineToPath(100, 100);
+    Vec.AddLineToPath(0, 100);
+    Vec.AddLineToPath(0, 0);
+    Vec.EndPath();
+    Vec.WriteToFile('single_line_3' + cExtension, cFormat);
+
+    // polyline_1       One line from (0, 0) to (10, 10) to (20, 30) to (30, 20)
     Vec.Clear;
     Vec.Clear;
     Vec.StartPath(0, 0);
     Vec.StartPath(0, 0);
     Vec.AddLineToPath(10, 10);
     Vec.AddLineToPath(10, 10);
@@ -81,18 +101,39 @@ begin
 
 
     // text_ascii       One text written at (10, 10)
     // text_ascii       One text written at (10, 10)
     Vec.Clear;
     Vec.Clear;
-    Vec.AddText('Some text in english.');
+    Vec.AddText(10, 10, 0, '10,10 Some text in english.');
     Vec.WriteToFile('text_ascii' + cExtension, cFormat);
     Vec.WriteToFile('text_ascii' + cExtension, cFormat);
 
 
     // text_europen     One text testing european languages at (20, 20)
     // text_europen     One text testing european languages at (20, 20)
     Vec.Clear;
     Vec.Clear;
-    Vec.AddText('Mówić, cześć, Włosku, Parabéns, Assunção, Correções.');
+    Vec.AddText(20, 20, 0, '20, 20 Mówić, cześć, Włosku, Parabéns, Assunção, Correções.');
     Vec.WriteToFile('text_europen' + cExtension, cFormat);
     Vec.WriteToFile('text_europen' + cExtension, cFormat);
 
 
     // text_asian       One text testing asian languages at (30, 30)
     // text_asian       One text testing asian languages at (30, 30)
     Vec.Clear;
     Vec.Clear;
-    Vec.AddText('森林,是一个高密度树木的区域');
+    Vec.AddText(30, 30, 0, '30, 30 森林,是一个高密度树木的区域');
     Vec.WriteToFile('text_asian' + cExtension, cFormat);
     Vec.WriteToFile('text_asian' + cExtension, cFormat);
+
+    // multi_test_1     Combines various elements
+    Vec.Clear;
+    Vec.StartPath(0, 20);
+    Vec.AddLineToPath(30, 30);
+    Vec.EndPath();
+    Vec.StartPath(0, 0);
+    Vec.AddLineToPath(100, 0);
+    Vec.AddLineToPath(100, 100);
+    Vec.AddLineToPath(0, 100);
+    Vec.AddLineToPath(0, 0);
+    Vec.EndPath();
+    Vec.StartPath(0, 0);
+    Vec.AddLineToPath(10, 10);
+    Vec.AddBezierToPath(10, 20, 20, 20, 20, 10);
+    Vec.AddLineToPath(30, 0);
+    Vec.EndPath();
+    Vec.AddText(10, 10, 0, '10,10 Some text in english.');
+    Vec.AddText(20, 20, 0, '20, 20 Mówić, cześć, Włosku, Parabéns.');
+    Vec.AddText(30, 30, 0, '30, 30 森林,是一个高密');
+    Vec.WriteToFile('multi_test_1' + cExtension, cFormat);
   finally
   finally
     Vec.Free;
     Vec.Free;
   end;
   end;

+ 2 - 1
packages/fpvectorial/src/fpvectbuildunit.pas

@@ -3,7 +3,8 @@ unit fpvectbuildunit;
 interface
 interface
 Uses
 Uses
    avisocncgcodereader,avisocncgcodewriter,avisozlib,fpvectorial,
    avisocncgcodereader,avisocncgcodewriter,avisozlib,fpvectorial,
-   fpvtocanvas,pdfvectorialreader,pdfvrlexico,pdfvrsemantico,pdfvrsintatico;
+   fpvtocanvas,pdfvectorialreader,pdfvrlexico,pdfvrsemantico,pdfvrsintatico,
+   svgvectorialwriter,cdrvectorialreader;
 
 
 implementation
 implementation
 end.
 end.

+ 35 - 16
packages/fpvectorial/src/fpvectorial.pas

@@ -41,7 +41,7 @@ const
 type
 type
   TSegmentType = (
   TSegmentType = (
     st2DLine, st2DBezier,
     st2DLine, st2DBezier,
-    st3DLine, st3DBezier);
+    st3DLine, st3DBezier, stMoveTo);
 
 
   {@@
   {@@
     The coordinates in fpvectorial are given in millimiters and
     The coordinates in fpvectorial are given in millimiters and
@@ -69,8 +69,12 @@ type
     At the moment fonts are unsupported, only simple texts
     At the moment fonts are unsupported, only simple texts
     up to 255 chars are supported.
     up to 255 chars are supported.
   }
   }
+
   TvText = record
   TvText = record
-    Value: array[0..255] of Char;
+    X, Y, Z: Double; // Z is ignored in 2D formats
+    FontSize: integer;
+    FontName: utf8string;
+    Value: utf8string;
   end;
   end;
 
 
   PText = ^TvText;
   PText = ^TvText;
@@ -87,6 +91,7 @@ type
     FPaths: TFPList;
     FPaths: TFPList;
     FTexts: TFPList;
     FTexts: TFPList;
     FTmpPath: TPath;
     FTmpPath: TPath;
+    FTmpText: TvText;
     procedure RemoveCallback(data, arg: pointer);
     procedure RemoveCallback(data, arg: pointer);
     function CreateVectorialWriter(AFormat: TvVectorialFormat): TvCustomVectorialWriter;
     function CreateVectorialWriter(AFormat: TvVectorialFormat): TvCustomVectorialWriter;
     function CreateVectorialReader(AFormat: TvVectorialFormat): TvCustomVectorialReader;
     function CreateVectorialReader(AFormat: TvVectorialFormat): TvCustomVectorialReader;
@@ -121,8 +126,8 @@ type
     procedure AddBezierToPath(AX1, AY1, AX2, AY2, AX3, AY3: Double); overload;
     procedure AddBezierToPath(AX1, AY1, AX2, AY2, AX3, AY3: Double); overload;
     procedure AddBezierToPath(AX1, AY1, AZ1, AX2, AY2, AZ2, AX3, AY3, AZ3: Double); overload;
     procedure AddBezierToPath(AX1, AY1, AZ1, AX2, AY2, AZ2, AX3, AY3, AZ3: Double); overload;
     procedure EndPath();
     procedure EndPath();
-    procedure AddText(AText: TvText); overload;
-    procedure AddText(AStr: utf8string); overload;
+    procedure AddText(AX, AY, AZ: Double; FontName: string; FontSize: integer; AText: utf8string); overload;
+    procedure AddText(AX, AY, AZ: Double; AStr: utf8string); overload;
     { properties }
     { properties }
     property PathCount: Integer read GetPathCount;
     property PathCount: Integer read GetPathCount;
     property Paths[Index: Cardinal]: TPath read GetPath;
     property Paths[Index: Cardinal]: TPath read GetPath;
@@ -338,7 +343,7 @@ end;
 procedure TvVectorialDocument.StartPath(AX, AY: Double);
 procedure TvVectorialDocument.StartPath(AX, AY: Double);
 begin
 begin
   FTmpPath.Len := 1;
   FTmpPath.Len := 1;
-  FTmpPath.Points[0].SegmentType := st2DLine;
+  FTmpPath.Points[0].SegmentType := stMoveTo;
   FTmpPath.Points[0].X := AX;
   FTmpPath.Points[0].X := AX;
   FTmpPath.Points[0].Y := AY;
   FTmpPath.Points[0].Y := AY;
 end;
 end;
@@ -394,8 +399,21 @@ end;
 
 
 procedure TvVectorialDocument.AddBezierToPath(AX1, AY1, AZ1, AX2, AY2, AZ2,
 procedure TvVectorialDocument.AddBezierToPath(AX1, AY1, AZ1, AX2, AY2, AZ2,
   AX3, AY3, AZ3: Double);
   AX3, AY3, AZ3: Double);
+var
+  L: Integer;
 begin
 begin
-
+  L := FTmPPath.Len;
+  Inc(FTmPPath.Len);
+  FTmPPath.Points[L].SegmentType := st3DBezier;
+  FTmPPath.Points[L].X := AX3;
+  FTmPPath.Points[L].Y := AY3;
+  FTmPPath.Points[L].Z := AZ3;
+  FTmPPath.Points[L].X2 := AX1;
+  FTmPPath.Points[L].Y2 := AY1;
+  FTmPPath.Points[L].Z2 := AZ1;
+  FTmPPath.Points[L].X3 := AX2;
+  FTmPPath.Points[L].Y3 := AY2;
+  FTmPPath.Points[L].Z3 := AZ2;
 end;
 end;
 
 
 {@@
 {@@
@@ -415,23 +433,24 @@ begin
   FTmPPath.Len := 0;
   FTmPPath.Len := 0;
 end;
 end;
 
 
-procedure TvVectorialDocument.AddText(AText: TvText);
+procedure TvVectorialDocument.AddText(AX, AY, AZ: Double; FontName: string; FontSize: integer; AText: utf8string);
 var
 var
   lText: PText;
   lText: PText;
-  Len: Integer;
 begin
 begin
-  Len := SizeOf(TvText);
-  lText := GetMem(Len);
-  Move(AText, lText^, Len);
+  lText := GetMem(SizeOf(TvText));
+  FillChar(lText^, SizeOf(TvText), 0);
+  lText.Value := AText;
+  lText.X := AX;
+  lText.Y := AY;
+  lText.Z := AZ;
+  lText.FontName := FontName;
+  lText.FontSize := FontSize;
   FTexts.Add(lText);
   FTexts.Add(lText);
 end;
 end;
 
 
-procedure TvVectorialDocument.AddText(AStr: utf8string);
-var
-  lText: TvText;
+procedure TvVectorialDocument.AddText(AX, AY, AZ: Double; AStr: utf8string);
 begin
 begin
-  lText.Value := AStr;
-  AddText(lText);
+  AddText(AX, AY, AZ, '', 10, AStr);
 end;
 end;
 
 
 {@@
 {@@

+ 125 - 14
packages/fpvectorial/src/svgvectorialwriter.pas

@@ -13,8 +13,7 @@ unit svgvectorialwriter;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils,
-  fpvectorial;
+  Classes, SysUtils, math, fpvectorial;
 
 
 type
 type
   { TvSVGVectorialWriter }
   { TvSVGVectorialWriter }
@@ -25,6 +24,10 @@ type
     procedure WriteDocumentSize(AStrings: TStrings; AData: TvVectorialDocument);
     procedure WriteDocumentSize(AStrings: TStrings; AData: TvVectorialDocument);
     procedure WriteDocumentName(AStrings: TStrings; AData: TvVectorialDocument);
     procedure WriteDocumentName(AStrings: TStrings; AData: TvVectorialDocument);
     procedure WritePaths(AStrings: TStrings; AData: TvVectorialDocument);
     procedure WritePaths(AStrings: TStrings; AData: TvVectorialDocument);
+    procedure WriteTexts(AStrings: TStrings; AData: TvVectorialDocument);
+    procedure ConvertFPVCoordinatesToSVGCoordinates(
+      const AData: TvVectorialDocument;
+      const ASrcX, ASrcY: Double; var ADestX, ADestY: double);
   public
   public
     { General reading methods }
     { General reading methods }
     procedure WriteToStrings(AStrings: TStrings; AData: TvVectorialDocument); override;
     procedure WriteToStrings(AStrings: TStrings; AData: TvVectorialDocument); override;
@@ -32,6 +35,18 @@ type
 
 
 implementation
 implementation
 
 
+const
+  // SVG requires hardcoding a DPI value
+
+  // The Opera Browser and Inkscape use 90 DPI, so we follow that
+
+  // 1 Inch = 25.4 milimiters
+  // 90 inches per pixel = (1 / 90) * 25.4 = 0.2822
+  // FLOAT_MILIMETERS_PER_PIXEL = 0.3528; // DPI 72 = 1 / 72 inches per pixel
+
+  FLOAT_MILIMETERS_PER_PIXEL = 0.2822; // DPI 90 = 1 / 90 inches per pixel
+  FLOAT_PIXELS_PER_MILIMETER = 3.5433; // DPI 90 = 1 / 90 inches per pixel
+
 { TvSVGVectorialWriter }
 { TvSVGVectorialWriter }
 
 
 procedure TvSVGVectorialWriter.WriteDocumentSize(AStrings: TStrings; AData: TvVectorialDocument);
 procedure TvSVGVectorialWriter.WriteDocumentSize(AStrings: TStrings; AData: TvVectorialDocument);
@@ -46,11 +61,15 @@ begin
 end;
 end;
 
 
 {@@
 {@@
-  SVG Coordinate system measures things in whatever unit we pass to it, so we
-  choose to pass in millimiters (mm), like FPVectorial uses.
+  SVG Coordinate system measures things only in pixels, so that we have to
+  hardcode a DPI value for the screen, which is usually 72.
+  FPVectorial uses only milimeters (mm).
 
 
-  The initial point is in the bottom-left corner of the document and it grows
-  to the top and to the right, just like in FPVectorial.
+  The initial point in FPVectorial is in the bottom-left corner of the document
+  and it grows to the top and to the right. In SVG, on the other hand, the
+  initial point is in the top-left corner, growing to the bottom and right.
+  Besides that, coordinates in SVG are also lengths in comparison to the
+  previous point and not absolute coordinates.
 
 
   SVG uses commas "," to separate the X,Y coordinates, so it always uses points
   SVG uses commas "," to separate the X,Y coordinates, so it always uses points
   "." as decimal separators and uses no thousand separators
   "." as decimal separators and uses no thousand separators
@@ -60,20 +79,71 @@ var
   i, j: Integer;
   i, j: Integer;
   PathStr: string;
   PathStr: string;
   lPath: TPath;
   lPath: TPath;
-  PtX, PtY: double;
+  PtX, PtY, OldPtX, OldPtY: double;
+  BezierCP1X, BezierCP1Y, BezierCP2X, BezierCP2Y: double;
 begin
 begin
   for i := 0 to AData.GetPathCount() - 1 do
   for i := 0 to AData.GetPathCount() - 1 do
   begin
   begin
-    PathStr := 'm ';
+    OldPtX := 0;
+    OldPtY := 0;
+
+    PathStr := '';
     lPath := AData.GetPath(i);
     lPath := AData.GetPath(i);
     for j := 0 to lPath.Len - 1 do
     for j := 0 to lPath.Len - 1 do
     begin
     begin
-      if lPath.Points[j].SegmentType <> st2DLine then Break; // unsupported line type
-
-      PtX := lPath.Points[j].X;
-      PtY := lPath.Points[j].Y;
-      PathStr := PathStr + FloatToStr(PtX, FPointSeparator) + 'mm,'
-        + FloatToStr(PtY, FPointSeparator) + 'mm ';
+      if (lPath.Points[j].SegmentType <> st2DLine)
+        and (lPath.Points[j].SegmentType <> stMoveTo)
+        and (lPath.Points[j].SegmentType <> st2DBezier)
+        then Break; // unsupported line type
+
+      // Coordinate conversion from fpvectorial to SVG
+      ConvertFPVCoordinatesToSVGCoordinates(
+        AData, lPath.Points[j].X, lPath.Points[j].Y, PtX, PtY);
+      PtX := PtX - OldPtX;
+      PtY := PtY - OldPtY;
+
+      if (lPath.Points[j].SegmentType = stMoveTo) then
+      begin
+        PathStr := PathStr + 'm '
+          + FloatToStr(PtX, FPointSeparator) + ','
+          + FloatToStr(PtY, FPointSeparator) + ' ';
+      end
+      else if (lPath.Points[j].SegmentType = st2DLine) then
+      begin
+        PathStr := PathStr + 'l '
+          + FloatToStr(PtX, FPointSeparator) + ','
+          + FloatToStr(PtY, FPointSeparator) + ' ';
+      end
+      else if (lPath.Points[j].SegmentType = st2DBezier) then
+      begin
+        // Converts all coordinates to absolute values
+        ConvertFPVCoordinatesToSVGCoordinates(
+          AData, lPath.Points[j].X2, lPath.Points[j].Y2, BezierCP1X, BezierCP1Y);
+        ConvertFPVCoordinatesToSVGCoordinates(
+          AData, lPath.Points[j].X3, lPath.Points[j].Y3, BezierCP2X, BezierCP2Y);
+
+        // Transforms them into values relative to the initial point
+        BezierCP1X := BezierCP1X - OldPtX;
+        BezierCP1Y := BezierCP1Y - OldPtY;
+        BezierCP2X := BezierCP2X - OldPtX;
+        BezierCP2Y := BezierCP2Y - OldPtY;
+
+        // PtX and PtY already contains the destination point
+
+        // Now render our 2D cubic bezier
+        PathStr := PathStr + 'c '
+          + FloatToStr(BezierCP1X, FPointSeparator) + ','
+          + FloatToStr(BezierCP1Y, FPointSeparator) + ' '
+          + FloatToStr(BezierCP2X, FPointSeparator) + ','
+          + FloatToStr(BezierCP2Y, FPointSeparator) + ' '
+          + FloatToStr(PtX, FPointSeparator) + ','
+          + FloatToStr(PtY, FPointSeparator) + ' '
+          ;
+      end;
+
+      // Store the current position for future points
+      OldPtX := OldPtX + PtX;
+      OldPtY := OldPtY + PtY;
     end;
     end;
 
 
     AStrings.Add('  <path');
     AStrings.Add('  <path');
@@ -83,6 +153,14 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TvSVGVectorialWriter.ConvertFPVCoordinatesToSVGCoordinates(
+  const AData: TvVectorialDocument; const ASrcX, ASrcY: Double; var ADestX,
+  ADestY: double);
+begin
+  ADestX := ASrcX / FLOAT_MILIMETERS_PER_PIXEL;
+  ADestY := (AData.Height - ASrcY) / FLOAT_MILIMETERS_PER_PIXEL;
+end;
+
 procedure TvSVGVectorialWriter.WriteToStrings(AStrings: TStrings;
 procedure TvSVGVectorialWriter.WriteToStrings(AStrings: TStrings;
   AData: TvVectorialDocument);
   AData: TvVectorialDocument);
 begin
 begin
@@ -113,12 +191,45 @@ begin
   // Now data
   // Now data
   AStrings.Add('  <g id="layer1">');
   AStrings.Add('  <g id="layer1">');
   WritePaths(AStrings, AData);
   WritePaths(AStrings, AData);
+  WriteTexts(AStrings, AData);
   AStrings.Add('  </g>');
   AStrings.Add('  </g>');
 
 
   // finalization
   // finalization
   AStrings.Add('</svg>');
   AStrings.Add('</svg>');
 end;
 end;
 
 
+procedure TvSVGVectorialWriter.WriteTexts(AStrings: TStrings; AData: TvVectorialDocument);
+var
+  i, j, FontSize: Integer;
+  TextStr, FontName, SVGFontFamily: string;
+  lText: TvText;
+  PtX, PtY: double;
+begin
+  for i := 0 to AData.GetTextCount() - 1 do
+  begin
+    TextStr := '';
+    lText := AData.GetText(i);
+
+    ConvertFPVCoordinatesToSVGCoordinates(
+        AData, lText.X, lText.Y, PtX, PtY);
+
+    TextStr := lText.Value;
+    FontSize:= ceil(lText.FontSize / FLOAT_MILIMETERS_PER_PIXEL);
+    SVGFontFamily := 'Arial, sans-serif';//lText.FontName;
+
+    AStrings.Add('  <text ');
+    AStrings.Add('    x="' + FloatToStr(PtX, FPointSeparator) + '"');
+    AStrings.Add('    y="' + FloatToStr(PtY, FPointSeparator) + '"');
+//    AStrings.Add('    font-size="' + IntToStr(FontSize) + '"'); Doesn't seam to work, we need to use the tspan
+    AStrings.Add('    font-family="' + SVGFontFamily + '">');
+    AStrings.Add('    <tspan ');
+    AStrings.Add('      style="font-size:' + IntToStr(FontSize) + '" ');
+//    AStrings.Add('      id="tspan2828" ');
+    AStrings.Add('    >');
+    AStrings.Add(TextStr + '</tspan></text>');
+  end;
+end;
+
 initialization
 initialization
 
 
   RegisterVectorialWriter(TvSVGVectorialWriter, vfSVG);
   RegisterVectorialWriter(TvSVGVectorialWriter, vfSVG);

+ 33 - 3
packages/libgbafpc/Makefile

@@ -1,8 +1,8 @@
 #
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2009/12/31]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2010/11/23]
 #
 #
 default: all
 default: all
-MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
 BSDs = freebsd netbsd openbsd darwin
 BSDs = freebsd netbsd openbsd darwin
 UNIXs = linux $(BSDs) solaris qnx haiku
 UNIXs = linux $(BSDs) solaris qnx haiku
 LIMIT83fs = go32v2 os2 emx watcom
 LIMIT83fs = go32v2 os2 emx watcom
@@ -392,6 +392,9 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 override TARGET_UNITS+=gba maxmod
 override TARGET_UNITS+=gba maxmod
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override TARGET_UNITS+=gba maxmod
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 override TARGET_UNITS+=gba maxmod
 override TARGET_UNITS+=gba maxmod
 endif
 endif
@@ -443,6 +446,9 @@ endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
 override TARGET_UNITS+=gba maxmod
 override TARGET_UNITS+=gba maxmod
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override TARGET_UNITS+=gba maxmod
+endif
 ifeq ($(FULL_TARGET),i386-linux)
 ifeq ($(FULL_TARGET),i386-linux)
 override TARGET_LOADERS+=core_asm
 override TARGET_LOADERS+=core_asm
 endif
 endif
@@ -566,6 +572,9 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 override TARGET_LOADERS+=core_asm
 override TARGET_LOADERS+=core_asm
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override TARGET_LOADERS+=core_asm
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 override TARGET_LOADERS+=core_asm
 override TARGET_LOADERS+=core_asm
 endif
 endif
@@ -617,6 +626,9 @@ endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
 override TARGET_LOADERS+=core_asm
 override TARGET_LOADERS+=core_asm
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override TARGET_LOADERS+=core_asm
+endif
 override INSTALL_FPCPACKAGE=y
 override INSTALL_FPCPACKAGE=y
 ifeq ($(FULL_TARGET),i386-linux)
 ifeq ($(FULL_TARGET),i386-linux)
 override COMPILER_INCLUDEDIR+=src src/maxmod
 override COMPILER_INCLUDEDIR+=src src/maxmod
@@ -741,6 +753,9 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 override COMPILER_INCLUDEDIR+=src src/maxmod
 override COMPILER_INCLUDEDIR+=src src/maxmod
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override COMPILER_INCLUDEDIR+=src src/maxmod
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 override COMPILER_INCLUDEDIR+=src src/maxmod
 override COMPILER_INCLUDEDIR+=src src/maxmod
 endif
 endif
@@ -792,6 +807,9 @@ endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
 override COMPILER_INCLUDEDIR+=src src/maxmod
 override COMPILER_INCLUDEDIR+=src src/maxmod
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override COMPILER_INCLUDEDIR+=src src/maxmod
+endif
 ifeq ($(FULL_TARGET),i386-linux)
 ifeq ($(FULL_TARGET),i386-linux)
 override COMPILER_SOURCEDIR+=src tests
 override COMPILER_SOURCEDIR+=src tests
 endif
 endif
@@ -915,6 +933,9 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 override COMPILER_SOURCEDIR+=src tests
 override COMPILER_SOURCEDIR+=src tests
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override COMPILER_SOURCEDIR+=src tests
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 override COMPILER_SOURCEDIR+=src tests
 override COMPILER_SOURCEDIR+=src tests
 endif
 endif
@@ -966,6 +987,9 @@ endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
 override COMPILER_SOURCEDIR+=src tests
 override COMPILER_SOURCEDIR+=src tests
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override COMPILER_SOURCEDIR+=src tests
+endif
 ifdef REQUIRE_UNITSDIR
 ifdef REQUIRE_UNITSDIR
 override UNITSDIR+=$(REQUIRE_UNITSDIR)
 override UNITSDIR+=$(REQUIRE_UNITSDIR)
 endif
 endif
@@ -2114,7 +2138,7 @@ ZIPCMD_CDPACK:=cd $(subst /,$(ZIPPATHSEP),$(PACKDIR))
 ZIPCMD_CDBASE:=cd $(subst /,$(ZIPPATHSEP),$(BASEDIR))
 ZIPCMD_CDBASE:=cd $(subst /,$(ZIPPATHSEP),$(BASEDIR))
 ifdef USETAR
 ifdef USETAR
 ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(TAREXT)
 ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(TAREXT)
-ZIPCMD_ZIP:=$(TARPROG) cf$(TAROPT) $(ZIPDESTFILE) *
+ZIPCMD_ZIP:=$(TARPROG) c$(TAROPT)f $(ZIPDESTFILE) *
 else
 else
 ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(ZIPEXT)
 ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(ZIPEXT)
 ZIPCMD_ZIP:=$(subst /,$(ZIPPATHSEP),$(ZIPPROG)) -Dr $(ZIPOPT) $(ZIPDESTFILE) *
 ZIPCMD_ZIP:=$(subst /,$(ZIPPATHSEP),$(ZIPPROG)) -Dr $(ZIPOPT) $(ZIPDESTFILE) *
@@ -2159,6 +2183,9 @@ fpc_zipdistinstall:
 ifdef EXEFILES
 ifdef EXEFILES
 override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
 override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
 endif
 endif
+ifdef CLEAN_PROGRAMS
+override CLEANEXEFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEEXT), $(CLEAN_PROGRAMS)))
+endif
 ifdef CLEAN_UNITS
 ifdef CLEAN_UNITS
 override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
 override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
 endif
 endif
@@ -2205,6 +2232,9 @@ endif
 ifdef CLEANRSTFILES
 ifdef CLEANRSTFILES
 	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
 	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
 endif
 endif
+endif
+ifdef CLEAN_FILES
+	-$(DEL) $(CLEAN_FILES)
 endif
 endif
 	-$(DELTREE) units
 	-$(DELTREE) units
 	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
 	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)

+ 193 - 11
packages/libgbafpc/examples/audio/Makefile

@@ -1,8 +1,8 @@
 #
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2009/12/31]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2010/11/23]
 #
 #
 default: all
 default: all
-MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
 BSDs = freebsd netbsd openbsd darwin
 BSDs = freebsd netbsd openbsd darwin
 UNIXs = linux $(BSDs) solaris qnx haiku
 UNIXs = linux $(BSDs) solaris qnx haiku
 LIMIT83fs = go32v2 os2 emx watcom
 LIMIT83fs = go32v2 os2 emx watcom
@@ -264,6 +264,8 @@ ifeq ($(UNITSDIR),)
 UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
 UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
 endif
 endif
 PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
 PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
+override PACKAGE_NAME=libgbafpc-audio-examples
+override PACKAGE_VERSION=2.4.0
 ifeq ($(FULL_TARGET),i386-linux)
 ifeq ($(FULL_TARGET),i386-linux)
 override TARGET_DIRS+=PlayBoyScout
 override TARGET_DIRS+=PlayBoyScout
 endif
 endif
@@ -387,6 +389,9 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 override TARGET_DIRS+=PlayBoyScout
 override TARGET_DIRS+=PlayBoyScout
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override TARGET_DIRS+=PlayBoyScout
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 override TARGET_DIRS+=PlayBoyScout
 override TARGET_DIRS+=PlayBoyScout
 endif
 endif
@@ -438,6 +443,9 @@ endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
 override TARGET_DIRS+=PlayBoyScout
 override TARGET_DIRS+=PlayBoyScout
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override TARGET_DIRS+=PlayBoyScout
+endif
 override INSTALL_FPCPACKAGE=y
 override INSTALL_FPCPACKAGE=y
 ifdef REQUIRE_UNITSDIR
 ifdef REQUIRE_UNITSDIR
 override UNITSDIR+=$(REQUIRE_UNITSDIR)
 override UNITSDIR+=$(REQUIRE_UNITSDIR)
@@ -1329,6 +1337,9 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 REQUIRE_PACKAGES_LIBGBAFPC=1
 REQUIRE_PACKAGES_LIBGBAFPC=1
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+REQUIRE_PACKAGES_LIBGBAFPC=1
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 REQUIRE_PACKAGES_LIBGBAFPC=1
 REQUIRE_PACKAGES_LIBGBAFPC=1
 endif
 endif
@@ -1380,6 +1391,9 @@ endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
 REQUIRE_PACKAGES_LIBGBAFPC=1
 REQUIRE_PACKAGES_LIBGBAFPC=1
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+REQUIRE_PACKAGES_LIBGBAFPC=1
+endif
 ifdef REQUIRE_PACKAGES_LIBGBAFPC
 ifdef REQUIRE_PACKAGES_LIBGBAFPC
 PACKAGEDIR_LIBGBAFPC:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /libgbafpc/Makefile.fpc,$(PACKAGESDIR))))))
 PACKAGEDIR_LIBGBAFPC:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /libgbafpc/Makefile.fpc,$(PACKAGESDIR))))))
 ifneq ($(PACKAGEDIR_LIBGBAFPC),)
 ifneq ($(PACKAGEDIR_LIBGBAFPC),)
@@ -1563,10 +1577,169 @@ ifdef TARGET_RSTS
 override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
 override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
 override CLEANRSTFILES+=$(RSTFILES)
 override CLEANRSTFILES+=$(RSTFILES)
 endif
 endif
+.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall
+ifdef INSTALL_UNITS
+override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(INSTALL_UNITS))
+endif
+ifdef INSTALL_BUILDUNIT
+override INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT),$(INSTALLPPUFILES))
+endif
+ifdef INSTALLPPUFILES
+override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES)))
+ifneq ($(UNITTARGETDIRPREFIX),)
+override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPUFILES)))
+override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPULINKFILES))))
+endif
+override INSTALL_CREATEPACKAGEFPC=1
+endif
+ifdef INSTALLEXEFILES
+ifneq ($(TARGETDIRPREFIX),)
+override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(INSTALLEXEFILES)))
+endif
+endif
+fpc_install: all $(INSTALLTARGET)
+ifdef INSTALLEXEFILES
+	$(MKDIR) $(INSTALL_BINDIR)
+ifdef UPXPROG
+	-$(UPXPROG) $(INSTALLEXEFILES)
+endif
+	$(INSTALLEXE) $(INSTALLEXEFILES) $(INSTALL_BINDIR)
+endif
+ifdef INSTALL_CREATEPACKAGEFPC
+ifdef FPCMAKE
+ifdef PACKAGE_VERSION
+ifneq ($(wildcard Makefile.fpc),)
+	$(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc
+	$(MKDIR) $(INSTALL_UNITDIR)
+	$(INSTALL) Package.fpc $(INSTALL_UNITDIR)
+endif
+endif
+endif
+endif
+ifdef INSTALLPPUFILES
+	$(MKDIR) $(INSTALL_UNITDIR)
+	$(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR)
+ifneq ($(INSTALLPPULINKFILES),)
+	$(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR)
+endif
+ifneq ($(wildcard $(LIB_FULLNAME)),)
+	$(MKDIR) $(INSTALL_LIBDIR)
+	$(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR)
+ifdef inUnix
+	ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME)
+endif
+endif
+endif
+ifdef INSTALL_FILES
+	$(MKDIR) $(INSTALL_DATADIR)
+	$(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADIR)
+endif
+fpc_sourceinstall: distclean
+	$(MKDIR) $(INSTALL_SOURCEDIR)
+	$(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR)
+fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
+ifdef HASEXAMPLES
+	$(MKDIR) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef EXAMPLESOURCEFILES
+	$(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef TARGET_EXAMPLEDIRS
+	$(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR)
+endif
+.PHONY: fpc_distinstall
+fpc_distinstall: install exampleinstall
+.PHONY: fpc_zipinstall fpc_zipsourceinstall fpc_zipexampleinstall
+ifndef PACKDIR
+ifndef inUnix
+PACKDIR=$(BASEDIR)/../fpc-pack
+else
+PACKDIR=/tmp/fpc-pack
+endif
+endif
+ifndef ZIPNAME
+ifdef DIST_ZIPNAME
+ZIPNAME=$(DIST_ZIPNAME)
+else
+ZIPNAME=$(PACKAGE_NAME)
+endif
+endif
+ifndef FULLZIPNAME
+FULLZIPNAME=$(ZIPCROSSPREFIX)$(ZIPPREFIX)$(ZIPNAME)$(ZIPSUFFIX)
+endif
+ifndef ZIPTARGET
+ifdef DIST_ZIPTARGET
+ZIPTARGET=DIST_ZIPTARGET
+else
+ZIPTARGET=install
+endif
+endif
+ifndef USEZIP
+ifdef inUnix
+USETAR=1
+endif
+endif
+ifndef inUnix
+USEZIPWRAPPER=1
+endif
+ifdef USEZIPWRAPPER
+ZIPPATHSEP=$(PATHSEP)
+ZIPWRAPPER=$(subst /,$(PATHSEP),$(DIST_DESTDIR)/fpczip$(SRCBATCHEXT))
+else
+ZIPPATHSEP=/
+endif
+ZIPCMD_CDPACK:=cd $(subst /,$(ZIPPATHSEP),$(PACKDIR))
+ZIPCMD_CDBASE:=cd $(subst /,$(ZIPPATHSEP),$(BASEDIR))
+ifdef USETAR
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(TAREXT)
+ZIPCMD_ZIP:=$(TARPROG) c$(TAROPT)f $(ZIPDESTFILE) *
+else
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(ZIPEXT)
+ZIPCMD_ZIP:=$(subst /,$(ZIPPATHSEP),$(ZIPPROG)) -Dr $(ZIPOPT) $(ZIPDESTFILE) *
+endif
+fpc_zipinstall:
+	$(MAKE) $(ZIPTARGET) INSTALL_PREFIX=$(PACKDIR) ZIPINSTALL=1
+	$(MKDIR) $(DIST_DESTDIR)
+	$(DEL) $(ZIPDESTFILE)
+ifdef USEZIPWRAPPER
+ifneq ($(ECHOREDIR),echo)
+	$(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDPACK))" > $(ZIPWRAPPER)
+	$(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_ZIP))" >> $(ZIPWRAPPER)
+	$(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDBASE))" >> $(ZIPWRAPPER)
+else
+	echo $(ZIPCMD_CDPACK) > $(ZIPWRAPPER)
+	echo $(ZIPCMD_ZIP) >> $(ZIPWRAPPER)
+	echo $(ZIPCMD_CDBASE) >> $(ZIPWRAPPER)
+endif
+ifdef inUnix
+	/bin/sh $(ZIPWRAPPER)
+else
+ifdef RUNBATCH
+	$(RUNBATCH) $(ZIPWRAPPER)
+else
+	$(ZIPWRAPPER)
+endif
+endif
+	$(DEL) $(ZIPWRAPPER)
+else
+	$(ZIPCMD_CDPACK) ; $(ZIPCMD_ZIP) ; $(ZIPCMD_CDBASE)
+endif
+	$(DELTREE) $(PACKDIR)
+fpc_zipsourceinstall:
+	$(MAKE) fpc_zipinstall ZIPTARGET=sourceinstall ZIPSUFFIX=$(ZIPSOURCESUFFIX)
+fpc_zipexampleinstall:
+ifdef HASEXAMPLES
+	$(MAKE) fpc_zipinstall ZIPTARGET=exampleinstall ZIPSUFFIX=$(ZIPEXAMPLESUFFIX)
+endif
+fpc_zipdistinstall:
+	$(MAKE) fpc_zipinstall ZIPTARGET=distinstall
 .PHONY: fpc_clean fpc_cleanall fpc_distclean
 .PHONY: fpc_clean fpc_cleanall fpc_distclean
 ifdef EXEFILES
 ifdef EXEFILES
 override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
 override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
 endif
 endif
+ifdef CLEAN_PROGRAMS
+override CLEANEXEFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEEXT), $(CLEAN_PROGRAMS)))
+endif
 ifdef CLEAN_UNITS
 ifdef CLEAN_UNITS
 override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
 override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
 endif
 endif
@@ -1613,6 +1786,9 @@ endif
 ifdef CLEANRSTFILES
 ifdef CLEANRSTFILES
 	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
 	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
 endif
 endif
+endif
+ifdef CLEAN_FILES
+	-$(DEL) $(CLEAN_FILES)
 endif
 endif
 	-$(DELTREE) units
 	-$(DELTREE) units
 	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
 	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
@@ -1859,6 +2035,9 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 TARGET_DIRS_PLAYBOYSCOUT=1
 TARGET_DIRS_PLAYBOYSCOUT=1
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+TARGET_DIRS_PLAYBOYSCOUT=1
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 TARGET_DIRS_PLAYBOYSCOUT=1
 TARGET_DIRS_PLAYBOYSCOUT=1
 endif
 endif
@@ -1910,6 +2089,9 @@ endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
 TARGET_DIRS_PLAYBOYSCOUT=1
 TARGET_DIRS_PLAYBOYSCOUT=1
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+TARGET_DIRS_PLAYBOYSCOUT=1
+endif
 ifdef TARGET_DIRS_PLAYBOYSCOUT
 ifdef TARGET_DIRS_PLAYBOYSCOUT
 PlayBoyScout_all:
 PlayBoyScout_all:
 	$(MAKE) -C PlayBoyScout all
 	$(MAKE) -C PlayBoyScout all
@@ -1962,19 +2144,19 @@ release: $(addsuffix _release,$(TARGET_DIRS))
 units: $(addsuffix _units,$(TARGET_DIRS))
 units: $(addsuffix _units,$(TARGET_DIRS))
 examples: $(addsuffix _examples,$(TARGET_DIRS))
 examples: $(addsuffix _examples,$(TARGET_DIRS))
 shared: $(addsuffix _shared,$(TARGET_DIRS))
 shared: $(addsuffix _shared,$(TARGET_DIRS))
-install: $(addsuffix _install,$(TARGET_DIRS))
-sourceinstall: $(addsuffix _sourceinstall,$(TARGET_DIRS))
-exampleinstall: $(addsuffix _exampleinstall,$(TARGET_DIRS))
-distinstall: $(addsuffix _distinstall,$(TARGET_DIRS))
-zipinstall: $(addsuffix _zipinstall,$(TARGET_DIRS))
-zipsourceinstall: $(addsuffix _zipsourceinstall,$(TARGET_DIRS))
-zipexampleinstall: $(addsuffix _zipexampleinstall,$(TARGET_DIRS))
-zipdistinstall: $(addsuffix _zipdistinstall,$(TARGET_DIRS))
+install: fpc_install $(addsuffix _install,$(TARGET_DIRS))
+sourceinstall: fpc_sourceinstall
+exampleinstall: fpc_exampleinstall $(addsuffix _exampleinstall,$(TARGET_DIRS))
+distinstall: fpc_distinstall
+zipinstall: fpc_zipinstall
+zipsourceinstall: fpc_zipsourceinstall
+zipexampleinstall: fpc_zipexampleinstall $(addsuffix _zipexampleinstall,$(TARGET_DIRS))
+zipdistinstall: fpc_zipdistinstall
 clean: $(addsuffix _clean,$(TARGET_DIRS))
 clean: $(addsuffix _clean,$(TARGET_DIRS))
 distclean: $(addsuffix _distclean,$(TARGET_DIRS))
 distclean: $(addsuffix _distclean,$(TARGET_DIRS))
 cleanall: $(addsuffix _cleanall,$(TARGET_DIRS))
 cleanall: $(addsuffix _cleanall,$(TARGET_DIRS))
 info: fpc_info
 info: fpc_info
-makefiles: fpc_makefiles $(addsuffix _makefiles,$(TARGET_DIRS))
+makefiles: fpc_makefiles
 .PHONY: all debug smart release units examples shared install sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall clean distclean cleanall info makefiles
 .PHONY: all debug smart release units examples shared install sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall clean distclean cleanall info makefiles
 ifneq ($(wildcard fpcmake.loc),)
 ifneq ($(wildcard fpcmake.loc),)
 include fpcmake.loc
 include fpcmake.loc

+ 3 - 0
packages/libgbafpc/examples/audio/Makefile.fpc

@@ -1,6 +1,9 @@
 #
 #
 #   Makefile.fpc for Free Pascal libgbafpc 2.x.y Examples
 #   Makefile.fpc for Free Pascal libgbafpc 2.x.y Examples
 #
 #
+[package]
+name=libgbafpc-audio-examples
+version=2.4.0
 
 
 [target]
 [target]
 dirs=PlayBoyScout 
 dirs=PlayBoyScout 

+ 197 - 11
packages/libgbafpc/examples/graphics/Makefile

@@ -1,8 +1,8 @@
 #
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2009/12/31]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2010/11/23]
 #
 #
 default: all
 default: all
-MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
 BSDs = freebsd netbsd openbsd darwin
 BSDs = freebsd netbsd openbsd darwin
 UNIXs = linux $(BSDs) solaris qnx haiku
 UNIXs = linux $(BSDs) solaris qnx haiku
 LIMIT83fs = go32v2 os2 emx watcom
 LIMIT83fs = go32v2 os2 emx watcom
@@ -264,6 +264,8 @@ ifeq ($(UNITSDIR),)
 UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
 UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
 endif
 endif
 PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
 PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
+override PACKAGE_NAME=libgbafpc-graphics-examples
+override PACKAGE_VERSION=2.4.0
 ifeq ($(FULL_TARGET),i386-linux)
 ifeq ($(FULL_TARGET),i386-linux)
 override TARGET_DIRS+=ansi_console PCXView SimpleBGScroll
 override TARGET_DIRS+=ansi_console PCXView SimpleBGScroll
 endif
 endif
@@ -387,6 +389,9 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 override TARGET_DIRS+=ansi_console PCXView SimpleBGScroll
 override TARGET_DIRS+=ansi_console PCXView SimpleBGScroll
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override TARGET_DIRS+=ansi_console PCXView SimpleBGScroll
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 override TARGET_DIRS+=ansi_console PCXView SimpleBGScroll
 override TARGET_DIRS+=ansi_console PCXView SimpleBGScroll
 endif
 endif
@@ -438,6 +443,9 @@ endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
 override TARGET_DIRS+=ansi_console PCXView SimpleBGScroll
 override TARGET_DIRS+=ansi_console PCXView SimpleBGScroll
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override TARGET_DIRS+=ansi_console PCXView SimpleBGScroll
+endif
 override INSTALL_FPCPACKAGE=y
 override INSTALL_FPCPACKAGE=y
 ifdef REQUIRE_UNITSDIR
 ifdef REQUIRE_UNITSDIR
 override UNITSDIR+=$(REQUIRE_UNITSDIR)
 override UNITSDIR+=$(REQUIRE_UNITSDIR)
@@ -1329,6 +1337,9 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 REQUIRE_PACKAGES_LIBGBAFPC=1
 REQUIRE_PACKAGES_LIBGBAFPC=1
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+REQUIRE_PACKAGES_LIBGBAFPC=1
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 REQUIRE_PACKAGES_LIBGBAFPC=1
 REQUIRE_PACKAGES_LIBGBAFPC=1
 endif
 endif
@@ -1380,6 +1391,9 @@ endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
 REQUIRE_PACKAGES_LIBGBAFPC=1
 REQUIRE_PACKAGES_LIBGBAFPC=1
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+REQUIRE_PACKAGES_LIBGBAFPC=1
+endif
 ifdef REQUIRE_PACKAGES_LIBGBAFPC
 ifdef REQUIRE_PACKAGES_LIBGBAFPC
 PACKAGEDIR_LIBGBAFPC:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /libgbafpc/Makefile.fpc,$(PACKAGESDIR))))))
 PACKAGEDIR_LIBGBAFPC:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /libgbafpc/Makefile.fpc,$(PACKAGESDIR))))))
 ifneq ($(PACKAGEDIR_LIBGBAFPC),)
 ifneq ($(PACKAGEDIR_LIBGBAFPC),)
@@ -1563,10 +1577,169 @@ ifdef TARGET_RSTS
 override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
 override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
 override CLEANRSTFILES+=$(RSTFILES)
 override CLEANRSTFILES+=$(RSTFILES)
 endif
 endif
+.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall
+ifdef INSTALL_UNITS
+override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(INSTALL_UNITS))
+endif
+ifdef INSTALL_BUILDUNIT
+override INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT),$(INSTALLPPUFILES))
+endif
+ifdef INSTALLPPUFILES
+override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES)))
+ifneq ($(UNITTARGETDIRPREFIX),)
+override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPUFILES)))
+override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPULINKFILES))))
+endif
+override INSTALL_CREATEPACKAGEFPC=1
+endif
+ifdef INSTALLEXEFILES
+ifneq ($(TARGETDIRPREFIX),)
+override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(INSTALLEXEFILES)))
+endif
+endif
+fpc_install: all $(INSTALLTARGET)
+ifdef INSTALLEXEFILES
+	$(MKDIR) $(INSTALL_BINDIR)
+ifdef UPXPROG
+	-$(UPXPROG) $(INSTALLEXEFILES)
+endif
+	$(INSTALLEXE) $(INSTALLEXEFILES) $(INSTALL_BINDIR)
+endif
+ifdef INSTALL_CREATEPACKAGEFPC
+ifdef FPCMAKE
+ifdef PACKAGE_VERSION
+ifneq ($(wildcard Makefile.fpc),)
+	$(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc
+	$(MKDIR) $(INSTALL_UNITDIR)
+	$(INSTALL) Package.fpc $(INSTALL_UNITDIR)
+endif
+endif
+endif
+endif
+ifdef INSTALLPPUFILES
+	$(MKDIR) $(INSTALL_UNITDIR)
+	$(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR)
+ifneq ($(INSTALLPPULINKFILES),)
+	$(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR)
+endif
+ifneq ($(wildcard $(LIB_FULLNAME)),)
+	$(MKDIR) $(INSTALL_LIBDIR)
+	$(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR)
+ifdef inUnix
+	ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME)
+endif
+endif
+endif
+ifdef INSTALL_FILES
+	$(MKDIR) $(INSTALL_DATADIR)
+	$(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADIR)
+endif
+fpc_sourceinstall: distclean
+	$(MKDIR) $(INSTALL_SOURCEDIR)
+	$(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR)
+fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
+ifdef HASEXAMPLES
+	$(MKDIR) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef EXAMPLESOURCEFILES
+	$(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef TARGET_EXAMPLEDIRS
+	$(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR)
+endif
+.PHONY: fpc_distinstall
+fpc_distinstall: install exampleinstall
+.PHONY: fpc_zipinstall fpc_zipsourceinstall fpc_zipexampleinstall
+ifndef PACKDIR
+ifndef inUnix
+PACKDIR=$(BASEDIR)/../fpc-pack
+else
+PACKDIR=/tmp/fpc-pack
+endif
+endif
+ifndef ZIPNAME
+ifdef DIST_ZIPNAME
+ZIPNAME=$(DIST_ZIPNAME)
+else
+ZIPNAME=$(PACKAGE_NAME)
+endif
+endif
+ifndef FULLZIPNAME
+FULLZIPNAME=$(ZIPCROSSPREFIX)$(ZIPPREFIX)$(ZIPNAME)$(ZIPSUFFIX)
+endif
+ifndef ZIPTARGET
+ifdef DIST_ZIPTARGET
+ZIPTARGET=DIST_ZIPTARGET
+else
+ZIPTARGET=install
+endif
+endif
+ifndef USEZIP
+ifdef inUnix
+USETAR=1
+endif
+endif
+ifndef inUnix
+USEZIPWRAPPER=1
+endif
+ifdef USEZIPWRAPPER
+ZIPPATHSEP=$(PATHSEP)
+ZIPWRAPPER=$(subst /,$(PATHSEP),$(DIST_DESTDIR)/fpczip$(SRCBATCHEXT))
+else
+ZIPPATHSEP=/
+endif
+ZIPCMD_CDPACK:=cd $(subst /,$(ZIPPATHSEP),$(PACKDIR))
+ZIPCMD_CDBASE:=cd $(subst /,$(ZIPPATHSEP),$(BASEDIR))
+ifdef USETAR
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(TAREXT)
+ZIPCMD_ZIP:=$(TARPROG) c$(TAROPT)f $(ZIPDESTFILE) *
+else
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(ZIPEXT)
+ZIPCMD_ZIP:=$(subst /,$(ZIPPATHSEP),$(ZIPPROG)) -Dr $(ZIPOPT) $(ZIPDESTFILE) *
+endif
+fpc_zipinstall:
+	$(MAKE) $(ZIPTARGET) INSTALL_PREFIX=$(PACKDIR) ZIPINSTALL=1
+	$(MKDIR) $(DIST_DESTDIR)
+	$(DEL) $(ZIPDESTFILE)
+ifdef USEZIPWRAPPER
+ifneq ($(ECHOREDIR),echo)
+	$(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDPACK))" > $(ZIPWRAPPER)
+	$(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_ZIP))" >> $(ZIPWRAPPER)
+	$(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDBASE))" >> $(ZIPWRAPPER)
+else
+	echo $(ZIPCMD_CDPACK) > $(ZIPWRAPPER)
+	echo $(ZIPCMD_ZIP) >> $(ZIPWRAPPER)
+	echo $(ZIPCMD_CDBASE) >> $(ZIPWRAPPER)
+endif
+ifdef inUnix
+	/bin/sh $(ZIPWRAPPER)
+else
+ifdef RUNBATCH
+	$(RUNBATCH) $(ZIPWRAPPER)
+else
+	$(ZIPWRAPPER)
+endif
+endif
+	$(DEL) $(ZIPWRAPPER)
+else
+	$(ZIPCMD_CDPACK) ; $(ZIPCMD_ZIP) ; $(ZIPCMD_CDBASE)
+endif
+	$(DELTREE) $(PACKDIR)
+fpc_zipsourceinstall:
+	$(MAKE) fpc_zipinstall ZIPTARGET=sourceinstall ZIPSUFFIX=$(ZIPSOURCESUFFIX)
+fpc_zipexampleinstall:
+ifdef HASEXAMPLES
+	$(MAKE) fpc_zipinstall ZIPTARGET=exampleinstall ZIPSUFFIX=$(ZIPEXAMPLESUFFIX)
+endif
+fpc_zipdistinstall:
+	$(MAKE) fpc_zipinstall ZIPTARGET=distinstall
 .PHONY: fpc_clean fpc_cleanall fpc_distclean
 .PHONY: fpc_clean fpc_cleanall fpc_distclean
 ifdef EXEFILES
 ifdef EXEFILES
 override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
 override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
 endif
 endif
+ifdef CLEAN_PROGRAMS
+override CLEANEXEFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEEXT), $(CLEAN_PROGRAMS)))
+endif
 ifdef CLEAN_UNITS
 ifdef CLEAN_UNITS
 override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
 override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
 endif
 endif
@@ -1613,6 +1786,9 @@ endif
 ifdef CLEANRSTFILES
 ifdef CLEANRSTFILES
 	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
 	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
 endif
 endif
+endif
+ifdef CLEAN_FILES
+	-$(DEL) $(CLEAN_FILES)
 endif
 endif
 	-$(DELTREE) units
 	-$(DELTREE) units
 	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
 	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
@@ -1941,6 +2117,11 @@ TARGET_DIRS_ANSI_CONSOLE=1
 TARGET_DIRS_PCXVIEW=1
 TARGET_DIRS_PCXVIEW=1
 TARGET_DIRS_SIMPLEBGSCROLL=1
 TARGET_DIRS_SIMPLEBGSCROLL=1
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+TARGET_DIRS_ANSI_CONSOLE=1
+TARGET_DIRS_PCXVIEW=1
+TARGET_DIRS_SIMPLEBGSCROLL=1
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 TARGET_DIRS_ANSI_CONSOLE=1
 TARGET_DIRS_ANSI_CONSOLE=1
 TARGET_DIRS_PCXVIEW=1
 TARGET_DIRS_PCXVIEW=1
@@ -2026,6 +2207,11 @@ TARGET_DIRS_ANSI_CONSOLE=1
 TARGET_DIRS_PCXVIEW=1
 TARGET_DIRS_PCXVIEW=1
 TARGET_DIRS_SIMPLEBGSCROLL=1
 TARGET_DIRS_SIMPLEBGSCROLL=1
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+TARGET_DIRS_ANSI_CONSOLE=1
+TARGET_DIRS_PCXVIEW=1
+TARGET_DIRS_SIMPLEBGSCROLL=1
+endif
 ifdef TARGET_DIRS_ANSI_CONSOLE
 ifdef TARGET_DIRS_ANSI_CONSOLE
 ansi_console_all:
 ansi_console_all:
 	$(MAKE) -C ansi_console all
 	$(MAKE) -C ansi_console all
@@ -2168,19 +2354,19 @@ release: $(addsuffix _release,$(TARGET_DIRS))
 units: $(addsuffix _units,$(TARGET_DIRS))
 units: $(addsuffix _units,$(TARGET_DIRS))
 examples: $(addsuffix _examples,$(TARGET_DIRS))
 examples: $(addsuffix _examples,$(TARGET_DIRS))
 shared: $(addsuffix _shared,$(TARGET_DIRS))
 shared: $(addsuffix _shared,$(TARGET_DIRS))
-install: $(addsuffix _install,$(TARGET_DIRS))
-sourceinstall: $(addsuffix _sourceinstall,$(TARGET_DIRS))
-exampleinstall: $(addsuffix _exampleinstall,$(TARGET_DIRS))
-distinstall: $(addsuffix _distinstall,$(TARGET_DIRS))
-zipinstall: $(addsuffix _zipinstall,$(TARGET_DIRS))
-zipsourceinstall: $(addsuffix _zipsourceinstall,$(TARGET_DIRS))
-zipexampleinstall: $(addsuffix _zipexampleinstall,$(TARGET_DIRS))
-zipdistinstall: $(addsuffix _zipdistinstall,$(TARGET_DIRS))
+install: fpc_install $(addsuffix _install,$(TARGET_DIRS))
+sourceinstall: fpc_sourceinstall
+exampleinstall: fpc_exampleinstall $(addsuffix _exampleinstall,$(TARGET_DIRS))
+distinstall: fpc_distinstall
+zipinstall: fpc_zipinstall
+zipsourceinstall: fpc_zipsourceinstall
+zipexampleinstall: fpc_zipexampleinstall $(addsuffix _zipexampleinstall,$(TARGET_DIRS))
+zipdistinstall: fpc_zipdistinstall
 clean: $(addsuffix _clean,$(TARGET_DIRS))
 clean: $(addsuffix _clean,$(TARGET_DIRS))
 distclean: $(addsuffix _distclean,$(TARGET_DIRS))
 distclean: $(addsuffix _distclean,$(TARGET_DIRS))
 cleanall: $(addsuffix _cleanall,$(TARGET_DIRS))
 cleanall: $(addsuffix _cleanall,$(TARGET_DIRS))
 info: fpc_info
 info: fpc_info
-makefiles: fpc_makefiles $(addsuffix _makefiles,$(TARGET_DIRS))
+makefiles: fpc_makefiles
 .PHONY: all debug smart release units examples shared install sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall clean distclean cleanall info makefiles
 .PHONY: all debug smart release units examples shared install sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall clean distclean cleanall info makefiles
 ifneq ($(wildcard fpcmake.loc),)
 ifneq ($(wildcard fpcmake.loc),)
 include fpcmake.loc
 include fpcmake.loc

+ 3 - 0
packages/libgbafpc/examples/graphics/Makefile.fpc

@@ -1,6 +1,9 @@
 #
 #
 #   Makefile.fpc for Free Pascal libgbafpc 2.x.y Examples
 #   Makefile.fpc for Free Pascal libgbafpc 2.x.y Examples
 #
 #
+[package]
+name=libgbafpc-graphics-examples
+version=2.4.0
 
 
 [target]
 [target]
 dirs=ansi_console PCXView SimpleBGScroll
 dirs=ansi_console PCXView SimpleBGScroll

+ 125 - 7
packages/libgbafpc/examples/template/Makefile

@@ -1,8 +1,8 @@
 #
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2009/12/31]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2010/11/23]
 #
 #
 default: all
 default: all
-MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
 BSDs = freebsd netbsd openbsd darwin
 BSDs = freebsd netbsd openbsd darwin
 UNIXs = linux $(BSDs) solaris qnx haiku
 UNIXs = linux $(BSDs) solaris qnx haiku
 LIMIT83fs = go32v2 os2 emx watcom
 LIMIT83fs = go32v2 os2 emx watcom
@@ -266,6 +266,8 @@ ifeq ($(UNITSDIR),)
 UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
 UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
 endif
 endif
 PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
 PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
+override PACKAGE_NAME=libgbafpc-template-examples
+override PACKAGE_VERSION=2.4.0
 BUILD = build
 BUILD = build
 INC = inc
 INC = inc
 AUDIO_FILES = $(foreach dir, $(notdir $(wildcard audio/*.*)), $(CURDIR)/audio/$(dir))
 AUDIO_FILES = $(foreach dir, $(notdir $(wildcard audio/*.*)), $(CURDIR)/audio/$(dir))
@@ -394,6 +396,9 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 override TARGET_PROGRAMS+=template
 override TARGET_PROGRAMS+=template
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override TARGET_PROGRAMS+=template
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 override TARGET_PROGRAMS+=template
 override TARGET_PROGRAMS+=template
 endif
 endif
@@ -445,6 +450,9 @@ endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
 override TARGET_PROGRAMS+=template
 override TARGET_PROGRAMS+=template
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override TARGET_PROGRAMS+=template
+endif
 ifeq ($(FULL_TARGET),i386-linux)
 ifeq ($(FULL_TARGET),i386-linux)
 override CLEAN_UNITS+=*
 override CLEAN_UNITS+=*
 endif
 endif
@@ -568,6 +576,9 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 override CLEAN_UNITS+=*
 override CLEAN_UNITS+=*
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override CLEAN_UNITS+=*
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 override CLEAN_UNITS+=*
 override CLEAN_UNITS+=*
 endif
 endif
@@ -619,6 +630,9 @@ endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
 override CLEAN_UNITS+=*
 override CLEAN_UNITS+=*
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override CLEAN_UNITS+=*
+endif
 ifeq ($(FULL_TARGET),i386-linux)
 ifeq ($(FULL_TARGET),i386-linux)
 override CLEAN_FILES+=*.elf *.o *.s *.gba *.h *.bin *.map $(BUILD)/* $(INC)/*
 override CLEAN_FILES+=*.elf *.o *.s *.gba *.h *.bin *.map $(BUILD)/* $(INC)/*
 endif
 endif
@@ -742,6 +756,9 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 override CLEAN_FILES+=*.elf *.o *.s *.gba *.h *.bin *.map $(BUILD)/* $(INC)/*
 override CLEAN_FILES+=*.elf *.o *.s *.gba *.h *.bin *.map $(BUILD)/* $(INC)/*
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override CLEAN_FILES+=*.elf *.o *.s *.gba *.h *.bin *.map $(BUILD)/* $(INC)/*
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 override CLEAN_FILES+=*.elf *.o *.s *.gba *.h *.bin *.map $(BUILD)/* $(INC)/*
 override CLEAN_FILES+=*.elf *.o *.s *.gba *.h *.bin *.map $(BUILD)/* $(INC)/*
 endif
 endif
@@ -793,6 +810,9 @@ endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
 override CLEAN_FILES+=*.elf *.o *.s *.gba *.h *.bin *.map $(BUILD)/* $(INC)/*
 override CLEAN_FILES+=*.elf *.o *.s *.gba *.h *.bin *.map $(BUILD)/* $(INC)/*
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override CLEAN_FILES+=*.elf *.o *.s *.gba *.h *.bin *.map $(BUILD)/* $(INC)/*
+endif
 override INSTALL_FPCPACKAGE=y
 override INSTALL_FPCPACKAGE=y
 ifdef REQUIRE_UNITSDIR
 ifdef REQUIRE_UNITSDIR
 override UNITSDIR+=$(REQUIRE_UNITSDIR)
 override UNITSDIR+=$(REQUIRE_UNITSDIR)
@@ -1684,6 +1704,9 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 REQUIRE_PACKAGES_LIBGBAFPC=1
 REQUIRE_PACKAGES_LIBGBAFPC=1
 endif
 endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+REQUIRE_PACKAGES_LIBGBAFPC=1
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 ifeq ($(FULL_TARGET),x86_64-darwin)
 REQUIRE_PACKAGES_LIBGBAFPC=1
 REQUIRE_PACKAGES_LIBGBAFPC=1
 endif
 endif
@@ -1735,6 +1758,9 @@ endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 ifeq ($(FULL_TARGET),armeb-embedded)
 REQUIRE_PACKAGES_LIBGBAFPC=1
 REQUIRE_PACKAGES_LIBGBAFPC=1
 endif
 endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+REQUIRE_PACKAGES_LIBGBAFPC=1
+endif
 ifdef REQUIRE_PACKAGES_LIBGBAFPC
 ifdef REQUIRE_PACKAGES_LIBGBAFPC
 PACKAGEDIR_LIBGBAFPC:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /libgbafpc/Makefile.fpc,$(PACKAGESDIR))))))
 PACKAGEDIR_LIBGBAFPC:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /libgbafpc/Makefile.fpc,$(PACKAGESDIR))))))
 ifneq ($(PACKAGEDIR_LIBGBAFPC),)
 ifneq ($(PACKAGEDIR_LIBGBAFPC),)
@@ -2079,10 +2105,99 @@ endif
 ifdef TARGET_EXAMPLEDIRS
 ifdef TARGET_EXAMPLEDIRS
 	$(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR)
 	$(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR)
 endif
 endif
+.PHONY: fpc_distinstall
+fpc_distinstall: install exampleinstall
+.PHONY: fpc_zipinstall fpc_zipsourceinstall fpc_zipexampleinstall
+ifndef PACKDIR
+ifndef inUnix
+PACKDIR=$(BASEDIR)/../fpc-pack
+else
+PACKDIR=/tmp/fpc-pack
+endif
+endif
+ifndef ZIPNAME
+ifdef DIST_ZIPNAME
+ZIPNAME=$(DIST_ZIPNAME)
+else
+ZIPNAME=$(PACKAGE_NAME)
+endif
+endif
+ifndef FULLZIPNAME
+FULLZIPNAME=$(ZIPCROSSPREFIX)$(ZIPPREFIX)$(ZIPNAME)$(ZIPSUFFIX)
+endif
+ifndef ZIPTARGET
+ifdef DIST_ZIPTARGET
+ZIPTARGET=DIST_ZIPTARGET
+else
+ZIPTARGET=install
+endif
+endif
+ifndef USEZIP
+ifdef inUnix
+USETAR=1
+endif
+endif
+ifndef inUnix
+USEZIPWRAPPER=1
+endif
+ifdef USEZIPWRAPPER
+ZIPPATHSEP=$(PATHSEP)
+ZIPWRAPPER=$(subst /,$(PATHSEP),$(DIST_DESTDIR)/fpczip$(SRCBATCHEXT))
+else
+ZIPPATHSEP=/
+endif
+ZIPCMD_CDPACK:=cd $(subst /,$(ZIPPATHSEP),$(PACKDIR))
+ZIPCMD_CDBASE:=cd $(subst /,$(ZIPPATHSEP),$(BASEDIR))
+ifdef USETAR
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(TAREXT)
+ZIPCMD_ZIP:=$(TARPROG) c$(TAROPT)f $(ZIPDESTFILE) *
+else
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(ZIPEXT)
+ZIPCMD_ZIP:=$(subst /,$(ZIPPATHSEP),$(ZIPPROG)) -Dr $(ZIPOPT) $(ZIPDESTFILE) *
+endif
+fpc_zipinstall:
+	$(MAKE) $(ZIPTARGET) INSTALL_PREFIX=$(PACKDIR) ZIPINSTALL=1
+	$(MKDIR) $(DIST_DESTDIR)
+	$(DEL) $(ZIPDESTFILE)
+ifdef USEZIPWRAPPER
+ifneq ($(ECHOREDIR),echo)
+	$(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDPACK))" > $(ZIPWRAPPER)
+	$(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_ZIP))" >> $(ZIPWRAPPER)
+	$(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDBASE))" >> $(ZIPWRAPPER)
+else
+	echo $(ZIPCMD_CDPACK) > $(ZIPWRAPPER)
+	echo $(ZIPCMD_ZIP) >> $(ZIPWRAPPER)
+	echo $(ZIPCMD_CDBASE) >> $(ZIPWRAPPER)
+endif
+ifdef inUnix
+	/bin/sh $(ZIPWRAPPER)
+else
+ifdef RUNBATCH
+	$(RUNBATCH) $(ZIPWRAPPER)
+else
+	$(ZIPWRAPPER)
+endif
+endif
+	$(DEL) $(ZIPWRAPPER)
+else
+	$(ZIPCMD_CDPACK) ; $(ZIPCMD_ZIP) ; $(ZIPCMD_CDBASE)
+endif
+	$(DELTREE) $(PACKDIR)
+fpc_zipsourceinstall:
+	$(MAKE) fpc_zipinstall ZIPTARGET=sourceinstall ZIPSUFFIX=$(ZIPSOURCESUFFIX)
+fpc_zipexampleinstall:
+ifdef HASEXAMPLES
+	$(MAKE) fpc_zipinstall ZIPTARGET=exampleinstall ZIPSUFFIX=$(ZIPEXAMPLESUFFIX)
+endif
+fpc_zipdistinstall:
+	$(MAKE) fpc_zipinstall ZIPTARGET=distinstall
 .PHONY: fpc_clean fpc_cleanall fpc_distclean
 .PHONY: fpc_clean fpc_cleanall fpc_distclean
 ifdef EXEFILES
 ifdef EXEFILES
 override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
 override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
 endif
 endif
+ifdef CLEAN_PROGRAMS
+override CLEANEXEFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEEXT), $(CLEAN_PROGRAMS)))
+endif
 ifdef CLEAN_UNITS
 ifdef CLEAN_UNITS
 override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
 override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
 endif
 endif
@@ -2129,6 +2244,9 @@ endif
 ifdef CLEANRSTFILES
 ifdef CLEANRSTFILES
 	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
 	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
 endif
 endif
+endif
+ifdef CLEAN_FILES
+	-$(DEL) $(CLEAN_FILES)
 endif
 endif
 	-$(DELTREE) units
 	-$(DELTREE) units
 	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
 	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
@@ -2297,11 +2415,11 @@ shared: fpc_shared
 install: fpc_install
 install: fpc_install
 sourceinstall: fpc_sourceinstall
 sourceinstall: fpc_sourceinstall
 exampleinstall: fpc_exampleinstall
 exampleinstall: fpc_exampleinstall
-distinstall:
-zipinstall:
-zipsourceinstall:
-zipexampleinstall:
-zipdistinstall:
+distinstall: fpc_distinstall
+zipinstall: fpc_zipinstall
+zipsourceinstall: fpc_zipsourceinstall
+zipexampleinstall: fpc_zipexampleinstall
+zipdistinstall: fpc_zipdistinstall
 distclean: fpc_distclean
 distclean: fpc_distclean
 cleanall: fpc_cleanall
 cleanall: fpc_cleanall
 info: fpc_info
 info: fpc_info

+ 3 - 0
packages/libgbafpc/examples/template/Makefile.fpc

@@ -1,6 +1,9 @@
 #
 #
 #   Makefile.fpc for Free Pascal libgbafpc 2.x.y Examples
 #   Makefile.fpc for Free Pascal libgbafpc 2.x.y Examples
 #
 #
+[package]
+name=libgbafpc-template-examples
+version=2.4.0
 
 
 [target]
 [target]
 loaders=
 loaders=

File diff suppressed because it is too large
+ 318 - 93
packages/openssl/src/openssl.pas


+ 3 - 0
packages/winunits-base/fpmake.pp

@@ -25,6 +25,9 @@ begin
     P.Description := 'Base Delphi compatible windows headers units outside the RTL';
     P.Description := 'Base Delphi compatible windows headers units outside the RTL';
     P.NeedLibC:= true;
     P.NeedLibC:= true;
 
 
+    P.Dependencies.Add('fcl-registry');
+    P.Dependencies.Add('fcl-base');
+
     P.SourcePath.Add('src');
     P.SourcePath.Add('src');
     P.IncludePath.Add('src');
     P.IncludePath.Add('src');
 
 

+ 81 - 0
rtl/i386/i386.inc

@@ -634,6 +634,15 @@ end;
 function fpc_shortstr_to_shortstr(len:longint; const sstr: shortstring): shortstring; [public,alias: 'FPC_SHORTSTR_TO_SHORTSTR']; compilerproc;
 function fpc_shortstr_to_shortstr(len:longint; const sstr: shortstring): shortstring; [public,alias: 'FPC_SHORTSTR_TO_SHORTSTR']; compilerproc;
 begin
 begin
   asm
   asm
+  {$ifdef FPC_PROFILE}
+        push  %eax
+        push  %edx
+        push  %ecx
+        call  mcount
+        pop   %ecx
+        pop   %edx
+        pop   %eax
+  {$endif FPC_PROFILE}
         cld
         cld
         movl    __RESULT,%edi
         movl    __RESULT,%edi
         movl    sstr,%esi
         movl    sstr,%esi
@@ -671,6 +680,15 @@ procedure fpc_shortstr_to_shortstr(out res:shortstring; const sstr: shortstring)
   var
   var
    saveesi,saveedi : longint;
    saveesi,saveedi : longint;
   asm
   asm
+  {$ifdef FPC_PROFILE}
+        push  %eax
+        push  %edx
+        push  %ecx
+        call  mcount
+        pop   %ecx
+        pop   %edx
+        pop   %eax
+  {$endif FPC_PROFILE}
         movl    %edi,saveedi
         movl    %edi,saveedi
         movl    %esi,saveesi
         movl    %esi,saveesi
         cld
         cld
@@ -714,6 +732,15 @@ procedure fpc_shortstr_to_shortstr(out res:shortstring; const sstr: shortstring)
 procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN'];
 procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN'];
 begin
 begin
   asm
   asm
+  {$ifdef FPC_PROFILE}
+        push  %eax
+        push  %edx
+        push  %ecx
+        call  mcount
+        pop   %ecx
+        pop   %edx
+        pop   %eax
+  {$endif FPC_PROFILE}
         pushl   %eax
         pushl   %eax
         pushl   %ecx
         pushl   %ecx
         cld
         cld
@@ -759,6 +786,15 @@ end;
 function fpc_shortstr_concat(const s1,s2:shortstring):shortstring;compilerproc;
 function fpc_shortstr_concat(const s1,s2:shortstring):shortstring;compilerproc;
 begin
 begin
   asm
   asm
+  {$ifdef FPC_PROFILE}
+        push  %eax
+        push  %edx
+        push  %ecx
+        call  mcount
+        pop   %ecx
+        pop   %edx
+        pop   %eax
+  {$endif FPC_PROFILE}
         movl    __RESULT,%edi
         movl    __RESULT,%edi
         movl    %edi,%ebx
         movl    %edi,%ebx
         movl    s1,%esi         { first string }
         movl    s1,%esi         { first string }
@@ -821,6 +857,15 @@ procedure fpc_shortstr_append_shortstr(var s1:shortstring;const s2:shortstring);
     [public,alias:'FPC_SHORTSTR_APPEND_SHORTSTR'];
     [public,alias:'FPC_SHORTSTR_APPEND_SHORTSTR'];
 begin
 begin
   asm
   asm
+  {$ifdef FPC_PROFILE}
+        push  %eax
+        push  %edx
+        push  %ecx
+        call  mcount
+        pop   %ecx
+        pop   %edx
+        pop   %eax
+  {$endif FPC_PROFILE}
         movl    s1,%edi
         movl    s1,%edi
         movl    s2,%esi
         movl    s2,%esi
         movl    %edi,%ebx
         movl    %edi,%ebx
@@ -866,6 +911,15 @@ function fpc_shortstr_compare(const left,right:shortstring): longint;assembler;
 var
 var
   saveesi,saveedi,saveebx : longint;
   saveesi,saveedi,saveebx : longint;
 asm
 asm
+{$ifdef FPC_PROFILE}
+        push  %eax
+        push  %edx
+        push  %ecx
+        call  mcount
+        pop   %ecx
+        pop   %edx
+        pop   %eax
+{$endif FPC_PROFILE}
         movl    %edi,saveedi
         movl    %edi,saveedi
         movl    %esi,saveesi
         movl    %esi,saveesi
         movl    %ebx,saveebx
         movl    %ebx,saveebx
@@ -930,6 +984,15 @@ procedure fpc_pchar_to_shortstr(out res : shortstring;p:pchar);assembler;[public
 var
 var
   saveres,saveebx,saveesi,saveedi : longint;
   saveres,saveebx,saveesi,saveedi : longint;
 asm
 asm
+{$ifdef FPC_PROFILE}
+        push  %eax
+        push  %edx
+        push  %ecx
+        call  mcount
+        pop   %ecx
+        pop   %edx
+        pop   %eax
+{$endif FPC_PROFILE}
         movl    %ebx,saveebx
         movl    %ebx,saveebx
         movl    %esi,saveesi
         movl    %esi,saveesi
         movl    %edi,saveedi
         movl    %edi,saveedi
@@ -1031,6 +1094,15 @@ function fpc_pchar_length(p:pchar):longint;assembler;[public,alias:'FPC_PCHAR_LE
 var
 var
   saveedi : longint;
   saveedi : longint;
 asm
 asm
+{$ifdef FPC_PROFILE}
+        push  %eax
+        push  %edx
+        push  %ecx
+        call  mcount
+        pop   %ecx
+        pop   %edx
+        pop   %eax
+{$endif FPC_PROFILE}
         movl    %edi,saveedi
         movl    %edi,saveedi
 {$ifdef REGCALL}
 {$ifdef REGCALL}
         movl    %eax,%edi
         movl    %eax,%edi
@@ -1123,6 +1195,15 @@ const digits:array[0..9] of cardinal=(0,10,100,1000,10000,
                                       100000000,1000000000);
                                       100000000,1000000000);
 
 
 asm
 asm
+{$ifdef FPC_PROFILE}
+  push  %eax
+  push  %edx
+  push  %ecx
+  call  mcount
+  pop   %ecx
+  pop   %edx
+  pop   %eax
+{$endif FPC_PROFILE}
   push %esi
   push %esi
   push %edi
   push %edi
   push %ebx
   push %ebx

+ 1 - 0
rtl/inc/matrix.pp

@@ -30,6 +30,7 @@ unit matrix;
 interface
 interface
 
 
 {*****************************************************************************}
 {*****************************************************************************}
+{$mode fpc}
 
 
 {$ifndef FPUNONE}
 {$ifndef FPUNONE}
 {$MACRO on}
 {$MACRO on}

+ 4 - 1
rtl/inc/variants.pp

@@ -2804,7 +2804,10 @@ begin
   I:=Low(AVarTypes);
   I:=Low(AVarTypes);
   Result:=False;
   Result:=False;
   While Not Result and (I<=High(AVarTypes)) do
   While Not Result and (I<=High(AVarTypes)) do
-    Result:=((TVarData(V).vType and varTypeMask)=AVarTypes[I]);
+    begin
+      Result:=((TVarData(V).vType and varTypeMask)=AVarTypes[I]);
+      inc(i);
+    end;
 end;
 end;
 
 
 
 

+ 1 - 1
rtl/linux/i386/si_dll.inc

@@ -11,6 +11,7 @@
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 
  **********************************************************************}
  **********************************************************************}
+{$asmmode att}
 {$goto on}
 {$goto on}
 {
 {
  Linux ELF startup code for Free Pascal
  Linux ELF startup code for Free Pascal
@@ -44,7 +45,6 @@ end;
 {******************************************************************************
 {******************************************************************************
                         Shared library start/halt
                         Shared library start/halt
  ******************************************************************************}
  ******************************************************************************}
-{$asmmode ATT}
 
 
 procedure _FPC_shared_lib_start(argc : dword;argv,envp : pointer); cdecl; public name 'FPC_SHARED_LIB_START'; public name '_start';
 procedure _FPC_shared_lib_start(argc : dword;argv,envp : pointer); cdecl; public name 'FPC_SHARED_LIB_START'; public name '_start';
 begin
 begin

+ 1 - 1
rtl/linux/i386/si_prc.inc

@@ -11,6 +11,7 @@
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 
  **********************************************************************}
  **********************************************************************}
+{$asmmode att}
 
 
 {
 {
  Linux ELF startup code for Free Pascal
  Linux ELF startup code for Free Pascal
@@ -44,7 +45,6 @@ end;
 {******************************************************************************
 {******************************************************************************
                           Process start/halt
                           Process start/halt
  ******************************************************************************}
  ******************************************************************************}
-{$asmmode att}
 
 
 var
 var
   dlexitproc: pointer;
   dlexitproc: pointer;

+ 61 - 0
rtl/linux/i386/syscall.inc

@@ -77,9 +77,18 @@ end;
 
 
 Procedure fpc_geteipasebx;[external name 'fpc_geteipasebx'];
 Procedure fpc_geteipasebx;[external name 'fpc_geteipasebx'];
 
 
+{$ifdef FPC_PROFILE}
+procedure mcount; external name 'mcount';
+{$endif FPC_PROFILE}
+
 function FpSysCall(sysnr:TSysParam):TSysResult; assembler; register;  [public,alias:'FPC_SYSCALL0'];
 function FpSysCall(sysnr:TSysParam):TSysResult; assembler; register;  [public,alias:'FPC_SYSCALL0'];
 { Var sysnr located in register eax }
 { Var sysnr located in register eax }
 asm
 asm
+  {$ifdef FPC_PROFILE}
+        push  %eax
+        call  mcount
+        pop   %eax
+ {$endif FPC_PROFILE}
         push  %ebx
         push  %ebx
         push  %ecx
         push  %ecx
   {$ifdef FPC_PIC}
   {$ifdef FPC_PIC}
@@ -118,6 +127,13 @@ function FpSysCall(sysnr,param1 : TSysParam):TSysResult; assembler; register; [p
 { Var sysnr located in register eax
 { Var sysnr located in register eax
   Var param1 located in register edx }
   Var param1 located in register edx }
 asm
 asm
+  {$ifdef FPC_PROFILE}
+        push  %eax
+        push  %edx
+        call  mcount
+        pop   %edx
+        pop   %eax
+  {$endif FPC_PROFILE}
         push  %ebx
         push  %ebx
         push  %ecx
         push  %ecx
   {$ifdef FPC_PIC}
   {$ifdef FPC_PIC}
@@ -160,6 +176,15 @@ function FpSysCall(sysnr,param1,param2 : TSysParam):TSysResult; assembler; regis
   Var param1 located in register edx
   Var param1 located in register edx
   Var param2 located in register ecx }
   Var param2 located in register ecx }
 asm
 asm
+  {$ifdef FPC_PROFILE}
+        push  %eax
+        push  %edx
+        push  %ecx
+        call  mcount
+        pop   %ecx
+        pop   %edx
+        pop   %eax
+  {$endif FPC_PROFILE}
         push  %ebx
         push  %ebx
         push  %edx
         push  %edx
         push  %ecx
         push  %ecx
@@ -208,6 +233,15 @@ function FpSysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; assembler;
 var
 var
   _psysinfo: LongWord;
   _psysinfo: LongWord;
 asm
 asm
+  {$ifdef FPC_PROFILE}
+        push  %eax
+        push  %edx
+        push  %ecx
+        call  mcount
+        pop   %ecx
+        pop   %edx
+        pop   %eax
+  {$endif FPC_PROFILE}
         push  %ebx
         push  %ebx
         push  %edx
         push  %edx
         push  %ecx
         push  %ecx
@@ -261,6 +295,15 @@ function FpSysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; asse
 var
 var
   _psysinfo: LongWord;
   _psysinfo: LongWord;
 asm
 asm
+  {$ifdef FPC_PROFILE}
+        push  %eax
+        push  %edx
+        push  %ecx
+        call  mcount
+        pop   %ecx
+        pop   %edx
+        pop   %eax
+  {$endif FPC_PROFILE}
         push  %ebx
         push  %ebx
         push  %esi
         push  %esi
         push  %ecx
         push  %ecx
@@ -318,6 +361,15 @@ function FpSysCall(sysnr,param1,param2,param3,param4,param5 : TSysParam):TSysRes
 var
 var
   _psysinfo: LongWord;
   _psysinfo: LongWord;
 asm
 asm
+  {$ifdef FPC_PROFILE}
+        push  %eax
+        push  %edx
+        push  %ecx
+        call  mcount
+        pop   %ecx
+        pop   %edx
+        pop   %eax
+  {$endif FPC_PROFILE}
         push  %ebx
         push  %ebx
         push  %edx
         push  %edx
         push  %esi
         push  %esi
@@ -383,6 +435,15 @@ function FpSysCall(sysnr,param1,param2,param3,param4,param5,param6: TSysParam):T
 var
 var
   _psysinfo: LongWord;
   _psysinfo: LongWord;
 asm
 asm
+  {$ifdef FPC_PROFILE}
+        push  %eax
+        push  %edx
+        push  %ecx
+        call  mcount
+        pop   %ecx
+        pop   %edx
+        pop   %eax
+  {$endif FPC_PROFILE}
         push  %ebx
         push  %ebx
 	push  %edx
 	push  %edx
         push  %esi
         push  %esi

+ 82 - 0
rtl/linux/x86_64/syscall.inc

@@ -17,9 +17,18 @@
 
 
 {$ASMMODE GAS}
 {$ASMMODE GAS}
 
 
+{$ifdef FPC_PROFILE}
+procedure mcount; external name 'mcount';
+{$endif FPC_PROFILE}
+
 function FpSysCall(sysnr:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL0'];
 function FpSysCall(sysnr:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL0'];
 
 
 asm
 asm
+{$ifdef FPC_PROFILE}
+  pushq sysnr
+  call mcount
+  popq sysnr
+{$endif FPC_PROFILE}
   movq sysnr, %rax        { Syscall number -> rax.  }
   movq sysnr, %rax        { Syscall number -> rax.  }
   syscall                 { Do the system call. }
   syscall                 { Do the system call. }
   cmpq $-4095, %rax       { Check %rax for error.  }
   cmpq $-4095, %rax       { Check %rax for error.  }
@@ -52,6 +61,13 @@ end;
 function FpSysCall(sysnr,param1 : TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL1'];
 function FpSysCall(sysnr,param1 : TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL1'];
 
 
 asm
 asm
+{$ifdef FPC_PROFILE}
+  pushq sysnr
+  pushq param1
+  call mcount
+  popq param1
+  popq sysnr
+{$endif FPC_PROFILE}
   movq sysnr, %rax        { Syscall number -> rax.  }
   movq sysnr, %rax        { Syscall number -> rax.  }
   movq param1, %rdi         { shift arg1 - arg5. }
   movq param1, %rdi         { shift arg1 - arg5. }
   syscall                 { Do the system call. }
   syscall                 { Do the system call. }
@@ -85,6 +101,15 @@ end;
 function FpSysCall(sysnr,param1,param2 : TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL2'];
 function FpSysCall(sysnr,param1,param2 : TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL2'];
 
 
 asm
 asm
+{$ifdef FPC_PROFILE}
+  pushq sysnr
+  pushq param1
+  pushq param2
+  call mcount
+  popq param2
+  popq param1
+  popq sysnr
+{$endif FPC_PROFILE}
   movq sysnr, %rax        { Syscall number -> rax.  }
   movq sysnr, %rax        { Syscall number -> rax.  }
   movq param1, %rdi         { shift arg1 - arg5. }
   movq param1, %rdi         { shift arg1 - arg5. }
   movq param2, %rsi
   movq param2, %rsi
@@ -119,6 +144,17 @@ end;
 function FpSysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL3'];
 function FpSysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL3'];
 
 
 asm
 asm
+{$ifdef FPC_PROFILE}
+  pushq sysnr
+  pushq param1
+  pushq param2
+  pushq param3
+  call mcount
+  popq param3
+  popq param2
+  popq param1
+  popq sysnr
+{$endif FPC_PROFILE}
   movq sysnr, %rax        { Syscall number -> rax.  }
   movq sysnr, %rax        { Syscall number -> rax.  }
   movq param1, %rdi         { shift arg1 - arg5. }
   movq param1, %rdi         { shift arg1 - arg5. }
   movq param2, %rsi
   movq param2, %rsi
@@ -154,6 +190,19 @@ end;
 function FpSysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL4'];
 function FpSysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL4'];
 
 
 asm
 asm
+{$ifdef FPC_PROFILE}
+  pushq sysnr
+  pushq param1
+  pushq param2
+  pushq param3
+  pushq param4
+  call mcount
+  popq param4
+  popq param3
+  popq param2
+  popq param1
+  popq sysnr
+{$endif FPC_PROFILE}
   movq sysnr, %rax        { Syscall number -> rax.  }
   movq sysnr, %rax        { Syscall number -> rax.  }
   movq param1, %rdi         { shift arg1 - arg5. }
   movq param1, %rdi         { shift arg1 - arg5. }
   movq param2, %rsi
   movq param2, %rsi
@@ -190,6 +239,21 @@ end;
 function FpSysCall(sysnr,param1,param2,param3,param4,param5 : TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL5'];
 function FpSysCall(sysnr,param1,param2,param3,param4,param5 : TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL5'];
 
 
 asm
 asm
+{$ifdef FPC_PROFILE}
+  pushq sysnr
+  pushq param1
+  pushq param2
+  pushq param3
+  pushq param4
+  pushq param5
+  call mcount
+  popq param5
+  popq param4
+  popq param3
+  popq param2
+  popq param1
+  popq sysnr
+{$endif FPC_PROFILE}
   movq sysnr, %rax        { Syscall number -> rax.  }
   movq sysnr, %rax        { Syscall number -> rax.  }
   movq param1, %rdi         { shift arg1 - arg5. }
   movq param1, %rdi         { shift arg1 - arg5. }
   movq param2, %rsi
   movq param2, %rsi
@@ -228,6 +292,23 @@ end;
 function FpSysCall(sysnr,param1,param2,param3,param4,param5,param6 : TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL6'];
 function FpSysCall(sysnr,param1,param2,param3,param4,param5,param6 : TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL6'];
 
 
 asm
 asm
+{$ifdef FPC_PROFILE}
+  pushq sysnr
+  pushq param1
+  pushq param2
+  pushq param3
+  pushq param4
+  pushq param5
+  pushq param6
+  call mcount
+  popq param6
+  popq param5
+  popq param4
+  popq param3
+  popq param2
+  popq param1
+  popq sysnr
+{$endif FPC_PROFILE}
   movq sysnr, %rax        { Syscall number -> rax.  }
   movq sysnr, %rax        { Syscall number -> rax.  }
   movq param1, %rdi         { shift arg1 - arg5. }
   movq param1, %rdi         { shift arg1 - arg5. }
   movq param2, %rsi
   movq param2, %rsi
@@ -268,3 +349,4 @@ end;
 {$IFDEF SYS_LINUX}
 {$IFDEF SYS_LINUX}
   {$UNDEF SYSCALL_DEBUG}
   {$UNDEF SYSCALL_DEBUG}
 {$ENDIF SYS_LINUX}
 {$ENDIF SYS_LINUX}
+

+ 4 - 0
rtl/objpas/classes/classesh.inc

@@ -666,6 +666,7 @@ type
     FDuplicates: TDuplicates;
     FDuplicates: TDuplicates;
     FCaseSensitive : Boolean;
     FCaseSensitive : Boolean;
     FSorted: Boolean;
     FSorted: Boolean;
+    FOwnsObjects : Boolean;
     procedure ExchangeItems(Index1, Index2: Integer);
     procedure ExchangeItems(Index1, Index2: Integer);
     procedure Grow;
     procedure Grow;
     procedure QuickSort(L, R: Integer; CompareFn: TStringListSortCompare);
     procedure QuickSort(L, R: Integer; CompareFn: TStringListSortCompare);
@@ -702,6 +703,7 @@ type
     property CaseSensitive: Boolean read FCaseSensitive write SetCaseSensitive;
     property CaseSensitive: Boolean read FCaseSensitive write SetCaseSensitive;
     property OnChange: TNotifyEvent read FOnChange write FOnChange;
     property OnChange: TNotifyEvent read FOnChange write FOnChange;
     property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
     property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
+    property OwnsObjects : boolean read FOwnsObjects write FOwnsObjects;
   end;
   end;
 
 
 {$else}
 {$else}
@@ -717,6 +719,7 @@ type
     FOnChange: TNotifyEvent;
     FOnChange: TNotifyEvent;
     FOnChanging: TNotifyEvent;
     FOnChanging: TNotifyEvent;
     FOnCompareText: TStringListTextCompare;
     FOnCompareText: TStringListTextCompare;
+    FOwnsObjects : Boolean;
     procedure SetCaseSensitive(NewSensitive: Boolean);
     procedure SetCaseSensitive(NewSensitive: Boolean);
   protected
   protected
     procedure Changed; virtual;
     procedure Changed; virtual;
@@ -755,6 +758,7 @@ type
     property OnChange: TNotifyEvent read FOnChange write FOnChange;
     property OnChange: TNotifyEvent read FOnChange write FOnChange;
     property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
     property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
     property OnCompareText: TStringListTextCompare read FOnCompareText write FOnCompareText;
     property OnCompareText: TStringListTextCompare read FOnCompareText write FOnCompareText;
+    property OwnsObjects : boolean read FOwnsObjects write FOwnsObjects;
   end;
   end;
 
 
 {$endif}
 {$endif}

+ 16 - 6
rtl/objpas/classes/stringl.inc

@@ -1156,8 +1156,6 @@ begin
    InsertItem (Result,S);
    InsertItem (Result,S);
 end;
 end;
 
 
-
-
 Procedure TStringList.Clear;
 Procedure TStringList.Clear;
 
 
 Var I : longint;
 Var I : longint;
@@ -1165,15 +1163,24 @@ Var I : longint;
 begin
 begin
   if FCount = 0 then Exit;
   if FCount = 0 then Exit;
   Changing;
   Changing;
-  For I:=0 to FCount-1 do
-    Flist^[I].FString:='';
+  if FOwnsObjects then
+    begin
+      For I:=0 to FCount-1 do
+        begin
+          Flist^[I].FString:='';
+          freeandnil(Flist^[i].FObject);
+        end;
+    end
+  else
+    begin
+      For I:=0 to FCount-1 do
+        Flist^[I].FString:='';
+    end;
   FCount:=0;
   FCount:=0;
   SetCapacity(0);
   SetCapacity(0);
   Changed;
   Changed;
 end;
 end;
 
 
-
-
 Procedure TStringList.Delete(Index: Integer);
 Procedure TStringList.Delete(Index: Integer);
 
 
 begin
 begin
@@ -1181,6 +1188,8 @@ begin
     Error(SlistINdexError,Index);
     Error(SlistINdexError,Index);
   Changing;
   Changing;
   Flist^[Index].FString:='';
   Flist^[Index].FString:='';
+  if FOwnsObjects then
+    FreeAndNil(Flist^[Index].FObject);
   Dec(FCount);
   Dec(FCount);
   If Index<FCount then
   If Index<FCount then
     System.Move(Flist^[Index+1],
     System.Move(Flist^[Index+1],
@@ -1316,6 +1325,7 @@ end;
 constructor TStringList.Create;
 constructor TStringList.Create;
 begin
 begin
   inherited;
   inherited;
+  FOwnsObjects:=false;
   FMap := TFPStrObjMap.Create;
   FMap := TFPStrObjMap.Create;
   FMap.OnPtrCompare := @MapPtrCompare;
   FMap.OnPtrCompare := @MapPtrCompare;
   FOnCompareText := @DefaultCompareText;
   FOnCompareText := @DefaultCompareText;

+ 41 - 1
rtl/objpas/sysutils/sysstr.inc

@@ -753,6 +753,8 @@ const
 function IntToHex(Value: integer; Digits: integer): string;
 function IntToHex(Value: integer; Digits: integer): string;
 var i: integer;
 var i: integer;
 begin
 begin
+ If Digits=0 then 
+   Digits:=1;
  SetLength(result, digits);
  SetLength(result, digits);
  for i := 0 to digits - 1 do
  for i := 0 to digits - 1 do
   begin
   begin
@@ -768,6 +770,8 @@ end ;
 function IntToHex(Value: int64; Digits: integer): string;
 function IntToHex(Value: int64; Digits: integer): string;
 var i: integer;
 var i: integer;
 begin
 begin
+ If Digits=0 then 
+   Digits:=1;
  SetLength(result, digits);
  SetLength(result, digits);
  for i := 0 to digits - 1 do
  for i := 0 to digits - 1 do
   begin
   begin
@@ -1162,6 +1166,32 @@ Var
   Negative, TooSmall, TooLarge: Boolean;
   Negative, TooSmall, TooLarge: Boolean;
   DS: Char;
   DS: Char;
 
 
+  function RemoveLeadingNegativeSign(var AValue: String): Boolean;
+  // removes negative sign in case when result is zero eg. -0.00
+  var
+    i: PtrInt;
+    S: String;
+    TS: Char;
+    B: Boolean;
+    StartPos: PtrInt;
+  begin
+    Result := False;
+    if Format = ffCurrency then
+      StartPos := 1
+    else
+      StartPos := 2;
+    TS := FormatSettings.ThousandSeparator;
+    S := '';
+    for i := StartPos to length(AValue) do
+    begin
+      Result := (AValue[i] in ['0', DS, 'E', '+', TS]);
+      if not Result then
+        break;
+    end;
+    if (Result) and (Format <> ffCurrency) then
+      Delete(AValue, 1, 1);
+  end;
+
 Begin
 Begin
   DS:=FormatSettings.DecimalSeparator;
   DS:=FormatSettings.DecimalSeparator;
   Case format Of
   Case format Of
@@ -1387,6 +1417,9 @@ Begin
           Dec(P, 3);
           Dec(P, 3);
         End;
         End;
 
 
+        if (length(Result) > 1) and Negative then
+          Negative := not RemoveLeadingNegativeSign(Result);
+
         If Not Negative Then
         If Not Negative Then
         Begin
         Begin
           Case FormatSettings.CurrencyFormat Of
           Case FormatSettings.CurrencyFormat Of
@@ -1409,11 +1442,18 @@ Begin
             7: Result := Result + FormatSettings.CurrencyString + '-';
             7: Result := Result + FormatSettings.CurrencyString + '-';
             8: Result := '-' + Result + ' ' + FormatSettings.CurrencyString;
             8: Result := '-' + Result + ' ' + FormatSettings.CurrencyString;
             9: Result := '-' + FormatSettings.CurrencyString + ' ' + Result;
             9: Result := '-' + FormatSettings.CurrencyString + ' ' + Result;
-            10: Result := FormatSettings.CurrencyString + ' ' + Result + '-';
+            10: Result := Result + ' ' + FormatSettings.CurrencyString + '-';
+            11: Result := FormatSettings.CurrencyString + ' ' + Result + '-';
+            12: Result := FormatSettings.CurrencyString + ' ' + '-' + Result;
+            13: Result := Result + '-' + ' ' + FormatSettings.CurrencyString;
+            14: Result := '(' + FormatSettings.CurrencyString + ' ' + Result + ')';
+            15: Result := '(' + Result + ' ' + FormatSettings.CurrencyString + ')';
           End;
           End;
         End;
         End;
       End;
       End;
   End;
   End;
+  if not (format in [ffCurrency]) and (length(Result) > 1) and (Result[1] = '-') then
+    RemoveLeadingNegativeSign(Result);
 End;
 End;
 
 
 
 

+ 3 - 2
rtl/x86_64/mathu.inc

@@ -12,8 +12,9 @@
 
 
 **********************************************************************}
 **********************************************************************}
 
 
-{$ifndef WIN64}
-{$define FPC_MATH_HAS_ARCTAN2}
+{$ASMMODE GAS}
+
+{$ifndef win64}
 function arctan2(y,x : float) : float;assembler;
 function arctan2(y,x : float) : float;assembler;
   asm
   asm
      fldt y
      fldt y

+ 2 - 0
rtl/x86_64/strings.inc

@@ -15,6 +15,8 @@
 
 
  **********************************************************************}
  **********************************************************************}
 
 
+{$ASMMODE GAS}
+
 {$ifndef FPC_UNIT_HAS_STRCOPY}
 {$ifndef FPC_UNIT_HAS_STRCOPY}
 {$define FPC_UNIT_HAS_STRCOPY}
 {$define FPC_UNIT_HAS_STRCOPY}
 { Created from glibc: libc/sysdeps/x86_64/strcpy.S Version 1.2 }
 { Created from glibc: libc/sysdeps/x86_64/strcpy.S Version 1.2 }

+ 154 - 0
tests/test/tstrreal4.pp

@@ -0,0 +1,154 @@
+program tstrreal4;
+{ test for issue #13722 by Zeljan Rikalo}
+uses SysUtils;
+
+procedure test;
+var
+ s: string;
+ r: double;
+ DS: Char;
+begin
+ DecimalSeparator := '.';
+ DS := DecimalSeparator;
+ r := 0.001;
+ s := FloatToStrF(r, ffGeneral, 12, 2);
+ {must print 0.001  }
+ writeln(s);
+ if (s <> '0'+DS+'001') then
+   halt(1);
+
+ s := FloatToStrF(r, ffFixed, 12, 2);
+ {must print 0.00  }
+ writeln(s);
+ if (s <> '0'+DS+'00') then
+   halt(1);
+
+ s := FloatToStrF(r, ffNumber, 12, 2);
+ {must print 0.00  }
+ writeln(s);
+ if (s <> '0'+DS+'00') then
+   halt(1);
+
+ r := -0.00001;
+
+ s := FloatToStrF(r, ffGeneral, 12, 2);
+ {must print -0.00001  }
+ writeln(s);
+ {$IFDEF FPC}
+ if (s <> '-0'+DS+'00001') then
+ {$ELSE}
+ if (s <> '-1E-05') then // is this DCC bug ?
+ {$ENDIF}
+   halt(1);
+
+ s := FloatToStrF(r, ffExponent, 12, 2);
+ {must print -1.00000000000E-05  }
+ writeln(s);
+ if (s <> '-1'+DS+'00000000000E-05') then
+   halt(1);
+
+ s := FloatToStrF(r, ffFixed, 12, 2);
+ {must print 0.00  }
+ writeln(s);
+ if (s <> '0'+DS+'00') then
+   halt(1);
+
+ s := FloatToStrF(r, ffNumber, 12, 2);
+ {must print 0.00  }
+ writeln(s);
+ if (s <> '0'+DS+'00') then
+   halt(1);
+
+ s := FloatToStrF(r, ffCurrency, 12, 2);
+ {must print without leading zero  }
+ writeln(s);
+ if (length(s) > 0) and 
+  ((Pos('-', s) > 0) or ((Pos('(', s) > 0) and  (Pos(')', s) > 0))) then
+   halt(1);
+
+ r := -0.00000;
+
+ s := FloatToStrF(r, ffGeneral, 12, 2);
+ {must print 0  }
+ writeln(s);
+ if (s <> '0') then
+   halt(1);
+
+ s := FloatToStrF(r, ffExponent, 12, 2);
+ {must print 0.00  }
+ writeln(s);
+ if (s <> '0'+DS+'00000000000E+00') then
+   halt(1);
+
+ s := FloatToStrF(r, ffFixed, 12, 2);
+ {must print 0.00  }
+ writeln(s);
+ if (s <> '0'+DS+'00') then
+   halt(1);
+
+ s := FloatToStrF(r, ffNumber, 12, 2);
+ {must print 0.00  }
+ writeln(s);
+ if (s <> '0'+DS+'00') then
+   halt(1);
+
+ s := FloatToStrF(r, ffCurrency, 12, 2);
+ {must print without leading zero  }
+ writeln(s);
+ if (length(s) > 0) and 
+  ((Pos('-', s) > 0) or ((Pos('(', s) > 0) and  (Pos(')', s) > 0))) then
+   halt(1);
+
+ // Now check if we remove leading negative sign by mistake
+ r := -0.00001;
+
+ s := FloatToStrF(r, ffGeneral, 12, 5);
+ {must print -0.00001  }
+ writeln(s);
+ {$IFDEF FPC}
+ if (s <> '-0'+DS+'00001') then
+ {$ELSE}
+ if (s <> '-1E-5') then // is this DCC bug ?
+ {$ENDIF}
+   halt(1);
+
+ s := FloatToStrF(r, ffExponent, 12, 5);
+ {must print -0.00001  }
+ writeln(s);
+ {$IFDEF FPC}
+ if (s <> '-1'+DS+'00000000000E-0005') then
+ {$ELSE}
+ if (s <> '-1.00000000000E-5') then
+ {$ENDIF}
+   halt(1);
+
+ s := FloatToStrF(r, ffFixed, 12, 5);
+ {must print 0.00  }
+ writeln(s);
+ if (s <> '-0'+DS+'00001') then
+   halt(1);
+
+ s := FloatToStrF(r, ffNumber, 12, 5);
+ {must print 0.00  }
+ writeln(s);
+ if (s <> '-0'+DS+'00001') then
+   halt(1);
+
+ s := FloatToStrF(r, ffCurrency, 12, 5);
+
+ {here we check for various currency negative formats.
+ There's bug in rtl cause NegCurFormat can be > 10
+ and in that case it isn't handled by FloatToStrIntl().
+ So that's why we check NegCurFormat range here.}
+
+ writeln(s);
+
+ if (length(s) > 0) and (NegCurrFormat in [0..10]) and
+   (Pos('-', s) = 0) and (Pos('(', s) = 0) and  (Pos(')', s) = 0) then
+   halt(1);
+ writeln('Tests for FloatToStrF(): SUCCESS');
+end;
+
+begin
+  test;
+end.

+ 56 - 0
tests/test/tstrreal5.pp

@@ -0,0 +1,56 @@
+program tstrreal4;
+{ test for NegCurFormat values  by Zeljan Rikalo
+  valid values are at:
+  http://msdn.microsoft.com/en-us/library/dd373791%28VS.85%29.aspx
+ }
+uses SysUtils;
+
+procedure test;
+const
+  MaxNegCurFormats = 15;
+var
+  s: string;
+  r: double;
+  i: integer;
+begin
+  DecimalSeparator := '.';
+  r := -1.1;
+  writeln('NegCurrFormat test pass 1 ...');
+  for i := 0 to MaxNegCurFormats do
+  begin
+    NegCurrFormat := i;
+    s := FloatToStrF(r, ffCurrency, 12, 1);
+    writeln('NegCurrFormat: ',i,' value: ',s);
+    case i of
+      0,4,14,15: 
+        if (Pos('(', s) = 0) and (Pos(')', s) = 0) then
+          halt(1);
+      else
+      if Pos('-', s) = 0 then
+        halt(1);
+    end; 
+  end;
+
+  r := -0.001;
+  writeln('NegCurrFormat test pass 2 ...');
+  for i := 0 to MaxNegCurFormats do
+  begin
+    NegCurrFormat := i;
+    s := FloatToStrF(r, ffCurrency, 12, 4);
+    writeln('NegCurrFormat: ',i,' value: ',s);
+    case i of
+      0,4,14,15: 
+        if (Pos('(', s) = 0) and (Pos(')', s) = 0) then
+          halt(1);
+      else
+      if Pos('-', s) = 0 then
+        halt(1);
+    end; 
+  end;
+
+  writeln('Tests for NegCurrFormat: SUCCESS');
+end;
+
+begin
+  test;
+end.

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