Ver Fonte

* Fix bug #34348
* Backport pas2js changes/bugfixes
* Split extjs dataset from json dataset

git-svn-id: trunk@39841 -

michael há 6 anos atrás
pai
commit
e6574526db

+ 1 - 0
.gitattributes

@@ -2217,6 +2217,7 @@ packages/fcl-db/src/export/fptexexport.pp svneol=native#text/plain
 packages/fcl-db/src/export/fpxmlxsdexport.pp svneol=native#text/plain
 packages/fcl-db/src/json/Makefile svneol=native#text/plain
 packages/fcl-db/src/json/Makefile.fpc svneol=native#text/plain
+packages/fcl-db/src/json/extjsdataset.pp svneol=native#text/plain
 packages/fcl-db/src/json/fpjsondataset.pp svneol=native#text/plain
 packages/fcl-db/src/memds/Makefile svneol=native#text/plain
 packages/fcl-db/src/memds/Makefile.fpc svneol=native#text/plain

+ 7 - 0
packages/fcl-db/fpmake.pp

@@ -822,6 +822,13 @@ begin
     T.ResourceStrings := True;
 
     T:=P.Targets.AddUnit('fpjsondataset.pp');
+    with T.Dependencies do
+      AddUnit('db');
+    
+    T:=P.Targets.AddUnit('extjsdataset.pp');
+    with T.Dependencies do
+      AddUnit('fpjsondataset');
+
 
     P.ExamplePath.Add('tests');
     T:=P.Targets.AddExampleProgram('dbftoolsunit.pas', DBaseOSes);

+ 89 - 142
packages/fcl-db/src/json/Makefile

@@ -1,8 +1,8 @@
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2018-03-05 rev 38412]
 #
 default: all
-MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim i386-android i386-aros m68k-linux m68k-netbsd m68k-amiga m68k-atari m68k-palmos m68k-macos 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 x86_64-iphonesim x86_64-aros x86_64-dragonfly arm-linux arm-netbsd arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian arm-android arm-aros powerpc64-linux powerpc64-darwin powerpc64-embedded powerpc64-aix avr-embedded armeb-linux armeb-embedded mips-linux mipsel-linux mipsel-embedded mipsel-android jvm-java jvm-android i8086-embedded i8086-msdos i8086-win16 aarch64-linux aarch64-darwin wasm-wasm sparc64-linux riscv32-linux riscv32-embedded riscv64-linux riscv64-embedded
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim i386-android i386-aros m68k-linux m68k-netbsd m68k-amiga m68k-atari m68k-palmos m68k-macos 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 x86_64-iphonesim x86_64-aros x86_64-dragonfly arm-linux arm-netbsd arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian arm-android arm-aros powerpc64-linux powerpc64-darwin powerpc64-embedded powerpc64-aix avr-embedded armeb-linux armeb-embedded mips-linux mipsel-linux mipsel-embedded mipsel-android jvm-java jvm-android i8086-embedded i8086-msdos i8086-win16 aarch64-linux aarch64-darwin wasm-wasm sparc64-linux
 BSDs = freebsd netbsd openbsd darwin dragonfly
 UNIXs = linux $(BSDs) solaris qnx haiku aix
 LIMIT83fs = go32v2 os2 emx watcom msdos win16 atari
@@ -334,271 +334,259 @@ 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+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-nativent)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-iphonesim)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-android)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i386-aros)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),m68k-macos)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),powerpc-wii)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),powerpc-aix)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),x86_64-netbsd)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),x86_64-openbsd)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),x86_64-iphonesim)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),x86_64-aros)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),x86_64-dragonfly)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),arm-netbsd)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),arm-darwin)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),arm-android)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),arm-aros)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),powerpc64-aix)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),mips-linux)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),mipsel-linux)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),mipsel-embedded)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),mipsel-android)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),jvm-java)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),jvm-android)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i8086-embedded)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i8086-msdos)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),i8086-win16)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),aarch64-linux)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),aarch64-darwin)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),wasm-wasm)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 ifeq ($(FULL_TARGET),sparc64-linux)
-override TARGET_UNITS+=fpjsondataset
-endif
-ifeq ($(FULL_TARGET),riscv32-linux)
-override TARGET_UNITS+=fpjsondataset
-endif
-ifeq ($(FULL_TARGET),riscv32-embedded)
-override TARGET_UNITS+=fpjsondataset
-endif
-ifeq ($(FULL_TARGET),riscv64-linux)
-override TARGET_UNITS+=fpjsondataset
-endif
-ifeq ($(FULL_TARGET),riscv64-embedded)
-override TARGET_UNITS+=fpjsondataset
+override TARGET_UNITS+=fpjsondataset extjsdataset
 endif
 override INSTALL_FPCPACKAGE=y
 ifdef REQUIRE_UNITSDIR
@@ -975,7 +963,6 @@ endif
 ifeq ($(OS_TARGET),aix)
 BATCHEXT=.sh
 EXEEXT=
-SHAREDLIBEXT=.a
 SHORTSUFFIX=aix
 endif
 ifeq ($(OS_TARGET),java)
@@ -2117,46 +2104,6 @@ REQUIRE_PACKAGES_FPMKUNIT=1
 REQUIRE_PACKAGES_FCL-BASE=1
 REQUIRE_PACKAGES_FCL-JSON=1
 endif
-ifeq ($(FULL_TARGET),riscv32-linux)
-REQUIRE_PACKAGES_RTL=1
-REQUIRE_PACKAGES_PASZLIB=1
-REQUIRE_PACKAGES_FCL-PROCESS=1
-REQUIRE_PACKAGES_HASH=1
-REQUIRE_PACKAGES_LIBTAR=1
-REQUIRE_PACKAGES_FPMKUNIT=1
-REQUIRE_PACKAGES_FCL-BASE=1
-REQUIRE_PACKAGES_FCL-JSON=1
-endif
-ifeq ($(FULL_TARGET),riscv32-embedded)
-REQUIRE_PACKAGES_RTL=1
-REQUIRE_PACKAGES_PASZLIB=1
-REQUIRE_PACKAGES_FCL-PROCESS=1
-REQUIRE_PACKAGES_HASH=1
-REQUIRE_PACKAGES_LIBTAR=1
-REQUIRE_PACKAGES_FPMKUNIT=1
-REQUIRE_PACKAGES_FCL-BASE=1
-REQUIRE_PACKAGES_FCL-JSON=1
-endif
-ifeq ($(FULL_TARGET),riscv64-linux)
-REQUIRE_PACKAGES_RTL=1
-REQUIRE_PACKAGES_PASZLIB=1
-REQUIRE_PACKAGES_FCL-PROCESS=1
-REQUIRE_PACKAGES_HASH=1
-REQUIRE_PACKAGES_LIBTAR=1
-REQUIRE_PACKAGES_FPMKUNIT=1
-REQUIRE_PACKAGES_FCL-BASE=1
-REQUIRE_PACKAGES_FCL-JSON=1
-endif
-ifeq ($(FULL_TARGET),riscv64-embedded)
-REQUIRE_PACKAGES_RTL=1
-REQUIRE_PACKAGES_PASZLIB=1
-REQUIRE_PACKAGES_FCL-PROCESS=1
-REQUIRE_PACKAGES_HASH=1
-REQUIRE_PACKAGES_LIBTAR=1
-REQUIRE_PACKAGES_FPMKUNIT=1
-REQUIRE_PACKAGES_FCL-BASE=1
-REQUIRE_PACKAGES_FCL-JSON=1
-endif
 ifdef REQUIRE_PACKAGES_RTL
 PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
 ifneq ($(PACKAGEDIR_RTL),)
@@ -2827,7 +2774,7 @@ ifdef LIB_NAME
 	-$(DEL) $(LIB_NAME) $(LIB_FULLNAME)
 endif
 	-$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
-	-$(DEL) *$(ASMEXT) *_ppas$(BATCHEXT) ppas$(BATCHEXT) ppaslink$(BATCHEXT)
+	-$(DEL) *$(ASMEXT) *_ppas$(BATCHEXT)
 fpc_cleanall: $(CLEANTARGET)
 ifdef CLEANEXEFILES
 	-$(DEL) $(CLEANEXEFILES)
@@ -2853,7 +2800,7 @@ ifneq ($(PPUEXT),.ppu)
 endif
 	-$(DELTREE) *$(SMARTEXT)
 	-$(DEL) fpcmade.* Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
-	-$(DEL) *_ppas$(BATCHEXT) ppas$(BATCHEXT) ppaslink$(BATCHEXT)
+	-$(DEL) *_ppas$(BATCHEXT)
 ifdef AOUTEXT
 	-$(DEL) *$(AOUTEXT)
 endif

+ 1 - 1
packages/fcl-db/src/json/Makefile.fpc

@@ -6,7 +6,7 @@
 main=fcl-db
 
 [target]
-units=fpjsondataset
+units=fpjsondataset extjsdataset
 
 [require]
 packages=fcl-base fcl-json

+ 399 - 0
packages/fcl-db/src/json/extjsdataset.pp

@@ -0,0 +1,399 @@
+unit extjsdataset;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, db, fpjson, typinfo, fpjsondataset;
+
+Type
+   { TExtJSJSONDataSet }
+
+  // Base for ExtJS datasets. It handles MetaData conversion.
+  TExtJSJSONDataSet = Class(TBaseJSONDataset)
+  Private
+    FFields : TJSONArray;
+  Protected
+    Function GenerateMetaData : TJSONObject;
+    function ConvertDateFormat(S: String): String; virtual;
+    Procedure MetaDataToFieldDefs; override;
+    procedure InitDateTimeFields; override;
+    function StringToFieldType(S: String): TFieldType;virtual;
+    function GetStringFieldLength(F: TJSONObject; AName: String; AIndex: Integer): integer; virtual;
+  Public
+    // Use this to load MetaData/Rows from stream.
+    // If no metadata is present in the stream, FieldDefs must be filled manually.
+    Procedure LoadFromStream(S : TStream);
+    // Use this to load MetaData/Rows from file.
+    // If no metadata is present in the file, FieldDefs must be filled manually.
+    Procedure LoadFromFile(Const AFileName: string);
+    // Use this to save Rows and optionally metadata to Stream.
+    // Note that MetaData must be set.
+    Procedure SaveToStream(S : TStream; SaveMetaData : Boolean);
+    // Use this to save Rows and optionally metadata to Stream.
+    // Note that MetaData must be set.
+    Procedure SaveToFile(Const AFileName : String; SaveMetaData : Boolean);
+    // Can be set directly if the dataset is closed.
+    Property MetaData;
+    // Can be set directly if the dataset is closed. If metadata is set, it must match the data.
+    Property Rows;
+  Published
+    Property OwnsData;
+  end;
+
+  { TExtJSJSONObjectDataSet }
+  // Use this dataset for data where the data is an array of objects.
+  TExtJSJSONObjectDataSet = Class(TExtJSJSONDataSet)
+    Function CreateFieldMapper : TJSONFieldMapper; override;
+  end;
+
+  { TExtJSJSONArrayDataSet }
+  // Use this dataset for data where the data is an array of arrays.
+  TExtJSJSONArrayDataSet = Class(TExtJSJSONDataSet)
+    Function CreateFieldMapper : TJSONFieldMapper; override;
+  end;
+
+
+implementation
+
+{ TExtJSJSONDataSet }
+
+
+Function  TExtJSJSONDataSet.StringToFieldType(S : String) : TFieldType;
+
+begin
+  if (s='int') then
+    Result:=ftLargeInt
+  else if (s='float') then
+    Result:=ftFloat
+  else if (s='boolean') then
+    Result:=ftBoolean
+  else if (s='date') then
+    Result:=ftDateTime
+  else if (s='string') or (s='auto') or (s='') then
+    Result:=ftString
+  else
+    if MapUnknownToStringType then
+      Result:=ftString
+    else
+      Raise EJSONDataset.CreateFmt('Unknown JSON data type : %s',[s]);
+end;
+
+Function  TExtJSJSONDataSet.GetStringFieldLength(F : TJSONObject; AName : String; AIndex : Integer) : integer;
+
+Var
+  I,L : Integer;
+  D : TJSONData;
+
+begin
+  Result:=0;
+  I:=F.IndexOfName('maxlen');
+  if (I<>-1) and (F.Items[I].jsonType=jtNumber) then
+    begin
+    Result:=StrToIntDef(trim(F.Items[i].AsString),-1);
+    if (Result=-1) then
+      Raise EJSONDataset.CreateFmt('Invalid maximum length specifier for field %s : %s',[AName,F.Items[i].AsString])
+    end
+  else
+    begin
+    For I:=0 to Rows.Count-1 do
+      begin
+      D:=FieldMapper.GetJSONDataForField(Aname,AIndex,Rows[i]);
+      if (D<>Nil) and (D.JsonType<>jtNull) then
+        begin
+        l:=Length(D.AsString);
+        if L>Result then
+          Result:=L;
+        end;
+      end;
+    end;
+  if (Result=0) then
+    Result:=20;
+end;
+
+procedure TExtJSJSONDataSet.LoadFromStream(S: TStream);
+
+Var
+  D : TJSONData;
+  O : TJSONObject;
+  N : String;
+  I : Integer;
+
+begin
+  D:=GetJSON(S);
+  try
+    if (D.JSONType=jtObject) then
+      O:=D as TJSONObject
+    else
+      begin
+      FreeAndNil(D);
+      Raise EJSONDataset.Create('Not a valid ExtJS JSON data packet');
+      end;
+    N:='rows';
+    // Check metadata
+    I:=O.IndexOfName('metaData');
+    if (I<>-1) then
+      begin
+      If (O.Items[i].JSONType<>jtObject) then
+        Raise EJSONDataset.Create('Invalid ExtJS JSON metaData in data packet.');
+      Metadata:=O.Objects['metaData'];
+      O.Extract(I);
+      I:=Metadata.IndexOfName('root');
+      If (I<>-1) then
+        begin
+        if (MetaData.Items[i].JSONType<>jtString) then
+          Raise EJSONDataset.Create('Invalid ExtJS JSON root element in metaData.');
+        N:=MetaData.Strings['root'];
+        end;
+      end;
+    // Check rows
+    I:=O.IndexOfName(N);
+    if (I=-1) then
+      Raise EJSONDataset.Create('Missing rows in data packet');
+    if (O.Items[i].JSONType<>jtArray) then
+      Raise EJSONDataset.Create('Rows element must be an array');
+    Rows:=O.Items[i] as TJSONArray;
+    O.Extract(I);
+    OwnsData:=True;
+  finally
+    D.Free;
+  end;
+end;
+
+procedure TExtJSJSONDataSet.LoadFromFile(const AFileName: string);
+
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(AFileName,fmOpenRead or fmShareDenyWrite);
+  try
+    LoadFromStream(F);
+  finally
+    F.Free;
+  end;
+end;
+
+procedure TExtJSJSONDataSet.SaveToStream(S: TStream; SaveMetaData: Boolean);
+
+Var
+  O : TJSONObject;
+  SS : TStringStream;
+  N : String;
+  I : Integer;
+  M : TJSONobject;
+
+begin
+  O:=TJSONObject.Create;
+  try
+    N:='rows';
+    If SaveMetaData then
+      begin
+      M:=MetaData;
+      if M=Nil then
+        M:=GenerateMetaData;
+      O.Add('metaData',M);
+      if M.IndexOfName('root')<>-1 then
+        N:=M.Strings['root'];
+      end;
+    O.Add(N,Rows);
+    SS:=TStringStream.Create(O.FormatJSON());
+    try
+      S.CopyFrom(SS,0);
+    finally
+      SS.Free;
+    end;
+  finally
+    If (MetaData<>Nil) and SaveMetaData then
+      begin
+      I:=O.IndexOfName('metaData');
+      if (I<>-1) then
+        O.Extract(i);
+      end;
+    O.Extract(O.IndexOfName(N));
+    O.Free;
+  end;
+end;
+
+procedure TExtJSJSONDataSet.SaveToFile(const AFileName: String;
+  SaveMetaData: Boolean);
+
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(AFileName,fmCreate);
+  try
+    SaveToStream(F,SaveMetaData);
+  finally
+    F.Free;
+  end;
+end;
+
+procedure TExtJSJSONDataSet.MetaDataToFieldDefs;
+
+Var
+  A : TJSONArray;
+  F : TJSONObject;
+  MaxLen,I,J,FS : Integer;
+  N,idf : String;
+  ft: TFieldType;
+  D : TJSONData;
+
+begin
+  FieldDefs.Clear;
+  I:=Metadata.IndexOfName('fields');
+  if (I=-1) or (MetaData.Items[i].JSONType<>jtArray) then
+    Raise EJSONDataset.Create('Invalid metadata object');
+  A:=Metadata.Arrays['fields'];
+  For I:=0 to A.Count-1 do
+    begin
+    If (A.Types[i]<>jtObject) then
+      Raise EJSONDataset.CreateFmt('Field definition %d in metadata (%s) is not an object',[i,A[i].AsJSON]);
+    F:=A.Objects[i];
+    J:=F.IndexOfName('name');
+    If (J=-1) or (F.Items[J].JSONType<>jtString) then
+      Raise EJSONDataset.CreateFmt('Field definition %d in has no or invalid name property',[i]);
+    N:=F.Items[J].AsString;
+    J:=F.IndexOfName('type');
+    If (J=-1) then
+      ft:=ftstring
+    else If (F.Items[J].JSONType<>jtString) then
+      Raise EJSONDataset.CreateFmt('Field definition %d in has invalid type property',[i])
+    else
+      ft:=StringToFieldType(F.Items[J].asString);
+    if (ft=ftString) then
+      begin
+      fs:=F.Get('maxLen',0);
+      if fs=0 then
+        fs:=GetStringFieldLength(F,N,I)
+      end
+    else
+      fs:=0;
+    FieldDefs.Add(N,ft,fs);
+    end;
+  FFields:=A;
+end;
+
+function TExtJSJSONDataSet.GenerateMetaData: TJSONObject;
+
+Var
+  F : TJSONArray;
+  O : TJSONObject;
+  I,M : Integer;
+  T : STring;
+
+begin
+  Result:=TJSONObject.Create;
+  F:=TJSONArray.Create;
+  Result.Add('fields',F);
+  For I:=0 to FieldDefs.Count -1 do
+    begin
+    O:=TJSONObject.Create(['name',FieldDefs[i].name]);
+    F.Add(O);
+    M:=0;
+    case FieldDefs[i].DataType of
+      ftfixedwidechar,
+      ftwideString,
+      ftfixedchar,
+      ftString:
+        begin
+        T:='string';
+        M:=FieldDefs[i].Size;
+        end;
+      ftBoolean: T:='boolean';
+      ftDate,
+      ftTime,
+      ftDateTime: T:='date';
+      ftFloat: t:='float';
+      ftSmallint,
+      ftInteger,
+      ftAutoInc,
+      ftLargeInt,
+      ftword: t:='int';
+    else
+      Raise EJSONDataset.CreateFmt('Unsupported field type : %s',[GetEnumName(TypeInfo(TFieldType),Ord(FieldDefs[i].DataType))]);
+    end; // case
+    O.Strings['type']:=t;
+    if M<>0 then
+      O.Integers['maxlen']:=M;
+    end;
+  Result.strings['root']:='rows';
+end;
+
+Function TExtJSJSONDataSet.ConvertDateFormat(S : String) : String;
+
+{ Not handled: N S w z W t L o O P T Z c U MS }
+
+begin
+  Result:=StringReplace(S,'y','yy',[rfReplaceall]);
+  Result:=StringReplace(Result,'Y','yyyy',[rfReplaceall]);
+  Result:=StringReplace(Result,'g','h',[rfReplaceall]);
+  Result:=StringReplace(Result,'G','hh',[rfReplaceall]);
+  Result:=StringReplace(Result,'F','mmmm',[rfReplaceall]);
+  Result:=StringReplace(Result,'M','mmm',[rfReplaceall]);
+  Result:=StringReplace(Result,'n','m',[rfReplaceall]);
+  Result:=StringReplace(Result,'D','ddd',[rfReplaceall]);
+  Result:=StringReplace(Result,'j','d',[rfReplaceall]);
+  Result:=StringReplace(Result,'l','dddd',[rfReplaceall]);
+  Result:=StringReplace(Result,'i','nn',[rfReplaceall]);
+  Result:=StringReplace(Result,'u','zzz',[rfReplaceall]);
+  Result:=StringReplace(Result,'a','am/pm',[rfReplaceall,rfIgnoreCase]);
+  Result:=LowerCase(Result);
+end;
+
+procedure TExtJSJSONDataSet.InitDateTimeFields;
+
+Var
+  F : TJSONObject;
+  FF : TField;
+  I,J : Integer;
+  Fmt : String;
+
+begin
+  If (FFields=Nil) then
+    Exit;
+  For I:=0 to FFields.Count-1 do
+    begin
+    F:=FFields.Objects[i];
+    J:=F.IndexOfName('type');
+    if (J<>-1) and (F.Items[J].JSONType=jtString) and (F.items[J].AsString='date') then
+      begin
+      J:=F.IndexOfName('dateFormat');
+      if (J<>-1) and (F.Items[J].JSONType=jtString) then
+         begin
+         FMT:=ConvertDateFormat(F.Items[J].AsString);
+         FF:=FindField(F.Strings['name']);
+         if (FF<>Nil) and (FF.DataType in [ftDate,ftTime,ftDateTime]) and (FF.FieldKind=fkData) then
+           begin
+
+           if FF is TJSONDateField then
+             TJSONDateField(FF).DateFormat:=Fmt
+           else if FF is TJSONTimeField then
+             TJSONTimeField(FF).TimeFormat:=Fmt
+           else if FF is TJSONDateTimeField then
+             TJSONDateTimeField(FF).DateTimeFormat:=Fmt;
+           end;
+         end;
+      end;
+    end;
+end;
+
+
+{ TJSONArrayDataSet }
+
+function TExtJSJSONArrayDataSet.CreateFieldMapper: TJSONFieldMapper;
+begin
+  Result:=TJSONArrayFieldMapper.Create;
+end;
+
+{ TJSONObjectDataSet }
+
+function TExtJSJSONObjectDataSet.CreateFieldMapper: TJSONFieldMapper;
+begin
+  Result:=TJSONObjectFieldMapper.Create;
+end;
+
+end.
+

Diff do ficheiro suprimidas por serem muito extensas
+ 315 - 444
packages/fcl-db/src/json/fpjsondataset.pp


+ 231 - 157
packages/fcl-db/tests/testjsondataset.pp

@@ -1,190 +1,264 @@
 program testjsondataset;
 
-{$mode objfpc}{$H+}
+{$DEFINE TESTCALCFIELDS}
 
-uses
-  Classes, sysutils, DB, fpjsondataset, fpjson, jsonparser;
+uses sysutils, db, jsonparser, fpjson,fpjsondataset, extjsdataset;
 
-Function ExtractData(Const AFileName : string) : TJSONObject;
+Type
 
-Var
-  F : TFIleStream;
-  P : TJSONParser;
-  D : TJSONData;
+  { TApp }
 
-begin
-  Result:=Nil;
-  F:=TFileStream.Create(AFileName,fmOpenRead);
-  try
-    P:=TJSONParser.Create(F);
-    try
-      D:=P.Parse;
-      if (D.JSONType=jtObject) then
-        Result:=D as TJSONObject
-      else
-        FreeAndNil(D);
-    finally
-      P.Free;
-    end;
-  finally
-    F.Free;
+  TApp = Class(TObject)
+    Procedure DumpRecord(DS : TDataset);
+    Procedure DumpRecords(DS : TDataset);
+    Procedure Run;
+  private
+    procedure DoCalcFields(DataSet: TDataSet);
   end;
+
+Procedure TApp.DumpRecord(DS : TDataset);
+
+//Var
+//  F : TField;
+
+begin
+//  For F in  DS.Fields do
+//    Write(F.Name,' : ',F.IsNull,' ');
+//  WriteLn;
+  Writeln(
+  {$IFDEF TESTCALCFIELDS}
+          'Full name: ',DS.FieldByName('fullname').AsString,
+  {$ENDIF}
+          'First name: ',DS.FieldByName('firstname').AsString,
+          ', Last name: ', DS.FieldByName('lastname').AsString,
+          ', Children: ', DS.FieldByName('children').AsInteger,
+          ', Birthday: ', DS.FieldByName('birthday').AsString
+  );
 end;
-Procedure DumpDataset(DS : TDataset);
 
-Var
-  I,J : Integer;
+Procedure TApp.DumpRecords(DS : TDataset);
 
 begin
-  I:=0;
-  Writeln('Dataset contains ',DS.RecordCount,' records');
   While not DS.EOF do
     begin
-    Inc(I);
-    Writeln('=== Record ',I,' : ',DS.RecNo,' ===');
-    For J:=0 to DS.Fields.Count-1 do
-      With DS.Fields[J] do
-        Writeln(FieldName,' : ',AsString);
+    Write(DS.RecNo,': ');
+    DumpRecord(DS);
     DS.Next;
     end;
-  Writeln('Dataset contained ',I,' records');
 end;
 
-Procedure DoTest4(Const AFileName : string);
 
-Var
-  DS : TExtjsJSONObjectDataset;
-
-begin
-  DS:=TExtjsJSONObjectDataset.Create(Nil);
-  try
-    DS.LoadFromFile(AFileName);
-    DS.Open;
-    DumpDataset(DS);
-  finally
-    DS.Free;
-  end;
-end;
-
-Procedure DoTest1(Const AFileName : string);
+Procedure TApp.Run;
 
 Var
-  D,M : TJSONObject;
-  DS : TExtjsJSONObjectDataset;
-  I,J : Integer;
-  F : TFieldDef;
+  DS : TExtJSJSONObjectDataSet;
+  B : TBookmark;
+  t: TDataLink;
+  DSS : TDatasource;
+{$IFDEF TESTCALCFIELDS}
+  F : TField;
+{$ENDIF}
 
 begin
-  D:=ExtractData(AFileName);
-  try
-    DS:=TExtjsJSONObjectDataset.Create(Nil);
-    try
-      DS.Rows:=D.Arrays['rows'];
-      DS.Metadata:=D.Objects['metaData'];
-      DS.OwnsData:=False;
-      DS.Open;
-      For I:=0 to DS.FieldDefs.Count-1 do
-        begin
-        F:=DS.FieldDefs[i];
-        Writeln('FieldDefs.Add(''',F.Name,''',',F.DataType,',',F.Size,');');
-        end;
-      DumpDataset(DS);
-    finally
-      DS.Free;
-    end;
-  finally
-    D.Free;
-  end;
-end;
 
-Procedure DoTest2(Const AFileName : string);
+  DS:=TExtJSJSONObjectDataSet.Create(Nil);
+  DS.MetaData:=GetJSON(' { "fields" : [ {"name": "firstname", "maxLen" : 100}, {"name": "lastname","maxLen" : 100}, '+
+                       ' { "name" : "children", "type": "int" }, '+
+                       ' { "name" : "birthday", "type": "date", "dateFormat": "yyyy\"-\"mm\"-\"dd" } ]}') as TJSONObject;
+  DS.Rows:=GetJSON('[{"firstname" : "Michael", "lastname" : "Van Canneyt", "children" : 2, "birthday": "1970-07-07" },'+
+                                  '  {"firstname" : "Mattias", "lastname" : "Gaertner", "children" : 0, "birthday" : "1970-07-08" }, '+
+                                  '  {"firstname" : "Bruno", "lastname" : "Fierens", "children" : 3, "birthday" : "1970-07-09" },'+
+                                  '  {"firstname" : "Detlef", "lastname" : "Overbeek", "children" : 2, "birthday" : "1950-07-08" }'+
+                                  ' ]') as TJSONarray;
+{$IFDEF TESTCALCFIELDS}
+  F:=TStringField.Create(DS);
+  F.FieldKind:=fkCalculated;
+  F.Size:=200;
+  F.FieldName:='fullname';
+  F.Dataset:=DS;
+  F:=TStringField.Create(DS);
+  F.FieldKind:=fkData;
+  F.Size:=200;
+  F.FieldName:='firstname';
+  F.Dataset:=DS;
+  F:=TStringField.Create(DS);
+  F.FieldKind:=fkData;
+  F.Size:=200;
+  F.FieldName:='lastname';
+  F.Dataset:=DS;
+  F:=TIntegerField.Create(DS);
+  F.FieldKind:=fkData;
+  F.FieldName:='children';
+  F.Dataset:=DS;
+  F:=TJSONDateField.Create(DS);
+  TJSONDateField(F).DateFormat:='yyyy"-"mm"-"dd';
+  F.FieldKind:=fkData;
+  F.FieldName:='birthday';
 
-Var
-  D,M : TJSONObject;
-  DS : TExtjsJSONObjectDataset;
-  I,J : Integer;
-  F : TFieldDef;
-begin
-  D:=ExtractData(AFileName);
-  DS:=TExtjsJSONObjectDataset.Create(Nil);
-  DS.Rows:=D.Arrays['rows'];
-  With DS do
+  F.Dataset:=DS;
+  DS.OnCalcFields:=@DoCalcFields;
+{$ENDIF}
+  DS.Open;
+  Writeln('All records');
+  DumpRecords(DS);
+  Writeln('First record (expect Michael.)');
+  DS.First;
+  DumpRecord(DS);
+  Writeln('Jump to last (expect detlef)');
+  DS.Last;
+  DumpRecord(DS);
+  Writeln('Reverse order:');
+  While not DS.BOF do
     begin
-    FieldDefs.Add('ID',ftLargeint,0);
-    FieldDefs.Add('Name',ftString,20);
-    FieldDefs.Add('Email',ftString,30);
+    DumpRecord(DS);
+    DS.Prior;
     end;
-  DS.Open;
-  DumpDataset(DS);
-end;
-
-Procedure DoTest3(Const AFileName : string);
+  DS.Append;
+  Writeln('Dumping record after APPEND (expect empty)');
+  Writeln('Modified before dump (expect False): ',DS.Modified);
+  DumpRecord(DS);
+  DS.FieldByName('firstname').AsString:='Florian';
+  Write('Old value of field first name (expect null): ');
+  if DS.FieldByName('firstname').OldValue=Null then
+    Writeln('Null')
+  else
+    Writeln(DS.FieldByName('firstname').OldValue);
+  DS.FieldByName('lastname').AsString:='Klaempfl';
+  DS.FieldByName('children').AsInteger:=1;
+  DS.FieldByName('birthday').AsDateTime:=EncodeDate(1980,5,4);
+  Writeln('Modified after (expect true): ',DS.Modified);
+  Writeln('Dumping record before POST (Expect Florian)');
+  DumpRecord(DS);
+  DS.Post;
+  Writeln('Dumping record after POST (Expect Florian)');
+  DumpRecord(DS);
+  Writeln('Jump to first (expect Michael)');
+  DS.First;
+  DumpRecord(DS);
+  DS.Edit;
+  Writeln('Dumping record after EDIT');
+  Writeln('Modified before  (expect False): ',DS.Modified);
+  DumpRecord(DS);
+  DS.FieldByName('firstname').AsString:='Dolores';
+  DS.FieldByName('lastname').AsString:='Nabokov';
+  DS.FieldByName('children').AsInteger:=0;
+  DS.FieldByName('birthday').AsDateTime:=EncodeDate(1943,2,14);
+  Writeln('Modified after (expect true): ',DS.Modified);
+  Writeln('Dumping record before POST (expect Dolores)');
+  DumpRecord(DS);
+  DS.Post;
+  Writeln('Dumping record after POST (expect Dolores)');
+  DumpRecord(DS);
+  DS.Edit;
+  Writeln('Dumping record after second EDIT (Expect Dolores)');
+  DumpRecord(DS);
+  Writeln('Modified before  (expect False): ',DS.Modified);
+  DS.FieldByName('firstname').AsString:='Felicity';
+  Writeln('Old value of field first name (expect Dolores): ', DS.FieldByName('firstname').OldValue);
+  DS.FieldByName('lastname').AsString:='Brown';
+  DS.FieldByName('children').AsInteger:=0;
+  DS.FieldByName('birthday').AsDateTime:=EncodeDate(1943,2,14);
+  Writeln('Modified after (expect true): ',DS.Modified);
+  Writeln('Dumping record before Cancel (expect Filicity brown)');
+  DumpRecord(DS);
+  DS.Cancel;
+  Writeln('Dumping record after Cancel (expect Dolores)');
+  DumpRecord(DS);
+  Writeln('Jump to first and dumping all records (expect Dolores first)');
+  DS.First;
+  DumpRecords(DS);
+  Writeln('Jump to first  (expect Dolores)');
+  DS.First;
+  DumpRecord(DS);
+  DS.Next;
+  DS.Next;
+  DS.Next;
+  Writeln('Getting Bookmark (expect Detlef)');
+  DumpRecord(DS);
+  B:=DS.BookMark;
+  DS.First;
+  Writeln('Delete (expect Mattias)');
+  DS.Delete;
+  DumpRecord(DS);
+  Writeln('Setting Bookmark (expect Detlef)');
+  Writeln('BM value: ',PNativeInt(B)^);
+  DS.BookMark:=B;
+  DumpRecord(DS);
+  Writeln('Jump to second (expect Bruno)');
+  DS.First;
+  DS.Next;
+  DumpRecord(DS);
+  DS.Insert;
+  Writeln('Dumping record after second Insert (Expect empty)');
+  Writeln('Modified (expect False): ',DS.Modified);
+  DumpRecord(DS);
+  DS.FieldByName('firstname').AsString:='Felicity';
+  DS.FieldByName('lastname').AsString:='Brown';
+  DS.FieldByName('children').AsInteger:=0;
+  DS.FieldByName('birthday').AsDateTime:=EncodeDate(1963,4,6);
+  Writeln('Modified (expect true): ',DS.Modified);
+  Writeln('Dumping record before POST (expect Filicity)');
+  DumpRecord(DS);
+  DS.Post;
+  Writeln('Dumping record after POST (expect Felicity)');
+  DumpRecord(DS);
+  Writeln('Jump to first and dumping all records (expect Mattias first, then Felicity)');
+  DS.First;
+  DumpRecords(DS);
+  Writeln('Jump to first before edit');
+  DS.First;
+  DSS:=TDatasource.Create(Nil);
+  DSS.DataSet:=DS;
+  t:=TDataLink.Create;
+  try
+    Writeln('Buffercount');
+    t.BufferCount := 10;
+    t.DataSource := DSS;
+    Writeln('Doing edit');
+    t.Edit;
+    Writeln('Modified (expect false): ',DS.Modified);
+    Writeln('Done edit');
+    t.ActiveRecord := 0;
+    Writeln('Edit, expect Mattias');
+    DumpRecord(DS);
+    Writeln('Activerecord 1: expect Felicity');
+    t.ActiveRecord := 1;
+    DumpRecord(DS);
+    Writeln('Activerecord 2: expect Bruno');
+    t.ActiveRecord := 2;
+    DumpRecord(DS);
+    t.ActiveRecord := 0;
+  Finally
+    t.Free;
+  end;
+  t:=TDataLink.Create;
+  try
+    t.DataSource := DSS;
+    DS.Last;
+    Writeln('Last record :',DS.RecNo);
+    Writeln('Activerecord :',T.ActiveRecord);
+    DumpRecord(DS);
+    DS.First;
+    t.BufferCount := 3;
+    DS.Last;
+    Writeln('Last record after buffercount lessened:',DS.RecNo);
+    Writeln('Activerecord :',T.ActiveRecord);
+    DumpRecord(DS);
+    t.ActiveRecord := 0;
+  Finally
+    t.Free;
+  end;
 
-Var
-  DS : TExtjsJSONObjectDataset;
-  I,J : Integer;
-  F : TFieldDef;
+end;
 
+procedure TApp.DoCalcFields(DataSet: TDataSet);
 begin
-  DS:=TExtjsJSONObjectDataset.Create(Nil);
-  try
-    With DS do
-      begin
-      FieldDefs.Add('ID',ftLargeint,0);
-      FieldDefs.Add('Name',ftString,20);
-      FieldDefs.Add('Email',ftString,30);
-      Open;
-      // Record 1
-      Append;
-      FieldByName('ID').AsInteger:=3;
-      FieldByName('Name').AsString:='Michael';
-      FieldByName('Email').AsString:='[email protected]';
-      Post;
-      // Record 2
-      Append;
-      FieldByName('ID').AsInteger:=4;
-      FieldByName('Name').AsString:='jonas';
-      FieldByName('Email').AsString:='[email protected]';
-      Post;
-      DumpDataset(DS);
-      First;
-      // insert record 1
-      Insert;
-      FieldByName('ID').AsInteger:=1;
-      FieldByName('Name').AsString:='Florian';
-      FieldByName('Email').AsString:='[email protected]';
-      Post;
-      DumpDataset(DS);
-      Writeln('First');
-      First;
-      Writeln('Editing record ', RecNo,' ',FieldByName('Name').AsString);
-      Edit;
-      FieldByName('ID').AsInteger:=12;
-      FieldByName('Name').AsString:='Marco';
-      FieldByName('Email').AsString:='[email protected]';
-      Post;
-      First;
-      DumpDataset(DS);
-      First;
-      Next;
-      Writeln('Deleting record ', RecNo,' ',FieldByName('Name').AsString);
-      Delete;
-      First;
-      DumpDataset(DS);
-      SaveToFile(AFileName,True);
-      end;
-  finally
-    DS.Free
-  end;
+  Writeln('In calcfields callback');
+  Dataset.FieldByName('FullName').AsString:= Dataset.FieldByName('firstName').AsString+' '+Dataset.FieldByName('lastname').AsString;
 end;
+
 begin
-  Writeln('Test 1');
-  DoTest1('test.json');
-  Writeln('Test 2');
-  DoTest2('test.json');
-  Writeln('Test 3');
-  DoTest3('test3.json');
-  Writeln('Test 4');
-  DoTest4('test.json');
+  With Tapp.Create do
+    Run;
 end.
 

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff