Browse Source

+ Initial implementation

michael 23 years ago
parent
commit
d3df5063f0

+ 1206 - 0
fcl/db/odbc/Makefile

@@ -0,0 +1,1206 @@
+#
+# Don't edit, this file is generated by FPCMake Version 1.1 [2002/03/28]
+#
+default: all
+MAKEFILETARGETS=linux win32
+override PATH:=$(subst \,/,$(PATH))
+ifeq ($(findstring ;,$(PATH)),)
+inUnix=1
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+SEARCHPATH:=$(subst ;, ,$(PATH))
+endif
+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 cygwin,$(MACHTYPE)),)
+inCygWin=1
+endif
+endif
+ifeq ($(OS_TARGET),freebsd)
+BSDhier=1
+endif
+ifeq ($(OS_TARGET),netbsd)
+BSDhier=1
+endif
+ifdef inUnix
+BATCHEXT=.sh
+else
+ifdef inOS2
+BATCHEXT=.cmd
+else
+BATCHEXT=.bat
+endif
+endif
+ifdef inUnix
+PATHSEP=/
+else
+PATHSEP:=$(subst /,\,/)
+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))
+FPC:=$(shell $(FPCPROG) -PB)
+ifneq ($(findstring Error,$(FPC)),)
+override FPC=ppc386
+endif
+else
+override FPC=ppc386
+endif
+endif
+override FPC:=$(subst $(SRCEXEEXT),,$(FPC))
+override FPC:=$(subst \,/,$(FPC))$(SRCEXEEXT)
+ifndef FPC_VERSION
+FPC_VERSION:=$(shell $(FPC) -iV)
+endif
+export FPC FPC_VERSION
+unexport CHECKDEPEND ALLDEPENDENCIES
+ifeq ($(findstring 1.0.,$(FPC_VERSION)),)
+COMPILERINFO:=$(shell $(FPC) -iSP -iTP -iSO -iTO)
+ifndef CPU_SOURCE
+CPU_SOURCE:=$(word 1,$(COMPILERINFO))
+endif
+ifndef CPU_TARGET
+CPU_TARGET:=$(word 2,$(COMPILERINFO))
+endif
+ifndef OS_SOURCE
+OS_SOURCE:=$(word 3,$(COMPILERINFO))
+endif
+ifndef OS_TARGET
+OS_TARGET:=$(word 4,$(COMPILERINFO))
+endif
+else
+ifndef CPU_SOURCE
+CPU_SOURCE:=$(shell $(FPC) -iSP)
+endif
+ifndef CPU_TARGET
+CPU_TARGET:=$(shell $(FPC) -iTP)
+endif
+ifndef OS_SOURCE
+OS_SOURCE:=$(shell $(FPC) -iSO)
+endif
+ifndef OS_TARGET
+OS_TARGET:=$(shell $(FPC) -iTO)
+endif
+endif
+FULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+FULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifneq ($(FULL_TARGET),$(FULL_SOURCE))
+CROSSCOMPILE=1
+endif
+ifeq ($(findstring makefile,$(MAKECMDGOALS)),)
+ifeq ($(findstring $(OS_TARGET),$(MAKEFILETARGETS)),)
+$(error The Makefile doesn't support target $(OS_TARGET), please run fpcmake first)
+endif
+endif
+export OS_TARGET OS_SOURCE CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE 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=c:/pp
+endif
+endif
+endif
+endif
+ifndef CROSSDIR
+CROSSDIR:=$(FPCDIR)/cross/$(FULL_TARGET)
+endif
+ifndef CROSSTARGETDIR
+CROSSTARGETDIR=$(CROSSDIR)/$(FULL_TARGET)
+endif
+ifdef CROSSCOMPILE
+UNITSDIR:=$(wildcard $(CROSSTARGETDIR)/units)
+ifeq ($(UNITSDIR),)
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
+endif
+else
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
+endif
+PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
+override PACKAGE_NAME=fcl
+override TARGET_UNITS+=fpodbc
+override TARGET_EXAMPLES+=testbcon testcon testdrcon testenv testfl testpa testpktestpr testsql testst testtl
+override INSTALL_FPCPACKAGE=y
+override COMPILER_OPTIONS+=-S2
+override COMPILER_TARGETDIR+=../../$(OS_TARGET)
+ifdef REQUIRE_UNITSDIR
+override UNITSDIR+=$(REQUIRE_UNITSDIR)
+endif
+ifdef REQUIRE_PACKAGESDIR
+override PACKAGESDIR+=$(REQUIRE_PACKAGESDIR)
+endif
+ifdef ZIPINSTALL
+ifeq ($(OS_TARGET),linux)
+UNIXINSTALLDIR=1
+endif
+ifeq ($(OS_TARGET),freebsd)
+UNIXINSTALLDIR=1
+endif
+ifeq ($(OS_TARGET),netbsd)
+UNIXINSTALLDIR=1
+endif
+ifeq ($(OS_TARGET),sunos)
+UNIXINSTALLDIR=1
+endif
+else
+ifeq ($(OS_SOURCE),linux)
+UNIXINSTALLDIR=1
+endif
+ifeq ($(OS_SOURCE),freebsd)
+UNIXINSTALLDIR=1
+endif
+ifeq ($(OS_SOURCE),netbsd)
+UNIXINSTALLDIR=1
+endif
+ifeq ($(OS_TARGET),sunos)
+UNIXINSTALLDIR=1
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef PREFIX
+INSTALL_PREFIX=$(PREFIX)
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef UNIXINSTALLDIR
+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 INSTALL_BASEDIR
+ifdef UNIXINSTALLDIR
+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 UNIXINSTALLDIR
+INSTALL_BINDIR:=$(INSTALL_PREFIX)/bin
+else
+INSTALL_BINDIR:=$(INSTALL_BASEDIR)/bin
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(OS_TARGET)
+endif
+endif
+endif
+ifndef INSTALL_UNITDIR
+ifdef CROSSCOMPILE
+INSTALL_UNITDIR:=$(INSTALL_BASEDIR)/cross/$(FULL_TARGET)/units
+else
+INSTALL_UNITDIR:=$(INSTALL_BASEDIR)/units/$(OS_TARGET)
+endif
+ifdef INSTALL_FPCPACKAGE
+ifdef PACKAGE_NAME
+INSTALL_UNITDIR:=$(INSTALL_UNITDIR)/$(PACKAGE_NAME)
+endif
+endif
+endif
+ifndef INSTALL_LIBDIR
+ifdef UNIXINSTALLDIR
+INSTALL_LIBDIR:=$(INSTALL_PREFIX)/lib
+else
+INSTALL_LIBDIR:=$(INSTALL_UNITDIR)
+endif
+endif
+ifndef INSTALL_SOURCEDIR
+ifdef UNIXINSTALLDIR
+ifdef BSDhier
+SRCPREFIXDIR=share/src
+else
+SRCPREFIXDIR=src
+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 UNIXINSTALLDIR
+ifdef BSDhier
+DOCPREFIXDIR=share/doc
+else
+DOCPREFIXDIR=doc
+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 UNIXINSTALLDIR
+ifdef INSTALL_FPCPACKAGE
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/fpc-$(FPC_VERSION)/examples/$(PACKAGE_NAME)
+endif
+else
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+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
+ifdef CROSSCOMPILE
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(CROSSTARGETDIR)/bin/$(FULL_SOURCE))
+ifeq ($(CROSSBINDIR),)
+CROSSBINDIR:=$(wildcard $(INSTALL_BASEDIR)/cross/$(FULL_TARGET)/bin/$(FULL_SOURCE))
+endif
+endif
+else
+CROSSBINDIR=
+endif
+ifdef inUnix
+ifndef GCCLIBDIR
+GCCLIBDIR:=$(shell dirname `(gcc -v 2>&1)| head -n 1| awk '{ print $$4 } '`)
+endif
+ifeq ($(OS_TARGET),linux)
+ifndef OTHERLIBDIR
+OTHERLIBDIR:=$(shell grep -v "^\#" /etc/ld.so.conf | awk '{ ORS=" "; print $1 }')
+endif
+endif
+ifeq ($(OS_TARGET),netbsd)
+OTHERLIBDIR+=/usr/pkg/lib
+endif
+export GCCLIBDIR OTHERLIB
+endif
+LOADEREXT=.as
+EXEEXT=.exe
+PPLEXT=.ppl
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.so
+STATICLIBPREFIX=libp
+RSTEXT=.rst
+FPCMADE=fpcmade
+ifeq ($(OS_TARGET),go32v1)
+PPUEXT=.pp1
+OEXT=.o1
+ASMEXT=.s1
+SMARTEXT=.sl1
+STATICLIBEXT=.a1
+SHAREDLIBEXT=.so1
+STATICLIBPREFIX=
+FPCMADE=fpcmade.v1
+PACKAGESUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+FPCMADE=fpcmade.dos
+ZIPSUFFIX=go32
+endif
+ifeq ($(OS_TARGET),linux)
+EXEEXT=
+HASSHAREDLIB=1
+FPCMADE=fpcmade.lnx
+ZIPSUFFIX=linux
+endif
+ifeq ($(OS_TARGET),freebsd)
+EXEEXT=
+HASSHAREDLIB=1
+FPCMADE=fpcmade.freebsd
+ZIPSUFFIX=freebsd
+endif
+ifeq ($(OS_TARGET),netbsd)
+EXEEXT=
+HASSHAREDLIB=1
+FPCMADE=fpcmade.netbsd
+ZIPSUFFIX=netbsd
+endif
+ifeq ($(OS_TARGET),win32)
+PPUEXT=.ppw
+OEXT=.ow
+ASMEXT=.sw
+SMARTEXT=.slw
+STATICLIBEXT=.aw
+SHAREDLIBEXT=.dll
+FPCMADE=fpcmade.w32
+ZIPSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+PPUEXT=.ppo
+ASMEXT=.so2
+OEXT=.oo2
+AOUTEXT=.out
+SMARTEXT=.sl2
+STATICLIBPREFIX=
+STATICLIBEXT=.ao2
+SHAREDLIBEXT=.dll
+FPCMADE=fpcmade.os2
+ZIPSUFFIX=emx
+ECHO=echo
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+PPUEXT=.ppa
+ASMEXT=.asm
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.library
+FPCMADE=fpcmade.amg
+endif
+ifeq ($(OS_TARGET),atari)
+PPUEXT=.ppt
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=.ttp
+FPCMADE=fpcmade.ata
+endif
+ifeq ($(OS_TARGET),beos)
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+FPCMADE=fpcmade.be
+ZIPSUFFIX=be
+endif
+ifeq ($(OS_TARGET),sunos)
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+FPCMADE=fpcmade.sun
+ZIPSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+FPCMADE=fpcmade.qnx
+ZIPSUFFIX=qnx
+endif
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+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=
+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=
+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=
+else
+CPPROG:=$(firstword $(CPPROG))
+endif
+endif
+export CPPROG
+ifndef RMPROG
+RMPROG:=$(strip $(wildcard $(addsuffix /rm$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(RMPROG),)
+RMPROG=
+else
+RMPROG:=$(firstword $(RMPROG))
+endif
+endif
+export RMPROG
+ifndef MVPROG
+MVPROG:=$(strip $(wildcard $(addsuffix /mv$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MVPROG),)
+MVPROG=
+else
+MVPROG:=$(firstword $(MVPROG))
+endif
+endif
+export MVPROG
+ifndef ECHOREDIR
+ECHOREDIR:=$(subst /,$(PATHSEP),$(ECHO))
+endif
+ifndef COPY
+COPY:=$(CPPROG) -fp
+endif
+ifndef COPYTREE
+COPYTREE:=$(CPPROG) -rfp
+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=
+else
+PPUMOVE:=$(firstword $(PPUMOVE))
+endif
+endif
+export PPUMOVE
+ifndef FPCMAKE
+FPCMAKE:=$(strip $(wildcard $(addsuffix /fpcmake$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(FPCMAKE),)
+FPCMAKE=
+else
+FPCMAKE:=$(firstword $(FPCMAKE))
+endif
+endif
+export FPCMAKE
+ifndef ZIPPROG
+ZIPPROG:=$(strip $(wildcard $(addsuffix /zip$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ZIPPROG),)
+ZIPPROG=
+else
+ZIPPROG:=$(firstword $(ZIPPROG))
+endif
+endif
+export ZIPPROG
+ifndef TARPROG
+TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG=
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+endif
+export TARPROG
+ASNAME=as
+LDNAME=ld
+ARNAME=ar
+RCNAME=rc
+ifeq ($(OS_TARGET),win32)
+ASNAME=asw
+LDNAME=ldw
+ARNAME=arw
+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$(BATCHEXT)
+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=vI
+TAREXT=.tar.bz2
+else
+TAROPT=vz
+TAREXT=.tar.gz
+endif
+override REQUIRE_PACKAGES=rtl odbc
+ifeq ($(OS_TARGET),linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(OS_TARGET),win32)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifdef REQUIRE_PACKAGES_RTL
+PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/$(OS_TARGET)/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_RTL),)
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/$(OS_TARGET)),)
+UNITDIR_RTL=$(PACKAGEDIR_RTL)/$(OS_TARGET)
+else
+UNITDIR_RTL=$(PACKAGEDIR_RTL)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_RTL)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_RTL) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(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_ODBC
+PACKAGEDIR_ODBC:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /odbc/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_ODBC),)
+ifneq ($(wildcard $(PACKAGEDIR_ODBC)/$(OS_TARGET)),)
+UNITDIR_ODBC=$(PACKAGEDIR_ODBC)/$(OS_TARGET)
+else
+UNITDIR_ODBC=$(PACKAGEDIR_ODBC)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_ODBC)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_ODBC) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_ODBC)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_ODBC=
+UNITDIR_ODBC:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /odbc/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_ODBC),)
+UNITDIR_ODBC:=$(firstword $(UNITDIR_ODBC))
+else
+UNITDIR_ODBC=
+endif
+endif
+ifdef UNITDIR_ODBC
+override COMPILER_UNITDIR+=$(UNITDIR_ODBC)
+endif
+endif
+ifndef NOCPUDEF
+override FPCOPTDEF=$(CPU_TARGET)
+endif
+ifneq ($(OS_TARGET),$(OS_SOURCE))
+override FPCOPT+=-T$(OS_TARGET)
+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
+ifeq ($(CPU_TARGET),i386)
+FPCCPUOPT:=-OG2p3
+else
+FPCCPUOPT:=
+endif
+override FPCOPT+=-Xs $(FPCCPUOPT) -n
+override FPCOPTDEF+=RELEASE
+endif
+ifdef STRIP
+override FPCOPT+=-Xs
+endif
+ifdef OPTIMIZE
+ifeq ($(CPU_TARGET),i386)
+override FPCOPT+=-OG2p3
+endif
+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 GCCLIBDIR
+override FPCOPT+=-Fl$(GCCLIBDIR)
+endif
+ifdef OTHERLIBDIR
+override FPCOPT+=$(addprefix -Fl,$(OTHERLIBDIR))
+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 COMPILER:=$(FPC) $(FPCOPT)
+ifeq (,$(findstring -s ,$(COMPILER)))
+EXECPPAS=
+else
+ifeq ($(OS_SOURCE),$(OS_TARGET))
+EXECPPAS:=@$(PPAS)
+endif
+endif
+.PHONY: fpc_units
+ifdef TARGET_UNITS
+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: $(UNITPPUFILES)
+ifdef TARGET_RSTS
+override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
+override CLEANRSTFILES+=$(RSTFILES)
+endif
+.PHONY: fpc_examples
+ifdef TARGET_EXAMPLES
+HASEXAMPLES=1
+override EXAMPLESOURCEFILES:=$(wildcard $(addsuffix .pp,$(TARGET_EXAMPLES)) $(addsuffix .pas,$(TARGET_EXAMPLES)))
+override EXAMPLEFILES:=$(addsuffix $(EXEEXT),$(TARGET_EXAMPLES))
+override EXAMPLEOFILES:=$(addsuffix $(OEXT),$(TARGET_EXAMPLES)) $(addprefix $(STATICLIBPREFIX),$(addsuffix $(STATICLIBEXT),$(TARGET_EXAMPLES)))
+override CLEANEXEFILES+=$(EXAMPLEFILES) $(EXAMPLEOFILES)
+ifeq ($(OS_TARGET),os2)
+override CLEANEXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_EXAMPLES))
+endif
+endif
+ifdef TARGET_EXAMPLEDIRS
+HASEXAMPLES=1
+endif
+fpc_examples: all $(EXAMPLEFILES) $(addsuffix _all,$(TARGET_EXAMPLEDIRS))
+.PHONY: fpc_all fpc_smart fpc_debug fpc_release
+$(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 .pp .rc .res
+%$(PPUEXT): %.pp
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(PPUEXT): %.pas
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(EXEEXT): %.pp
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(EXEEXT): %.pas
+	$(COMPILER) $<
+	$(EXECPPAS)
+%.res: %.rc
+	windres -i $< -o $@
+vpath %.pp $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.pas $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %$(PPUEXT) $(COMPILER_UNITTARGETDIR)
+.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)))
+override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(INSTALLPPUFILES))
+override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(INSTALLPPULINKFILES)))
+override INSTALL_CREATEPACKAGEFPC=1
+endif
+ifdef INSTALLEXEFILES
+override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(INSTALLEXEFILES))
+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$(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_UNITS
+override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
+endif
+ifdef CLEANPPUFILES
+override CLEANPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES)))
+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)
+fpc_distclean: clean
+ifdef COMPILER_UNITTARGETDIR
+TARGETDIRCLEAN=fpc_clean
+endif
+fpc_cleanall: $(CLEANTARGET) $(TARGETDIRCLEAN)
+ifdef CLEANEXEFILES
+	-$(DEL) $(CLEANEXEFILES)
+endif
+	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+	-$(DELTREE) *$(SMARTEXT)
+	-$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+ifdef AOUTEXT
+	-$(DEL) *$(AOUTEXT)
+endif
+.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)
+	@$(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)  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)  ZipPrefix............ $(ZIPPREFIX)
+	@$(ECHO)  ZipSuffix............ $(ZIPSUFFIX)
+	@$(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
+examples: fpc_examples
+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 examples shared install sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall clean distclean cleanall info makefiles
+ifneq ($(wildcard fpcmake.loc),)
+include fpcmake.loc
+endif

+ 28 - 0
fcl/db/odbc/Makefile.fpc

@@ -0,0 +1,28 @@
+#
+# Makefile.fpc for fpODBC db units
+#
+
+[package]
+main=fcl
+
+[target]
+units=fpodbc
+examples=testbcon testcon testdrcon testenv testfl testpa testpk\
+         testpr testsql testst testtl
+
+
+[clean]
+units=
+
+[require]
+packages=odbc
+
+[compiler]
+options=-S2 
+targetdir=../../$(OS_TARGET)
+
+[install]
+fpcpackage=y
+
+[default]
+fpcdir=../../..

+ 181 - 0
fcl/db/odbc/README

@@ -0,0 +1,181 @@
+fpODBC - a OOP wrapper around the ODBC driver.
+
+This is a simple OOP wrapper around teh ODBC data calls.
+
+There are basically 3 classes:
+
+TODBCEnvironment
+----------------
+  A global object the contains the connection to the ODBC driver. Each
+  connection should have an environment assigned to it. If not, a
+  default environment will be used.
+
+  It has the following methods:
+  
+  Function GetDriverNames(List : Tstrings) : Integer;
+    Fills list with the available drivers. Returns the number of
+    drivers.
+  
+  Function GetDataSourceNames(List : Tstrings; Types : TDSNTypes;Descriptions : Boolean) : Integer;
+    Fills list with the available datasources.
+    Types is one of
+      dtUser   : Return only user DSNs
+      dtSystem : Return system DSNs
+      dtBoth   : Return both
+    The function returns the number of returned drivers.
+    
+  function GetDriverOptions(Driver: String; Options: TStrings): Integer;
+    Returns a list of options for the driver.
+
+TODBCConnection
+
+  Represents a connection to a ODBC datasource.
+  The connection is established according to the following rules:
+   - If OnBrowseConnection is assigned, SQLBrowseConnect is used. At
+     each browse step, the handler is called with the in and out
+     parameter lists filled.
+     TConnectionBrowseEvent = Procedure (Sender : TObject;InParams,OutParams : Tstrings) of Object;
+
+     This is as yet untested, since I have no driver which supports it.
+
+   - If the DSN property is assigned, this is used. Password and Username are also used.
+
+   - If The drivername is assigned, that is used, together with the
+     DriverParams. This should be a list name=value pairs which will be
+     passed to the driver.
+
+   - If none of the above conditions is fullfilled, an error is raised.
+ 
+   - To connect, set the Active property to 'True' or call connect.
+   
+   - To Disconnect, set the active property to false or call disconnect
+
+   The following methods exist:
+   
+    Procedure Connect;
+      Connects to the DSN/Driver
+      
+    Procedure Disconnect;
+      Disconnects from the DSN/Driver
+      
+    Procedure GetTableNames(S : TStrings; SystemTables : Boolean);
+    
+      returns a list of tables. If systemtables is true, then system
+      table names are also returned.
+      
+    Procedure GetFieldNames(TableName : String; S : TStrings);
+      returns a list of fieldnames for table 'tablename'
+    Procedure GetPrimaryKeyFields(TableName : String; S : TStrings);
+      returns a list of primary key fieldnames for table 'tablename'
+    procedure GetProcedureNames(S : TStrings);
+      returns a list of stored procedure names
+    procedure GetProcedureParams(ProcName : String;ParamTypes : TODBCParamTypes; S : TStrings);
+      returns a list of parameters for the stored procedure. ParamTypes is a set of 
+      ptUnknown,ptInput,ptInputOutput,ptResult,ptOutput,ptRetVal
+      
+
+TODBCStatement / TODBCSQLStatement.
+
+  TODBCStatement is an abstract class which encapsulates an ODBC Statement
+  handle. TODBCSQLStatement accepts an SQL Query which it can execute.
+
+  TODBCStatement has the following methods:
+   
+    Procedure BindFields(RestrictList : TStrings);virtual;
+      Binds fields. If restrictlist is assigned, then only fields whose
+      name appears in the list are bound.
+    Procedure ClearFields;virtual;
+      clears the field definitions.
+    Function Fetch : Boolean;
+      fetches the next row. Is false if there was no more data.
+    Property Connection : TODBCConnection Read FConnection Write SetConnection;
+      The connection object to use.
+    Property BOF : Boolean read FBOF;
+      True if at beginning of data
+    Property EOF : Boolean read FEOF;
+      True if at end of data
+    Property Fields : TODBCFieldList Read FFields;
+      Collection of fields in result set (if any)
+
+  TODBCSQLStatement has the following extra methods/properties:
+  
+    procedure Prepare;
+      prepares the query. After this, Bindfields may be called.
+    procedure Unprepare;
+      unprepares the query. After this, Bindfields nor execute may be called.
+    procedure ExecSQL;
+      executes the SQL query. If it was not prepared it is executed
+      directly.
+    Procedure Open;
+      prepares the query, binds all fields, allocates buffers and
+      fetches the first row of the result set.
+    Procedure Close;
+      Undoes the 'Open'
+    procedure GetFieldList(List: TStrings);
+      Retsurns a list of field names in the result set. Can only be
+      called after Prepare/Open and before close.
+    Property Active : Boolean Read GetActive Write SetActive;
+      Setting Active to true is the same as calling open.
+      Setting it to false is the same as calling close.
+    Property SQL : TStrings
+      The SQL statement to be executed.
+
+
+  A query result is returned in a collection of TODBCField objects:
+
+TODBCField :
+    Property Position : SQLSmallint Read FPosition;
+       (position in the query)
+    Property Name : String read FName;
+       (name of the field)
+    Property DataType : SQLSmallInt read FDatatype;
+       (original SQL data type)
+    Property Size : SQLUinteger read FSize;
+       (Original SQL data size)
+    property DecimalDigits : SQLSmallInt read FDecimalDigits;
+       (Original SQL digits after decimal point)
+    Property Nullable : Boolean Read FNullable;
+       (Field is nullable ?)
+    Property Data : Pchar Read GetData;
+       (pointer to raw data)    
+    Property BufType : SQLSmallInt Read FBufType;
+       (SQL type of the allocated data buffer)
+    Property BufSize : SQLInteger Read FBufSize;
+       (Allocated size of the buffer)
+    Property IsNull : Boolean Read GetIsNull;
+       (Was the returned field value null ?)
+       
+    Property AsString : String Read GetAsString;
+       Field value as string.  
+    Property AsInteger : Integer Read GetAsInteger;
+       Field value as integer.  
+    Property AsBoolean : Boolean Read GetAsBoolean;
+       Field value as boolean.  
+    Property AsDouble : Double Read GetAsDouble;
+       Field value as DOUBLE
+    Property AsDateTime : TDateTime Read GetAsDateTime;
+       Field value as TDateTime
+       
+    The latter properties do some basic conversion i.e. 
+    if the result is an integer, the AsString will return
+    the integer value converted to a string.
+
+    Blob is not yet supported, but should be soon.
+
+List of examples:
+
+Program       test functionality 
+-------       -----------------
+
+testbcon.pp   tests browseconnect.
+testcon.pp    tests DSN connect.
+testdrcon.pp  tests driverconnect. 
+testenv.pp    test ennvironment functions.
+testfl.pp     test fieldlist.
+testodbc.pp   test raw odbc.
+testpa.pp     test procedure arguments.
+testpk.pp     test primary key lists.   
+testpr.pp     test procedure list.
+testsql.pp    test execution of SQL and retrieval of results.
+testst.pp     test preparing of a statement.
+testtl.pp     test table list.

+ 1465 - 0
fcl/db/odbc/fpodbc.pp

@@ -0,0 +1,1465 @@
+unit fpodbc;
+
+{$mode objfpc}
+{$h+}
+
+interface
+
+uses odbcsql,SysUtils,Classes;
+
+Type
+  TDSNTypes = (dtUser,dtSystem,dtBoth);
+  TODBCParamType  = (ptUnknown,ptInput,ptInputOutput,ptResult,ptOutput,ptRetVal);
+  TODBCParamTypes = Set of TODBCParamType;
+
+  TODBCObject = Class(TComponent)
+  Private
+    FHandle : SQLHandle;
+    FHandleType : SQLSmallint;
+    Function GetHandle : SQLHandle;
+    function GetHandleAllocated: Boolean;
+    function GetExtendedErrorInfo: String;
+  Protected
+    Function CreateHandle : SQLHandle; Virtual;
+    Function ParentHandle : SQLHandle; Virtual;
+    Procedure FreeHandle;
+    Function CheckODBC(Res : Integer;Msg : String) : Integer;
+  Public
+    Destructor Destroy; override;
+    Property Handle : SQLHandle Read GetHandle;
+    Property HandleAllocated : Boolean Read GetHandleAllocated;
+  end;
+
+  TODBCEnvironment = Class(TODBCObject)
+  Private
+    FODBCBehaviour : Integer;
+    procedure SetODBCbehaviour(const Value: Integer);
+    function GetNullTerminate: Boolean;
+    procedure SetNullTerminate(const Value: Boolean);
+  protected
+    function CreateHandle: SQLHandle; override;
+    Procedure SetIntAttribute(Const Attr,Value : Integer);
+    Procedure SetStringAttribute(Const Attr: Integer; Value : String);
+    Function GetIntAttribute(Const Attr : Integer) : Integer;
+    Function GetStringAttribute(Const Attr : Integer) : String;
+  Public
+    Constructor Create(Aowner : TComponent);override;
+    Function GetDriverNames(List : Tstrings) : Integer;
+    Function GetDataSourceNames(List : Tstrings; Types : TDSNTypes;Descriptions : Boolean) : Integer;
+    function GetDriverOptions(Driver: String; Options: TStrings): Integer;
+    Property ODBCBehaviour : Integer Read FODBCBehaviour Write SetODBCbehaviour;
+    Property NullTerminateStrings : Boolean Read GetNullTerminate Write SetNullTerminate;
+  end;
+
+  TConnectionBrowseEvent = Procedure (Sender : TObject;InParams,OutParams : Tstrings) of Object;
+
+  TODBCConnection = Class(TODBCObject)
+  Private
+    FActive : Boolean;
+    FDriverParams : TStrings;
+    FDSN,
+    FDriverName,
+    FUserName,
+    FPassword : String;
+    FEnvironMent : TODBCEnvironment;
+    FOnBrowseConnection : TConnectionBrowseEvent;
+    FWindowHandle : integer;
+    FDriverCOmpletion: SQLUSmallInt;
+    function GetDriverName: String;
+    function GetDriverParams: TStrings;
+    procedure SetActive(const Value: Boolean);
+    procedure SetDriverName(const Value: String);
+    procedure SetDriverParams(const Value: TStrings);
+    procedure SetDSN(const Value: String);
+    function GetEnvironment: TODBCEnvironMent;
+    procedure SetEnvironment(const Value: TODBCEnvironMent);
+  Protected
+    procedure ConnectToDriver;
+    procedure ConnectToDSN;
+    Procedure ConnectBrowsing;
+    Function ParentHandle : SQLHandle; override;
+    Procedure CheckActive;
+    Procedure CheckInActive;
+  Public
+    Constructor Create(Aowner : TComponent);override;
+    Destructor Destroy; override;
+    Procedure Connect;
+    Procedure Disconnect;
+    Procedure GetTableNames(S : TStrings; SystemTables : Boolean);
+    Procedure GetFieldNames(TableName : String; S : TStrings);
+    Procedure GetPrimaryKeyFields(TableName : String; S : TStrings);
+    procedure GetProcedureNames(S : TStrings);
+    procedure GetProcedureParams(ProcName : String;ParamTypes : TODBCParamTypes; S : TStrings);
+    Property DSN : String Read FDSN Write SetDSN;
+    Property DriverName : String Read GetDriverName Write SetDriverName;
+    Property DriverCompletion : SQLUSmallInt Read FDriverCOmpletion Write FDriverCompletion;
+    Property DriverParams : TStrings Read GetDriverParams Write SetDriverParams;
+    Property Active : Boolean Read FActive Write SetActive;
+    Property Environment : TODBCEnvironMent Read GetEnvironment Write SetEnvironment;
+    Property UserName : String Read FUserName Write FUserName;
+    Property Password  : string Read FPassword Write FPassword;
+    Property OnBrowseConnection : TConnectionBrowseEvent Read FonBrowseConnection Write FOnBrowseConnection;
+    Property WindowHandle : integer Read FWindowHandle Write FWindowHandle;
+  end;
+
+  TODBCStatement = Class;
+
+  TODBCFieldList = Class(TCollection)
+  Private
+    FStatement : TODBCStatement;
+  Public
+    Constructor Create(Statement : TODBCStatement);
+  end;
+
+  {
+    TODBCStatement allocates 1 big data buffer. For each bound field
+    two things are allocated in the buffer:
+    - Size of fetched data as filled in by fetch.
+    - data. (may be zero for blobs etc)
+    The FBuffOffset contains the offset in the buffer of the size field.
+    Data immediatly follows the size.
+  }
+
+  TODBCField = Class(TCollectionItem)
+  Private
+    FDecimalDigits,
+    FPosition : SQLSmallInt;
+    FName : String;
+    FSize : SQLUInteger;       // Declared size, as returned by DescribeCol
+    FNullable : Boolean;
+    FDataType : SQLSmallInt;   // Declared type, as returned by DescribeCol
+    FBuffOffSet : SQLInteger;  // Offset in data buffer.
+    FBuffer : Pointer;         // Pointer to data.
+    FBufSize : SQLInteger;     // Allocated buffer size.
+    FBufType : SQLSmallInt;    // Allocated buffer type
+    function GetAsString: String;
+    function GetData : PChar;
+    Function GetIsNull : Boolean;
+    Function GetAsInteger : Integer;
+    Function GetAsBoolean : Boolean;
+    Function GetAsDouble : Double;
+    Function GetAsDateTime : TDateTime;
+  Public
+    Property Position : SQLSmallint Read FPosition;
+    Property Name : String read FName;
+    Property DataType : SQLSmallInt read FDatatype;
+    Property Size : SQLUinteger read FSize;
+    property DecimalDigits : SQLSmallInt read FDecimalDigits;
+    Property Nullable : Boolean Read FNullable;
+    Property Data : Pchar Read GetData;
+    Property BufType : SQLSmallInt Read FBufType;
+    Property BufSize : SQLInteger Read FBufSize;
+    Property IsNull : Boolean Read GetIsNull;
+    Property AsString : String Read GetAsString;
+    Property AsInteger : Integer Read GetAsInteger;
+    Property AsBoolean : Boolean Read GetAsBoolean;
+    Property AsDouble : Double Read GetAsDouble;
+    Property AsDateTime : TDateTime Read GetAsDateTime;
+  end;
+
+  TODBCStatement = Class(TODBCObject)
+  Private
+    FBOF,FEOF : Boolean;
+    FConnection: TODBCConnection;
+    FFields : TODBCFieldList;
+    FBuffer : Pointer;
+  Protected
+    Function ParentHandle : SQLHandle; override;
+    procedure SetConnection(const Value: TODBCConnection);
+    procedure AllocBuffers;
+  Public
+    Constructor Create(Aowner : TComponent);override;
+    Destructor Destroy; override;
+    Procedure BindFields(RestrictList : TStrings);virtual;
+    Procedure ClearFields;virtual;
+    Function Fetch : Boolean;
+    Property Connection : TODBCConnection Read FConnection Write SetConnection;
+    Property BOF : Boolean read FBOF;
+    Property EOF : Boolean read FEOF;
+    Property Fields : TODBCFieldList Read FFields;
+  end;
+
+  TODBCTableList = Class(TODBCStatement)
+  Public
+    Procedure GetTableNames(S : TStrings; SystemTables : Boolean);
+  end;
+
+  TODBCFieldNamesList = Class(TODBCStatement)
+  Public
+    Procedure GetFieldNames(TableName : String;S : TStrings);
+  end;
+
+  TODBCPrimaryKeyFieldsList = Class(TODBCStatement)
+  Public
+    Procedure GetPrimaryKeyFields(TableName : String;S : TStrings);
+  end;
+
+  TODBCProcedureList = Class(TODBCStatement)
+  Public
+    Procedure GetProcedureList(S : TStrings);
+  end;
+
+  TODBCProcedureParams = Class(TODBCStatement)
+    Procedure GetProcedureParams(ProcName: String; ParamTypes: TODBCParamTypes; S: TStrings);
+  end;
+
+  TStatementState = (ssInactive,ssPrepared,ssBound,ssOpen);
+
+  TODBCSQLStatement = Class(TODBCStatement)
+  Private
+    FSQL : TStrings;
+    FState : TStatementState;
+    function GetActive: Boolean;
+    procedure SetActive(const Value: Boolean);
+  Protected
+    procedure FreeStatement(Option: SQLUSMALLINT);
+    procedure ExecuteDirect;
+    procedure ExecutePrepared;
+    Procedure SetSQL(const Value: TStrings);
+  Public
+    Constructor Create(Aowner : TComponent);override;
+    Destructor Destroy; override;
+    procedure Prepare;
+    procedure Unprepare;
+    Procedure BindFields(RestrictList : TStrings);override;
+    procedure ExecSQL;
+    Procedure Open;
+    Procedure Close;
+    procedure GetFieldList(List: TStrings);
+    Property Active : Boolean Read GetActive Write SetActive;
+    Property SQL : TStrings Read FSQL Write SetSQL;
+  end;
+
+  EODBCError = Class(Exception);
+
+Const
+  ODBCParamTypeNames : Array [TODBCParamType] of string
+                     = ('Unknown','Input','Input/Output','Result','Output','RetVal');
+
+Function DefaultEnvironment : TODBCEnvironment;
+
+implementation
+
+{ TODBCObject }
+
+resourcestring
+  SErrUnexpected = 'Unexpected ODBC error:';
+  SErrEnvironmentHandle = 'Cannot allocate environment handle:';
+  SErrInvalidBehaviour = 'Invalid value for ODBC behaviour: %d';
+  SErrNotConnected = 'Operation invalid when not connected.';
+  SErrConnected = 'Operation invalid when connected.';
+  SNeedDSNOrDriver = 'Cannot connect with empty DSN and driver names.';
+  SErrGettingDataSources = 'Error getting datasources:';
+  SErrGettingDriverNames = 'Error getting driver names:';
+  SErrGettingDriverOptions = 'Error getting driver options:';
+  SErrSettingEnvAttribute = 'Error setting environment attribute:';
+  SErrGettingEnvAttribute = 'Error Getting environment attribute:';
+  SErrBrowseConnecting = 'Error connecting to datasource via browse:';
+  SErrDSNConnect = 'Error connecting to DSN:';
+  SErrDriverConnect = 'Error connecting to driver:';
+  SErrDisconnecting = 'Error disconnecting:';
+  SErrNoConnectionForStatement = 'Missing connection for statement.';
+  SErrNoSQLStatement = 'Missing SQL statement.';
+  SErrPreparing = 'Error preparing statement:';
+  SErrGettingTableNames = 'Error getting table names:';
+  SErrFetchingData = 'Error fetching data:';
+  SErrFieldNames = 'Error getting field names:';
+  SErrPrimaryKeys = 'Error getting primary key names:';
+  SErrProcedureNames = 'Error getting procedure names:';
+  SErrExecuting = 'Error while executing statement:';
+  SErrExecutingPrepared = 'Error while executing prepared statement:';
+  SErrNotPrepared = 'Statement is not prepared';
+  SErrNotInactive = 'Statement is already prepared or executed.';
+  SErrStatementActive = 'A statement is still active';
+  SErrColumnCount = 'Error retrieving cilumn count:';
+  SErrColDescription = 'Error retrieving column description';
+  SErrInvalidConversion = 'invalid type conversion';
+  SErrBindCol = 'Error binding column';
+Const
+  ODBCSuccess = [SQL_SUCCESS,SQL_SUCCESS_WITH_INFO];
+
+Procedure ODBCError (Msg : String);
+
+begin
+  Raise EODBCError.Create(Msg);
+end;
+
+Procedure ODBCErrorFmt (Fmt : String;Args : Array of const);
+
+begin
+  Raise EODBCError.CreateFmt(Fmt,Args);
+end;
+
+Function CheckODBC(Res : Integer;Msg : String) : Integer;
+
+begin
+  Result:=Res;
+  if not Res in [SQL_SUCCESS,SQL_SUCCESS_WITH_INFO] then
+    begin
+    If MSG='' then
+      MSG:=SErrUnexpected;
+    ODBCErrorFmt(msg,[res]);
+    end;
+end;
+
+function TODBCObject.CheckODBC(Res: Integer; Msg: String): Integer;
+
+Var S : String;
+
+begin
+  Result:=Res;
+  if not Res in [SQL_SUCCESS,SQL_SUCCESS_WITH_INFO] then
+    begin
+    If MSG='' then
+      MSG:=SErrUnexpected;
+    S:=GetExtendedErrorInfo;
+    If S<>'' then
+      Msg:=Msg+LineEnding+S;
+    ODBCError(msg);
+    end;
+end;
+
+function TODBCObject.GetExtendedErrorInfo : String;
+
+Var
+  Res : SQLreturn;
+  I,MsgLen : SQLSmallInt;
+  SQLState : Array[0..6] of Char;
+  NativeError : SQLInteger;
+  MSg : Array[0..SQL_MAX_MESSAGE_LENGTH] of Char;
+  SState,SMsg : String;
+
+begin
+   I:=0;
+   Result:='';
+   Repeat
+     Inc(i);
+     Res:=SQLGetDiagRec(FhandleType, FHandle, i, SqlState, NativeError,
+            Msg, sizeof(Msg), MsgLen);
+     If Res<>SQL_NO_DATA then
+       begin
+       SState:=SQLState;
+       SMsg:=Msg;
+       If Length(Result)>0 then
+         Result:=Result+LineEnding;
+       Result:=Result+Format('[%s] : %s (%d)',[SState,SMsg,NativeError]);
+       end;
+   Until (Res=SQL_NO_DATA);
+end;
+
+
+
+
+function TODBCObject.CreateHandle: SQLHandle;
+begin
+{$ifdef debug}
+  Writeln(Classname,': Creating handle of type ',FHAndleType,' and parent ',ParentHandle);
+{$endif}
+  CheckODBC(SQLAllocHandle(FHandleType,ParentHandle,FHandle),SErrEnvironmentHandle);
+  Result:=FHandle;
+end;
+
+
+destructor TODBCObject.Destroy;
+begin
+  If FHandle<>0 then
+    FreeHandle;
+  inherited;
+end;
+
+procedure TODBCObject.FreeHandle;
+begin
+  If FHandle<>0 then
+    begin
+    SQLFreeHandle(FHandleType,FHandle);
+    FHandle:=0;
+    end;
+end;
+
+function TODBCObject.GetHandle: SQLHandle;
+begin
+  If FHandle=0 then
+    CreateHandle;
+  Result:=FHandle;
+end;
+
+function TODBCObject.GetHandleAllocated: Boolean;
+begin
+  Result:=(FHandle<>0)
+end;
+
+function TODBCObject.ParentHandle: SQLHandle;
+begin
+  Result:=SQL_NULL_HANDLE;
+end;
+
+{ TODBCEnvironment }
+
+constructor TODBCEnvironment.Create(Aowner: TComponent);
+begin
+  FHandleType:=SQL_HANDLE_ENV;
+  inherited;
+end;
+
+function TODBCEnvironment.CreateHandle: SQLHandle;
+begin
+  Result:=Inherited CreateHandle;
+  ODBCbehaviour:=SQL_OV_ODBC3;
+end;
+
+function TODBCEnvironment.GetDataSourceNames(List: Tstrings;
+  Types: TDSNTypes;Descriptions : Boolean): Integer;
+
+var
+  DSNName,
+  DSNDesc: array[0..SQL_MAX_OPTION_STRING_LENGTH] of Char;
+  lenn,lend : SQLSmallInt;
+  Dir : SQLSmallInt;
+  Sn,SD : String;
+
+begin
+  Case Types of
+    dtSystem : Dir:=SQL_FETCH_FIRST_SYSTEM;
+    dtUser : Dir:=SQL_FETCH_FIRST_USER;
+    dtBoth : Dir:=SQL_FETCH_FIRST;
+  end;
+  List.Clear;
+  CheckODBC(SQLDatasources(Handle, Dir,
+                           DSNName,SQL_MAX_OPTION_STRING_LENGTH, @lenn,
+                           DSNDesc,SQL_MAX_OPTION_STRING_LENGTH, @lend),SErrGettingDataSources);
+  Repeat
+    If Not Descriptions then
+      List.Add(DSNName)
+    else
+      begin
+      SN:=DSNName;
+      SD:=DSNDesc;
+      List.Add(SN+'='+SD);
+      end;
+  Until Not (SQLDataSources(Handle, SQL_FETCH_NEXT,
+                            DSNName, SQL_MAX_OPTION_STRING_LENGTH, @lenn,
+                            DSNDesc,SQL_MAX_OPTION_STRING_LENGTH, @lend) in ODBCSuccess);
+  Result:=List.Count;
+end;
+
+function TODBCEnvironment.GetDriverNames(List : Tstrings): Integer;
+
+Var
+  DriverName: array[0..SQL_MAX_OPTION_STRING_LENGTH] of Char;
+  len : SQLSmallInt;
+
+begin
+  List.Clear;
+  CheckODBC(SQLDrivers(Handle, SQL_FETCH_FIRST, DriverName,
+        SQL_MAX_OPTION_STRING_LENGTH, @len, Nil,0,Nil),SErrGettingDriverNames);
+  Repeat
+    List.Add(DriverName);
+  Until Not (SQLDrivers(Handle, SQL_FETCH_NEXT, DriverName,
+        SQL_MAX_OPTION_STRING_LENGTH, @len, Nil,0,Nil) in ODBCSuccess);
+  Result:=List.Count;
+end;
+
+function TODBCEnvironment.GetDriverOptions(Driver : String;Options: Tstrings): Integer;
+
+Var
+  DriverName,
+  DriverOptions: array[0..SQL_MAX_OPTION_STRING_LENGTH] of Char;
+  lenn,leno : SQLSmallInt;
+  Found : Boolean;
+  P : PChar;
+  S : string;
+
+begin
+  CheckODBC(SQLDrivers(Handle, SQL_FETCH_FIRST, DriverName,
+        SQL_MAX_OPTION_STRING_LENGTH, @lenn, DriverOptions,
+        SQL_MAX_OPTION_STRING_LENGTH,@Leno),SErrGettingDriverOptions);
+  Result:=0;
+  Options.Clear;
+  Repeat
+    Found:=CompareText(Driver,DriverName)=0;
+    If Found then
+      begin
+      P:=@DriverOptions[0];
+      While P[0]<>#0 do
+        begin
+        S:=StrPas(P);
+        options.Add(S);
+        Inc(P,Length(S)+1);
+        end;
+      end;
+  Until Not (SQLDrivers(Handle, SQL_FETCH_NEXT, DriverName,
+        SQL_MAX_OPTION_STRING_LENGTH, @lenn, DriverOptions,
+        SQL_MAX_OPTION_STRING_LENGTH,@Leno) in ODBCSuccess) or Found;
+  Result:=Options.Count;
+end;
+
+function TODBCEnvironment.GetIntAttribute(const Attr: Integer): Integer;
+begin
+  CheckODBC(SQLSetEnvAttr(Handle,Attr,SQLPointer(@result),0),SErrSettingEnvAttribute);
+end;
+
+function TODBCEnvironment.GetNullTerminate: Boolean;
+begin
+  Result:=(GetIntAttribute(SQL_ATTR_OUTPUT_NTS)=SQL_TRUE);
+end;
+
+function TODBCEnvironment.GetStringAttribute(const Attr: Integer): String;
+
+Var
+  OldLen,Len: Integer;
+
+begin
+  OldLen:=0;
+  Repeat
+    Inc(OldLen,255);
+    SetLength(Result,OldLen);
+    CheckODBC(SQLGetEnvAttr(Handle,Attr,SQLPointer(@result),OldLen,@Len),SErrGettingEnvAttribute);
+  until (Len<=OldLen);
+  SetLength(Result,Len);
+end;
+
+procedure TODBCEnvironment.SetIntAttribute(const Attr, Value: Integer);
+begin
+  CheckODBC(SQLSetEnvAttr(Handle,Attr,SQLPointer(Value),0),SErrSettingEnvAttribute);
+end;
+
+procedure TODBCEnvironment.SetNullTerminate(const Value: Boolean);
+begin
+  If Value then
+    SetIntAttribute(SQL_ATTR_OUTPUT_NTS,SQL_TRUE)
+  else
+    SetIntAttribute(SQL_ATTR_OUTPUT_NTS,SQL_FALSE);
+end;
+
+procedure TODBCEnvironment.SetODBCbehaviour(const Value: Integer);
+begin
+  If (Value<>FODBCBehaviour) then
+    begin
+    If Not (Value in [SQL_OV_ODBC3,SQL_OV_ODBC2]) Then
+      ODBCErrorFmt(SErrInvalidBehaviour,[Value]);
+    SetIntAttribute(SQL_ATTR_ODBC_VERSION,Value);
+    FODBCBehaviour := Value;
+    end;
+end;
+
+procedure TODBCEnvironment.SetStringAttribute(const Attr: Integer;
+  Value: String);
+begin
+  CheckODBC(SQLSetEnvAttr(Handle,Attr,SQLPointer(Value),Length(Value)),SErrSettingEnvAttribute);
+end;
+
+{ TODBCConnection }
+
+procedure TODBCConnection.CheckActive;
+begin
+  If Not FActive then
+    ODBCError(SErrNotConnected);
+end;
+
+procedure TODBCConnection.CheckInActive;
+begin
+  If FActive then
+    ODBCError(SErrConnected);
+end;
+
+procedure TODBCConnection.Connect;
+begin
+  If Not FActive then
+    begin
+    If Assigned (FonBrowseConnection) then
+      ConnectBrowsing
+    else If (FDSN<>'') then
+      ConnectToDSN
+    else if FDriverName<>'' then
+      ConnectToDriver
+    else
+      ODBCError(SNeedDSNOrDriver);
+    FActive:=True;
+    end;
+end;
+
+Function ListToBuf(List : Tstrings; Buf : PChar; Sep : Char; MaxLen : Integer) : Boolean;
+
+Var
+  P : PChar;
+  S : String;
+  I,Len : Integer;
+
+begin
+  P:=Buf;
+  I:=0;
+  Result:=True;
+  While Result and (I<List.Count) do
+    begin
+    S:=List[i];
+    If I<List.Count-1 then
+      S:=S+Sep;
+    Len:=Length(S);
+    Result:=(Longint(P-Buf)+Len)<=MaxLen;
+    If Result then
+      begin
+      Move(S[1],P^,Len);
+      Inc(P,Len);
+      end;
+    Inc(i);
+    end;
+  P[0]:=#0;
+end;
+
+Function BufToList(Buf : PChar;MaxLen : Integer;List : Tstrings;Sep : Char) : Integer;
+
+Var
+  S : String;
+  P : PChar;
+  Totlen,Len : Integer;
+
+begin
+  List.Clear;
+  Result:=0;
+  P:=Buf;
+  TotLen:=0;
+  While (P[0]<>#0) or (totlen<Maxlen) do
+    begin
+    Len:=0;
+    While Not (P[len] in [Sep,#0]) do
+      Inc(len);
+    SetLength(S,Len);
+    List.Add(S);
+    Move(P[0],S[1],Len);
+    Inc(P,Len);
+    If P[0]<>#0 then
+      Inc(P,1);
+    inc(Totlen,Len+1);
+    end;
+  Result:=List.Count;
+end;
+
+
+Procedure TODBCConnection.ConnectBrowsing;
+
+Var
+  Inlist,OutList : TStringList;
+  InStr,
+  OutStr: Array[0..SQL_MAX_OPTION_STRING_LENGTH] of Char;
+  i,Res : Integer;
+  olen : SQLSmallint;
+
+begin
+  InList:=TStringList.Create;
+  OutList:=TstringList.Create;
+  try
+    If FDSN<>'' then
+      InList.Add('DSN='+FDSN)
+    else If FDriverName<>'' then
+      begin
+      Inlist.Add('DRIVER='+FDriverName);
+      For I:=0 to DriverParams.Count-1 do
+        Inlist.Add(DriverParams[i]);
+      end;
+    Repeat
+      ListToBuf(Inlist,Instr,';',SQL_MAX_OPTION_STRING_LENGTH);
+      Res:=SQLBrowseConnect(Handle,Instr,SQL_NTS,Outstr,SQL_MAX_OPTION_STRING_LENGTH,Olen);
+      If RES=SQL_NEED_DATA then
+        begin
+        OutList.Clear;
+        BufToList(OutStr,Olen,OutList,';');
+        FOnBrowseConnection(Self,InList,OutList);
+        end
+    Until (Res<>SQL_NEED_DATA);
+    CheckODBC(Res,SErrBrowseConnecting);
+  Finally
+    Outlist.free;
+    InList.Free;
+  end;
+end;
+
+Procedure TODBCConnection.ConnectToDSN;
+begin
+  CheckODBC(SQLConnect(Handle,PSQLChar(FDSN),SQL_NTS,
+                    PSQLChar(FUserName),SQL_NTS,
+                    PSQLChar(FPassword),SQL_NTS),SErrDSNConnect);
+end;
+
+
+Procedure TODBCConnection.ConnectToDriver;
+
+Var
+  Instr,
+  OutStr :  Array[0..SQL_MAX_OPTION_STRING_LENGTH] of Char;
+  OLen : SQLSmallint;
+  InList : TStringList;
+
+begin
+  InList:=TStringList.Create;
+  Try
+    Inlist.Assign(DriverParams);
+    Inlist.Insert(0,'DRIVER={'+DRIVERNAME+'}');
+    ListToBuf(Inlist,InStr,';',SQL_MAX_OPTION_STRING_LENGTH);
+  Finally
+    Inlist.Free;
+  end;
+  CheckODBC(SQLDriverConnect(Handle,FWindowHandle,
+               Instr,SQL_NTS,
+               OutStr,SQL_MAX_OPTION_STRING_LENGTH,
+               Olen,FDriverCompletion),SErrDriverConnect);
+end;
+
+constructor TODBCConnection.Create(Aowner: TComponent);
+begin
+  inherited;
+  FHandleType:=SQL_HANDLE_DBC;
+  FDriverParams:=TStringList.Create;
+  FDriverCompletion:=SQL_DRIVER_NOPROMPT;
+end;
+
+destructor TODBCConnection.Destroy;
+begin
+  Disconnect;
+  inherited;
+end;
+
+procedure TODBCConnection.Disconnect;
+begin
+  If FActive then
+    begin
+    CheckODBC(SQLDisconnect(Handle),SErrDisconnecting);
+    Factive:=False;
+    end;
+end;
+
+function TODBCConnection.GetDriverName: String;
+begin
+  Result:=FDriverName;
+end;
+
+function TODBCConnection.GetDriverParams: TStrings;
+begin
+  Result:=FDriverParams;
+end;
+
+function TODBCConnection.GetEnvironment: TODBCEnvironMent;
+begin
+  If FEnvironment=Nil then
+    result:=DefaultEnvironment
+  else
+    Result:=FEnvironment;
+end;
+
+procedure TODBCConnection.SetActive(const Value: Boolean);
+begin
+  If Value then
+    Connect
+  else
+    Disconnect;
+end;
+
+procedure TODBCConnection.SetDriverName(const Value: String);
+begin
+  CheckInactive;
+  FDSN:='';
+  If CompareText(FDriverName,Value)<>0 then
+    begin
+    FDriverName:=Value;
+    FDriverParams.Clear;
+    end;
+end;
+
+procedure TODBCConnection.SetDriverParams(const Value: TStrings);
+begin
+  CheckInactive;
+  FDriverParams.Assign(Value);
+end;
+
+procedure TODBCConnection.SetDSN(const Value: String);
+begin
+  CheckInactive;
+  FDSN := Value;
+end;
+
+procedure TODBCConnection.SetEnvironment(const Value: TODBCEnvironMent);
+begin
+  CheckInactive;
+  If (Value<>Environment) then // !! may be defaultenvironment...
+    begin
+    If HandleAllocated then
+      FreeHandle;
+    FEnvironment:=Value
+    end;
+end;
+
+
+function TODBCConnection.ParentHandle: SQLHandle;
+begin
+  Result:=Environment.Handle
+end;
+
+Const
+  DefEnv : Pointer = Nil;
+
+Function DefaultEnvironment : TODBCEnvironment;
+
+begin
+  If DefEnv=Nil then
+    DefEnv:=TODBCEnvironment.Create(Nil);
+  Result:=TODBCEnvironment(DefEnv);
+end;
+
+procedure TODBCConnection.GetTableNames(S: TStrings;
+  SystemTables: Boolean);
+begin
+  With TODBCTableList.Create(Self) do
+    try
+      GetTableNames(S,SystemTables);
+    finally
+      Free;
+    end;
+end;
+
+procedure TODBCConnection.GetFieldNames(TableName: String; S: TStrings);
+begin
+  With TODBCFieldNamesList.Create(Self) do
+    try
+      GetFieldNames(TableName,S);
+    finally
+      Free;
+    end;
+end;
+
+procedure TODBCConnection.GetPrimaryKeyFields(TableName: String;
+  S: TStrings);
+begin
+  With TODBCPrimaryKeyFieldsList.Create(Self) do
+    try
+      GetPrimaryKeyFields(TableName,S);
+    finally
+      Free;
+    end;
+end;
+
+procedure TODBCConnection.GetProcedureNames(S: TStrings);
+begin
+  With TODBCProcedureList.Create(Self) do
+    try
+      GetProcedureList(S);
+    Finally
+      Free;
+    end;
+end;
+
+procedure TODBCConnection.GetProcedureParams(ProcName: String;
+  ParamTypes: TODBCParamTypes; S: TStrings);
+begin
+  With TODBCProcedureParams.Create(Self) do
+    Try
+      GetProcedureParams(ProcName,Paramtypes,S);
+    finally
+      Free;
+    end;
+end;
+
+{ TODBCStatement }
+
+Type
+  TODBCFieldBufRec = Record
+    T{ype}    : SQlSmallint;
+    B{ufsize} : SQLInteger;
+    {Buftyp}e : SQLSmallint;
+  end;
+
+Const
+  BufDescrCount = 26;
+  BufDescr : Array[1..BufDescrCount] of TODBCFieldBufRec =
+  { Type                Bufsize              Buftype }
+  (
+  (T:SQL_CHAR          ;b:-1                  ;e: SQL_CHAR),
+  (T:SQL_NUMERIC       ;b:sizeof(SQLDouble)   ;e: SQL_DOUBLE),
+  (T:SQL_DECIMAL       ;b:sizeof(SQLDouble)   ;e: SQL_DOUBLE),
+  (T:SQL_INTEGER       ;b:sizeof(SQLInteger)  ;e: SQL_INTEGER),
+  (T:SQL_SMALLINT      ;b:sizeof(SQLSmallInt) ;e: SQL_SMALLINT),
+  (T:SQL_FLOAT         ;b:sizeof(SQLDOUBLE)   ;e: SQL_DOUBLE),
+  (T:SQL_REAL          ;b:sizeof(SQLDOUBLE)   ;e: SQL_DOUBLE),
+  (T:SQL_DOUBLE        ;b:Sizeof(SQLDOUBLE)   ;e: SQL_DOUBLE),
+  (T:SQL_DATE          ;b:Sizeof(SQL_DATE_STRUCT) ;e: SQL_DATE),
+  (T:SQL_TIME          ;b:sizeof(SQL_TIME_STRUCT) ;e: SQL_TIME),
+  (T:SQL_TIMESTAMP     ;b:sizeof(SQL_TIMESTAMP_STRUCT) ;e: SQL_TIMESTAMP),
+  (T:SQL_VARCHAR       ;b:-1                  ;e: SQL_CHAR),
+  (T:SQL_UNKNOWN_TYPE  ;b:0                   ;e: SQL_UNKNOWN_TYPE),
+  (T:SQL_LONGVARCHAR   ;b:-1                  ;e: SQL_CHAR),
+  (T:SQL_BINARY        ;b:-2                  ;e: SQL_BINARY),
+  (T:SQL_VARBINARY     ;b:-2                  ;e: SQL_BINARY),
+  (T:SQL_LONGVARBINARY ;b:-2                  ;e: SQL_BINARY),
+  (T:SQL_BIGINT        ;b:sizeOf(SQLDOUBLE)   ;e: SQL_DOUBLE),
+  (T:SQL_TINYINT       ;b:Sizeof(SQLSMALLINT) ;e: SQL_SMALLINT),
+  (T:SQL_BIT           ;b:sizeof(SQL_CHAR)    ;e: SQL_BIT),
+  (T:SQL_WCHAR         ;b:-1                  ;e: SQL_CHAR),
+  (T:SQL_WVARCHAR      ;b:-1                  ;e: SQL_CHAR),
+  (T:SQL_WLONGVARCHAR  ;b:-1                  ;e: SQL_CHAR),
+  (T:SQL_TYPE_DATE     ;b:sizeof(SQL_DATE_STRUCT) ;e: SQL_TYPE_DATE),
+  (T:SQL_TYPE_TIME     ;b:sizeof(SQL_TIME_STRUCT) ;e: SQL_TYPE_TIME),
+  (T:SQL_TYPE_TIMESTAMP;b:sizeof(SQL_TIMESTAMP_STRUCT) ;e: SQL_TYPE_TIMESTAMP)
+  );
+{  // template
+  (T: ;b: ;e: ),
+}
+
+Function GetColSizeBufType (Coltype: SQLSmallint;
+                             Var BufSize : SQLInteger;
+                             Var BufType : SQLSmallInt) : Boolean;
+Var
+  I : Integer;
+
+begin
+  I:=0;
+  BufSize:=0;
+  BufType:=0;
+  While (I<=BufDescrCount) and (BufDescr[i].t<>Coltype) do
+    Inc(i);
+  Result:=(i<=BufDescrCount);
+  If Result then
+    begin
+    BufSize:=BufDescr[i].b;
+    BufType:=BufDescr[i].e;
+    end;
+end;
+
+
+procedure TODBCStatement.BindFields(RestrictList : TStrings);
+
+Var
+  Count: SQLSmallInt;
+  CName : Array[0..SQL_NAME_LEN] of Char;
+  CSize : SQLUINTEGER;
+  CDataType,CDecimals,CNullable,CNameLen: SQLSmallInt;
+  I : integer;
+
+begin
+  CheckODBC(SQLNumResultCols(Handle,Count),SErrColumnCount);
+  For I:=1 to Count do
+    begin
+    CheckODBC(SQLDescribeCol(Handle,i,CName,SQL_NAME_LEN,CNameLen,
+                             CdataType,CSize, CDecimals,CNullable)
+              ,SErrColDescription);
+    If Not Assigned(RestrictList) or (RestrictList.IndexOf(Cname)<>-1) then
+      With FFields.Add as TODBCField do
+        begin
+        FPosition:=I;
+        FName:=Cname;
+        FDataType:=CDataType;
+        FSize:=CSize;
+        FDecimalDigits:=CDecimals;
+        FNullable:=(CNullable=SQL_TRUE);
+        GetColsizeBufType(FDataType,FBufSize,FBufType);
+        If FBufSize=-1 then
+          FBufSize:=FSize;
+        end;
+    end;
+  AllocBuffers;
+  For I:=0 to Count-1 do
+    With FFields.Items[i] as TODBCField do
+      CheckODBC(SQLBindCol(Handle,FPosition,FBufType,GetData,FBufSize,FBuffer+FBuffOffset)
+               ,SErrBindCol);
+
+end;
+
+procedure TODBCStatement.ClearFields;
+begin
+  FFields.Clear;
+end;
+
+constructor TODBCStatement.Create(Aowner: TComponent);
+begin
+  FHandleType:=SQL_HANDLE_STMT;
+  inherited;
+  If AOwner is TODBCConnection then
+    Connection:=TODBCConnection(Aowner);
+  FFields:=TODBCFieldList.Create(Self);
+end;
+
+function TODBCStatement.ParentHandle: SQLHandle;
+begin
+   If (Connection=Nil) then
+     ODBCError(SErrNoConnectionForStatement);
+   Result:=Connection.Handle;
+end;
+
+procedure TODBCStatement.SetConnection(const Value: TODBCConnection);
+begin
+  If Value<>FConnection then
+    begin
+    If HandleAllocated then
+      FreeHandle;
+    FConnection := Value;
+    end;
+end;
+
+Function TODBCStatement.fetch : Boolean;
+
+Var
+  res : SQLReturn;
+
+begin
+  Res:=SQLFetch(Handle);
+  Result:=(Res=SQL_SUCCESS);
+  If Not Result and (Res<>SQL_NO_DATA) then
+    CheckODBC(Res,SErrFetchingData);
+  FBof:=False;
+  If (Res=SQL_NO_DATA) then
+    FEOF:=True;
+end;
+
+destructor TODBCStatement.Destroy;
+begin
+  FFields.Free;
+  inherited;
+end;
+
+{ TODBCSQLStatement }
+
+procedure TODBCSQLStatement.GetFieldList(List : TStrings);
+
+Var
+  Count: SQLSmallInt;
+  CName : Array[0..SQL_NAME_LEN] of Char;
+  CSize : SQLUINTEGER;
+  CDataType,CDecimals,CNullable,CNameLen: SQLSmallInt;
+  I : integer;
+
+begin
+  if Not (FState in [ssPrepared,ssBound,ssOpen]) then
+    ODBCError(SErrNotPrepared);
+  List.Clear;
+  CheckODBC(SQLNumResultCols(Handle,Count),SErrColumnCount);
+  For I:=1 to Count do
+    begin
+    CheckODBC(SQLDescribeCol(Handle,i,CName,SQL_NAME_LEN,CNameLen,
+                             CdataType,CSize, CDecimals,CNullable)
+              ,SErrColDescription);
+    List.Add(CName);
+    end;
+end;
+
+
+procedure TODBCSQLStatement.Unprepare;
+
+begin
+  Case FState of
+    ssBound,ssOpen :
+              begin
+              ClearFields;
+              FreeStatement(SQL_CLOSE);
+              end;
+    ssPrepared : begin
+                 FreeStatement(SQL_CLOSE);
+                 end;
+  end;
+  FState:=ssInactive;
+end;
+
+procedure TODBCSQLStatement.FreeStatement(Option : SQLUSMALLINT);
+
+begin
+  SQLFreeStmt(Handle,SQL_CLOSE);
+end;
+
+procedure TODBCSQLStatement.Close;
+begin
+  if FState<>ssInactive then
+    begin
+    Unprepare;
+    FreeStatement(SQL_CLOSE);
+    FState:=ssInactive;
+    end;
+end;
+
+constructor TODBCSQLStatement.Create(Aowner: TComponent);
+begin
+  inherited;
+  FSQL:=TStringList.Create;
+end;
+
+destructor TODBCSQLStatement.Destroy;
+begin
+  if FState=ssOpen then
+    Close
+  else If FState<>ssInactive then
+    Unprepare;
+  FSQL.Free;
+  inherited;
+end;
+
+procedure TODBCSQLStatement.ExecSQL;
+begin
+  Case FState of
+    ssPrepared,ssBound : ExecutePrepared;
+    ssInactive : ExecuteDirect;
+  else
+    Raise Exception.Create(SErrStatementActive)
+  end;
+end;
+
+procedure TODBCSQLStatement.ExecuteDirect;
+
+Var
+  S : String;
+
+begin
+  if FState<>ssInactive then
+    ODBCError(SErrStatementActive);
+  S:=SQL.Text;
+  CheckODBC(SQLExecDirect(Handle,PChar(S),SQL_NTS),SErrExecuting);
+end;
+
+procedure TODBCSQLStatement.ExecutePrepared;
+begin
+  if Not (FState in [ssPrepared,ssBound]) then
+    ODBCError(SErrNotPrepared);
+  CheckODBC(SQLExecute(Handle),SErrExecutingPrepared);
+end;
+
+function TODBCSQLStatement.GetActive: Boolean;
+begin
+  Result:=(FState=ssOpen);
+end;
+
+procedure TODBCSQLStatement.Open;
+begin
+  if (FState<>ssOpen) then
+    begin
+    Writeln('Preparing');
+    If FState=ssInactive then
+      Prepare;
+    Writeln('Bind fields');
+    if FState=ssPrepared then
+      BindFields(Nil);
+    Writeln('Executing');
+    ExecSQL;
+    Writeln('Fetching');
+    If FState=ssBound then
+      Fetch;
+    FState:=ssOpen;
+    FBOF:=True;
+    end;
+end;
+
+procedure TODBCSQLStatement.Prepare;
+
+Var
+  S : String;
+
+begin
+  If FState<>ssInactive then
+    ODBCError(SErrNotInactive);
+  If (FSQL.Count=0) then
+    ODBCError(SErrNoSQLStatement);
+  S:=FSQL.Text;
+  CheckODBC(SQLPrepare(Handle,PChar(S),SQL_NTS),SErrPreparing);
+  FState:=ssPrepared;
+end;
+
+procedure TODBCSQLStatement.SetActive(const Value: Boolean);
+begin
+  If Value then
+    Open
+  else
+    Close;
+end;
+
+procedure TODBCSQLStatement.SetSQL(const Value: TStrings);
+
+begin
+  FSQL.Assign(Value);
+end;
+
+
+procedure TODBCSQLStatement.BindFields(RestrictList: TStrings);
+begin
+  inherited;
+  FState:=ssBound;
+end;
+
+
+procedure TODBCStatement.AllocBuffers;
+
+Var
+  I,TotalSize,AddSize : Integer;
+
+begin
+  TotalSize:=0;
+  For i:=0 to FFields.Count-1 do
+    With (FFields.Items[i] as TODBCField) do
+        begin
+        AddSize:=FBufSize;
+        If FBufSize=-2 then // Blob.
+          AddSize:=0
+        else if FBufSize=-1 then
+          AddSize:=FSize+1; // some Char variant.
+        // Store offset temporarily in FData
+        FBuffOffset:=TotalSize;
+        Inc(TotalSize,AddSize+SizeOf(SQLinteger));
+        end;
+  FBuffer:=GetMem(TotalSize);
+  TotalSize:=0;
+  For i:=0 to FFields.Count-1 do
+    With (FFields.Items[i] as TODBCField) do
+      FBuffer:=Self.FBuffer;
+end;
+
+{ TODBCTableList }
+
+procedure TODBCTableList.GetTableNames(S: TStrings; SystemTables : Boolean);
+
+var
+  TName,
+  TType: array[0..SQL_NAME_LEN+1] of char;
+  NL,TL: SQLINTEGER;
+  Res: SQLRETURN;
+
+begin
+  S.Clear;
+  Res:=CheckODBC(SQLTables(handle, nil,0,nil,0,nil,0,nil,0),SErrGettingTableNames);
+  if Res=SQL_SUCCESS then
+    begin
+    // Must bind by colno, because names changed between ODBC 2.0 and 3.0 !!
+    SQLBindCol(handle,3,SQL_CHAR,@TName,SQL_NAME_LEN,@NL);
+    SQLBindCol(handle,4,SQL_CHAR,@TType,SQL_NAME_LEN,@TL);
+    While Fetch do
+      if SystemTables or (CompareText(TType,'SYSTEM TABLE')<>0) then
+         S.Add(TName);
+    end;
+end;
+
+{ TODBCFieldNamesList }
+
+procedure TODBCFieldNamesList.GetFieldNames(TableName: String;
+  S: TStrings);
+
+var
+  FName : array[0..SQL_NAME_LEN+1] of char;
+  NF : SQLINTEGER;
+  Res: SQLRETURN;
+
+begin
+  S.Clear;
+  Res:=CheckODBC(SQLColumns(handle, nil, 0, nil, 0, pchar(TableName), SQL_NTS, nil, 0),SErrFieldNames);
+  if Res=SQL_SUCCESS then
+    begin
+    SQLBindCol(handle, 4, SQL_CHAR, @FNAme, SQL_NAME_LEN, @NF);
+    While Fetch do
+       S.Add(FName);
+    end;
+end;
+
+{ TODBCPrimaryKeyFieldsList }
+
+procedure TODBCPrimaryKeyFieldsList.GetPrimaryKeyFields(TableName: String;
+  S: TStrings);
+var
+  FName : array[0..SQL_NAME_LEN+1] of char;
+  NF : SQLINTEGER;
+  Res: SQLRETURN;
+
+begin
+  S.Clear;
+  Res:=CheckODBC(SQLPrimaryKeys(handle, nil, 0, nil, 0, pchar(TableName), SQL_NTS),SErrPrimaryKeys);
+  if Res=SQL_SUCCESS then
+    begin
+    SQLBindCol(handle, 4, SQL_CHAR, @FNAme, SQL_NAME_LEN, @NF);
+    While Fetch do
+       S.Add(FName);
+    end;
+
+end;
+
+{ TODBCProcedureList }
+
+procedure TODBCProcedureList.GetProcedureList(S: TStrings);
+
+var
+  PName : array[0..SQL_NAME_LEN+1] of char;
+  NP : SQLINTEGER;
+  Res: SQLRETURN;
+
+begin
+  S.Clear;
+  Res:=CheckODBC(SQLProcedures(handle, nil, 0, nil, 0, Nil, 0),SErrProcedureNames);
+  if Res=SQL_SUCCESS then
+    begin
+    SQLBindCol(handle, 3, SQL_CHAR, @PNAme, SQL_NAME_LEN, @NP);
+    While Fetch do
+      S.Add(PName);
+    end;
+
+end;
+
+{ TODBCProcedureParams }
+
+procedure TODBCProcedureParams.GetProcedureParams(ProcName: String;
+  ParamTypes: TODBCParamTypes; S: TStrings);
+
+var
+  PName : array[0..SQL_NAME_LEN+1] of char;
+  NP,NT : SQLINTEGER;
+  Ptype : SQLSmallInt;
+  Res: SQLRETURN;
+
+begin
+  S.Clear;
+  Res:=CheckODBC(SQLProcedureColumns(handle, nil, 0, nil, 0, PChar(ProcName),SQL_NTS,Nil, 0),SErrProcedureNames);
+  if Res=SQL_SUCCESS then
+    begin
+    SQLBindCol(handle, 4, SQL_CHAR, @PName, SQL_NAME_LEN, @NP);
+    SQLBindCol(handle, 5, SQL_SMALLINT, @PType, SizeOf(SQLSmallInt), @NT);
+    While Fetch do
+      begin
+      If TODBCParamType(PType) in ParamTypes then
+        S.Add(PName);
+      end;
+    end;
+end;
+
+{ TODBCFieldList }
+
+constructor TODBCFieldList.Create(Statement: TODBCStatement);
+begin
+  FStatement:=Statement;
+  Inherited Create(TODBCField);
+end;
+
+{ TODBCField }
+
+function TODBCField.GetAsString: String;
+begin
+  If IsNull then
+    Result:=''
+  else
+    Case FBufType of
+      SQL_Smallint : Result:=IntToStr(PSQLSmallInt(Data)^);
+      SQL_Integer  : Result:=IntToStr(PSQLINTEGER(Data)^);
+      SQL_BIT      : Result:=IntToStr(PByte(Data)^);
+      SQL_CHAR     : Result:=StrPas(Data);
+      SQL_DOUBLE   : Result:=FloatToStr(GetAsDouble);
+      SQL_DATE     : result:=DateToStr(AsDateTime);
+      SQL_TIME     : Result:=TimeToStr(AsDateTime);
+      SQL_TIMESTAMP : result:=datetimeToStr(AsDateTime);
+      SQL_TYPE_DATE  : result:=dateToStr(AsDateTime);
+      SQL_TYPE_TIMESTAMP : result:=datetimeToStr(AsDateTime);
+      SQL_TYPE_TIME : Result:=TimeToStr(AsDateTime);
+    else
+      ODBCError(SErrInvalidConversion)
+    end;
+end;
+
+function TODBCField.GetData : Pchar;
+
+begin
+  Result:=FBuffer+FBuffOffset+SizeOf(SQLinteger);
+end;
+
+function TODBCField.GetIsNull : boolean;
+
+begin
+  Result:=PSQLinteger(FBuffer+FBuffOffset)^=SQL_NULL_DATA;
+end;
+
+Function TODBCField.GetAsInteger : Integer;
+
+begin
+  If IsNull then
+    Result:=0
+  else
+    Case FBufType of
+      SQL_Smallint : Result:=PSQLSmallInt(Data)^;
+      SQL_Integer  : Result:=PSQLINTEGER(Data)^;
+      SQL_BIT      : Result:=PByte(Data)^;
+      SQL_CHAR     : Result:=StrToInt(GetAsString);
+      SQL_DOUBLE   : Result:=Round(GetAsDouble);
+      SQL_DATE,
+      SQL_TIME,
+      SQL_TIMESTAMP,
+      SQL_TYPE_DATE,
+      SQL_TYPE_TIMESTAMP,
+      SQL_TYPE_TIME : Result:=Round(AsDateTime);
+    else
+      ODBCError(SErrInvalidConversion)
+    end;
+end;
+
+Function TODBCField.GetAsBoolean : Boolean;
+
+begin
+  If IsNull then
+    Result:=False
+  else
+    Case FBufType of
+      SQL_Smallint : Result:=PSQLSmallInt(Data)^=0;
+      SQL_Integer  : Result:=PSQLINTEGER(Data)^=0;
+      SQL_BIT      : Result:=PBYTE(Data)^=0;
+      SQL_CHAR     : Result:=(StrToInt(GetAsString)=0);
+      SQL_DOUBLE   : Result:=Round(GetAsDouble)=0;
+      SQL_DATE,
+      SQL_TIME,
+      SQL_TIMESTAMP,
+      SQL_TYPE_DATE,
+      SQL_TYPE_TIMESTAMP,
+      SQL_TYPE_TIME : Result:=Round(AsDateTime)=0;
+    else
+      ODBCError(SErrInvalidConversion)
+    end;
+end;
+
+Function TODBCField.GetAsDouble : Double;
+
+begin
+  If IsNull then
+    Result:=0
+  else
+    Case FBufType of
+      SQL_Smallint : Result:=PSQLSmallInt(Data)^;
+      SQL_Integer  : Result:=PSQLINTEGER(Data)^;
+      SQL_BIT      : Result:=PBYTE(Data)^;
+      SQL_CHAR     : Result:=StrToFloat(GetAsString);
+      SQL_DOUBLE   : Result:=PSQLDOUBLE(GetData)^;
+      SQL_DATE,
+      SQL_TIME,
+      SQL_TIMESTAMP,
+      SQL_TYPE_DATE,
+      SQL_TYPE_TIMESTAMP,
+      SQL_TYPE_TIME : Result:=AsDateTime;
+    else
+      ODBCError(SErrInvalidConversion)
+    end;
+end;
+
+{
+function DateStructToDateTime( b:PSQL_DATE_STRUCT):TDateTime;
+function DateTimeToDateStruct( b:TDateTime):SQL_DATE_STRUCT;
+procedure DateTime2TimeStampStruct( var Value:SQL_TIMESTAMP_STRUCT; b:TDateTime);
+}
+Function TODBCField.GetAsDateTime : TDateTime;
+
+begin
+  If IsNull then
+    Result:=0
+  else
+    Case FBufType of
+      SQL_Smallint : Result:=PSQLSmallInt(Data)^;
+      SQL_Integer  : Result:=PSQLINTEGER(Data)^;
+      SQL_BIT      : Result:=PBYTE(Data)^;
+      SQL_CHAR     : Result:=StrToInt(GetAsString);
+      SQL_DOUBLE   : Result:=PSQLDOUBLE(GetData)^;
+      SQL_DATE     : Result:=DateStructToDateTime(PSQL_DATE_STRUCT(Data));
+      SQL_TIME     : Result:=TimeStructToDateTime(PSQL_TIME_STRUCT(Data));
+      SQL_TIMESTAMP : Result:=TimeStampStructToDateTime(PSQL_TIMESTAMP_STRUCT(Data));
+      SQL_TYPE_DATE : Result:=DateStructToDateTime(PSQL_DATE_STRUCT(Data));
+      SQL_TYPE_TIMESTAMP :  Result:=TimeStampStructToDateTime(PSQL_TIMESTAMP_STRUCT(Data));
+      SQL_TYPE_TIME : Result:=TimeStructToDateTime(PSQL_TIME_STRUCT(Data));
+    else
+      ODBCError(SErrInvalidConversion)
+    end;
+end;
+
+Finalization
+  If Assigned(DefEnv) then
+    TODBCEnvironment(DefEnv).Free;
+end.
+

+ 63 - 0
fcl/db/odbc/testbcon.pp

@@ -0,0 +1,63 @@
+program testbcon;
+{
+  Test browsingconnection
+  - I don't have a driver which supports it though :/
+}
+{$mode objfpc}
+uses fpodbc,Classes;
+
+Type
+  TApp = Class (TObject)
+    Conn : TODBCConnection;
+    Procedure GetParams (Sender : TObject; ListIn,ListOut : TStrings);
+    Procedure Run;
+  end;
+
+
+{ TApp }
+
+procedure TApp.GetParams(Sender: TObject; ListIn, ListOut: TStrings);
+
+Var
+  S : String;
+  i : integer;
+  
+begin
+  Writeln('Input parameters were :');
+  With ListIN do
+    For I:=0 to Count-1 do
+      Writeln(Strings[i]);
+  Writeln('Output parameters were :');
+  With Listout do
+    For I:=0 to Count-1 do
+      Writeln(Strings[i]);
+  Repeat
+    Writeln('Parameter to add to input (empty to quit):');
+    Readln(S);
+    If S<>'' then
+      ListIn.Add(S)
+  Until S='';
+end;
+
+procedure TApp.Run;
+begin
+  Conn:=TODBCConnection.Create(Nil);
+  Try
+    Conn.DSN:='FPC';
+    Conn.OnBrowseConnection:[email protected];
+    Conn.Active:=True;
+    Writeln('Connected !!');
+    Conn.Active:=False;
+  Finally
+    Conn.free;
+  end;
+end;
+
+begin
+  With Tapp.Create do
+    Try
+      Run;
+    Finally
+      Free;
+    end;
+end.

+ 19 - 0
fcl/db/odbc/testcon.pp

@@ -0,0 +1,19 @@
+program testcon;
+{$mode objfpc}
+uses fpodbc,Classes;
+
+var
+  Conn : TODBCConnection;
+
+begin
+  Conn:=TODBCConnection.Create(Nil);
+  Try
+    Conn.DSN:='FPC';
+    Conn.Active:=True;
+    Writeln('Connected !!');
+    Conn.Active:=False;
+    Writeln('Disconnected again');
+  Finally
+    Conn.free;
+  end;
+end.

+ 20 - 0
fcl/db/odbc/testdrcon.pp

@@ -0,0 +1,20 @@
+program testdrcon;
+{$mode objfpc}
+uses fpodbc,Classes;
+
+var
+  Conn : TODBCConnection;
+
+begin
+  Conn:=TODBCConnection.Create(Nil);
+  Try
+    Conn.drivername:='Microsoft Access Driver (*.mdb)';
+    Conn.DriverParams.Add('DBQ=d:\temp\odbc\testodbc.mdb');
+    Conn.Active:=True;
+    Writeln('Connected !!');
+    Conn.Active:=False;
+    Writeln('Disconnected again.');
+  Finally
+    Conn.free;
+  end;
+end.

+ 45 - 0
fcl/db/odbc/testenv.pp

@@ -0,0 +1,45 @@
+program testenv;
+{$mode objfpc}
+{$h+}
+uses fpodbc,Classes;
+
+Var
+  I,J : Integer;
+  List,Options : TStringList;
+  Env : TODBCEnvironment;
+  UseDefault : Boolean;
+
+begin
+   useDefault:=(ParamCount>0) and (Paramstr(1)='-d');
+   If UseDefault then
+     Env:=DefaultEnvironment
+   else
+     Env:=TODBCEnvironment.Create(Nil);
+  try
+    Writeln('Handle is : ',Env.Handle);
+    List:=TStringlist.Create;
+    Options:=TStringList.Create;
+    Writeln('List of drivers :');
+    Env.GetDriverNames(List);
+    Writeln('Count : ',List.Count);
+    For I:=0 to List.Count-1 do
+       Writeln(i:2,' : ',List[i]);
+    Writeln('List of driver options :');
+    For I:=0 to List.Count-1 do
+      begin
+      Env.GetDriverOptions(List[i],Options);
+      Writeln('Options for driver ',List[i],' : ');
+      For J:=0 to Options.Count-1 do
+        Writeln('  ',Options[j]);
+      end;
+    Env.GetDataSourceNames(List,dtBoth,True);
+    Writeln('List of datasource names : ');
+    For I:=0 to List.Count-1 do
+      writeln(i,' : ',List[i]);
+    List.free;
+    options.Free;
+  finally
+    If not UseDefault then
+      env.free;
+  end;
+end.

+ 29 - 0
fcl/db/odbc/testfl.pp

@@ -0,0 +1,29 @@
+program testfl;
+{$mode objfpc}
+uses fpodbc,Classes;
+
+var
+  Conn : TODBCConnection;
+  FieldNames : TStringList;
+  I : Integer;
+
+begin
+  Conn:=TODBCConnection.Create(Nil);
+  Try
+    Conn.DSN:='FPC';
+    Conn.Active:=True;
+    FieldNames:=TStringList.Create;
+    FieldNames.Sorted:=True;
+    Try
+      Conn.GetFieldNames('FPDev',FieldNames);
+      Writeln('Found ',FieldNames.Count,' Fields in table FPDev : ');
+      For I:=0 to FieldNames.Count-1 do
+        Writeln(FieldNames[i]);
+    finally
+      FieldNames.Free;
+    end;
+    Conn.Active:=False;
+  Finally
+    Conn.free;
+  end;
+end.

BIN
fcl/db/odbc/testodbc.mdb


+ 33 - 0
fcl/db/odbc/testpa.pp

@@ -0,0 +1,33 @@
+program testpa;
+{$mode objfpc}
+uses fpodbc,Classes;
+
+var
+  Conn : TODBCConnection;
+  ProcedureParams : TStringList;
+  I : Integer;
+  PT : TODBCParamType;
+
+begin
+  Conn:=TODBCConnection.Create(Nil);
+  Try
+    Conn.DSN:='BUGS';
+    Conn.Active:=True;
+    ProcedureParams:=TStringList.Create;
+    ProcedureParams.Sorted:=True;
+    Try
+      For PT:=ptUnknown to ptRetval do
+        begin
+        Conn.GetProcedureParams('GET_BUGID',[Pt],ProcedureParams);
+        Writeln('Found ',ProcedureParams.Count,' parameters of type ',ODBCParamTypeNames[Pt],' :');
+         For I:=0 to ProcedureParams.Count-1 do
+          Writeln(ProcedureParams[i]);
+        end;  
+    finally
+      ProcedureParams.Free;
+    end;
+    Conn.Active:=False;
+  Finally
+    Conn.free;
+  end;
+end.

+ 29 - 0
fcl/db/odbc/testpk.pp

@@ -0,0 +1,29 @@
+program testpl;
+{$mode objfpc}
+uses fpodbc,Classes;
+
+var
+  Conn : TODBCConnection;
+  PrimaryKeyFields : TStringList;
+  I : Integer;
+
+begin
+  Conn:=TODBCConnection.Create(Nil);
+  Try
+    Conn.DSN:='BUGS';
+    Conn.Active:=True;
+    PrimaryKeyFields:=TStringList.Create;
+    PrimaryKeyFields.Sorted:=True;
+    Try
+      Conn.GetPrimaryKeyFields('BUGS',PrimaryKeyFields);
+      Writeln('Found ',PrimaryKeyFields.Count,' primary key fields in table BUGS : ');
+      For I:=0 to PrimaryKeyFields.Count-1 do
+        Writeln(PrimaryKeyFields[i]);
+    finally
+      PrimaryKeyFields.Free;
+    end;
+    Conn.Active:=False;
+  Finally
+    Conn.free;
+  end;
+end.

+ 29 - 0
fcl/db/odbc/testpr.pp

@@ -0,0 +1,29 @@
+program testpr;
+{$mode objfpc}
+uses fpodbc,Classes;
+
+var
+  Conn : TODBCConnection;
+  ProcedureNames : TStringList;
+  I : Integer;
+
+begin
+  Conn:=TODBCConnection.Create(Nil);
+  Try
+    Conn.DSN:='BUGS';
+    Conn.Active:=True;
+    ProcedureNames:=TStringList.Create;
+    ProcedureNames.Sorted:=True;
+    Try
+      Conn.GetProcedureNames(ProcedureNames);
+      Writeln('Found ',ProcedureNames.Count,' procedures:');
+      For I:=0 to ProcedureNames.Count-1 do
+        Writeln(ProcedureNames[i]);
+    finally
+      ProcedureNames.Free;
+    end;
+    Conn.Active:=False;
+  Finally
+    Conn.free;
+  end;
+end.

+ 102 - 0
fcl/db/odbc/testsql.pp

@@ -0,0 +1,102 @@
+program testsql;
+{$mode objfpc}
+uses fpodbc,Classes,odbcsql;
+
+var
+  Conn : TODBCConnection;
+  St : TODBCSQLStatement;
+  FieldNames : TStringList;
+  I,Count : Integer;
+
+procedure DumpFielddef(F : TODBCField);
+
+begin
+  Writeln('Field ',F.Position,' : ',F.Name);
+  Writeln('Type : ',F.DataType);
+  Writeln('Size : ',F.Size);
+  Writeln('Decimal digits : ',F.DecimalDigits);
+  Writeln('Nullable : ',F.Nullable);
+end;
+
+procedure DumpField(F : TODBCField);
+
+begin
+  With F do
+    begin
+    Write(Name:12,BufType:5,'  ');
+    If IsNull then  
+      Writeln('(Null)')
+    else
+      Case BufType of
+        SQL_Smallint : Writeln(AsInteger);
+        SQL_Integer  : Writeln(AsInteger);
+        SQL_BIT      : Writeln(AsInteger);
+        SQL_CHAR     : Writeln(AsString);
+        SQL_DOUBLE   : Writeln(AsDouble);
+        SQL_DATE,
+        SQL_TIME,
+        SQL_TIMESTAMP,
+        SQL_TYPE_DATE,
+        SQL_TYPE_TIMESTAMP,
+        SQL_TYPE_TIME : Writeln(AsString);
+      else
+        Writeln('Unknown field type');
+      end;
+    end;
+end;
+
+
+begin
+  Conn:=TODBCConnection.Create(Nil);
+  Try
+    Conn.DSN:='FPC';
+    Conn.Active:=True;
+    ST:=TODBCSQLStatement.Create(Conn);
+    Try
+      ST.SQL.Text:='Select * from fpdev order by id';
+      Writeln('Opening');
+      ST.Open;
+      Writeln('Opened');
+      Try
+        FieldNames:=TStringList.Create;
+        Try
+        st.GetFieldList(FieldNames);
+        Writeln('Found ',FieldNames.Count,' Fields in result set :');
+        For I:=0 to FieldNames.Count-1 do
+          Writeln(i+1,': ',FieldNames[i]);
+        Writeln('End of list');
+        Writeln('FieldDefs:');
+        with st.fields do
+          for I:=0 to COunt-1 do
+            DumpFielddef(st.fields.items[i] as TODBCField);
+        Writeln('Data dump:');
+        Count:=0;
+        While not st.eof do
+          begin
+          Inc(Count);
+          Writeln('Record no ',Count,' : ');
+          Writeln('Name':12,'Type':5,'  Value');
+          for I:=0 to st.fields.COunt-1 do
+            DumpField(st.fields.items[i] as TODBCField);
+          st.fetch;
+          end;
+        Writeln('End of data');
+        finally
+          FieldNames.Free;
+          Writeln('Freed list');
+        end;
+      Finally
+        st.Close;
+        Writeln('Closed');
+      end;
+    Finally
+      ST.Free;
+      Writeln('Freed statement');
+    end;
+    Conn.Active:=False;
+    Writeln('Disactivated connection');
+  Finally
+    Conn.free;
+    Writeln('Freed Connection');
+  end;
+end.

+ 62 - 0
fcl/db/odbc/testst.pp

@@ -0,0 +1,62 @@
+program testst;
+{$mode objfpc}
+uses fpodbc,Classes;
+
+var
+  Conn : TODBCConnection;
+  St : TODBCSQLStatement;
+  FieldNames : TStringList;
+  I : Integer;
+  PT : TODBCParamType;
+
+procedure DumpFielddef(F : TODBCField);
+
+begin
+  Writeln('Field ',F.Position,' : ',F.Name);
+  Writeln('Type : ',F.DataType);
+  Writeln('Size : ',F.Size);
+  Writeln('Decimal digits : ',F.DecimalDigits);
+  Writeln('Nullable : ',F.Nullable);
+end;
+
+
+begin
+  Conn:=TODBCConnection.Create(Nil);
+  Try
+    Conn.DSN:='FPC';
+    Conn.Active:=True;
+    ST:=TODBCSQLStatement.Create(Conn);
+    Try
+      ST.SQL.Text:='Select * from fpdev';
+      ST.Prepare;
+      Try
+        FieldNames:=TStringList.Create;
+        Try
+          st.GetFieldList(FieldNames);
+          Writeln('Found ',FieldNames.Count,' Fields in result set :');
+          For I:=0 to FieldNames.Count-1 do
+            Writeln(i+1,': ',FieldNames[i]);
+          Writeln('End of list');
+          st.bindfields(nil);
+          with st.fields do
+            for I:=0 to COunt-1 do
+              DumpFielddef(st.fields.items[i] as TODBCField);
+        finally
+          FieldNames.Free;
+          Writeln('Freed list');
+        end;
+      Finally
+        St.Unprepare;
+        Writeln('Unprepared');
+      end;
+    Finally
+      ST.Free;
+      Writeln('Freed statement');
+    end;
+    Conn.Active:=False;
+    Writeln('Disactivated connection');
+  Finally
+    Conn.free;
+    Writeln('Freed Connection');
+  end;
+end.

+ 31 - 0
fcl/db/odbc/testtl.pp

@@ -0,0 +1,31 @@
+program testcon;
+
+{$mode objfpc}
+
+uses fpodbc,Classes;
+
+var
+  Conn : TODBCConnection;
+  TableNames : TStringList;
+  I : Integer;
+
+begin
+  Conn:=TODBCConnection.Create(Nil);
+  Try
+    Conn.DSN:='FPC';
+    Conn.Active:=True;
+    TableNames:=TStringList.Create;
+    TableNames.Sorted:=True;
+    Try
+      Conn.GetTableNames(TableNames,True);
+      Writeln('Found ',TableNames.Count,' tables : ');
+      For I:=0 to TableNames.Count-1 do
+        Writeln(TableNames[i]);
+    finally
+      TableNames.Free;
+    end;
+    Conn.Active:=False;
+  Finally
+    Conn.free;
+  end;
+end.