Browse Source

* SQL parser

git-svn-id: trunk@15832 -
michael 15 years ago
parent
commit
4c7f9238c7

+ 12 - 0
.gitattributes

@@ -1793,6 +1793,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
@@ -1857,12 +1862,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

+ 169 - 63
packages/fcl-db/Makefile

@@ -1,5 +1,5 @@
 #
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2010/03/21]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2010/07/16]
 #
 #
 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 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
 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
@@ -267,187 +267,187 @@ PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(F
 override PACKAGE_NAME=fcl-db
 override PACKAGE_NAME=fcl-db
 override PACKAGE_VERSION=2.5.1
 override PACKAGE_VERSION=2.5.1
 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),i386-nativent)
 ifeq ($(FULL_TARGET),i386-nativent)
-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)
@@ -2458,7 +2458,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) *
@@ -2683,6 +2683,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
@@ -2695,12 +2696,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
@@ -2713,12 +2716,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
@@ -2731,6 +2736,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
@@ -2743,6 +2749,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
@@ -2755,6 +2762,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
@@ -2764,6 +2772,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
@@ -2772,18 +2781,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
@@ -2793,12 +2805,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
@@ -2807,24 +2821,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
@@ -2836,24 +2854,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-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),i386-nativent)
 ifeq ($(FULL_TARGET),i386-nativent)
 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
@@ -2866,6 +2888,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
@@ -2878,6 +2901,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
@@ -2887,18 +2911,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
@@ -2908,18 +2935,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
@@ -2932,6 +2962,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
@@ -2941,18 +2972,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
@@ -2961,18 +2995,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
@@ -2985,6 +3022,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
@@ -2994,6 +3032,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
@@ -3002,12 +3041,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
@@ -3020,6 +3061,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
@@ -3032,6 +3074,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
@@ -3040,6 +3083,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
@@ -3048,6 +3092,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
@@ -3058,12 +3103,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
@@ -3076,12 +3123,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
@@ -3090,6 +3139,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
@@ -3101,30 +3151,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
@@ -3137,6 +3192,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
@@ -3145,18 +3201,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
@@ -3169,12 +3228,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
@@ -3362,6 +3423,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.5.1
 version=2.5.1
 
 
 [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:

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

@@ -0,0 +1,3709 @@
+{
+    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;
+    procedure ParseGranteeList(AParent: TSQLElement; List: TSQLElementList;
+      AllowObject, AllowGroup: Boolean);
+  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
+    function ParseGrantStatement(AParent: TSQLElement): TSQLGrantStatement;
+    function ParseGrantExecuteStatement(AParent: TSQLElement): TSQLProcedureGrantStatement;
+    function ParseGrantRoleStatement(AParent: TSQLElement): TSQLRoleGrantStatement;
+    function ParseGrantTableStatement(AParent: TSQLElement): TSQLTableGrantStatement;
+    // 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 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 : Boolean);
+
+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
+  Consume(tsqlTo);
+  E:=[tsqlIdentifier];
+  If AllowObject then
+    E:=E+[tsqlProcedure,tsqlView,tsqlTrigger,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 AllowGroup then
+          UnexpectedToken;
+        CreateGrantee(true,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
+              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);
+    If (CurrentToken=tsqlWith) then
+      begin
+      Consume(tsqlWith);
+      Consume(tsqlGrant);
+      Consume(tsqlOption);
+      Result.GrantOption:=True;
+      end;
+  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);
+    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);
+    Consume(tsqlTo);
+    ParseGranteeList(Result,Result.Grantees,False,False);
+    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);
+      tsqlUpdate,
+      tsqlReferences,
+      tsqlInsert,
+      tsqldelete,
+      tsqlSelect : Result:=ParseGrantTablestatement(AParent);
+      tsqlIdentifier : Result:=ParseGrantRolestatement(AParent);
+    else
+      UnExpectedToken([tsqlIdentifier, tsqlExecute,
+                       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);
+  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.
+

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

@@ -0,0 +1,947 @@
+{
+    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,
+   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', '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.

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

@@ -0,0 +1,4697 @@
+{
+    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) : TSQLStringType;
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Property Grantees : TSQLElementList Read FGrantees;
+  end;
+
+  { 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;
+
+  { TSQLProcedureGrantStatement }
+
+  TSQLProcedureGrantStatement = Class(TSQLGrantStatement)
+  private
+    FGrantOption: Boolean;
+    FProcedureName: TSQLIdentifierName;
+  Public
+    Destructor Destroy; override;
+    Property ProcedureName : TSQLIdentifierName Read FProcedureName Write FProcedureName;
+    Property GrantOption : Boolean Read FGrantOption Write FGrantOption;
+  end;
+
+  { TSQLRoleGrantStatement }
+
+  TSQLRoleGrantStatement = Class(TSQLGrantStatement)
+  private
+    FAdminOption: Boolean;
+    FRoles: TSQLElementList;
+  Public
+    Constructor Create(AParent : TSQLElement); override;
+    Destructor Destroy; override;
+    Property Roles : TSQLElementList Read FRoles;
+    Property AdminOption : Boolean Read FAdminOption Write FAdminOption;
+  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): 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;
+  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;
+
+{ TSQLRoleGrantStatement }
+
+constructor TSQLRoleGrantStatement.Create(AParent: TSQLElement);
+begin
+  inherited Create(AParent);
+  FRoles:=TSQLElementList.Create(True);
+end;
+
+destructor TSQLRoleGrantStatement.Destroy;
+begin
+  FreeAndNil(FRoles);
+  inherited Destroy;
+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;
+
+end.
+

+ 128 - 120
packages/fcl-db/tests/Makefile

@@ -1,10 +1,10 @@
 #
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2009/08/02]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2010/07/16]
 #
 #
 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 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
 BSDs = freebsd netbsd openbsd darwin
-UNIXs = linux $(BSDs) solaris qnx
+UNIXs = linux $(BSDs) solaris qnx haiku
 LIMIT83fs = go32v2 os2 emx watcom
 LIMIT83fs = go32v2 os2 emx watcom
 OSNeedsComspecToRunBatch = go32v2 watcom
 OSNeedsComspecToRunBatch = go32v2 watcom
 FORCE:
 FORCE:
@@ -326,6 +326,9 @@ endif
 ifeq ($(FULL_TARGET),i386-symbian)
 ifeq ($(FULL_TARGET),i386-symbian)
 override TARGET_UNITS+=toolsunit dbftoolsunit memdstoolsunit sqldbtoolsunit sdfdstoolsunit
 override TARGET_UNITS+=toolsunit dbftoolsunit memdstoolsunit sqldbtoolsunit sdfdstoolsunit
 endif
 endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override TARGET_UNITS+=toolsunit dbftoolsunit memdstoolsunit sqldbtoolsunit sdfdstoolsunit
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 ifeq ($(FULL_TARGET),m68k-linux)
 override TARGET_UNITS+=toolsunit dbftoolsunit memdstoolsunit sqldbtoolsunit sdfdstoolsunit
 override TARGET_UNITS+=toolsunit dbftoolsunit memdstoolsunit sqldbtoolsunit sdfdstoolsunit
 endif
 endif
@@ -389,6 +392,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 +446,191 @@ 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
+ifeq ($(FULL_TARGET),i386-nativent)
+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
@@ -988,6 +1006,10 @@ ifeq ($(OS_TARGET),symbian)
 SHAREDLIBEXT=.dll
 SHAREDLIBEXT=.dll
 SHORTSUFFIX=symbian
 SHORTSUFFIX=symbian
 endif
 endif
+ifeq ($(OS_TARGET),NativeNT)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=nativent
+endif
 else
 else
 ifeq ($(OS_TARGET),go32v1)
 ifeq ($(OS_TARGET),go32v1)
 PPUEXT=.pp1
 PPUEXT=.pp1
@@ -1443,8 +1465,6 @@ ifeq ($(FULL_TARGET),i386-win32)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_HASH=1
 REQUIRE_PACKAGES_HASH=1
 REQUIRE_PACKAGES_PASZLIB=1
 REQUIRE_PACKAGES_PASZLIB=1
-REQUIRE_PACKAGES_WINUNITS-BASE=1
-REQUIRE_PACKAGES_WINUNITS-JEDI=1
 REQUIRE_PACKAGES_FCL-BASE=1
 REQUIRE_PACKAGES_FCL-BASE=1
 REQUIRE_PACKAGES_FCL-XML=1
 REQUIRE_PACKAGES_FCL-XML=1
 REQUIRE_PACKAGES_FCL-FPCUNIT=1
 REQUIRE_PACKAGES_FCL-FPCUNIT=1
@@ -1658,6 +1678,15 @@ 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),i386-nativent)
+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
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 ifeq ($(FULL_TARGET),m68k-linux)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_HASH=1
 REQUIRE_PACKAGES_HASH=1
@@ -1932,6 +1961,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
@@ -1953,8 +1992,6 @@ ifeq ($(FULL_TARGET),x86_64-win64)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_HASH=1
 REQUIRE_PACKAGES_HASH=1
 REQUIRE_PACKAGES_PASZLIB=1
 REQUIRE_PACKAGES_PASZLIB=1
-REQUIRE_PACKAGES_WINUNITS-BASE=1
-REQUIRE_PACKAGES_WINUNITS-JEDI=1
 REQUIRE_PACKAGES_FCL-BASE=1
 REQUIRE_PACKAGES_FCL-BASE=1
 REQUIRE_PACKAGES_FCL-XML=1
 REQUIRE_PACKAGES_FCL-XML=1
 REQUIRE_PACKAGES_FCL-FPCUNIT=1
 REQUIRE_PACKAGES_FCL-FPCUNIT=1
@@ -2145,6 +2182,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),)
@@ -2154,9 +2208,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=
@@ -2535,58 +2589,6 @@ ifdef UNITDIR_PXLIB
 override COMPILER_UNITDIR+=$(UNITDIR_PXLIB)
 override COMPILER_UNITDIR+=$(UNITDIR_PXLIB)
 endif
 endif
 endif
 endif
-ifdef REQUIRE_PACKAGES_WINUNITS-BASE
-PACKAGEDIR_WINUNITS-BASE:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /winunits-base/Makefile.fpc,$(PACKAGESDIR))))))
-ifneq ($(PACKAGEDIR_WINUNITS-BASE),)
-ifneq ($(wildcard $(PACKAGEDIR_WINUNITS-BASE)/units/$(TARGETSUFFIX)),)
-UNITDIR_WINUNITS-BASE=$(PACKAGEDIR_WINUNITS-BASE)/units/$(TARGETSUFFIX)
-else
-UNITDIR_WINUNITS-BASE=$(PACKAGEDIR_WINUNITS-BASE)
-endif
-ifdef CHECKDEPEND
-$(PACKAGEDIR_WINUNITS-BASE)/$(FPCMADE):
-	$(MAKE) -C $(PACKAGEDIR_WINUNITS-BASE) $(FPCMADE)
-override ALLDEPENDENCIES+=$(PACKAGEDIR_WINUNITS-BASE)/$(FPCMADE)
-endif
-else
-PACKAGEDIR_WINUNITS-BASE=
-UNITDIR_WINUNITS-BASE:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /winunits-base/Package.fpc,$(UNITSDIR)))))
-ifneq ($(UNITDIR_WINUNITS-BASE),)
-UNITDIR_WINUNITS-BASE:=$(firstword $(UNITDIR_WINUNITS-BASE))
-else
-UNITDIR_WINUNITS-BASE=
-endif
-endif
-ifdef UNITDIR_WINUNITS-BASE
-override COMPILER_UNITDIR+=$(UNITDIR_WINUNITS-BASE)
-endif
-endif
-ifdef REQUIRE_PACKAGES_WINUNITS-JEDI
-PACKAGEDIR_WINUNITS-JEDI:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /winunits-jedi/Makefile.fpc,$(PACKAGESDIR))))))
-ifneq ($(PACKAGEDIR_WINUNITS-JEDI),)
-ifneq ($(wildcard $(PACKAGEDIR_WINUNITS-JEDI)/units/$(TARGETSUFFIX)),)
-UNITDIR_WINUNITS-JEDI=$(PACKAGEDIR_WINUNITS-JEDI)/units/$(TARGETSUFFIX)
-else
-UNITDIR_WINUNITS-JEDI=$(PACKAGEDIR_WINUNITS-JEDI)
-endif
-ifdef CHECKDEPEND
-$(PACKAGEDIR_WINUNITS-JEDI)/$(FPCMADE):
-	$(MAKE) -C $(PACKAGEDIR_WINUNITS-JEDI) $(FPCMADE)
-override ALLDEPENDENCIES+=$(PACKAGEDIR_WINUNITS-JEDI)/$(FPCMADE)
-endif
-else
-PACKAGEDIR_WINUNITS-JEDI=
-UNITDIR_WINUNITS-JEDI:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /winunits-jedi/Package.fpc,$(UNITSDIR)))))
-ifneq ($(UNITDIR_WINUNITS-JEDI),)
-UNITDIR_WINUNITS-JEDI:=$(firstword $(UNITDIR_WINUNITS-JEDI))
-else
-UNITDIR_WINUNITS-JEDI=
-endif
-endif
-ifdef UNITDIR_WINUNITS-JEDI
-override COMPILER_UNITDIR+=$(UNITDIR_WINUNITS-JEDI)
-endif
-endif
 ifdef REQUIRE_PACKAGES_UNIVINT
 ifdef REQUIRE_PACKAGES_UNIVINT
 PACKAGEDIR_UNIVINT:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /univint/Makefile.fpc,$(PACKAGESDIR))))))
 PACKAGEDIR_UNIVINT:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /univint/Makefile.fpc,$(PACKAGESDIR))))))
 ifneq ($(PACKAGEDIR_UNIVINT),)
 ifneq ($(PACKAGEDIR_UNIVINT),)
@@ -2951,6 +2953,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
@@ -2997,6 +3002,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]

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

@@ -0,0 +1,2261 @@
+{
+    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;
+
+  { 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 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;
+  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;
+
+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;
+
+
+initialization
+  RegisterTest(TTestGenerateSQL);
+end.
+

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

@@ -0,0 +1,7025 @@
+{
+    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;
+
+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;
+
+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]);
+end.
+

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

@@ -0,0 +1,1620 @@
+{
+    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 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.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.
+

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

@@ -0,0 +1,287 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="8"/>
+    <General>
+      <MainUnit Value="0"/>
+      <TargetFileExt Value=""/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <Icon Value="0"/>
+      <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"/>
+        <IsVisibleTab Value="True"/>
+        <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="1"/>
+        <CursorPos X="1" Y="15"/>
+        <UsageCount Value="208"/>
+        <Loaded Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="../src/sql/fpsqltree.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="fpsqltree"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="263"/>
+        <CursorPos X="41" Y="278"/>
+        <UsageCount Value="208"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="../src/sql/fpsqlscanner.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="fpsqlscanner"/>
+        <EditorIndex Value="4"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="466"/>
+        <CursorPos X="1" Y="480"/>
+        <UsageCount Value="208"/>
+        <Loaded Value="True"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="fpsqlparser"/>
+        <EditorIndex Value="6"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="737"/>
+        <CursorPos X="3" Y="740"/>
+        <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="1"/>
+        <CursorPos X="1" Y="15"/>
+        <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="1"/>
+        <CursorPos X="41" Y="5"/>
+        <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="9"/>
+      </Unit8>
+    </Units>
+    <JumpHistory Count="30" HistoryIndex="29">
+      <Position1>
+        <Filename Value="tcsqlscanner.pas"/>
+        <Caret Line="108" Column="24" TopLine="84"/>
+      </Position1>
+      <Position2>
+        <Filename Value="tcsqlscanner.pas"/>
+        <Caret Line="156" Column="26" TopLine="138"/>
+      </Position2>
+      <Position3>
+        <Filename Value="tcsqlscanner.pas"/>
+        <Caret Line="37" Column="24" TopLine="23"/>
+      </Position3>
+      <Position4>
+        <Filename Value="tcsqlscanner.pas"/>
+        <Caret Line="156" Column="29" TopLine="142"/>
+      </Position4>
+      <Position5>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="376" Column="15" TopLine="361"/>
+      </Position5>
+      <Position6>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="163" Column="24" TopLine="136"/>
+      </Position6>
+      <Position7>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="19" Column="15" TopLine="4"/>
+      </Position7>
+      <Position8>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="78" Column="29" TopLine="63"/>
+      </Position8>
+      <Position9>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="208" Column="33" TopLine="199"/>
+      </Position9>
+      <Position10>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="648" Column="34" TopLine="636"/>
+      </Position10>
+      <Position11>
+        <Filename Value="../src/sql/fpsqlparser.pas"/>
+        <Caret Line="1208" Column="27" TopLine="1187"/>
+      </Position11>
+      <Position12>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="655" Column="31" TopLine="634"/>
+      </Position12>
+      <Position13>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="682" Column="15" TopLine="667"/>
+      </Position13>
+      <Position14>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="61" Column="1" TopLine="61"/>
+      </Position14>
+      <Position15>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="317" Column="36" TopLine="295"/>
+      </Position15>
+      <Position16>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="328" Column="15" TopLine="313"/>
+      </Position16>
+      <Position17>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="2990" Column="31" TopLine="2974"/>
+      </Position17>
+      <Position18>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="2994" Column="90" TopLine="2974"/>
+      </Position18>
+      <Position19>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="3001" Column="31" TopLine="2974"/>
+      </Position19>
+      <Position20>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="3006" Column="90" TopLine="2991"/>
+      </Position20>
+      <Position21>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="3008" Column="90" TopLine="2991"/>
+      </Position21>
+      <Position22>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="3110" Column="35" TopLine="3095"/>
+      </Position22>
+      <Position23>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="3251" Column="34" TopLine="3230"/>
+      </Position23>
+      <Position24>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="3393" Column="1" TopLine="3371"/>
+      </Position24>
+      <Position25>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="3405" Column="29" TopLine="3390"/>
+      </Position25>
+      <Position26>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="3427" Column="29" TopLine="3412"/>
+      </Position26>
+      <Position27>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="3443" Column="29" TopLine="3428"/>
+      </Position27>
+      <Position28>
+        <Filename Value="tcparser.pas"/>
+        <Caret Line="664" Column="6" TopLine="664"/>
+      </Position28>
+      <Position29>
+        <Filename Value="tcsqlscanner.pas"/>
+        <Caret Line="168" Column="15" TopLine="168"/>
+      </Position29>
+      <Position30>
+        <Filename Value="tcgensql.pas"/>
+        <Caret Line="513" Column="27" TopLine="513"/>
+      </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.