瀏覽代碼

Merged revisions 577-578 via svnmerge from
/trunk

git-svn-id: branches/fixes_2_0@673 -

peter 20 年之前
父節點
當前提交
d176fe6cc5

+ 3 - 0
.gitattributes

@@ -637,7 +637,9 @@ fcl/db/sqlite/Makefile.fpc svneol=native#text/plain
 fcl/db/sqlite/browseds.pas svneol=native#text/plain
 fcl/db/sqlite/concurrencyds.pas svneol=native#text/plain
 fcl/db/sqlite/createds.pas svneol=native#text/plain
+fcl/db/sqlite/customsqliteds.pas svneol=native#text/plain
 fcl/db/sqlite/fillds.pas svneol=native#text/plain
+fcl/db/sqlite/sqlite3ds.pas svneol=native#text/plain
 fcl/db/sqlite/sqlitedataset.pas svneol=native#text/plain
 fcl/db/sqlite/sqliteds.pas svneol=native#text/plain
 fcl/db/sqlite/testds.pas svneol=native#text/plain
@@ -1560,6 +1562,7 @@ packages/base/regexpr/testreg1.pp svneol=native#text/plain
 packages/base/sqlite/Makefile svneol=native#text/plain
 packages/base/sqlite/Makefile.fpc svneol=native#text/plain
 packages/base/sqlite/sqlite.pp svneol=native#text/plain
+packages/base/sqlite/sqlite3.pp svneol=native#text/plain
 packages/base/sqlite/sqlitedb.pas svneol=native#text/plain
 packages/base/sqlite/test.pas svneol=native#text/plain
 packages/extra/Makefile svneol=native#text/plain

+ 34 - 34
fcl/db/sqlite/Makefile

@@ -1,5 +1,5 @@
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2005/05/05]
+# Don't edit, this file is generated by FPCMake Version 1.9.8 [2005/04/10]
 #
 default: all
 MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-emx i386-watcom i386-netwlibc m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos powerpc-linux powerpc-netbsd powerpc-macos powerpc-darwin powerpc-morphos sparc-linux sparc-netbsd sparc-solaris x86_64-linux x86_64-freebsd arm-linux
@@ -233,103 +233,103 @@ PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages/base $(FPCDIR)/packages/ext
 override PACKAGE_NAME=fcl
 PACKAGEDIR_MAIN:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fcl/Makefile.fpc,$(PACKAGESDIR))))))
 ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_UNITS+=sqliteds
+override TARGET_UNITS+=customsqliteds sqliteds sqlite3ds
 endif
 override INSTALL_FPCPACKAGE=y
 ifdef REQUIRE_UNITSDIR

+ 1 - 1
fcl/db/sqlite/Makefile.fpc

@@ -6,7 +6,7 @@
 main=fcl
 
 [target]
-units=sqliteds
+units=customsqliteds sqliteds sqlite3ds
 
 [require]
 packages=sqlite

+ 1139 - 0
fcl/db/sqlite/customsqliteds.pas

@@ -0,0 +1,1139 @@
+unit customsqliteds;
+
+{
+    This is TCustomSqliteDataset, a TDataset descendant class for use with fpc compiler
+    Copyright (C) 2004  Luiz Américo Pereira Câmara
+    Email: [email protected]
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+}
+
+{$Mode ObjFpc}
+{$H+}
+{ $Define USE_SQLITEDS_INTERNALS}
+{ $Define DEBUG}
+{ $Define DEBUGACTIVEBUFFER}
+
+interface
+
+uses
+  Classes, SysUtils, Db;
+
+type
+  PDataRecord = ^DataRecord;
+  PPDataRecord = ^PDataRecord;
+  DataRecord = record
+    Row: PPchar;
+    BookmarkData: Pointer;
+    BookmarkFlag: TBookmarkFlag;
+    Next: PDataRecord;
+    Previous: PDataRecord;
+  end;
+  
+  TDSStream = class(TStream)
+  private
+    FActiveItem:PDataRecord;
+    FFieldRow:PChar;  
+    FFieldIndex:Integer;
+    FRowSize: Integer;
+    FPosition: Longint;
+  public
+    constructor Create(const ActiveItem: PDataRecord; FieldIndex:Integer);
+    function Write(const Buffer; Count: Longint): Longint; override;
+    function Read(var Buffer; Count: Longint): Longint; override;
+    function Seek(Offset: Longint; Origin: Word): Longint; override;
+  end;
+  
+  TSqliteCallback = function (UserData:Pointer; Columns:longint; Values:PPchar; ColumnNames:PPchar):longint;cdecl;
+  
+  { TCustomSqliteDataset }
+
+  TCustomSqliteDataset = class(TDataSet)
+  private
+    FPrimaryKey: String;
+    FPrimaryKeyNo: Integer;
+
+    {$ifdef DEBUGACTIVEBUFFER}
+    FFCurrentItem: PDataRecord;
+    {$else}
+    FCurrentItem: PDataRecord;
+    {$endif}
+    FBufferSize: Integer;
+    FExpectedAppends: Integer;
+    FExpectedDeletes: Integer;
+    FExpectedUpdates: Integer;
+    FSaveOnClose: Boolean;
+    FSaveOnRefetch: Boolean;
+    FComplexSql: Boolean;
+    FUpdatedItems: TList;
+    FAddedItems: TList;
+    FDeletedItems: TList;
+    FOrphanItems: TList;
+    FMasterLink: TMasterDataLink;
+    FIndexFieldNames: String;
+    FIndexFieldList: TList;
+    function GetIndexFields(Value: Integer): TField;
+    procedure UpdateIndexFields;
+  protected
+    FFileName: String;
+    FSql: String;
+    FTableName: String;
+    FAutoIncFieldNo: Integer;
+    FNextAutoInc:Integer;
+    FSqliteReturnId: Integer;
+    FSqliteHandle: Pointer;
+    FDataAllocated: Boolean;
+    FRowBufferSize: Integer;
+    FRowCount: Integer;
+    FRecordCount: Integer;
+    FBeginItem: PDataRecord;
+    FEndItem: PDataRecord;
+    FCacheItem: PDataRecord;
+    function SqliteExec(AHandle: Pointer; Sql:PChar):Integer;virtual; abstract;
+    procedure SqliteClose(AHandle: Pointer);virtual;abstract;
+    function GetSqliteHandle: Pointer; virtual; abstract;
+    procedure BuildLinkedList; virtual; abstract;
+    function SqliteReturnString: String; virtual; abstract;
+    function TableExists: Boolean;virtual;abstract;
+    procedure DisposeLinkedList;
+    procedure MasterChanged(Sender: TObject);
+    procedure MasterDisabled(Sender: TObject);
+    procedure SetMasterFields(Value:String);
+    function GetMasterFields:String;
+    procedure SetMasterSource(Value: TDataSource);
+    function GetMasterSource:TDataSource;
+    //TDataSet overrides
+    function AllocRecordBuffer: PChar; override;
+    function CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream; override;
+    procedure FreeRecordBuffer(var Buffer: PChar); override;
+    procedure GetBookmarkData(Buffer: PChar; Data: Pointer); override;
+    function GetBookmarkFlag(Buffer: PChar): TBookmarkFlag; override;
+    function GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult; override;
+    function GetRecordCount: Integer; override;
+    function GetRecNo: Integer; override;
+    function GetRecordSize: Word; override; 
+    procedure InternalAddRecord(Buffer: Pointer; DoAppend: Boolean); override;
+    procedure InternalClose; override;
+    procedure InternalDelete; override;
+    procedure InternalFirst; override;
+    procedure InternalGotoBookmark(ABookmark: Pointer); override;
+    procedure InternalHandleException; override;
+    procedure InternalInitRecord(Buffer: PChar); override;
+    procedure InternalLast; override;
+    procedure InternalOpen; override;
+    procedure InternalPost; override;
+    procedure InternalSetToRecord(Buffer: PChar); override;
+    function IsCursorOpen: Boolean; override;    
+    procedure SetBookmarkData(Buffer: PChar; Data: Pointer); override;
+    procedure SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); override;
+    procedure SetExpectedAppends(AValue:Integer);
+    procedure SetExpectedUpdates(AValue:Integer);
+    procedure SetExpectedDeletes(AValue:Integer);
+    procedure SetFieldData(Field: TField; Buffer: Pointer); override;  
+    procedure SetRecNo(Value: Integer); override;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    function GetFieldData(Field: TField; Buffer: Pointer): Boolean; override;
+    // Additional procedures
+    function ApplyUpdates: Boolean; virtual;
+    function CreateTable: Boolean; virtual;
+    function ExecSQL:Integer;
+    function ExecSQL(const ASql:String):Integer;
+    procedure RefetchData;
+    function UpdatesPending: Boolean;
+    {$ifdef DEBUGACTIVEBUFFER}
+    procedure SetCurrentItem(Value:PDataRecord);
+    property FCurrentItem: PDataRecord read FFCurrentItem write SetCurrentItem;
+    {$endif}
+    {$ifdef USE_SQLITEDS_INTERNALS}
+    property BeginItem: PDataRecord read FBeginItem;
+    property EndItem: PDataRecord read FEndItem;
+    property UpdatedItems: TList read FUpdatedItems;
+    property AddedItems: TList read FAddedItems;
+    property DeletedItems: TList read FDeletedItems;
+    {$endif}
+    property ComplexSql: Boolean read FComplexSql write FComplexSql;
+    property ExpectedAppends: Integer read FExpectedAppends write SetExpectedAppends;
+    property ExpectedUpdates: Integer read FExpectedUpdates write SetExpectedUpdates;
+    property ExpectedDeletes: Integer read FExpectedDeletes write SetExpectedDeletes;
+    property IndexFields[Value: Integer]: TField read GetIndexFields;
+    property SqliteReturnId: Integer read FSqliteReturnId;
+   published
+    property IndexFieldNames: string read FIndexFieldNames write FIndexFieldNames;
+    property FileName: String read FFileName write FFileName;
+    property PrimaryKey: String read FPrimaryKey write FPrimaryKey;
+    property SaveOnClose: Boolean read FSaveOnClose write FSaveOnClose; 
+    property SaveOnRefetch: Boolean read FSaveOnRefetch write FSaveOnRefetch;
+    property SQL: String read FSql write FSql;
+    property TableName: String read FTableName write FTableName;   
+    property MasterSource: TDataSource read GetMasterSource write SetMasterSource;
+    property MasterFields: string read GetMasterFields write SetMasterFields;
+    
+    property Active;
+    property FieldDefs;
+     
+    //Events
+    property BeforeOpen;
+    property AfterOpen;
+    property BeforeClose;
+    property AfterClose;
+    property BeforeInsert;
+    property AfterInsert;
+    property BeforeEdit;
+    property AfterEdit;
+    property BeforePost;
+    property AfterPost;
+    property BeforeCancel;
+    property AfterCancel;
+    property BeforeDelete;
+    property AfterDelete;
+    property BeforeScroll;
+    property AfterScroll;
+    property OnDeleteError;
+    property OnEditError;
+  end;
+  
+implementation
+
+uses
+  strutils;
+
+const
+  SQLITE_OK = 0;//sqlite2.x.x and sqlite3.x.x defines this equal
+
+// TDSStream
+
+constructor TDSStream.Create(const ActiveItem: PDataRecord; FieldIndex:Integer);
+begin
+  inherited Create;
+  FPosition:=0;
+  FActiveItem:=ActiveItem;
+  FFieldIndex:=FieldIndex;
+  FFieldRow:=ActiveItem^.Row[FieldIndex];
+  if FFieldRow <> nil then
+    FRowSize:=StrLen(FFieldRow)
+  else
+    FRowSize:=0;  
+end;  
+
+function TDSStream.Seek(Offset: Longint; Origin: Word): Longint;
+begin
+  Case Origin of
+    soFromBeginning : FPosition:=Offset;
+    soFromEnd       : FPosition:=FRowSize+Offset;
+    soFromCurrent   : FPosition:=FPosition+Offset;
+  end;
+  Result:=FPosition;
+end;
+
+function TDSStream.Write(const Buffer; Count: Longint): Longint; 
+var
+  NewRow:PChar;
+begin
+  Result:=Count;
+  if Count = 0 then
+    Exit;
+  //Todo: see how TDbMemo read/write to field and choose best if order
+  if FPosition = 0 then
+  begin
+    NewRow:=StrAlloc(Count+1);
+    (NewRow+Count)^:=#0;
+    Move(Buffer,NewRow^,Count);    
+  end
+  else
+  begin
+    NewRow:=StrAlloc(FRowSize+Count+1);
+    (NewRow+Count+FRowSize)^:=#0;
+    Move(FFieldRow^,NewRow^,FRowSize);
+    Move(Buffer,(NewRow+FRowSize)^,Count);
+  end;
+  FActiveItem^.Row[FFieldIndex]:=NewRow;    
+  StrDispose(FFieldRow);
+  FFieldRow:=NewRow;
+  FRowSize:=StrLen(NewRow);
+  Inc(FPosition,Count);
+  {$ifdef DEBUG}
+  WriteLn('Writing a BlobStream');
+  WriteLn('Stream.Size: ',StrLen(NewRow));
+  WriteLn('Stream Value: ',NewRow);
+  WriteLn('FPosition:',FPosition);
+  {$endif}
+end; 
+ 
+function TDSStream.Read(var Buffer; Count: Longint): Longint; 
+var
+  BytesToMove:Integer;
+begin
+  if (FRowSize - FPosition) >= Count then
+    BytesToMove:=Count
+  else
+    BytesToMove:=FRowSize - FPosition;   
+  Move((FFieldRow+FPosition)^,Buffer,BytesToMove);
+  Inc(FPosition,BytesToMove);
+  Result:=BytesToMove;  
+  {$ifdef DEBUG}
+  WriteLn('Reading a BlobStream');
+  WriteLn('Bytes requested: ',Count);
+  WriteLn('Bytes Moved: ',BytesToMove);
+  WriteLn('Stream.Size: ',FRowSize);
+  WriteLn('Stream Value: ',FFieldRow);
+  {$endif}
+end; 
+ 
+// TCustomSqliteDataset override methods
+
+function TCustomSqliteDataset.AllocRecordBuffer: PChar;
+var
+  APointer:Pointer;
+begin
+  APointer := AllocMem(FBufferSize);
+  PDataRecord(APointer^):=FBeginItem;
+  Result:=APointer;
+end;
+
+constructor TCustomSqliteDataset.Create(AOwner: TComponent);
+begin
+  // setup special items
+  New(FBeginItem);
+  New(FCacheItem);
+  New(FEndItem);
+  
+  FBeginItem^.Previous:=nil;
+  FEndItem^.Next:=nil;
+  
+  FBeginItem^.BookMarkFlag:=bfBOF;
+  FCacheItem^.BookMarkFlag:=bfEOF;
+  FEndItem^.BookMarkFlag:=bfEOF;
+  
+  FMasterLink:=TMasterDataLink.Create(Self);
+  FMasterLink.OnMasterChange:=@MasterChanged;
+  FMasterLink.OnMasterDisable:=@MasterDisabled;
+  FIndexFieldList:=TList.Create;
+  BookmarkSize := SizeOf(Pointer);
+  FBufferSize := SizeOf(PPDataRecord);
+  FUpdatedItems:= TList.Create;
+  FUpdatedItems.Capacity:=20;
+  FAddedItems:= TList.Create;
+  FAddedItems.Capacity:=20;
+  FOrphanItems:= TList.Create;
+  FOrphanItems.Capacity:=20;
+  FDeletedItems:= TList.Create;
+  FDeletedItems.Capacity:=20;
+  inherited Create(AOwner);
+end;
+
+function TCustomSqliteDataset.CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream;
+begin
+  Result:= TDSStream.Create(PPDataRecord(ActiveBuffer)^,Field.FieldNo - 1);
+end;  
+
+destructor TCustomSqliteDataset.Destroy;
+begin
+  inherited Destroy;
+  FUpdatedItems.Destroy;
+  FAddedItems.Destroy;
+  FDeletedItems.Destroy;
+  FOrphanItems.Destroy;
+  FMasterLink.Destroy;
+  FIndexFieldList.Destroy;
+  // dispose special items
+  Dispose(FBeginItem);
+  Dispose(FCacheItem);
+  Dispose(FEndItem);
+end;
+
+function TCustomSqliteDataset.GetIndexFields(Value: Integer): TField;
+begin
+  if (Value < 0) or (Value > FIndexFieldList.Count - 1) then
+    DatabaseError('Error acessing IndexFields: Index out of bonds');
+  Result:= TField(FIndexFieldList[Value]);
+end;
+
+procedure TCustomSqliteDataset.DisposeLinkedList;
+var
+  TempItem:PDataRecord;
+  Counter,I:Integer;
+begin
+  //Todo: insert debug info
+  FDataAllocated:=False;
+  TempItem:=FBeginItem^.Next;
+  if TempItem <> nil then
+    while TempItem^.Next <> nil do
+    begin
+      for Counter:= 0 to FRowCount - 1 do
+        StrDispose(TempItem^.Row[Counter]);  
+      FreeMem(TempItem^.Row,FRowBufferSize);
+      TempItem:=TempItem^.Next;
+      Dispose(TempItem^.Previous);
+    end; 
+  
+  //Dispose FBeginItem.Row
+  FreeMem(FBeginItem^.Row,FRowBufferSize);
+    
+  //Dispose cache item
+  for Counter:= 0 to FRowCount - 1 do
+    StrDispose(FCacheItem^.Row[Counter]);
+  FreeMem(FCacheItem^.Row,FRowBufferSize);
+
+  //Dispose OrphanItems
+  for Counter:= 0 to FOrphanItems.Count - 1 do
+  begin
+    TempItem:=PDataRecord(FOrphanItems[Counter]);
+    for I:= 0 to FRowCount - 1 do
+      StrDispose(TempItem^.Row[I]);  
+    FreeMem(TempItem^.Row,FRowBufferSize);
+    Dispose(TempItem);  
+  end;     
+end;
+
+procedure TCustomSqliteDataset.FreeRecordBuffer(var Buffer: PChar);
+begin
+  FreeMem(Buffer);
+end;
+
+procedure TCustomSqliteDataset.GetBookmarkData(Buffer: PChar; Data: Pointer);
+begin
+  Pointer(Data^) := PPDataRecord(Buffer)^^.BookmarkData;
+end;
+
+function TCustomSqliteDataset.GetBookmarkFlag(Buffer: PChar): TBookmarkFlag;
+begin
+  Result := PPDataRecord(Buffer)^^.BookmarkFlag;
+end;
+
+function TCustomSqliteDataset.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
+var
+  ValError:Word;
+  FieldRow:PChar;
+begin
+  FieldRow:=PPDataRecord(ActiveBuffer)^^.Row[Field.FieldNo - 1];
+  Result := FieldRow <> nil;  
+  if Result and (Buffer <> nil) then //supports GetIsNull
+  begin
+    case Field.Datatype of
+    ftString:
+      begin
+        Move(FieldRow^,PChar(Buffer)^,StrLen(FieldRow)+1);
+      end;
+    ftInteger,ftBoolean,ftWord,ftAutoInc:
+      begin
+        Val(StrPas(FieldRow),LongInt(Buffer^),ValError);
+        Result:= ValError = 0;  
+      end;
+    ftFloat,ftDateTime,ftTime,ftDate:
+      begin
+        Val(StrPas(FieldRow),Double(Buffer^),ValError);
+        Result:= ValError = 0; 
+      end;    
+    end;
+  end;        
+end;
+
+function TCustomSqliteDataset.GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult;
+begin
+  Result := grOk;
+  case GetMode of
+    gmPrior:
+      if (FCurrentItem^.Previous = FBeginItem) or (FCurrentItem = FBeginItem) then
+      begin
+        Result := grBOF;
+        FCurrentItem := FBeginItem;
+      end
+      else
+        FCurrentItem:=FCurrentItem^.Previous;
+    gmCurrent:
+      if (FCurrentItem = FBeginItem) or (FCurrentItem = FEndItem) then
+         Result := grError;
+    gmNext:
+      if (FCurrentItem = FEndItem) or (FCurrentItem^.Next = FEndItem) then
+        Result := grEOF
+      else
+        FCurrentItem:=FCurrentItem^.Next;
+  end; //case
+  if Result = grOk then
+  begin
+    PDataRecord(Pointer(Buffer)^):=FCurrentItem;
+    with FCurrentItem^ do
+    begin
+      BookmarkData := FCurrentItem;
+      BookmarkFlag := bfCurrent;
+    end;
+  end
+    else if (Result = grError) and DoCheck then
+      DatabaseError('SqliteDs - No records',Self);
+end;
+
+function TCustomSqliteDataset.GetRecordCount: Integer;
+begin
+  Result := FRecordCount;
+end;
+
+function TCustomSqliteDataset.GetRecNo: Integer;
+var
+  TempItem,TempActive:PDataRecord;
+begin
+  Result:= -1;
+  if FRecordCount = 0 then
+    Exit;  
+  TempItem:=FBeginItem;
+  TempActive:=PPDataRecord(ActiveBuffer)^;
+  if TempActive = FCacheItem then // Record not posted yet
+    Result:=FRecordCount 
+  else
+    while TempActive <> TempItem do
+    begin
+      if TempItem^.Next <> nil then
+      begin
+        inc(Result);
+        TempItem:=TempItem^.Next;
+      end  
+      else
+      begin
+        Result:=-1;
+        DatabaseError('Sqliteds.GetRecNo - ActiveItem Not Found',Self);
+        break;    
+      end;      
+    end;  
+end;
+
+function TCustomSqliteDataset.GetRecordSize: Word;
+begin
+  Result := FBufferSize; //??
+end;
+
+procedure TCustomSqliteDataset.InternalAddRecord(Buffer: Pointer; DoAppend: Boolean);
+var
+  NewItem: PDataRecord;
+  Counter:Integer;
+begin
+  {$ifdef DEBUG}
+  if PPDataRecord(Buffer)^ <> FCacheItem then
+    DatabaseError('PPDataRecord(Buffer) <> FCacheItem - Problem',Self);
+  {$endif}
+  New(NewItem);
+  GetMem(NewItem^.Row,FRowBufferSize);
+  for Counter := 0 to FRowCount - 1 do 
+    NewItem^.Row[Counter]:=StrNew(FCacheItem^.Row[Counter]);   
+  FEndItem^.Previous^.Next:=NewItem;
+  NewItem^.Previous:=FEndItem^.Previous;
+  NewItem^.Next:=FEndItem;
+  FEndItem^.Previous:=NewItem;
+  Inc(FRecordCount);
+  if FAutoIncFieldNo <> - 1 then
+    Inc(FNextAutoInc);
+  FAddedItems.Add(NewItem);
+end;
+
+procedure TCustomSqliteDataset.InternalClose;
+begin
+  if FSaveOnClose then
+    ApplyUpdates;
+  //BindFields(False);
+  if DefaultFields then
+    DestroyFields;
+  if FDataAllocated then
+    DisposeLinkedList;  
+  if FSqliteHandle <> nil then
+  begin
+    SqliteClose(FSqliteHandle);
+    FSqliteHandle := nil;
+  end;
+  FAddedItems.Clear;
+  FUpdatedItems.Clear;
+  FDeletedItems.Clear;
+  FOrphanItems.Clear;
+  FRecordCount:=0;
+end;
+
+procedure TCustomSqliteDataset.InternalDelete;
+var
+  TempItem:PDataRecord;
+  ValError,TempInteger:Integer;
+begin
+  If FRecordCount = 0 then
+    Exit;
+  Dec(FRecordCount);
+  TempItem:=PPDataRecord(ActiveBuffer)^;
+  // Remove from changed list
+  FUpdatedItems.Remove(TempItem);
+  if FAddedItems.Remove(TempItem) = -1 then
+    FDeletedItems.Add(TempItem);
+  FOrphanItems.Add(TempItem);
+  TempItem^.Next^.Previous:=TempItem^.Previous;
+  TempItem^.Previous^.Next:=TempItem^.Next;
+  if FCurrentItem = TempItem then
+  begin
+    if FCurrentItem^.Previous <> FBeginItem then
+      FCurrentItem:= FCurrentItem^.Previous
+    else
+      FCurrentItem:= FCurrentItem^.Next;  
+  end; 
+  // Dec FNextAutoInc (only if deleted item is the last record)  
+  if FAutoIncFieldNo <> -1 then
+  begin
+    Val(StrPas(TempItem^.Row[FAutoIncFieldNo]),TempInteger,ValError);
+    if (ValError = 0) and (TempInteger = (FNextAutoInc - 1)) then
+      Dec(FNextAutoInc);
+  end;    
+end;
+
+procedure TCustomSqliteDataset.InternalFirst;
+begin
+  FCurrentItem := FBeginItem;
+end;
+
+procedure TCustomSqliteDataset.InternalGotoBookmark(ABookmark: Pointer);
+begin
+  FCurrentItem := PDataRecord(ABookmark^);
+end;
+
+procedure TCustomSqliteDataset.InternalHandleException;
+begin
+  //??
+end;
+
+procedure TCustomSqliteDataset.InternalInitRecord(Buffer: PChar);
+var
+  Counter:Integer;
+  TempStr:String;  
+begin
+  for Counter:= 0 to FRowCount - 1 do
+  begin
+    StrDispose(FCacheItem^.Row[Counter]);
+    FCacheItem^.Row[Counter]:=nil;
+  end;
+  if FAutoIncFieldNo <> - 1 then
+  begin
+    Str(FNextAutoInc,TempStr);
+    FCacheItem^.Row[FAutoIncFieldNo]:=StrAlloc(Length(TempStr)+1);
+    StrPCopy(FCacheItem^.Row[FAutoIncFieldNo],TempStr);
+  end;  
+  PPDataRecord(Buffer)^:=FCacheItem;    
+end;
+
+procedure TCustomSqliteDataset.InternalLast;
+begin
+  FCurrentItem := FEndItem;
+end;
+
+procedure TCustomSqliteDataset.InternalOpen;
+begin
+  FAutoIncFieldNo:=-1;
+  if not FileExists(FFileName) then
+    DatabaseError('TCustomSqliteDataset - File '+FFileName+' not found');
+  if (FTablename = '') and not (FComplexSql) then
+    DatabaseError('TCustomSqliteDataset - Tablename not set');
+
+  if MasterSource <> nil then
+  begin
+    FSql := 'Select * from '+FTableName+';'; // forced to obtain all fields
+    FMasterLink.FieldNames:=MasterFields; //this should fill MasterLinks.Fields
+    //todo: ignore if Fields.Count = 0 (OnMasterChanged will not be called) or
+    // raise a error?
+    //if (FMasterLink.Fields.Count = 0) and (MasterSource.DataSet.Active) then
+    //   DatabaseError('Master Fields are not defined correctly');
+  end;
+  
+  FSqliteHandle:=GetSqliteHandle;
+  if FSql = '' then
+    FSql := 'Select * from '+FTableName+';';
+  InternalInitFieldDefs;
+
+  if DefaultFields then 
+    CreateFields;
+
+  BindFields(True);
+
+  UpdateIndexFields;
+  if FMasterLink.Active and (FIndexFieldList.Count <> FMasterLink.Fields.Count) then
+    DatabaseError('MasterFields count doesnt match IndexFields count');
+
+  // Get PrimaryKeyNo if available
+  if Fields.FindField(FPrimaryKey) <> nil then
+    FPrimaryKeyNo:=Fields.FindField(FPrimaryKey).FieldNo - 1  
+  else
+    FPrimaryKeyNo:=FAutoIncFieldNo; // -1 if there's no AutoIncField 
+       
+  BuildLinkedList;               
+  FCurrentItem:=FBeginItem;
+end;
+
+procedure TCustomSqliteDataset.InternalPost;
+begin
+  if (State<>dsEdit) then 
+    InternalAddRecord(ActiveBuffer,True);
+end;
+
+procedure TCustomSqliteDataset.InternalSetToRecord(Buffer: PChar);
+begin
+  FCurrentItem:=PPDataRecord(Buffer)^;
+end;
+
+function TCustomSqliteDataset.IsCursorOpen: Boolean;
+begin
+   Result := FDataAllocated;
+end;
+
+procedure TCustomSqliteDataset.SetBookmarkData(Buffer: PChar; Data: Pointer);
+begin
+  PPDataRecord(Buffer)^^.BookmarkData := Pointer(Data^);
+end;
+
+procedure TCustomSqliteDataset.SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag);
+begin
+  PPDataRecord(Buffer)^^.BookmarkFlag := Value;
+end;
+
+procedure TCustomSqliteDataset.SetExpectedAppends(AValue:Integer);
+begin
+  if Assigned(FAddedItems) then
+    FAddedItems.Capacity:=AValue;
+end;  
+
+procedure TCustomSqliteDataset.SetExpectedUpdates(AValue:Integer);
+begin
+  if Assigned(FUpdatedItems) then
+    FUpdatedItems.Capacity:=AValue;
+end;  
+
+procedure TCustomSqliteDataset.SetExpectedDeletes(AValue:Integer);
+begin
+  if Assigned(FDeletedItems) then
+    FDeletedItems.Capacity:=AValue;
+end;  
+
+procedure TCustomSqliteDataset.SetFieldData(Field: TField; Buffer: Pointer);
+var
+  TempStr:String;
+  ActiveItem:PDataRecord;
+begin
+  ActiveItem:=PPDataRecord(ActiveBuffer)^;
+  if (ActiveItem <> FCacheItem) and (FUpdatedItems.IndexOf(ActiveItem) = -1) and (FAddedItems.IndexOf(ActiveItem) = -1) then
+    FUpdatedItems.Add(ActiveItem);
+    
+  StrDispose(ActiveItem^.Row[Pred(Field.FieldNo)]);
+  if Buffer <> nil then
+  begin
+    case Field.Datatype of
+    ftString:
+      begin            
+        ActiveItem^.Row[Pred(Field.FieldNo)]:=StrNew(PChar(Buffer));
+      end;
+    ftInteger,ftBoolean,ftWord:
+      begin          
+        Str(LongInt(Buffer^),TempStr);  
+        ActiveItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr)+1);
+        StrPCopy(ActiveItem^.Row[Pred(Field.FieldNo)],TempStr);
+      end;
+    ftFloat,ftDateTime,ftDate,ftTime:
+      begin
+        Str(Double(Buffer^),TempStr);  
+        ActiveItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr)+1);
+        StrPCopy(ActiveItem^.Row[Pred(Field.FieldNo)],TempStr);
+      end;    
+    end;// case
+  end//if
+  else
+    ActiveItem^.Row[Pred(Field.FieldNo)]:=nil;        
+end;
+
+procedure TCustomSqliteDataset.SetRecNo(Value: Integer);
+var
+  Counter:Integer;
+  TempItem:PDataRecord;
+begin
+  if (Value >= FRecordCount) or (Value < 0) then
+    DatabaseError('SqliteDs - Record Number Out Of Range');
+  TempItem:=FBeginItem;
+  for Counter := 0 to Value do
+    TempItem:=TempItem^.Next;
+  PPDataRecord(ActiveBuffer)^:=TempItem;   
+end;
+
+// Specific functions 
+
+procedure TCustomSqliteDataset.MasterChanged(Sender: TObject);
+  function GetSqlStr(AField:TField):String;
+  begin
+    case AField.DataType of
+      ftString,ftMemo: Result:='"'+AField.AsString+'"';//todo: handle " caracter properly
+      ftDateTime,ftDate,ftTime:Str(AField.AsDateTime,Result);
+    else
+      Result:=AField.AsString;  
+    end;//case
+  end;//function
+
+var
+  AFilter:String;
+  i:Integer;
+begin
+  AFilter:=' where ';
+  for i:= 0 to FMasterLink.Fields.Count - 1 do
+  begin
+    AFilter:=AFilter + IndexFields[i].FieldName +' = '+ GetSqlStr(TField(FMasterLink.Fields[i]));
+    if i <> FMasterLink.Fields.Count - 1 then
+      AFilter:= AFilter + ' and ';
+  end;
+  FSql:='Select * from '+FTableName+AFilter;
+  {$ifdef DEBUG}
+  writeln('Sql used to filter detail dataset:');
+  writeln(FSql);
+  {$endif}
+  RefetchData;
+end;
+
+procedure TCustomSqliteDataset.MasterDisabled(Sender: TObject);
+begin
+  FSql:='Select * from '+FTableName+';'; 
+  RefetchData;
+end;
+
+procedure TCustomSqliteDataset.SetMasterFields(Value: String);
+begin
+  if Active then
+    DatabaseError('It''s not allowed to set MasterFields property in a open dataset');
+  FMasterLink.FieldNames:=Value;
+end;
+
+function TCustomSqliteDataset.GetMasterFields: String;
+begin
+  Result:=FMasterLink.FieldNames;
+end;
+
+
+procedure TCustomSqliteDataset.UpdateIndexFields;
+begin
+  if FIndexFieldNames <> '' then
+  begin
+    FIndexFieldList.Clear;
+    try
+      GetFieldList(FIndexFieldList, FIndexFieldNames);
+    except
+      FIndexFieldList.Clear;
+      raise;
+    end;
+  end;
+end;
+
+function TCustomSqliteDataset.GetMasterSource: TDataSource;
+begin
+  Result := FMasterLink.DataSource;
+end;
+
+procedure TCustomSqliteDataset.SetMasterSource(Value: TDataSource);
+begin
+  FMasterLink.DataSource := Value;
+end;
+
+
+function TCustomSqliteDataset.ExecSQL(const ASql:String):Integer;
+var
+  AHandle: Pointer;
+begin
+  Result:=0;
+  //Todo check if Filename exists
+  if FSqliteHandle <> nil then
+    AHandle:=FSqliteHandle
+  else 
+    if FFileName <> '' then  
+      AHandle := GetSqliteHandle
+    else
+      DatabaseError ('ExecSql - FileName not set');    
+  FSqliteReturnId:= SqliteExec(AHandle,PChar(ASql));
+  //todo: add a way to get the num of changes
+  //Result:=sqlite_changes(AHandle);
+  if AHandle <> FSqliteHandle then
+    SqliteClose(AHandle);
+end;    
+
+function TCustomSqliteDataset.ExecSQL:Integer;
+begin
+  Result:=ExecSQL(FSql);  
+end;
+
+function TCustomSqliteDataset.ApplyUpdates:Boolean;
+var
+  CounterFields,CounterItems,StatementsCounter:Integer;
+  SqlTemp,KeyName,ASqlLine,TemplateStr:String;
+begin
+  Result:=False;
+  if (FPrimaryKeyNo <> -1) and not FComplexSql then
+  begin
+    StatementsCounter:=0;
+    KeyName:=Fields[FPrimaryKeyNo].FieldName;
+    {$ifdef DEBUG}
+    WriteLn('ApplyUpdates called');
+    if FPrimaryKeyNo = FAutoIncFieldNo then
+      WriteLn('Using an AutoInc field as primary key');
+    WriteLn('PrimaryKey: ',KeyName);
+    WriteLn('PrimaryKeyNo: ',FPrimaryKeyNo);
+    {$endif}
+    SqlTemp:='BEGIN TRANSACTION;';
+    // In some situations (LCL apps) FBeginItems is inserted in FUpdatedItems
+    FUpdatedItems.Remove(FBeginItem);
+    // Update changed records
+    if FUpdatedItems.Count > 0 then
+      TemplateStr:='UPDATE '+FTableName+' SET ';
+    for CounterItems:= 0 to FUpdatedItems.Count - 1 do  
+    begin
+      ASqlLine:=TemplateStr;
+      for CounterFields:= 0 to Fields.Count - 1 do
+      begin
+        if PDataRecord(FUpdatedItems[CounterItems])^.Row[CounterFields] <> nil then
+        begin
+          ASqlLine:=ASqlLine + Fields[CounterFields].FieldName +' = ';
+          if not (Fields[CounterFields].DataType in [ftString,ftMemo]) then
+            ASqlLine:=ASqlLine+StrPas(PDataRecord(FUpdatedItems[CounterItems])^.Row[CounterFields])+ ','
+          else
+            ASqlLine:=ASqlLine+''''+
+              AnsiReplaceStr(StrPas(PDataRecord(FUpdatedItems[CounterItems])^.Row[CounterFields]),'''','''''')+''',';  
+        end
+        else
+          ASqlLine:=ASqlLine + Fields[CounterFields].FieldName +' = NULL,';  
+      end;
+      //Todo: see if system.delete trunks AnsiString
+      system.delete(ASqlLine,Length(ASqlLine),1);
+      SqlTemp:=SqlTemp + ASqlLine+' WHERE '+KeyName+' = '+StrPas(PDataRecord(FUpdatedItems[CounterItems])^.Row[FPrimaryKeyNo])+';';
+      inc(StatementsCounter);
+      //ApplyUpdates each 400 statements
+      if StatementsCounter = 400 then
+      begin
+        SqlTemp:=SqlTemp+'END TRANSACTION;';
+        FSqliteReturnId:=SqliteExec(FSqliteHandle,PChar(SqlTemp));
+        StatementsCounter:=0;
+        SqlTemp:='BEGIN TRANSACTION;';
+      end;  
+    end;
+    // Add new records
+    // Build TemplateStr
+    if FAddedItems.Count > 0 then
+    begin
+      TemplateStr:='INSERT INTO '+FTableName+ ' (';
+      for CounterFields:= 0 to Fields.Count - 1 do
+      begin
+        TemplateStr:=TemplateStr + Fields[CounterFields].FieldName; 
+        if CounterFields <> Fields.Count - 1 then
+          TemplateStr:=TemplateStr+',';
+      end; 
+      TemplateStr:=TemplateStr+') VALUES (';
+    end;  
+    for CounterItems:= 0 to FAddedItems.Count - 1 do  
+    begin
+      ASqlLine:=TemplateStr;
+      for CounterFields:= 0 to Fields.Count - 1 do
+      begin
+        if PDataRecord(FAddedItems[CounterItems])^.Row[CounterFields] <> nil then
+        begin
+          if not (Fields[CounterFields].DataType in [ftString,ftMemo]) then
+            ASqlLine:=ASqlLine+StrPas(PDataRecord(FAddedItems[CounterItems])^.Row[CounterFields])
+          else
+            ASqlLine:=ASqlLine+''''+
+              AnsiReplaceStr(StrPas(PDataRecord(FAddedItems[CounterItems])^.Row[CounterFields]),'''','''''')+'''';  
+        end
+        else
+          ASqlLine:=ASqlLine + 'NULL';
+        //Todo: see if delete ASqline is faster
+        if CounterFields <> Fields.Count - 1 then
+          ASqlLine:=ASqlLine+',';
+      end;
+      SqlTemp:=SqlTemp+ASqlLine+');';    
+      inc(StatementsCounter);
+      //ApplyUpdates each 400 statements
+      if StatementsCounter = 400 then
+      begin
+        SqlTemp:=SqlTemp+'END TRANSACTION;';
+        FSqliteReturnId:=SqliteExec(FSqliteHandle,PChar(SqlTemp));
+        StatementsCounter:=0;
+        SqlTemp:='BEGIN TRANSACTION;';
+      end;  
+    end;  
+    // Delete Items
+    if FDeletedItems.Count > 0 then
+      TemplateStr:='DELETE FROM '+FTableName+ ' WHERE '+KeyName+' = ';
+    for CounterItems:= 0 to FDeletedItems.Count - 1 do  
+    begin
+      SqlTemp:=SqlTemp+TemplateStr+
+        StrPas(PDataRecord(FDeletedItems[CounterItems])^.Row[FPrimaryKeyNo])+';';    
+      inc(StatementsCounter);
+      //ApplyUpdates each 400 statements
+      if StatementsCounter = 400 then
+      begin
+        SqlTemp:=SqlTemp+'END TRANSACTION;';
+        FSqliteReturnId:=SqliteExec(FSqliteHandle,PChar(SqlTemp));
+        StatementsCounter:=0;
+        SqlTemp:='BEGIN TRANSACTION;';
+      end;    
+    end;
+    SqlTemp:=SqlTemp+'END TRANSACTION;';
+    {$ifdef DEBUG}
+    writeln('ApplyUpdates Sql: ',SqlTemp);
+    {$endif}  
+   FAddedItems.Clear;
+   FUpdatedItems.Clear;
+   FDeletedItems.Clear;   
+   FSqliteReturnId:=SqliteExec(FSqliteHandle,PChar(SqlTemp));
+   Result:= FSqliteReturnId = SQLITE_OK;
+  end;  
+  {$ifdef DEBUG}
+    writeln('ApplyUpdates Result: ',Result);
+  {$endif}   
+end;    
+
+function TCustomSqliteDataset.CreateTable: Boolean;
+var
+  SqlTemp:String;
+  Counter:Integer;
+begin
+  {$ifdef DEBUG}
+  if FTableName = '' then
+    WriteLn('CreateTable : TableName Not Set');
+  if FieldDefs.Count = 0 then 
+    WriteLn('CreateTable : FieldDefs Not Initialized');
+  {$endif}
+  if (FTableName <> '') and (FieldDefs.Count > 0) then
+  begin
+    FSqliteHandle:= GetSqliteHandle;
+    SqlTemp:='CREATE TABLE '+FTableName+' (';
+    for Counter := 0 to FieldDefs.Count-1 do
+    begin
+      SqlTemp:=SqlTemp + FieldDefs[Counter].Name;
+      case FieldDefs[Counter].DataType of
+        ftInteger:
+          SqlTemp:=SqlTemp + ' INTEGER';
+        ftString:
+          SqlTemp:=SqlTemp + ' VARCHAR';
+        ftBoolean:
+          SqlTemp:=SqlTemp + ' BOOLEAN';
+        ftFloat:
+          SqlTemp:=SqlTemp + ' FLOAT';  
+        ftWord:
+          SqlTemp:=SqlTemp + ' WORD';
+        ftDateTime:
+          SqlTemp:=SqlTemp + ' DATETIME';
+        ftDate:
+          SqlTemp:=SqlTemp + ' DATE';
+        ftTime:
+          SqlTemp:=SqlTemp + ' TIME';                
+        ftAutoInc:
+          SqlTemp:=SqlTemp + ' AUTOINC'; 
+        ftMemo:
+          SqlTemp:=SqlTemp + ' MEMO';   
+      else
+        SqlTemp:=SqlTemp + ' VARCHAR';    
+      end;
+      if Counter <>  FieldDefs.Count - 1 then
+        SqlTemp:=SqlTemp+ ' , ';   
+    end;
+    SqlTemp:=SqlTemp+');';
+    {$ifdef DEBUG}
+    writeln('CreateTable Sql: ',SqlTemp);
+    {$endif}  
+    FSqliteReturnId:=SqliteExec(FSqliteHandle,PChar(SqlTemp));
+    Result:= FSqliteReturnId = SQLITE_OK;
+    SqliteClose(FSqliteHandle);
+    FSqliteHandle:=nil;
+  end
+  else
+    Result:=False;  
+end; 
+
+procedure TCustomSqliteDataset.RefetchData;
+var
+  i:Integer;
+begin
+  //Close
+  if FSaveOnRefetch then
+    ApplyUpdates;
+  if FDataAllocated then
+    DisposeLinkedList;  
+  FAddedItems.Clear;
+  FUpdatedItems.Clear;
+  FDeletedItems.Clear;
+  FOrphanItems.Clear;
+  //Reopen
+  BuildLinkedList;               
+  FCurrentItem:=FBeginItem;
+  for i := 0 to BufferCount - 1 do
+    PPDataRecord(Buffers[i])^:=FBeginItem;
+  Resync([]);
+end;  
+
+
+function TCustomSqliteDataset.UpdatesPending: Boolean;
+begin
+  Result:= (FDeletedItems.Count > 0) or
+    (FAddedItems.Count > 0) or (FUpdatedItems.Count > 0);
+end;
+
+{$ifdef DEBUGACTIVEBUFFER}
+procedure TCustomSqliteDataset.SetCurrentItem(Value:PDataRecord);
+var
+ ANo:Integer;
+
+  function GetItemPos:Integer;
+  var
+    TempItem:PDataRecord;
+  begin
+    Result:= -1;
+    TempItem:=FBeginItem;
+    if Value = FCacheItem then
+       Result:=-2
+    else
+    while Value <> TempItem do
+    begin
+     if TempItem^.Next <> nil then
+     begin
+       inc(Result);
+       TempItem:=TempItem^.Next;
+     end
+     else
+     begin
+      Result:=-1;
+      break;
+     end;
+    end;
+  end;
+
+begin
+  if Value = FBeginItem then
+  begin
+    writeln('FCurrentItem set to FBeginItem: ',IntToHex(Integer(Value),0));
+    FFCurrentItem:=Value;
+  end
+  else
+    if Value = FEndItem then
+    begin
+      writeln('FCurrentItem set to FEndItem: ',IntToHex(Integer(Value),0));
+      FFCurrentItem:=Value;
+    end
+    else
+      if Value = FCacheItem then
+      begin
+        writeln('FCurrentItem set to FCacheItem: ',IntToHex(Integer(Value),0));
+        FFCurrentItem:=Value;
+      end
+      else
+      begin
+        writeln('FCurrentItem set from ',IntToHex(Integer(FFCurrentItem),0),' to ',IntToHex(Integer(Value),0));
+        Ano:=GetItemPos;
+        writeln('Item position is ',ANo);
+        FFCurrentItem:=Value;
+      end;
+end;
+{$endif}
+
+end.

+ 290 - 0
fcl/db/sqlite/sqlite3ds.pas

@@ -0,0 +1,290 @@
+unit sqlite3ds;
+
+{
+    This is TSqlite3Dataset, a TDataset descendant class for use with fpc compiler
+    Copyright (C) 2004  Luiz Américo Pereira Câmara
+    Email: [email protected]
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+}
+
+{$mode objfpc}
+{$H+}
+{ $Define DEBUG}
+
+interface
+
+uses
+  Classes, SysUtils, customsqliteds;
+
+type
+  { TSqlite3Dataset }
+
+  TSqlite3Dataset = class (TCustomSqliteDataset)
+  private
+    function SqliteExec(AHandle: Pointer; ASql:PChar):Integer;override;
+    function GetSqliteHandle: Pointer; override;
+    procedure SqliteClose(AHandle: Pointer);override;
+    procedure BuildLinkedList; override;
+  protected
+    procedure InternalInitFieldDefs; override;
+  public
+    function SqliteReturnString: String; override;
+    function TableExists: Boolean;override;
+  end;
+
+implementation
+
+uses
+  sqlite3,db;
+
+function GetAutoIncValue(NextValue: Pointer; Columns: Integer; ColumnValues: PPChar; ColumnNames: PPChar): integer; cdecl;
+var
+  CodeError, TempInt: Integer;
+begin
+  TempInt:=-1;
+  if ColumnValues[0] <> nil then
+  begin
+    Val(StrPas(ColumnValues[0]),TempInt,CodeError);
+    if CodeError <> 0 then
+      DatabaseError('SqliteDs - Error trying to get last autoinc value');
+  end;
+  Integer(NextValue^):=Succ(TempInt);
+  Result:=1;
+end;
+
+{ TSqlite3Dataset }
+
+function TSqlite3Dataset.SqliteExec(AHandle: Pointer; ASql: PChar): Integer;
+begin
+  Result:=sqlite3_exec(AHandle, ASql, nil, nil, nil);
+end;
+
+procedure TSqlite3Dataset.SqliteClose(AHandle: Pointer);
+begin
+  sqlite3_close(AHandle);
+  //todo:handle return data
+end;
+
+
+function TSqlite3Dataset.GetSqliteHandle: Pointer;
+begin
+  FSqliteReturnId:=sqlite3_open(PChar(FFileName),@Result);
+end;
+
+procedure TSqlite3Dataset.InternalInitFieldDefs;
+var
+  vm:Pointer;
+  ColumnStr:String;
+  Counter,FieldSize:Integer;
+  AType:TFieldType;
+begin
+  FieldDefs.Clear;
+  sqlite3_prepare(FSqliteHandle,PChar(FSql),-1,@vm,nil);
+	sqlite3_step(vm);
+	for Counter:= 0 to sqlite3_column_count(vm) - 1 do
+	begin
+   ColumnStr:= UpperCase(StrPas(sqlite3_column_decltype(vm,Counter)));
+   if (ColumnStr = 'INTEGER') then
+   begin
+     AType:= ftInteger;
+     FieldSize:=SizeOf(Integer);
+   end else if (ColumnStr = 'BOOLEAN') then
+   begin
+     AType:= ftBoolean;
+     FieldSize:=SizeOf(Boolean);
+   end else if (ColumnStr = 'FLOAT') then
+   begin
+     AType:= ftFloat;
+     FieldSize:=SizeOf(Double);
+   end else if (ColumnStr = 'WORD') then
+   begin
+     AType:= ftWord;
+     FieldSize:=SizeOf(Word);
+   end else if (ColumnStr = 'DATETIME') then
+   begin
+     AType:= ftDateTime;
+     FieldSize:=SizeOf(TDateTime);
+   end else if (ColumnStr = 'DATE') then
+   begin
+     AType:= ftDate;
+     FieldSize:=SizeOf(TDateTime);
+   end else if (ColumnStr = 'TIME') then
+   begin
+     AType:= ftTime;
+     FieldSize:=SizeOf(TDateTime);
+   end else if (ColumnStr = 'MEMO') then
+   begin
+     AType:= ftMemo;
+     FieldSize:=10;//??
+   end else if (ColumnStr = 'AUTOINC') then
+   begin
+     AType:= ftAutoInc;
+     FieldSize:=SizeOf(Integer);
+     if FAutoIncFieldNo = -1 then
+       FAutoIncFieldNo:= Counter;
+   end else
+   begin
+     AType:= ftString;
+     FieldSize:=10; //??
+   end;
+   FieldDefs.Add(StrPas(sqlite3_column_name(vm,Counter)), AType, FieldSize, False);
+   {$ifdef DEBUG}
+   writeln('Field Name: ',sqlite3_column_name(vm,Counter));
+   writeln('Field Type: ',sqlite3_column_decltype(vm,Counter));
+   {$endif}
+  end;
+	sqlite3_finalize(vm);
+  FRowBufferSize:=(SizeOf(PPChar)*FieldDefs.Count);
+  {$ifdef DEBUG}
+  writeln('FieldDefs.Count: ',FieldDefs.Count);
+  {$endif}
+end;
+
+procedure TSqlite3Dataset.BuildLinkedList;
+var
+  TempItem:PDataRecord;
+  vm:Pointer;
+  Counter:Integer;
+begin
+  //Get AutoInc Field initial value
+  if FAutoIncFieldNo <> -1 then
+    sqlite3_exec(FSqliteHandle,PChar('Select Max('+Fields[FAutoIncFieldNo].FieldName+') from ' + FTableName),
+      @GetAutoIncValue,@FNextAutoInc,nil);
+
+  FSqliteReturnId:=sqlite3_prepare(FSqliteHandle,Pchar(FSql),-1,@vm,nil);
+  if FSqliteReturnId <> SQLITE_OK then
+  case FSqliteReturnId of
+  SQLITE_ERROR:
+    DatabaseError('Invalid SQL',Self);
+  else
+    DatabaseError('Error returned by sqlite while retrieving data: '+SqliteReturnString,Self);
+  end;
+
+  FDataAllocated:=True;
+
+  TempItem:=FBeginItem;
+  FRecordCount:=0;
+  FRowCount:=sqlite3_column_count(vm);
+  FSqliteReturnId:=sqlite3_step(vm);
+  while FSqliteReturnId = SQLITE_ROW do
+  begin
+    Inc(FRecordCount);
+    New(TempItem^.Next);
+    TempItem^.Next^.Previous:=TempItem;
+    TempItem:=TempItem^.Next;
+    GetMem(TempItem^.Row,FRowBufferSize);
+    For Counter := 0 to FRowCount - 1 do
+      TempItem^.Row[Counter]:=StrNew(sqlite3_column_text(vm,Counter));
+    FSqliteReturnId:=sqlite3_step(vm);
+  end;
+  sqlite3_finalize(vm);
+
+  // Attach EndItem
+  TempItem^.Next:=FEndItem;
+  FEndItem^.Previous:=TempItem;
+
+  // Alloc item used in append/insert
+  GetMem(FCacheItem^.Row,FRowBufferSize);
+  for Counter := 0 to FRowCount - 1 do
+    FCacheItem^.Row[Counter]:=nil;
+  // Fill FBeginItem.Row with nil -> necessary for avoid exceptions in empty datasets
+  GetMem(FBeginItem^.Row,FRowBufferSize);
+  for Counter := 0 to FRowCount - 1 do
+    FBeginItem^.Row[Counter]:=nil;
+end;
+
+function TSqlite3Dataset.TableExists: Boolean;
+var
+  AHandle,vm:Pointer;
+begin
+  Result:=False;
+  if not (FTableName = '') and FileExists(FFileName) then
+  begin
+    if FSqliteHandle = nil then
+    begin
+      {$ifdef DEBUG}
+      writeln('TableExists - FSqliteHandle=nil : Opening a file');
+      {$endif}
+      AHandle:=GetSqliteHandle;
+    end
+    else
+    begin
+      {$ifdef DEBUG}
+      writeln('TableExists - FSqliteHandle<>nil : Using FSqliteHandle');
+      {$endif}
+      AHandle:=FSqliteHandle;
+    end;
+    FSqliteReturnId:=sqlite3_prepare(AHandle,
+    Pchar('SELECT name FROM SQLITE_MASTER WHERE type = ''table'' AND name LIKE '''+ FTableName+ ''';'),
+      -1,@vm,nil);
+    {$ifdef DEBUG}
+    WriteLn('TableExists.sqlite3_prepare - SqliteReturnString:',SqliteReturnString);
+    {$endif}
+    FSqliteReturnId:=sqlite3_step(vm);
+    {$ifdef DEBUG}
+    WriteLn('TableExists.sqlite3_step - SqliteReturnString:',SqliteReturnString);
+    {$endif}
+    Result:=FSqliteReturnId = SQLITE_ROW;
+    sqlite3_finalize(vm);
+    if (FSqliteHandle = nil) then
+      sqlite3_close(AHandle);
+  end;
+  {$ifdef DEBUG}
+  WriteLn('TableExists ('+FTableName+') Result:',Result);
+  {$endif}
+end;
+
+function TSqlite3Dataset.SqliteReturnString: String;
+begin
+ case FSqliteReturnId of
+      SQLITE_OK           : Result := 'SQLITE_OK          ';
+      SQLITE_ERROR        : Result := 'SQLITE_ERROR       ';
+      SQLITE_INTERNAL     : Result := 'SQLITE_INTERNAL    ';
+      SQLITE_PERM         : Result := 'SQLITE_PERM        ';
+      SQLITE_ABORT        : Result := 'SQLITE_ABORT       ';
+      SQLITE_BUSY         : Result := 'SQLITE_BUSY        ';
+      SQLITE_LOCKED       : Result := 'SQLITE_LOCKED      ';
+      SQLITE_NOMEM        : Result := 'SQLITE_NOMEM       ';
+      SQLITE_READONLY     : Result := 'SQLITE_READONLY    ';
+      SQLITE_INTERRUPT    : Result := 'SQLITE_INTERRUPT   ';
+      SQLITE_IOERR        : Result := 'SQLITE_IOERR       ';
+      SQLITE_CORRUPT      : Result := 'SQLITE_CORRUPT     ';
+      SQLITE_NOTFOUND     : Result := 'SQLITE_NOTFOUND    ';
+      SQLITE_FULL         : Result := 'SQLITE_FULL        ';
+      SQLITE_CANTOPEN     : Result := 'SQLITE_CANTOPEN    ';
+      SQLITE_PROTOCOL     : Result := 'SQLITE_PROTOCOL    ';
+      SQLITE_EMPTY        : Result := 'SQLITE_EMPTY       ';
+      SQLITE_SCHEMA       : Result := 'SQLITE_SCHEMA      ';
+      SQLITE_TOOBIG       : Result := 'SQLITE_TOOBIG      ';
+      SQLITE_CONSTRAINT   : Result := 'SQLITE_CONSTRAINT  ';
+      SQLITE_MISMATCH     : Result := 'SQLITE_MISMATCH    ';
+      SQLITE_MISUSE       : Result := 'SQLITE_MISUSE      ';
+      SQLITE_NOLFS        : Result := 'SQLITE_NOLFS       ';
+      SQLITE_AUTH         : Result := 'SQLITE_AUTH        ';
+      SQLITE_FORMAT       : Result := 'SQLITE_FORMAT      ';
+      SQLITE_RANGE        : Result := 'SQLITE_RANGE       ';
+      SQLITE_ROW          : Result := 'SQLITE_ROW         ';
+      SQLITE_NOTADB       : Result := 'SQLITE_NOTADB      ';
+      SQLITE_DONE         : Result := 'SQLITE_DONE        ';
+  else
+    Result:='Unknow Return Value';
+ end;
+end;
+
+
+end.
+

文件差異過大導致無法顯示
+ 71 - 1034
fcl/db/sqlite/sqliteds.pas


+ 34 - 34
packages/base/sqlite/Makefile

@@ -1,5 +1,5 @@
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2005/05/05]
+# Don't edit, this file is generated by FPCMake Version 1.9.8 [2005/04/10]
 #
 default: all
 MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-emx i386-watcom i386-netwlibc m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos powerpc-linux powerpc-netbsd powerpc-macos powerpc-darwin powerpc-morphos sparc-linux sparc-netbsd sparc-solaris x86_64-linux x86_64-freebsd arm-linux
@@ -233,103 +233,103 @@ PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages/base $(FPCDIR)/packages/ext
 override PACKAGE_NAME=sqlite
 override PACKAGE_VERSION=2.0.0
 ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_UNITS+=sqlite
+override TARGET_UNITS+=sqlite sqlite3
 endif
 override INSTALL_FPCPACKAGE=y
 ifdef REQUIRE_UNITSDIR

+ 1 - 1
packages/base/sqlite/Makefile.fpc

@@ -7,7 +7,7 @@ name=sqlite
 version=2.0.0
 
 [target]
-units=sqlite
+units=sqlite sqlite3
 
 [require]
 

+ 336 - 0
packages/base/sqlite/sqlite3.pp

@@ -0,0 +1,336 @@
+{$mode objfpc}
+unit sqlite3;
+
+interface
+
+{
+  Automatically converted by H2Pas 0.99.16 from sqlite3.h
+  The following command line parameters were used:
+    -D
+    -c
+    sqlite3.h
+
+  Manual corrections made by Luiz Américo - 2005
+}
+
+    const
+      External_library='sqlite3'; {Setup as you need}
+
+    Type
+    PPPChar = ^PPChar;
+    Plongint  = ^longint;
+    Psqlite3  = Pointer;
+    PPSqlite3 = ^PSqlite3;
+    Psqlite3_context  = Pointer;
+    Psqlite3_stmt  = Pointer;
+    PPsqlite3_stmt = ^Psqlite3_stmt;
+    Psqlite3_value  = Pointer;
+    PPsqlite3_value  = ^Psqlite3_value;
+    
+{$IFDEF FPC}
+{$PACKRECORDS C}
+{$ENDIF}
+
+//Callback function types
+//Notice that most functions were named using as prefix the function name that uses them,
+//rather than describing their functions  
+
+type
+  sqlite3_callback = function (_para1:pointer; _para2:longint; _para3:PPchar; _para4:PPchar):longint;cdecl;
+  busy_handler_func = function (_para1:pointer; _para2:longint):longint;cdecl;
+  sqlite3_set_authorizer_func = function (_para1:pointer; _para2:longint; _para3:Pchar; _para4:Pchar; _para5:Pchar; _para6:Pchar):longint;cdecl;
+  sqlite3_trace_func = procedure (_para1:pointer; _para2:Pchar);cdecl;
+  sqlite3_progress_handler_func = function (_para1:pointer):longint;cdecl;
+  sqlite3_commit_hook_func = function (_para1:pointer):longint;cdecl;
+  bind_destructor_func = procedure (_para1:pointer);cdecl;
+  create_function_step_func = procedure (_para1:Psqlite3_context; _para2:longint; _para3:PPsqlite3_value);cdecl;
+  create_function_func_func = procedure (_para1:Psqlite3_context; _para2:longint; _para3:PPsqlite3_value);cdecl;
+  create_function_final_func = procedure (_para1:Psqlite3_context);cdecl;
+  sqlite3_set_auxdata_func = procedure (_para1:pointer);cdecl;
+  sqlite3_result_func = procedure (_para1:pointer);cdecl;
+  sqlite3_create_collation_func = function (_para1:pointer; _para2:longint; _para3:pointer; _para4:longint; _para5:pointer):longint;cdecl;
+  sqlite3_collation_needed_func = procedure (_para1:pointer; _para2:Psqlite3; eTextRep:longint; _para4:Pchar);cdecl;
+  
+
+const
+   SQLITE_VERSION = '3.2.1';   
+   SQLITE_VERSION_NUMBER = 3002001;   
+
+
+   SQLITE_INTEGER = 1;   
+   SQLITE_FLOAT = 2;   
+{ #define SQLITE_TEXT  3  // See below  }
+   SQLITE_BLOB = 4;   
+   SQLITE_NULL = 5;   
+  
+   SQLITE_TEXT = 3;   
+
+   SQLITE3_TEXT = 3;   
+
+   SQLITE_UTF8 = 1;       
+   SQLITE_UTF16LE = 2;       
+   SQLITE_UTF16BE = 3;       
+{ Use native byte order  }
+   SQLITE_UTF16 = 4;       
+{ sqlite3_create_function only  }
+   SQLITE_ANY = 5;  
+
+
+var
+  sqlite3_version : Pchar;cvar;external;
+  sqlite3_temp_directory : Pchar;cvar;external;
+ 
+
+function sqlite3_libversion:PChar;cdecl;external External_library name 'sqlite3_libversion';
+//function sqlite3_libversion_number:longint;cdecl;external External_library name 'sqlite3_libversion_number';
+
+type
+   sqlite_int64 = int64;
+   sqlite_uint64 = qword;
+
+function sqlite3_close(_para1:Psqlite3):longint;cdecl;external External_library name 'sqlite3_close';
+
+function sqlite3_exec(_para1:Psqlite3; sql:Pchar; _para3:sqlite3_callback; _para4:pointer; errmsg:PPchar):longint;cdecl;external External_library name 'sqlite3_exec';
+
+const
+   SQLITE_OK = 0;   { SQL error or missing database  }
+   SQLITE_ERROR = 1;{ An internal logic error in SQLite  }
+   SQLITE_INTERNAL = 2;{ Access permission denied  }
+   SQLITE_PERM = 3;   { Callback routine requested an abort  }
+   SQLITE_ABORT = 4; { The database file is locked  }
+   SQLITE_BUSY = 5;  { A table in the database is locked  }
+   SQLITE_LOCKED = 6;{ A malloc() failed  }
+   SQLITE_NOMEM = 7; { Attempt to write a readonly database  }
+   SQLITE_READONLY = 8;{ Operation terminated by sqlite3_interrupt() }
+   SQLITE_INTERRUPT = 9;{ Some kind of disk I/O error occurred  }
+   SQLITE_IOERR = 10;   { The database disk image is malformed  }
+   SQLITE_CORRUPT = 11;   
+{ (Internal Only) Table or record not found  }
+   SQLITE_NOTFOUND = 12;   
+{ Insertion failed because database is full  }
+   SQLITE_FULL = 13;   
+{ Unable to open the database file  }
+   SQLITE_CANTOPEN = 14;   
+{ Database lock protocol error  }
+   SQLITE_PROTOCOL = 15;   
+{ Database is empty  }
+   SQLITE_EMPTY = 16;   
+{ The database schema changed  }
+   SQLITE_SCHEMA = 17;   
+{ Too much data for one row of a table  }
+   SQLITE_TOOBIG = 18;   
+{ Abort due to contraint violation  }
+   SQLITE_CONSTRAINT = 19;   
+{ Data type mismatch  }
+   SQLITE_MISMATCH = 20;   
+{ Library used incorrectly  }
+   SQLITE_MISUSE = 21;   
+{ Uses OS features not supported on host  }
+   SQLITE_NOLFS = 22;   
+{ Authorization denied  }
+   SQLITE_AUTH = 23;   
+{ Auxiliary database format error  }
+   SQLITE_FORMAT = 24;   
+{ 2nd parameter to sqlite3_bind out of range  }
+   SQLITE_RANGE = 25;   
+{ File opened that is not a database file  }
+   SQLITE_NOTADB = 26;   
+{ sqlite3_step() has another row ready  }
+   SQLITE_ROW = 100;   
+{ sqlite3_step() has finished executing  }
+   SQLITE_DONE = 101;   
+
+function sqlite3_last_insert_rowid(_para1:Psqlite3):sqlite_int64;cdecl;external External_library name 'sqlite3_last_insert_rowid';
+function sqlite3_changes(_para1:Psqlite3):longint;cdecl;external External_library name 'sqlite3_changes';
+function sqlite3_total_changes(_para1:Psqlite3):longint;cdecl;external External_library name 'sqlite3_total_changes';
+procedure sqlite3_interrupt(_para1:Psqlite3);cdecl;external External_library name 'sqlite3_interrupt';
+function sqlite3_complete(sql:Pchar):longint;cdecl;external External_library name 'sqlite3_complete';
+function sqlite3_complete16(sql:pointer):longint;cdecl;external External_library name 'sqlite3_complete16';
+function sqlite3_busy_handler(_para1:Psqlite3; _para2:busy_handler_func; _para3:pointer):longint;cdecl;external External_library name 'sqlite3_busy_handler';
+function sqlite3_busy_timeout(_para1:Psqlite3; ms:longint):longint;cdecl;external External_library name 'sqlite3_busy_timeout';
+function sqlite3_get_table(_para1:Psqlite3; sql:Pchar; resultp:PPPchar; nrow:Plongint; ncolumn:Plongint; 
+           errmsg:PPchar):longint;cdecl;external External_library name 'sqlite3_get_table';
+procedure sqlite3_free_table(result:PPchar);cdecl;external External_library name 'sqlite3_free_table';
+
+// Todo: see how translate sqlite3_mprintf, sqlite3_vmprintf, sqlite3_snprintf
+// function sqlite3_mprintf(_para1:Pchar; args:array of const):Pchar;cdecl;external External_library name 'sqlite3_mprintf';
+function sqlite3_mprintf(_para1:Pchar):Pchar;cdecl;external External_library name 'sqlite3_mprintf';
+//function sqlite3_vmprintf(_para1:Pchar; _para2:va_list):Pchar;cdecl;external External_library name 'sqlite3_vmprintf';
+procedure sqlite3_free(z:Pchar);cdecl;external External_library name 'sqlite3_free';
+//function sqlite3_snprintf(_para1:longint; _para2:Pchar; _para3:Pchar; args:array of const):Pchar;cdecl;external External_library name 'sqlite3_snprintf';
+function sqlite3_snprintf(_para1:longint; _para2:Pchar; _para3:Pchar):Pchar;cdecl;external External_library name 'sqlite3_snprintf';
+
+function sqlite3_set_authorizer(_para1:Psqlite3; xAuth:sqlite3_set_authorizer_func; pUserData:pointer):longint;cdecl;external External_library name 'sqlite3_set_authorizer';
+
+
+const
+   SQLITE_COPY = 0;   
+{ Index Name      Table Name       }
+   SQLITE_CREATE_INDEX = 1;   
+{ Table Name      NULL             }
+   SQLITE_CREATE_TABLE = 2;   
+{ Index Name      Table Name       }
+   SQLITE_CREATE_TEMP_INDEX = 3;   
+{ Table Name      NULL             }
+   SQLITE_CREATE_TEMP_TABLE = 4;   
+{ Trigger Name    Table Name       }
+   SQLITE_CREATE_TEMP_TRIGGER = 5;   
+{ View Name       NULL             }
+   SQLITE_CREATE_TEMP_VIEW = 6;   
+{ Trigger Name    Table Name       }
+   SQLITE_CREATE_TRIGGER = 7;   
+{ View Name       NULL             }
+   SQLITE_CREATE_VIEW = 8;   
+{ Table Name      NULL             }
+   SQLITE_DELETE = 9;   
+{ Index Name      Table Name       }
+   SQLITE_DROP_INDEX = 10;   
+{ Table Name      NULL             }
+   SQLITE_DROP_TABLE = 11;   
+{ Index Name      Table Name       }
+   SQLITE_DROP_TEMP_INDEX = 12;   
+{ Table Name      NULL             }
+   SQLITE_DROP_TEMP_TABLE = 13;   
+{ Trigger Name    Table Name       }
+   SQLITE_DROP_TEMP_TRIGGER = 14;   
+{ View Name       NULL             }
+   SQLITE_DROP_TEMP_VIEW = 15;   
+{ Trigger Name    Table Name       }
+   SQLITE_DROP_TRIGGER = 16;   
+{ View Name       NULL             }
+   SQLITE_DROP_VIEW = 17;   
+{ Table Name      NULL             }
+   SQLITE_INSERT = 18;   
+{ Pragma Name     1st arg or NULL  }
+   SQLITE_PRAGMA = 19;   
+{ Table Name      Column Name      }
+   SQLITE_READ = 20;   
+{ NULL            NULL             }
+   SQLITE_SELECT = 21;   
+{ NULL            NULL             }
+   SQLITE_TRANSACTION = 22;   
+{ Table Name      Column Name      }
+   SQLITE_UPDATE = 23;   
+{ Filename        NULL             }
+   SQLITE_ATTACH = 24;   
+{ Database Name   NULL             }
+   SQLITE_DETACH = 25;   
+{ Database Name   Table Name       }
+   SQLITE_ALTER_TABLE = 26;   
+{ Index Name      NULL             }
+   SQLITE_REINDEX = 27;   
+
+{ #define SQLITE_OK  0   // Allow access (This is actually defined above)  }
+{ Abort the SQL statement with an error  }
+   SQLITE_DENY = 1;   
+{ Don't allow access, but don't generate an error  }
+   SQLITE_IGNORE = 2;   
+
+function sqlite3_trace(_para1:Psqlite3; xTrace:sqlite3_trace_func; _para3:pointer):pointer;cdecl;external External_library name 'sqlite3_trace';
+procedure sqlite3_progress_handler(_para1:Psqlite3; _para2:longint; _para3:sqlite3_progress_handler_func; _para4:pointer);cdecl;external External_library name 'sqlite3_progress_handler';
+function sqlite3_commit_hook(_para1:Psqlite3; _para2:sqlite3_commit_hook_func; _para3:pointer):pointer;cdecl;external External_library name 'sqlite3_commit_hook';
+function sqlite3_open(filename:Pchar; ppDb:PPsqlite3):longint;cdecl;external External_library name 'sqlite3_open';
+function sqlite3_open16(filename:pointer; ppDb:PPsqlite3):longint;cdecl;external External_library name 'sqlite3_open16';
+function sqlite3_errcode(db:Psqlite3):longint;cdecl;external External_library name 'sqlite3_errcode';
+function sqlite3_errmsg(_para1:Psqlite3):Pchar;cdecl;external External_library name 'sqlite3_errmsg';
+function sqlite3_errmsg16(_para1:Psqlite3):pointer;cdecl;external External_library name 'sqlite3_errmsg16';
+function sqlite3_prepare(db:Psqlite3; zSql:Pchar; nBytes:longint; ppStmt:PPsqlite3_stmt; pzTail:PPchar):longint;cdecl;external External_library name 'sqlite3_prepare';
+function sqlite3_prepare16(db:Psqlite3; zSql:pointer; nBytes:longint; ppStmt:PPsqlite3_stmt; pzTail:Ppointer):longint;cdecl;external External_library name 'sqlite3_prepare16';
+function sqlite3_bind_blob(_para1:Psqlite3_stmt; _para2:longint; _para3:pointer; n:longint; _para5:bind_destructor_func):longint;cdecl;external External_library name 'sqlite3_bind_blob';
+function sqlite3_bind_double(_para1:Psqlite3_stmt; _para2:longint; _para3:double):longint;cdecl;external External_library name 'sqlite3_bind_double';
+function sqlite3_bind_int(_para1:Psqlite3_stmt; _para2:longint; _para3:longint):longint;cdecl;external External_library name 'sqlite3_bind_int';
+function sqlite3_bind_int64(_para1:Psqlite3_stmt; _para2:longint; _para3:sqlite_int64):longint;cdecl;external External_library name 'sqlite3_bind_int64';
+function sqlite3_bind_null(_para1:Psqlite3_stmt; _para2:longint):longint;cdecl;external External_library name 'sqlite3_bind_null';
+function sqlite3_bind_text(_para1:Psqlite3_stmt; _para2:longint; _para3:Pchar; n:longint; _para5:bind_destructor_func):longint;cdecl;external External_library name 'sqlite3_bind_text';
+function sqlite3_bind_text16(_para1:Psqlite3_stmt; _para2:longint; _para3:pointer; _para4:longint; _para5:bind_destructor_func):longint;cdecl;external External_library name 'sqlite3_bind_text16';
+//function sqlite3_bind_value(_para1:Psqlite3_stmt; _para2:longint; _para3:Psqlite3_value):longint;cdecl;external External_library name 'sqlite3_bind_value';
+
+// Original from sqlite3.h: 
+//#define SQLITE_STATIC      ((void(*)(void *))0)
+//#define SQLITE_TRANSIENT   ((void(*)(void *))-1)
+Const
+  SQLITE_STATIC    =  0;
+  SQLITE_TRANSIENT =  -1;
+  
+//These overloaded functions were introduced to allow the use of SQLITE_STATIC and SQLITE_TRANSIENT
+//It's the c world man ;-)
+function sqlite3_bind_blob(_para1:Psqlite3_stmt; _para2:longint; _para3:pointer; n:longint; _para5:longint):longint;cdecl;external External_library name 'sqlite3_bind_blob';
+function sqlite3_bind_text(_para1:Psqlite3_stmt; _para2:longint; _para3:Pchar; n:longint; _para5:longint):longint;cdecl;external External_library name 'sqlite3_bind_text';
+function sqlite3_bind_text16(_para1:Psqlite3_stmt; _para2:longint; _para3:pointer; _para4:longint; _para5:longint):longint;cdecl;external External_library name 'sqlite3_bind_text16';
+
+function sqlite3_bind_parameter_count(_para1:Psqlite3_stmt):longint;cdecl;external External_library name 'sqlite3_bind_parameter_count';
+function sqlite3_bind_parameter_name(_para1:Psqlite3_stmt; _para2:longint):Pchar;cdecl;external External_library name 'sqlite3_bind_parameter_name';
+function sqlite3_bind_parameter_index(_para1:Psqlite3_stmt; zName:Pchar):longint;cdecl;external External_library name 'sqlite3_bind_parameter_index';
+//function sqlite3_clear_bindings(_para1:Psqlite3_stmt):longint;cdecl;external External_library name 'sqlite3_clear_bindings';
+function sqlite3_column_count(pStmt:Psqlite3_stmt):longint;cdecl;external External_library name 'sqlite3_column_count';
+function sqlite3_column_name(_para1:Psqlite3_stmt; _para2:longint):Pchar;cdecl;external External_library name 'sqlite3_column_name';
+function sqlite3_column_name16(_para1:Psqlite3_stmt; _para2:longint):pointer;cdecl;external External_library name 'sqlite3_column_name16';
+function sqlite3_column_decltype(_para1:Psqlite3_stmt; i:longint):Pchar;cdecl;external External_library name 'sqlite3_column_decltype';
+function sqlite3_column_decltype16(_para1:Psqlite3_stmt; _para2:longint):pointer;cdecl;external External_library name 'sqlite3_column_decltype16';
+function sqlite3_step(_para1:Psqlite3_stmt):longint;cdecl;external External_library name 'sqlite3_step';
+function sqlite3_data_count(pStmt:Psqlite3_stmt):longint;cdecl;external External_library name 'sqlite3_data_count';
+function sqlite3_column_blob(_para1:Psqlite3_stmt; iCol:longint):pointer;cdecl;external External_library name 'sqlite3_column_blob';
+function sqlite3_column_bytes(_para1:Psqlite3_stmt; iCol:longint):longint;cdecl;external External_library name 'sqlite3_column_bytes';
+function sqlite3_column_bytes16(_para1:Psqlite3_stmt; iCol:longint):longint;cdecl;external External_library name 'sqlite3_column_bytes16';
+function sqlite3_column_double(_para1:Psqlite3_stmt; iCol:longint):double;cdecl;external External_library name 'sqlite3_column_double';
+function sqlite3_column_int(_para1:Psqlite3_stmt; iCol:longint):longint;cdecl;external External_library name 'sqlite3_column_int';
+function sqlite3_column_int64(_para1:Psqlite3_stmt; iCol:longint):sqlite_int64;cdecl;external External_library name 'sqlite3_column_int64';
+function sqlite3_column_text(_para1:Psqlite3_stmt; iCol:longint):PChar;cdecl;external External_library name 'sqlite3_column_text';
+function sqlite3_column_text16(_para1:Psqlite3_stmt; iCol:longint):pointer;cdecl;external External_library name 'sqlite3_column_text16';
+function sqlite3_column_type(_para1:Psqlite3_stmt; iCol:longint):longint;cdecl;external External_library name 'sqlite3_column_type';
+function sqlite3_finalize(pStmt:Psqlite3_stmt):longint;cdecl;external External_library name 'sqlite3_finalize';
+function sqlite3_reset(pStmt:Psqlite3_stmt):longint;cdecl;external External_library name 'sqlite3_reset';
+function sqlite3_create_function(_para1:Psqlite3; zFunctionName:Pchar; nArg:longint; eTextRep:longint; _para5:pointer; 
+           xFunc:create_function_func_func; xStep:create_function_step_func; xFinal:create_function_final_func):longint;cdecl;external External_library name 'sqlite3_create_function';
+function sqlite3_create_function16(_para1:Psqlite3; zFunctionName:pointer; nArg:longint; eTextRep:longint; _para5:pointer; 
+           xFunc:create_function_func_func; xStep:create_function_step_func; xFinal:create_function_final_func):longint;cdecl;external External_library name 'sqlite3_create_function16';
+function sqlite3_aggregate_count(_para1:Psqlite3_context):longint;cdecl;external External_library name 'sqlite3_aggregate_count';
+function sqlite3_value_blob(_para1:Psqlite3_value):pointer;cdecl;external External_library name 'sqlite3_value_blob';
+function sqlite3_value_bytes(_para1:Psqlite3_value):longint;cdecl;external External_library name 'sqlite3_value_bytes';
+function sqlite3_value_bytes16(_para1:Psqlite3_value):longint;cdecl;external External_library name 'sqlite3_value_bytes16';
+function sqlite3_value_double(_para1:Psqlite3_value):double;cdecl;external External_library name 'sqlite3_value_double';
+function sqlite3_value_int(_para1:Psqlite3_value):longint;cdecl;external External_library name 'sqlite3_value_int';
+function sqlite3_value_int64(_para1:Psqlite3_value):sqlite_int64;cdecl;external External_library name 'sqlite3_value_int64';
+function sqlite3_value_text(_para1:Psqlite3_value):PChar;cdecl;external External_library name 'sqlite3_value_text';
+function sqlite3_value_text16(_para1:Psqlite3_value):pointer;cdecl;external External_library name 'sqlite3_value_text16';
+function sqlite3_value_text16le(_para1:Psqlite3_value):pointer;cdecl;external External_library name 'sqlite3_value_text16le';
+function sqlite3_value_text16be(_para1:Psqlite3_value):pointer;cdecl;external External_library name 'sqlite3_value_text16be';
+function sqlite3_value_type(_para1:Psqlite3_value):longint;cdecl;external External_library name 'sqlite3_value_type';
+function sqlite3_aggregate_context(_para1:Psqlite3_context; nBytes:longint):pointer;cdecl;external External_library name 'sqlite3_aggregate_context';
+function sqlite3_user_data(_para1:Psqlite3_context):pointer;cdecl;external External_library name 'sqlite3_user_data';
+function sqlite3_get_auxdata(_para1:Psqlite3_context; _para2:longint):pointer;cdecl;external External_library name 'sqlite3_get_auxdata';
+procedure sqlite3_set_auxdata(_para1:Psqlite3_context; _para2:longint; _para3:pointer; _para4:sqlite3_set_auxdata_func);cdecl;external External_library name 'sqlite3_set_auxdata';
+procedure sqlite3_result_blob(_para1:Psqlite3_context; _para2:pointer; _para3:longint; _para4:sqlite3_result_func);cdecl;external External_library name 'sqlite3_result_blob';
+procedure sqlite3_result_double(_para1:Psqlite3_context; _para2:double);cdecl;external External_library name 'sqlite3_result_double';
+procedure sqlite3_result_error(_para1:Psqlite3_context; _para2:Pchar; _para3:longint);cdecl;external External_library name 'sqlite3_result_error';
+procedure sqlite3_result_error16(_para1:Psqlite3_context; _para2:pointer; _para3:longint);cdecl;external External_library name 'sqlite3_result_error16';
+procedure sqlite3_result_int(_para1:Psqlite3_context; _para2:longint);cdecl;external External_library name 'sqlite3_result_int';
+procedure sqlite3_result_int64(_para1:Psqlite3_context; _para2:sqlite_int64);cdecl;external External_library name 'sqlite3_result_int64';
+procedure sqlite3_result_null(_para1:Psqlite3_context);cdecl;external External_library name 'sqlite3_result_null';
+procedure sqlite3_result_text(_para1:Psqlite3_context; _para2:Pchar; _para3:longint; _para4:sqlite3_result_func);cdecl;external External_library name 'sqlite3_result_text';
+procedure sqlite3_result_text16(_para1:Psqlite3_context; _para2:pointer; _para3:longint; _para4:sqlite3_result_func);cdecl;external External_library name 'sqlite3_result_text16';
+procedure sqlite3_result_text16le(_para1:Psqlite3_context; _para2:pointer; _para3:longint; _para4:sqlite3_result_func);cdecl;external External_library name 'sqlite3_result_text16le';
+procedure sqlite3_result_text16be(_para1:Psqlite3_context; _para2:pointer; _para3:longint; _para4:sqlite3_result_func);cdecl;external External_library name 'sqlite3_result_text16be';
+procedure sqlite3_result_value(_para1:Psqlite3_context; _para2:Psqlite3_value);cdecl;external External_library name 'sqlite3_result_value';     
+    
+function sqlite3_create_collation(_para1:Psqlite3; zName:Pchar; eTextRep:longint; _para4:pointer; xCompare:sqlite3_create_collation_func):longint;cdecl;external External_library name 'sqlite3_create_collation';
+function sqlite3_create_collation16(_para1:Psqlite3; zName:Pchar; eTextRep:longint; _para4:pointer; xCompare:sqlite3_create_collation_func):longint;cdecl;external External_library name 'sqlite3_create_collation16';
+ 
+function sqlite3_collation_needed(_para1:Psqlite3; _para2:pointer; _para3:sqlite3_collation_needed_func):longint;cdecl;external External_library name 'sqlite3_collation_needed';
+function sqlite3_collation_needed16(_para1:Psqlite3; _para2:pointer; _para3:sqlite3_collation_needed_func):longint;cdecl;external External_library name 'sqlite3_collation_needed16';
+ 
+//function sqlite3_key(db:Psqlite3; pKey:pointer; nKey:longint):longint;cdecl;external External_library name 'sqlite3_key';
+ 
+//function sqlite3_rekey(db:Psqlite3; pKey:pointer; nKey:longint):longint;cdecl;external External_library name 'sqlite3_rekey';
+ 
+//function sqlite3_sleep(_para1:longint):longint;cdecl;external External_library name 'sqlite3_sleep';
+ 
+//function sqlite3_expired(_para1:Psqlite3_stmt):longint;cdecl;external External_library name 'sqlite3_expired';
+   
+//function sqlite3_global_recover:longint;cdecl;external External_library name 'sqlite3_global_recover';
+
+
+implementation
+
+
+end.

部分文件因文件數量過多而無法顯示