Browse Source

--- Merging r22401 into '.':
U packages/fcl-db/tests/dbtestframework.pas
U packages/fcl-db/tests/dbtestframework_gui.lpi
U packages/fcl-db/tests/database.ini.txt
U packages/fcl-db/tests/dbtestframework_gui.lpr
U packages/fcl-db/tests/tcsdfdata.pp
U packages/fcl-db/tests/toolsunit.pas
U packages/fcl-db/tests/sdfdstoolsunit.pas
U packages/fcl-db/tests/README.txt
--- Merging r22470 into '.':
U packages/fcl-db/src/sqldb/postgres/pqconnection.pp
--- Merging r22559 into '.':
C packages/fcl-db/fpmake.pp
A packages/fcl-db/src/sqlite/sqlite3backup.pas
--- Merging r22560 into '.':
G packages/fcl-db/tests/README.txt
--- Merging r22583 into '.':
G packages/fcl-db/fpmake.pp
D packages/fcl-db/src/sqlite/sqlite3backup.pas
A packages/fcl-db/src/sqldb/sqlite/sqlite3backup.pas
--- Merging r22609 into '.':
U packages/fcl-db/src/README.txt
Summary of conflicts:
Text conflicts: 1

# revisions: 22401,22470,22559,22560,22583,22609
r22401 | michael | 2012-09-16 13:38:49 +0200 (Sun, 16 Sep 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-db/tests/README.txt
M /trunk/packages/fcl-db/tests/database.ini.txt
M /trunk/packages/fcl-db/tests/dbtestframework.pas
M /trunk/packages/fcl-db/tests/dbtestframework_gui.lpi
M /trunk/packages/fcl-db/tests/dbtestframework_gui.lpr
M /trunk/packages/fcl-db/tests/sdfdstoolsunit.pas
M /trunk/packages/fcl-db/tests/tcsdfdata.pp
M /trunk/packages/fcl-db/tests/toolsunit.pas

* Applied patch from #22899
r22470 | michael | 2012-09-27 11:10:08 +0200 (Thu, 27 Sep 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-db/src/sqldb/postgres/pqconnection.pp

* Patch to add support for charset (bug 22985)
r22559 | marco | 2012-10-06 14:29:36 +0200 (Sat, 06 Oct 2012) | 3 lines
Changed paths:
M /trunk/packages/fcl-db/fpmake.pp
A /trunk/packages/fcl-db/src/sqlite/sqlite3backup.pas

* Sqlite3backup, implements backups between 2 TSQLite3Connections, TSQLite3Connection backup to file and TSQLite3Connection restore from file.
by Ludo Brands, mantis #22394
r22560 | marco | 2012-10-06 14:31:15 +0200 (Sat, 06 Oct 2012) | 2 lines
Changed paths:
M /trunk/packages/fcl-db/tests/README.txt

* patch from Reinier: More details on setting up test database, ignoring tests for certain databases.... mantis #22970
r22583 | ludob | 2012-10-08 11:09:27 +0200 (Mon, 08 Oct 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-db/fpmake.pp
A /trunk/packages/fcl-db/src/sqldb/sqlite/sqlite3backup.pas
D /trunk/packages/fcl-db/src/sqlite/sqlite3backup.pas

Moved sqlite3backup.pas to src/sqldb/sqlite
r22609 | reiniero | 2012-10-10 09:45:56 +0200 (Wed, 10 Oct 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-db/src/README.txt

fcl-db readme: sdfdataset is meant to be RFC4180 CSV compliant; list of dbs updated; typos fixed.

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

marco 13 years ago
parent
commit
ab6ac01c9e

+ 1 - 0
.gitattributes

@@ -1983,6 +1983,7 @@ packages/fcl-db/src/sqldb/sqldb.pp svneol=native#text/plain
 packages/fcl-db/src/sqldb/sqldblib.pp svneol=native#text/plain
 packages/fcl-db/src/sqldb/sqlite/Makefile svneol=native#text/plain
 packages/fcl-db/src/sqldb/sqlite/Makefile.fpc svneol=native#text/plain
+packages/fcl-db/src/sqldb/sqlite/sqlite3backup.pas svneol=native#text/pascal
 packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp svneol=native#text/plain
 packages/fcl-db/src/sqldb/testsqldb.pp svneol=native#text/plain
 packages/fcl-db/src/sqlite/Makefile svneol=native#text/plain

+ 8 - 7
packages/fcl-db/src/README.txt

@@ -1,15 +1,16 @@
 This is the Database directory of the Free Component Library.
 
-All base classes are in the db unit, the dbconst unit contains the 
+All base classes are in the db unit; the dbconst unit contains the 
 used resourcestrings.
 
 memds
-  contains a dataset-class in memory which can be read from, and
+  contains a dataset class in memory which can be read from, and
   written to a stream
 
 sqldb
-  contains a framework to work with several SQL-based databases
-  as Interbase, Firebird, MySQL, ODBC, SQLite3 and Oracle
+  contains a framework to work with several SQL-based databases such
+  as Interbase, Firebird, MySQL, ODBC, Oracle, Microsoft SQL Server, 
+	PostgreSQL, SQLite3 and Sybase ASE
 
 dbase
   contains the tDbf components, to work with DBASE and FoxPro
@@ -17,11 +18,11 @@ dbase
 
 sdf
   contains a dataset class to use text files directly as a
-  database. That could be fixed-size, or limited (SDF)
+  database. That could be fixed-size, or delimited (RFC 4180 CSV)
 
 sqlite
-  contains datases classes to use sqlite and sqlite3
+  contains dataset classes to use sqlite and sqlite3
 
-Succes !
+Good luck !
 
 Joost van der Sluis.              

+ 5 - 6
packages/fcl-db/src/sqldb/postgres/pqconnection.pp

@@ -247,10 +247,7 @@ function TPQConnection.StartdbTransaction(trans : TSQLHandle; AParams : string)
 var
   res : PPGresult;
   tr  : TPQTrans;
-  msg : string;
 begin
-  result := false;
-
   tr := trans as TPQTrans;
 
   tr.PGConn := PQconnectdb(pchar(FConnectString));
@@ -264,6 +261,10 @@ begin
   else
     begin
     tr.ErrorOccured := False;
+
+    if CharSet <> '' then
+      PQsetClientEncoding(tr.PGConn, pchar(CharSet));
+
     res := PQexec(tr.PGConn, 'BEGIN');
     CheckResultError(res,tr.PGConn,sErrTransactionFailed);
 
@@ -276,7 +277,6 @@ procedure TPQConnection.RollBackRetaining(trans : TSQLHandle);
 var
   res : PPGresult;
   tr  : TPQTrans;
-  msg : string;
 begin
   tr := trans as TPQTrans;
   res := PQexec(tr.PGConn, 'ROLLBACK');
@@ -293,7 +293,6 @@ procedure TPQConnection.CommitRetaining(trans : TSQLHandle);
 var
   res : PPGresult;
   tr  : TPQTrans;
-  msg : string;
 begin
   tr := trans as TPQTrans;
   res := PQexec(tr.PGConn, 'COMMIT');
@@ -538,7 +537,7 @@ const TypeStrings : array[TFieldType] of string =
     );
 
 
-var s,serr : string;
+var s : string;
     i : integer;
 
 begin

+ 279 - 72
packages/fcl-db/src/sqldb/sqlite/Makefile

@@ -1,10 +1,10 @@
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2011/12/30]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2012/10/14]
 #
 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 i386-iphonesim 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 powerpc-wii 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 i386-iphonesim 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 powerpc-wii powerpc-aix sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd 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 powerpc64-aix avr-embedded armeb-linux armeb-embedded mips-linux mipsel-linux jvm-java jvm-android
 BSDs = freebsd netbsd openbsd darwin
-UNIXs = linux $(BSDs) solaris qnx haiku
+UNIXs = linux $(BSDs) solaris qnx haiku aix
 LIMIT83fs = go32v2 os2 emx watcom
 OSNeedsComspecToRunBatch = go32v2 watcom
 FORCE:
@@ -178,6 +178,12 @@ else
 ARCH=$(CPU_TARGET)
 endif
 endif
+ifeq ($(FULL_TARGET),arm-embedded)
+ifeq ($(SUBARCH),)
+$(error When compiling for arm-embedded, a sub-architecture (e.g. SUBARCH=armv4t or SUBARCH=armv7m) must be defined)
+endif
+override FPCOPT+=-Cp$(SUBARCH)
+endif
 ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
 TARGETSUFFIX=$(OS_TARGET)
 SOURCESUFFIX=$(OS_SOURCE)
@@ -203,6 +209,14 @@ endif
 ifeq ($(OS_TARGET),linux)
 linuxHier=1
 endif
+ifndef CROSSCOMPILE
+BUILDFULLNATIVE=1
+export BUILDFULLNATIVE
+endif
+ifdef BUILDFULLNATIVE
+BUILDNATIVE=1
+export BUILDNATIVE
+endif
 export OS_TARGET OS_SOURCE ARCH CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE
 ifdef FPCDIR
 override FPCDIR:=$(subst \,/,$(FPCDIR))
@@ -252,11 +266,13 @@ ifndef BINUTILSPREFIX
 ifndef CROSSBINDIR
 ifdef CROSSCOMPILE
 ifndef DARWIN2DARWIN
+ifneq ($(CPU_TARGET),jvm)
 BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)-
 endif
 endif
 endif
 endif
+endif
 UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX))
 ifeq ($(UNITSDIR),)
 UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
@@ -289,193 +305,214 @@ endif
 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+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-nativent)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),i386-iphonesim)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),powerpc-wii)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
+endif
+ifeq ($(FULL_TARGET),powerpc-aix)
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
+endif
+ifeq ($(FULL_TARGET),x86_64-netbsd)
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
+endif
+ifeq ($(FULL_TARGET),x86_64-openbsd)
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),arm-darwin)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
+endif
+ifeq ($(FULL_TARGET),powerpc64-aix)
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
+endif
+ifeq ($(FULL_TARGET),mips-linux)
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 ifeq ($(FULL_TARGET),mipsel-linux)
-override TARGET_UNITS+=sqlite3conn
+override TARGET_UNITS+=sqlite3conn sqlite3backup
+endif
+ifeq ($(FULL_TARGET),jvm-java)
+override TARGET_UNITS+=sqlite3conn sqlite3backup
+endif
+ifeq ($(FULL_TARGET),jvm-android)
+override TARGET_UNITS+=sqlite3conn sqlite3backup
 endif
 override INSTALL_FPCPACKAGE=y
 ifeq ($(FULL_TARGET),i386-linux)
@@ -592,6 +629,9 @@ endif
 ifeq ($(FULL_TARGET),powerpc-wii)
 override COMPILER_OPTIONS+=-S2
 endif
+ifeq ($(FULL_TARGET),powerpc-aix)
+override COMPILER_OPTIONS+=-S2
+endif
 ifeq ($(FULL_TARGET),sparc-linux)
 override COMPILER_OPTIONS+=-S2
 endif
@@ -610,9 +650,15 @@ endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 override COMPILER_OPTIONS+=-S2
 endif
+ifeq ($(FULL_TARGET),x86_64-netbsd)
+override COMPILER_OPTIONS+=-S2
+endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
 override COMPILER_OPTIONS+=-S2
 endif
+ifeq ($(FULL_TARGET),x86_64-openbsd)
+override COMPILER_OPTIONS+=-S2
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 override COMPILER_OPTIONS+=-S2
 endif
@@ -655,6 +701,9 @@ endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
 override COMPILER_OPTIONS+=-S2
 endif
+ifeq ($(FULL_TARGET),powerpc64-aix)
+override COMPILER_OPTIONS+=-S2
+endif
 ifeq ($(FULL_TARGET),avr-embedded)
 override COMPILER_OPTIONS+=-S2
 endif
@@ -664,9 +713,18 @@ endif
 ifeq ($(FULL_TARGET),armeb-embedded)
 override COMPILER_OPTIONS+=-S2
 endif
+ifeq ($(FULL_TARGET),mips-linux)
+override COMPILER_OPTIONS+=-S2
+endif
 ifeq ($(FULL_TARGET),mipsel-linux)
 override COMPILER_OPTIONS+=-S2
 endif
+ifeq ($(FULL_TARGET),jvm-java)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),jvm-android)
+override COMPILER_OPTIONS+=-S2
+endif
 ifdef REQUIRE_UNITSDIR
 override UNITSDIR+=$(REQUIRE_UNITSDIR)
 endif
@@ -1050,6 +1108,23 @@ EXEEXT=.dol
 SHAREDLIBEXT=.so
 SHORTSUFFIX=wii
 endif
+ifeq ($(OS_TARGET),aix)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=aix
+endif
+ifeq ($(OS_TARGET),java)
+OEXT=.class
+ASMEXT=.j
+SHAREDLIBEXT=.jar
+SHORTSUFFIX=java
+endif
+ifeq ($(OS_TARGET),android)
+OEXT=.class
+ASMEXT=.j
+SHAREDLIBEXT=.jar
+SHORTSUFFIX=android
+endif
 ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
 FPCMADE=fpcmade.$(SHORTSUFFIX)
 ZIPSUFFIX=$(SHORTSUFFIX)
@@ -1533,6 +1608,12 @@ REQUIRE_PACKAGES_FCL-BASE=1
 REQUIRE_PACKAGES_FCL-XML=1
 REQUIRE_PACKAGES_SQLITE=1
 endif
+ifeq ($(FULL_TARGET),powerpc-aix)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_SQLITE=1
+endif
 ifeq ($(FULL_TARGET),sparc-linux)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_FCL-BASE=1
@@ -1572,12 +1653,24 @@ REQUIRE_PACKAGES_ICONVENC=1
 REQUIRE_PACKAGES_FCL-XML=1
 REQUIRE_PACKAGES_SQLITE=1
 endif
+ifeq ($(FULL_TARGET),x86_64-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_SQLITE=1
+endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_FCL-BASE=1
 REQUIRE_PACKAGES_FCL-XML=1
 REQUIRE_PACKAGES_SQLITE=1
 endif
+ifeq ($(FULL_TARGET),x86_64-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_SQLITE=1
+endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_UNIVINT=1
@@ -1670,6 +1763,12 @@ REQUIRE_PACKAGES_FCL-BASE=1
 REQUIRE_PACKAGES_FCL-XML=1
 REQUIRE_PACKAGES_SQLITE=1
 endif
+ifeq ($(FULL_TARGET),powerpc64-aix)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_SQLITE=1
+endif
 ifeq ($(FULL_TARGET),avr-embedded)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_FCL-BASE=1
@@ -1689,6 +1788,13 @@ REQUIRE_PACKAGES_FCL-BASE=1
 REQUIRE_PACKAGES_FCL-XML=1
 REQUIRE_PACKAGES_SQLITE=1
 endif
+ifeq ($(FULL_TARGET),mips-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_SQLITE=1
+endif
 ifeq ($(FULL_TARGET),mipsel-linux)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_FCL-BASE=1
@@ -1696,6 +1802,18 @@ REQUIRE_PACKAGES_ICONVENC=1
 REQUIRE_PACKAGES_FCL-XML=1
 REQUIRE_PACKAGES_SQLITE=1
 endif
+ifeq ($(FULL_TARGET),jvm-java)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_SQLITE=1
+endif
+ifeq ($(FULL_TARGET),jvm-android)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_SQLITE=1
+endif
 ifdef REQUIRE_PACKAGES_RTL
 PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
 ifneq ($(PACKAGEDIR_RTL),)
@@ -1940,12 +2058,16 @@ endif
 ifndef CROSSBOOTSTRAP
 ifneq ($(BINUTILSPREFIX),)
 override FPCOPT+=-XP$(BINUTILSPREFIX)
-override FPCMAKEOPT+=-XP$(BINUTILSPREFIX)
 endif
 ifneq ($(BINUTILSPREFIX),)
 override FPCOPT+=-Xr$(RLINKPATH)
 endif
 endif
+ifndef CROSSCOMPILE
+ifneq ($(BINUTILSPREFIX),)
+override FPCMAKEOPT+=-XP$(BINUTILSPREFIX)
+endif
+endif
 ifdef UNITDIR
 override FPCOPT+=$(addprefix -Fu,$(UNITDIR))
 endif
@@ -2032,17 +2154,12 @@ endif
 endif
 ifdef CREATESHARED
 override FPCOPT+=-Cg
-ifeq ($(CPU_TARGET),i386)
-override FPCOPT+=-Aas
-endif
 endif
-ifeq ($(findstring 2.0.,$(FPC_VERSION)),)
 ifneq ($(findstring $(OS_TARGET),freebsd openbsd netbsd linux solaris),)
 ifeq ($(CPU_TARGET),x86_64)
 override FPCOPT+=-Cg
 endif
 endif
-endif
 ifdef LINKSHARED
 endif
 ifdef GCCLIBDIR
@@ -2423,6 +2540,96 @@ 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
+ifdef TARGET_DIRS_TARGET_DIRS
+TARGET_DIRS_all:
+	$(MAKE) -C TARGET_DIRS all
+TARGET_DIRS_debug:
+	$(MAKE) -C TARGET_DIRS debug
+TARGET_DIRS_smart:
+	$(MAKE) -C TARGET_DIRS smart
+TARGET_DIRS_release:
+	$(MAKE) -C TARGET_DIRS release
+TARGET_DIRS_units:
+	$(MAKE) -C TARGET_DIRS units
+TARGET_DIRS_examples:
+	$(MAKE) -C TARGET_DIRS examples
+TARGET_DIRS_shared:
+	$(MAKE) -C TARGET_DIRS shared
+TARGET_DIRS_install:
+	$(MAKE) -C TARGET_DIRS install
+TARGET_DIRS_sourceinstall:
+	$(MAKE) -C TARGET_DIRS sourceinstall
+TARGET_DIRS_exampleinstall:
+	$(MAKE) -C TARGET_DIRS exampleinstall
+TARGET_DIRS_distinstall:
+	$(MAKE) -C TARGET_DIRS distinstall
+TARGET_DIRS_zipinstall:
+	$(MAKE) -C TARGET_DIRS zipinstall
+TARGET_DIRS_zipsourceinstall:
+	$(MAKE) -C TARGET_DIRS zipsourceinstall
+TARGET_DIRS_zipexampleinstall:
+	$(MAKE) -C TARGET_DIRS zipexampleinstall
+TARGET_DIRS_zipdistinstall:
+	$(MAKE) -C TARGET_DIRS zipdistinstall
+TARGET_DIRS_clean:
+	$(MAKE) -C TARGET_DIRS clean
+TARGET_DIRS_distclean:
+	$(MAKE) -C TARGET_DIRS distclean
+TARGET_DIRS_cleanall:
+	$(MAKE) -C TARGET_DIRS cleanall
+TARGET_DIRS_info:
+	$(MAKE) -C TARGET_DIRS info
+TARGET_DIRS_makefiles:
+	$(MAKE) -C TARGET_DIRS makefiles
+TARGET_DIRS:
+	$(MAKE) -C TARGET_DIRS all
+.PHONY: TARGET_DIRS_all TARGET_DIRS_debug TARGET_DIRS_smart TARGET_DIRS_release TARGET_DIRS_units TARGET_DIRS_examples TARGET_DIRS_shared TARGET_DIRS_install TARGET_DIRS_sourceinstall TARGET_DIRS_exampleinstall TARGET_DIRS_distinstall TARGET_DIRS_zipinstall TARGET_DIRS_zipsourceinstall TARGET_DIRS_zipexampleinstall TARGET_DIRS_zipdistinstall TARGET_DIRS_clean TARGET_DIRS_distclean TARGET_DIRS_cleanall TARGET_DIRS_info TARGET_DIRS_makefiles TARGET_DIRS
+endif
+ifdef TARGET_EXAMPLEDIRS_TARGET_EXAMPLEDIRS
+TARGET_EXAMPLEDIRS_all:
+	$(MAKE) -C TARGET_EXAMPLEDIRS all
+TARGET_EXAMPLEDIRS_debug:
+	$(MAKE) -C TARGET_EXAMPLEDIRS debug
+TARGET_EXAMPLEDIRS_smart:
+	$(MAKE) -C TARGET_EXAMPLEDIRS smart
+TARGET_EXAMPLEDIRS_release:
+	$(MAKE) -C TARGET_EXAMPLEDIRS release
+TARGET_EXAMPLEDIRS_units:
+	$(MAKE) -C TARGET_EXAMPLEDIRS units
+TARGET_EXAMPLEDIRS_examples:
+	$(MAKE) -C TARGET_EXAMPLEDIRS examples
+TARGET_EXAMPLEDIRS_shared:
+	$(MAKE) -C TARGET_EXAMPLEDIRS shared
+TARGET_EXAMPLEDIRS_install:
+	$(MAKE) -C TARGET_EXAMPLEDIRS install
+TARGET_EXAMPLEDIRS_sourceinstall:
+	$(MAKE) -C TARGET_EXAMPLEDIRS sourceinstall
+TARGET_EXAMPLEDIRS_exampleinstall:
+	$(MAKE) -C TARGET_EXAMPLEDIRS exampleinstall
+TARGET_EXAMPLEDIRS_distinstall:
+	$(MAKE) -C TARGET_EXAMPLEDIRS distinstall
+TARGET_EXAMPLEDIRS_zipinstall:
+	$(MAKE) -C TARGET_EXAMPLEDIRS zipinstall
+TARGET_EXAMPLEDIRS_zipsourceinstall:
+	$(MAKE) -C TARGET_EXAMPLEDIRS zipsourceinstall
+TARGET_EXAMPLEDIRS_zipexampleinstall:
+	$(MAKE) -C TARGET_EXAMPLEDIRS zipexampleinstall
+TARGET_EXAMPLEDIRS_zipdistinstall:
+	$(MAKE) -C TARGET_EXAMPLEDIRS zipdistinstall
+TARGET_EXAMPLEDIRS_clean:
+	$(MAKE) -C TARGET_EXAMPLEDIRS clean
+TARGET_EXAMPLEDIRS_distclean:
+	$(MAKE) -C TARGET_EXAMPLEDIRS distclean
+TARGET_EXAMPLEDIRS_cleanall:
+	$(MAKE) -C TARGET_EXAMPLEDIRS cleanall
+TARGET_EXAMPLEDIRS_info:
+	$(MAKE) -C TARGET_EXAMPLEDIRS info
+TARGET_EXAMPLEDIRS_makefiles:
+	$(MAKE) -C TARGET_EXAMPLEDIRS makefiles
+TARGET_EXAMPLEDIRS:
+	$(MAKE) -C TARGET_EXAMPLEDIRS all
+.PHONY: TARGET_EXAMPLEDIRS_all TARGET_EXAMPLEDIRS_debug TARGET_EXAMPLEDIRS_smart TARGET_EXAMPLEDIRS_release TARGET_EXAMPLEDIRS_units TARGET_EXAMPLEDIRS_examples TARGET_EXAMPLEDIRS_shared TARGET_EXAMPLEDIRS_install TARGET_EXAMPLEDIRS_sourceinstall TARGET_EXAMPLEDIRS_exampleinstall TARGET_EXAMPLEDIRS_distinstall TARGET_EXAMPLEDIRS_zipinstall TARGET_EXAMPLEDIRS_zipsourceinstall TARGET_EXAMPLEDIRS_zipexampleinstall TARGET_EXAMPLEDIRS_zipdistinstall TARGET_EXAMPLEDIRS_clean TARGET_EXAMPLEDIRS_distclean TARGET_EXAMPLEDIRS_cleanall TARGET_EXAMPLEDIRS_info TARGET_EXAMPLEDIRS_makefiles TARGET_EXAMPLEDIRS
+endif
 all: fpc_all
 debug: fpc_debug
 smart: fpc_smart

+ 1 - 1
packages/fcl-db/src/sqldb/sqlite/Makefile.fpc

@@ -6,7 +6,7 @@
 main=fcl-db
 
 [target]
-units=sqlite3conn
+units=sqlite3conn sqlite3backup
 
 [require]
 packages=fcl-xml sqlite

+ 161 - 0
packages/fcl-db/src/sqldb/sqlite/sqlite3backup.pas

@@ -0,0 +1,161 @@
+unit sqlite3backup;
+
+{ SQLite3 backup class.
+
+  Copyright (C) 2012 Ludo Brands
+
+  This library is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Library General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or (at your
+  option) any later version with the following modification:
+
+  As a special exception, the copyright holders of this library give you
+  permission to link this library with independent modules to produce an
+  executable, regardless of the license terms of these independent modules,and
+  to copy and distribute the resulting executable under terms of your choice,
+  provided that you also meet, for each linked independent module, the terms
+  and conditions of the license of that module. An independent module is a
+  module which is not derived from or based on this library. If you modify
+  this library, you may extend this exception to your version of the library,
+  but you are not obligated to do so. If you do not wish to do so, delete this
+  exception statement from your version.
+
+  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. See the GNU Library General Public License
+  for more details.
+
+  You should have received a copy of the GNU Library General Public License
+  along with this library; if not, write to the Free Software Foundation,
+  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+}
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils,sqlite3conn,sqlite3dyn;
+
+type
+
+  TOnBackupProgress = procedure (Sender: TObject; Remaining, PageCount: integer) of object;
+
+  { TSQLite3Backup }
+
+  TSQLite3Backup=class
+  private
+    FErrorMessage: string;
+    FLockReleaseTime: integer;
+    FOnBackupProgress: TOnBackupProgress;
+    FPageStep: integer;
+  public
+    constructor Create;
+    //Backup one TSQLite3Connection to another TSQLite3Connection
+    //SourceDBName and DestinationDBName is "main" for the main database, "temp" for the temporary
+    //database, or the name specified after the AS keyword in an ATTACH statement for an
+    //attached database
+    //LockUntilFinished: Set to false when simultanuous access from other processes is required.
+    //The backup process will restart when another process writes to the database.
+    //Pro: the backup is a correct snapshot
+    //Contra: the backup can take a very long time when a lot of writes to the database are made during backup
+    //Warning: don't use the destination TSQLite3Connection (the handle) for anything else while doing a backup.
+    //It can corrupt the database and even cause a mutex deadlock.
+    function Backup(Source,Destination:TSQLite3Connection;LockUntilFinished:boolean=true;
+         SourceDBName:string='main';DestinationDBName:string='main'):boolean;
+    //Backup a database to file
+    function Backup(Source:TSQLite3Connection;FileName:string;LockUntilFinished:boolean=true;
+         SourceDBName:string='main'):boolean;
+    //Restore a database from file
+    function Restore(FileName:string;Destination:TSQLite3Connection;LockUntilFinished:boolean=true;
+         DestinationDBName:string='main'):boolean;
+  published
+    //Delay between backup steps in ms. Default:100ms. Only used when LockUntilFinished=false
+    property LockReleaseTime:integer read FLockReleaseTime write FLockReleaseTime;
+    //Page size between backup steps. Default:10 Only used when LockUntilFinished=false
+    property PageStep:integer read FPageStep write FPageStep;
+    property ErrorMessage:string read FErrorMessage;
+    property OnBackupProgress:TOnBackupProgress read FOnBackupProgress write FOnBackupProgress;
+  end;
+
+implementation
+
+
+
+
+{ TSQLite3Backup }
+
+constructor TSQLite3Backup.Create;
+begin
+  FLockReleaseTime:=100;
+  FPageStep:=10;
+end;
+
+function TSQLite3Backup.Backup(Source, Destination: TSQLite3Connection;
+  LockUntilFinished: boolean; SourceDBName: string; DestinationDBName: string
+  ): boolean;
+var
+  pBackup:psqlite3backup;
+  nPage:integer;
+  res: integer;
+begin
+   FErrorMessage:='';
+   Source.Connected:=true;
+   Destination.Connected:=true;
+   pBackup := sqlite3_backup_init(Destination.Handle, pchar(DestinationDBName),
+      Source.Handle, pchar(SourceDBName));
+   if LockUntilFinished then
+     nPage:=-1
+   else
+     nPage:=FPageStep;
+   result:=false;
+   if assigned(pBackup) then
+     begin
+{  Each iteration of this loop copies PageStep database pages from database
+   pDb to the backup database. If the return value of backup_step()
+   indicates that there are still further pages to copy, sleep for
+   LockReleaseTime ms before repeating. }
+     repeat
+       res := sqlite3_backup_step(pBackup, nPage);
+       if assigned(FOnBackupProgress) then
+         FOnBackupProgress(self,sqlite3_backup_remaining(pBackup),
+           sqlite3_backup_pagecount(pBackup));
+       if not LockUntilFinished and (res in [SQLITE_OK,SQLITE_BUSY,SQLITE_LOCKED]) then
+         sqlite3_sleep(LockReleaseTime);
+     until LockUntilFinished or not (res in [SQLITE_OK,SQLITE_BUSY,SQLITE_LOCKED]);
+     result:=sqlite3_backup_finish(pBackup)=SQLITE_OK;
+     end;
+   if not result then
+     FErrorMessage:=strpas(sqlite3_errmsg(Destination.Handle));
+end;
+
+function TSQLite3Backup.Backup(Source: TSQLite3Connection; FileName: string;
+  LockUntilFinished: boolean; SourceDBName: string): boolean;
+var conn:TSQLite3Connection;
+begin
+  conn:=TSQLite3Connection.Create(nil);
+  try
+    conn.DatabaseName:=FileName;
+    conn.Connected:=true;
+    result:=Backup(Source,conn,LockUntilFinished,SourceDBName);
+  finally
+    conn.Destroy;
+  end;
+end;
+
+function TSQLite3Backup.Restore(FileName: string;
+  Destination: TSQLite3Connection; LockUntilFinished: boolean;
+  DestinationDBName: string): boolean;
+var conn:TSQLite3Connection;
+begin
+  conn:=TSQLite3Connection.Create(nil);
+  try
+    conn.DatabaseName:=FileName;
+    conn.Connected:=true;
+    result:=Backup(conn,Destination,LockUntilFinished,'main',DestinationDBName);
+  finally
+    conn.Destroy;
+  end;
+end;
+
+end.
+

+ 41 - 3
packages/fcl-db/tests/README.txt

@@ -2,7 +2,7 @@ This directory contains a framework to test several TDataset descendents.
 A lot of these tests are only applicable for SQL databases, but there are several tests that also apply to other objects, such as TBufDataset.
 
 The framework is based on the fpcunit unit test system. The tests can be
-executed using any fpcunit-testrunner. For example the console and graphical
+executed using any fpcunit testrunner. For example the console and graphical
 fpcunit test runners from Lazarus.
 Simply add the test* units in this directory to the uses statement of the
 test runner and all tests will get registered and executed.
@@ -10,6 +10,8 @@ test runner and all tests will get registered and executed.
 A simple test runner (dbtestframework.pas) which generates XML output is
 included in this directory.
 
+DBTestframework architecture
+============================
 To test a TDataset descendent, a 'connector' is needed to test the database.
 To add a new connector, create a new *toolsunit.pas file, then add it to 
 the uses section in 'dbtestframework.pas'. Several connectors are available 
@@ -29,11 +31,47 @@ They call InternalGetNDataset and InternalGetFieldDataset which should be implem
 Toolsunit.pas defines some variables for use, e.g. testValuesCount is the number of records/test values in the FieldDataset dataset; MaxDataset is the same for NDataset.
 See e.g. the SQLDBToolsUnit for the implementation for SQL Databases.
 
+Tests
+=====
+In your test units, you can specify that you only want to run for certain groups/connectors.
+E.g. this example to only run for Bufdataset tests:
+  TTestSpecificTBufDataset = class(TTestCase)
+  ...
+initialization  
+  if uppercase(dbconnectorname)='BUFDATASET' then
+    begin
+    RegisterTestDecorator(TDBBasicsTestSetup, TTestSpecificTBufDataset);
+    end;
+	
+In your individual tests, you can indicate you want to run tests only in certain cases, e.g. for certain SQLDB databases:
+  if not(SQLDbType in [interbase]) then Ignore(STestNotApplicable);
+  
+Setting up your database
+========================
+Some tests are file based (e.g. those for bufdataset); others by their nature need databases (e.g. a Firebird SQLDB test).
+File-based tests will generally write to the current/test directory, a subdirectory or a temp file.
+
+For SQLDB database servers, please make sure you have a username/password and a database set up that the test suite can use and abuse.
+The database can be empty: the test suite will create and delete tables etc. in this database as needed.
+
+Specifying databases, connector names
+=====================================
 Which connector is currently used is dependent on the 'database.ini'
 configuration file. Also some settings which are connector-dependent can be set
 in that file. See 'database.ini.txt' for an example.
 
-I hope this is enough information to get you started,
+The connector names to be used are derived from the connector classes.
+
+For example, the SQL RDBMS connector defined in sqldbtoolsunit:
+- it has this class definition
+TSQLDBConnector = class(TDBConnector)
+- its name in database.ini is sqldb
+- incidentally, in databases.ini, more parameter such as
+connectorparams=postgresql (which specify db type) are needed
+The parameters use depend on the connector type (sql,...)
+
+If you specify the wrong (or no) name (or don't have database.ini), you will get an exception in your test runner:
+Unknown db connector specified
 
 Joost van der Sluis (30-12-2006), 
-amended by Reinier Olislagers (April 2012)
+amended by Reinier Olislagers (2012)

+ 7 - 1
packages/fcl-db/tests/database.ini.txt

@@ -3,7 +3,7 @@
 ; Select here which section has to be used currently, 
 ; i.e. which database you want to use
 [Database]
-type=interbase
+type=bufdataset
 
 
 ; These sections are for the several SQLDB-types of databases:
@@ -117,3 +117,9 @@ connector=memds
 ; BufDataset in memory dataset:
 [bufdataset]
 connector=bufdataset
+
+; sdfdataset file-based dataset:
+[sdfdataset]
+connector=sdfds
+; subdirectory for the sdf files:
+name=sdftest

+ 2 - 2
packages/fcl-db/tests/dbtestframework.pas

@@ -11,14 +11,14 @@ uses
   fpcunit,  testreport, testregistry,
   DigestTestReport,
   toolsunit,
-// List of supported database-connectors
+// List of supported database connectors
   sqldbtoolsunit,
   dbftoolsunit,
   bufdatasettoolsunit,
   memdstoolsunit,
   SdfDSToolsUnit,
   tcsdfdata,
-// Units wich contains the tests
+// Units wich contain the tests
   TestBasics,
   TestFieldTypes,
   TestDatasources,

+ 21 - 2
packages/fcl-db/tests/dbtestframework_gui.lpi

@@ -7,7 +7,6 @@
       <MainUnit Value="0"/>
       <ResourceType Value="res"/>
       <UseXPManifest Value="True"/>
-      <Icon Value="0"/>
     </General>
     <i18n>
       <EnableI18N LFM="False"/>
@@ -15,8 +14,23 @@
     <VersionInfo>
       <StringTable ProductVersion=""/>
     </VersionInfo>
-    <BuildModes Count="1">
+    <BuildModes Count="2">
       <Item1 Name="Default" Default="True"/>
+      <Item2 Name="debug">
+        <CompilerOptions>
+          <Version Value="11"/>
+          <SearchPaths>
+            <IncludeFiles Value="$(ProjOutDir)"/>
+            <OtherUnitFiles Value="../src/base;../src/sqldb/odbc;../src/sqldb/mssql;../src/sqldb/sqlite;../src/sqldb/postgres;../src/sqldb/oracle;../src/memds;../src/sqldb;../src/sqldb/interbase;../src/sqldb/mysql;../src/dbase;../src/sdf"/>
+          </SearchPaths>
+          <Other>
+            <CompilerMessages>
+              <UseMsgFile Value="True"/>
+            </CompilerMessages>
+            <CompilerPath Value="$(CompPath)"/>
+          </Other>
+        </CompilerOptions>
+      </Item2>
     </BuildModes>
     <PublishOptions>
       <Version Value="2"/>
@@ -53,6 +67,11 @@
       <IncludeFiles Value="$(ProjOutDir)"/>
       <OtherUnitFiles Value="../src/base;../src/sqldb/odbc;../src/sqldb/mssql;../src/sqldb/sqlite;../src/sqldb/postgres;../src/sqldb/oracle;../src/memds;../src/sqldb;../src/sqldb/interbase;../src/sqldb/mysql;../src/dbase;../src/sdf"/>
     </SearchPaths>
+    <Linking>
+      <Debugging>
+        <GenerateDebugInfo Value="False"/>
+      </Debugging>
+    </Linking>
     <Other>
       <CompilerMessages>
         <UseMsgFile Value="True"/>

+ 3 - 2
packages/fcl-db/tests/dbtestframework_gui.lpr

@@ -11,14 +11,15 @@ program dbtestframework_gui;
 
 uses
   Interfaces, Forms, GuiTestRunner,
-  // Generic DB-testframework units
+  // Generic DB test framework units
   ToolsUnit,
-  // Connecors for different database-types
+  // Connectors for different database-types
   sqldbtoolsunit,
   dbftoolsunit,
   bufdatasettoolsunit,
   memdstoolsunit,
   SdfDSToolsUnit,
+  tcsdfdata,
   // DB unittest
   testbasics,
   TestFieldTypes,

+ 6 - 0
packages/fcl-db/tests/sdfdstoolsunit.pas

@@ -46,11 +46,14 @@ end;
 procedure TSdfDSDBConnector.CreateNDatasets;
 var countID,n : integer;
 begin
+  if dbname='' then raise Exception.Create('dbname variable not specified. You must specify name= in database.ini');
   for n := 0 to MaxDataSet do
     begin
     with TSdfDataSet.Create(nil) do
       begin
       FileName := dbname+PathDelim+'fpdev_'+inttostr(n)+'.dat';
+      // Make sure the directory exists so we can write
+      ForceDirectories(dbname);
       DeleteFile(FileName);
       FileMustExist:=False;
       
@@ -78,10 +81,13 @@ end;
 procedure TSdfDSDBConnector.CreateFieldDataset;
 var i : integer;
 begin
+  if dbname='' then raise Exception.Create('dbname variable not specified. You must specify name= in database.ini');
   with TSdfDataSet.Create(nil) do
     begin
     FileName := dbname+PathDelim+'fpdev_field.dat';
       DeleteFile(FileName);
+    // Make sure the directory exists so we can write
+    ForceDirectories(dbname);
     FileMustExist:=False;
     
     SetFieldDatasetSchema(Schema);

+ 118 - 12
packages/fcl-db/tests/tcsdfdata.pp

@@ -1,24 +1,28 @@
 unit tcsdfdata;
-// Tests multiline functionality of sdfdataset
+// Tests specific functionality of sdfdataset (multiline etc)
 
 {$mode objfpc}{$H+}
 
 interface
 
 uses
-  Classes, SysUtils, Fpcunit, Testutils, Testregistry,
-  dateutils, sdfdata;
+  Classes, SysUtils, Fpcunit, Testutils, Testregistry, testdecorator,
+  dateutils,sdfdata,ToolsUnit;
 
 type
 
-  { Ttestexport1 }
+  { Ttestsdfspecific }
 
-  Ttestexport1 = class(Ttestcase)
+  Ttestsdfspecific = class(Ttestcase)
   protected
     TestDataset: TSDFDataset;
     procedure Setup; override;
     procedure Teardown; override;
   published
+    procedure TestEmptyFileHeader;
+    procedure TestEmptyFileNoHeader;
+    procedure TestSingleLineHeader;
+    procedure TestSingleLineNoHeader;
     procedure TestOutput;
     procedure TestInputOurFormat;
     procedure TestDelimitedTextOutput;
@@ -26,7 +30,104 @@ type
 
 implementation
 
-procedure Ttestexport1.TestOutput;
+procedure Ttestsdfspecific.TestEmptyFileHeader;
+// An empty file should return 0 records even if it has a header
+const
+  InputFilename='empty.csv';
+begin
+  TestDataSet.Close;
+
+  if FileExists(InputFilename) then DeleteFile(InputFilename);
+  TestDataset.FileMustExist:=false;
+  TestDataset.FirstLineAsSchema := True;  
+  TestDataset.FileName:=InputFilename;
+  TestDataset.Open;
+
+  TestDataset.Last;
+  TestDataset.First;  
+  AssertEquals('Number of records in test dataset', 0, TestDataset.RecordCount);
+  TestDataset.Close;
+end;
+
+procedure Ttestsdfspecific.TestEmptyFileNoHeader;
+// An empty file should return 0 records even if it has a header
+const
+  InputFilename='empty.csv';
+begin
+  TestDataSet.Close;
+
+  if FileExists(InputFilename) then DeleteFile(InputFilename);
+  TestDataset.FileMustExist:=false;
+  TestDataset.FirstLineAsSchema := false;  
+  TestDataset.FileName:=InputFilename;
+  TestDataset.Open;
+
+  TestDataset.Last;
+  TestDataset.First;  
+  AssertEquals('Number of records in test dataset', 0, TestDataset.RecordCount);
+  TestDataset.Close;
+end;
+
+procedure Ttestsdfspecific.TestSingleLineHeader;
+// A file with a single data line and header should return 1 records
+const
+  InputFilename='singleh.csv';
+var
+  FileStrings: TStringList;
+begin
+  TestDataSet.Close;
+
+  if FileExists(InputFilename) then DeleteFile(InputFilename);
+  FileStrings:=TStringList.Create;
+  try
+    FileStrings.Add('ID,NAME,BIRTHDAY');
+    FileStrings.Add('1,SimpleName,31-12-1976');
+    FileStrings.SaveToFile(InputFileName);
+  finally
+    FileStrings.Free;
+  end;
+
+  TestDataset.FileMustExist:=false;
+  TestDataset.FirstLineAsSchema := true;
+  TestDataset.FileName:=InputFilename;
+  TestDataset.Open;
+
+  TestDataset.Last;
+  TestDataset.First;
+  AssertEquals('Number of records in test dataset', 1, TestDataset.RecordCount);
+  TestDataset.Close;
+end;
+
+procedure Ttestsdfspecific.TestSingleLineNoHeader;
+// A file with a single data line, no header should return 1 records
+const
+  InputFilename='single.csv';
+var
+  FileStrings: TStringList;
+begin
+  TestDataSet.Close;
+
+  if FileExists(InputFilename) then DeleteFile(InputFilename);
+  FileStrings:=TStringList.Create;
+  try
+    FileStrings.Add('1,SimpleName,31-12-1976');
+    FileStrings.SaveToFile(InputFileName);
+  finally
+    FileStrings.Free;
+  end;
+
+  TestDataset.FileMustExist:=false;
+  TestDataset.FirstLineAsSchema := false;
+  TestDataset.FileName:=InputFilename;
+  TestDataset.Open;
+
+  TestDataset.Last;
+  TestDataset.First;
+  AssertEquals('Number of records in test dataset', 1, TestDataset.RecordCount);
+  TestDataset.Close;
+end;
+
+procedure Ttestsdfspecific.TestOutput;
 const
   OutputFilename='output.csv';
 begin
@@ -72,7 +173,7 @@ begin
   TestDataset.Close;
 end;
 
-procedure Ttestexport1.TestInputOurFormat;
+procedure Ttestsdfspecific.TestInputOurFormat;
 // Test if input works with our format
 // Mainly check if reading quotes is according to Delphi sdf specs and works.
 // See test results from bug 19610 for evidence that the strings below should work.
@@ -136,7 +237,7 @@ begin
   AssertEquals(Expected7, TestDataSet.FieldByName('NAME').AsString);
 end;
 
-procedure Ttestexport1.TestDelimitedTextOutput;
+procedure Ttestsdfspecific.TestDelimitedTextOutput;
 // Test if input works with our format
 // Mainly check if reading quotes is according to Delphi sdf specs and works.
 // See test results from bug 19610 for evidence that the strings below should work.
@@ -193,7 +294,7 @@ begin
 end;
 
 
-procedure Ttestexport1.Setup;
+procedure Ttestsdfspecific.Setup;
 
 begin
   TestDataset := TSDFDataset.Create(nil);
@@ -205,7 +306,7 @@ begin
   TestDataset.Schema.Add('BIRTHDAY');
 end;
 
-procedure Ttestexport1.Teardown;
+procedure Ttestsdfspecific.Teardown;
 begin
   try
     TestDataset.Close;
@@ -222,7 +323,12 @@ begin
 end;
 
 initialization
-
-  Registertest(Ttestexport1);
+  // Only run these tests if we are running
+  // sdf tests. After all, running these when testing
+  // e.g. SQL RDBMS doesn't make sense.
+  if uppercase(dbconnectorname)='SDFDS' then
+    begin
+    Registertest(Ttestsdfspecific);
+    end;
 end.
 

+ 2 - 2
packages/fcl-db/tests/toolsunit.pas

@@ -330,11 +330,11 @@ begin
       testValues[ftDateTime,i] := testDateValues[i];
     end;
 
-  if dbconnectorname = '' then raise Exception.Create('There is no db-connector specified');
+  if dbconnectorname = '' then raise Exception.Create('There is no db connector specified');
   DBConnectorClass := GetClass('T'+dbconnectorname+'DBConnector');
   if assigned(DBConnectorClass) then
     DBConnector := TDBConnectorClass(DBConnectorClass).create
-  else Raise Exception.Create('Unknown db-connector specified: ' + 'T'+dbconnectorname+'DBConnector');
+  else Raise Exception.Create('Unknown db connector specified: ' + 'T'+dbconnectorname+'DBConnector');
   inc(DBConnectorRefCount);
 end;