From dc2616a471905229cebc6225c98264c737161825 Mon Sep 17 00:00:00 2001
From: tobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c>
Date: Mon, 13 Oct 2008 12:04:24 +0000
Subject: SQLiteTable3 update to current trunk
 (http://www.itwriting.com/repos/sqlitewrapper/trunk)

git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@1445 b956fd51-792f-4845-bead-9b4dfca2ff2c
---
 src/lib/SQLite/SQLite3.patch      | 252 ++++++++++++++++++++
 src/lib/SQLite/SQLiteTable3.pas   |  86 +++++--
 src/lib/SQLite/SQLiteTable3.patch | 472 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 786 insertions(+), 24 deletions(-)
 create mode 100644 src/lib/SQLite/SQLite3.patch
 create mode 100644 src/lib/SQLite/SQLiteTable3.patch

diff --git a/src/lib/SQLite/SQLite3.patch b/src/lib/SQLite/SQLite3.patch
new file mode 100644
index 00000000..6fb38db2
--- /dev/null
+++ b/src/lib/SQLite/SQLite3.patch
@@ -0,0 +1,252 @@
+--- D:/daten/SQLite3.pas	Mon Oct 13 12:38:56 2008
++++ D:/daten/Projekte/ultrastardx/linuxtrunk/src/lib/SQLite/SQLite3.pas	Mon Oct 13 13:31:18 2008
+@@ -8,49 +8,66 @@
+   which was based on SQLite.pas by Ben Hochstrasser (bhoc@surfeu.ch)
+ }
+ 
++{$IFDEF FPC}
++  {$MODE DELPHI}
++  {$H+}            (* use AnsiString *)
++  {$PACKENUM 4}    (* use 4-byte enums *)
++  {$PACKRECORDS C} (* C/C++-compatible record packing *)
++{$ELSE}
++  {$MINENUMSIZE 4} (* use 4-byte enums *)
++{$ENDIF}
++
+ interface
+ 
+ const
+-
++{$IF Defined(MSWINDOWS)}
+   SQLiteDLL = 'sqlite3.dll';
++{$ELSEIF Defined(DARWIN)}
++  SQLiteDLL = 'libsqlite3.dylib';
++  {$linklib libsqlite3}
++{$ELSEIF Defined(UNIX)}
++  SQLiteDLL = 'sqlite3.so';
++{$IFEND}
+ 
+ // Return values for sqlite3_exec() and sqlite3_step()
+ 
+-  SQLITE_OK = 0; // Successful result
+-  SQLITE_ERROR = 1; // SQL error or missing database
+-  SQLITE_INTERNAL = 2; // An internal logic error in SQLite
+-  SQLITE_PERM = 3; // Access permission denied
+-  SQLITE_ABORT = 4; // Callback routine requested an abort
+-  SQLITE_BUSY = 5; // The database file is locked
+-  SQLITE_LOCKED = 6; // A table in the database is locked
+-  SQLITE_NOMEM = 7; // A malloc() failed
+-  SQLITE_READONLY = 8; // Attempt to write a readonly database
+-  SQLITE_INTERRUPT = 9; // Operation terminated by sqlite3_interrupt()
+-  SQLITE_IOERR = 10; // Some kind of disk I/O error occurred
+-  SQLITE_CORRUPT = 11; // The database disk image is malformed
+-  SQLITE_NOTFOUND = 12; // (Internal Only) Table or record not found
+-  SQLITE_FULL = 13; // Insertion failed because database is full
+-  SQLITE_CANTOPEN = 14; // Unable to open the database file
+-  SQLITE_PROTOCOL = 15; // Database lock protocol error
+-  SQLITE_EMPTY = 16; // Database is empty
+-  SQLITE_SCHEMA = 17; // The database schema changed
+-  SQLITE_TOOBIG = 18; // Too much data for one row of a table
+-  SQLITE_CONSTRAINT = 19; // Abort due to contraint violation
+-  SQLITE_MISMATCH = 20; // Data type mismatch
+-  SQLITE_MISUSE = 21; // Library used incorrectly
+-  SQLITE_NOLFS = 22; // Uses OS features not supported on host
+-  SQLITE_AUTH = 23; // Authorization denied
+-  SQLITE_FORMAT = 24; // Auxiliary database format error
+-  SQLITE_RANGE = 25; // 2nd parameter to sqlite3_bind out of range
+-  SQLITE_NOTADB = 26; // File opened that is not a database file
+-  SQLITE_ROW = 100; // sqlite3_step() has another row ready
+-  SQLITE_DONE = 101; // sqlite3_step() has finished executing
++const
++  SQLITE_OK          =  0; // Successful result
++  (* beginning-of-error-codes *)
++  SQLITE_ERROR       =  1; // SQL error or missing database
++  SQLITE_INTERNAL    =  2; // An internal logic error in SQLite
++  SQLITE_PERM        =  3; // Access permission denied
++  SQLITE_ABORT       =  4; // Callback routine requested an abort
++  SQLITE_BUSY        =  5; // The database file is locked
++  SQLITE_LOCKED      =  6; // A table in the database is locked
++  SQLITE_NOMEM       =  7; // A malloc() failed
++  SQLITE_READONLY    =  8; // Attempt to write a readonly database
++  SQLITE_INTERRUPT   =  9; // Operation terminated by sqlite3_interrupt()
++  SQLITE_IOERR       = 10; // Some kind of disk I/O error occurred
++  SQLITE_CORRUPT     = 11; // The database disk image is malformed
++  SQLITE_NOTFOUND    = 12; // (Internal Only) Table or record not found
++  SQLITE_FULL        = 13; // Insertion failed because database is full
++  SQLITE_CANTOPEN    = 14; // Unable to open the database file
++  SQLITE_PROTOCOL    = 15; // Database lock protocol error
++  SQLITE_EMPTY       = 16; // Database is empty
++  SQLITE_SCHEMA      = 17; // The database schema changed
++  SQLITE_TOOBIG      = 18; // Too much data for one row of a table
++  SQLITE_CONSTRAINT  = 19; // Abort due to contraint violation
++  SQLITE_MISMATCH    = 20; // Data type mismatch
++  SQLITE_MISUSE      = 21; // Library used incorrectly
++  SQLITE_NOLFS       = 22; // Uses OS features not supported on host
++  SQLITE_AUTH        = 23; // Authorization denied
++  SQLITE_FORMAT      = 24; // Auxiliary database format error
++  SQLITE_RANGE       = 25; // 2nd parameter to sqlite3_bind out of range
++  SQLITE_NOTADB      = 26; // File opened that is not a database file
++  SQLITE_ROW         = 100; // sqlite3_step() has another row ready
++  SQLITE_DONE        = 101; // sqlite3_step() has finished executing
+ 
+   SQLITE_INTEGER = 1;
+-  SQLITE_FLOAT = 2;
+-  SQLITE_TEXT = 3;
+-  SQLITE_BLOB = 4;
+-  SQLITE_NULL = 5;
++  SQLITE_FLOAT   = 2;
++  SQLITE_TEXT    = 3;
++  SQLITE_BLOB    = 4;
++  SQLITE_NULL    = 5;
+ 
+   SQLITE_UTF8     = 1;
+   SQLITE_UTF16    = 2;
+@@ -58,21 +75,31 @@
+   SQLITE_UTF16LE  = 4;
+   SQLITE_ANY      = 5;
+ 
+-  SQLITE_TRANSIENT = pointer(-1);
+-  SQLITE_STATIC = pointer(0);
++  SQLITE_STATIC    {: TSQLite3Destructor} = Pointer(0);
++  SQLITE_TRANSIENT {: TSQLite3Destructor} = Pointer(-1);
+ 
+ type
+   TSQLiteDB = Pointer;
+   TSQLiteResult = ^PChar;
+   TSQLiteStmt = Pointer;
+ 
++type
++  PPCharArray = ^TPCharArray; 
++  TPCharArray = array[0 .. (MaxInt div SizeOf(PChar))-1] of PChar;
++
++type
++  TSQLiteExecCallback = function(UserData: Pointer; NumCols: integer; ColValues:
++    PPCharArray; ColNames: PPCharArray): integer; cdecl;
++  TSQLiteBusyHandlerCallback = function(UserData: Pointer; P2: integer): integer; cdecl;
++
+   //function prototype for define own collate
+-  TCollateXCompare = function(Userdta: pointer; Buf1Len: integer; Buf1: pointer;
++  TCollateXCompare = function(UserData: pointer; Buf1Len: integer; Buf1: pointer;
+     Buf2Len: integer; Buf2: pointer): integer; cdecl;
++    
+ 
+-function SQLite3_Open(dbname: PChar; var db: TSqliteDB): integer; cdecl; external SQLiteDLL name 'sqlite3_open';
++function SQLite3_Open(filename: PChar; var db: TSQLiteDB): integer; cdecl; external SQLiteDLL name 'sqlite3_open';
+ function SQLite3_Close(db: TSQLiteDB): integer; cdecl; external SQLiteDLL name 'sqlite3_close';
+-function SQLite3_Exec(db: TSQLiteDB; SQLStatement: PChar; CallbackPtr: Pointer; Sender: TObject; var ErrMsg: PChar): integer; cdecl; external SQLiteDLL name 'sqlite3_exec';
++function SQLite3_Exec(db: TSQLiteDB; SQLStatement: PChar; CallbackPtr: TSQLiteExecCallback; UserData: Pointer; var ErrMsg: PChar): integer; cdecl; external SQLiteDLL name 'sqlite3_exec';
+ function SQLite3_Version(): PChar; cdecl; external SQLiteDLL name 'sqlite3_libversion';
+ function SQLite3_ErrMsg(db: TSQLiteDB): PChar; cdecl; external SQLiteDLL name 'sqlite3_errmsg';
+ function SQLite3_ErrCode(db: TSQLiteDB): integer; cdecl; external SQLiteDLL name 'sqlite3_errcode';
+@@ -82,76 +109,78 @@
+ function SQLite3_Complete(P: PChar): boolean; cdecl; external SQLiteDLL name 'sqlite3_complete';
+ function SQLite3_LastInsertRowID(db: TSQLiteDB): int64; cdecl; external SQLiteDLL name 'sqlite3_last_insert_rowid';
+ procedure SQLite3_Interrupt(db: TSQLiteDB); cdecl; external SQLiteDLL name 'sqlite3_interrupt';
+-procedure SQLite3_BusyHandler(db: TSQLiteDB; CallbackPtr: Pointer; Sender: TObject); cdecl; external SQLiteDLL name 'sqlite3_busy_handler';
++procedure SQLite3_BusyHandler(db: TSQLiteDB; CallbackPtr: TSQLiteBusyHandlerCallback; UserData: Pointer); cdecl; external SQLiteDLL name 'sqlite3_busy_handler';
+ procedure SQLite3_BusyTimeout(db: TSQLiteDB; TimeOut: integer); cdecl; external SQLiteDLL name 'sqlite3_busy_timeout';
+ function SQLite3_Changes(db: TSQLiteDB): integer; cdecl; external SQLiteDLL name 'sqlite3_changes';
+ function SQLite3_TotalChanges(db: TSQLiteDB): integer; cdecl; external SQLiteDLL name 'sqlite3_total_changes';
+ function SQLite3_Prepare(db: TSQLiteDB; SQLStatement: PChar; nBytes: integer; var hStmt: TSqliteStmt; var pzTail: PChar): integer; cdecl; external SQLiteDLL name 'sqlite3_prepare';
+ function SQLite3_Prepare_v2(db: TSQLiteDB; SQLStatement: PChar; nBytes: integer; var hStmt: TSqliteStmt; var pzTail: PChar): integer; cdecl; external SQLiteDLL name 'sqlite3_prepare_v2';
+ function SQLite3_ColumnCount(hStmt: TSqliteStmt): integer; cdecl; external SQLiteDLL name 'sqlite3_column_count';
+-function Sqlite3_ColumnName(hStmt: TSqliteStmt; ColNum: integer): pchar; cdecl; external SQLiteDLL name 'sqlite3_column_name';
+-function Sqlite3_ColumnDeclType(hStmt: TSqliteStmt; ColNum: integer): pchar; cdecl; external SQLiteDLL name 'sqlite3_column_decltype';
+-function Sqlite3_Step(hStmt: TSqliteStmt): integer; cdecl; external SQLiteDLL name 'sqlite3_step';
++function SQLite3_ColumnName(hStmt: TSqliteStmt; ColNum: integer): pchar; cdecl; external SQLiteDLL name 'sqlite3_column_name';
++function SQLite3_ColumnDeclType(hStmt: TSqliteStmt; ColNum: integer): pchar; cdecl; external SQLiteDLL name 'sqlite3_column_decltype';
++function SQLite3_Step(hStmt: TSqliteStmt): integer; cdecl; external SQLiteDLL name 'sqlite3_step';
+ function SQLite3_DataCount(hStmt: TSqliteStmt): integer; cdecl; external SQLiteDLL name 'sqlite3_data_count';
+ 
+-function Sqlite3_ColumnBlob(hStmt: TSqliteStmt; ColNum: integer): pointer; cdecl; external SQLiteDLL name 'sqlite3_column_blob';
+-function Sqlite3_ColumnBytes(hStmt: TSqliteStmt; ColNum: integer): integer; cdecl; external SQLiteDLL name 'sqlite3_column_bytes';
+-function Sqlite3_ColumnDouble(hStmt: TSqliteStmt; ColNum: integer): double; cdecl; external SQLiteDLL name 'sqlite3_column_double';
+-function Sqlite3_ColumnInt(hStmt: TSqliteStmt; ColNum: integer): integer; cdecl; external SQLiteDLL name 'sqlite3_column_int';
+-function Sqlite3_ColumnText(hStmt: TSqliteStmt; ColNum: integer): pchar; cdecl; external SQLiteDLL name 'sqlite3_column_text';
+-function Sqlite3_ColumnType(hStmt: TSqliteStmt; ColNum: integer): integer; cdecl; external SQLiteDLL name 'sqlite3_column_type';
+-function Sqlite3_ColumnInt64(hStmt: TSqliteStmt; ColNum: integer): Int64; cdecl; external SQLiteDLL name 'sqlite3_column_int64';
++function SQLite3_ColumnBlob(hStmt: TSqliteStmt; ColNum: integer): pointer; cdecl; external SQLiteDLL name 'sqlite3_column_blob';
++function SQLite3_ColumnBytes(hStmt: TSqliteStmt; ColNum: integer): integer; cdecl; external SQLiteDLL name 'sqlite3_column_bytes';
++function SQLite3_ColumnDouble(hStmt: TSqliteStmt; ColNum: integer): double; cdecl; external SQLiteDLL name 'sqlite3_column_double';
++function SQLite3_ColumnInt(hStmt: TSqliteStmt; ColNum: integer): integer; cdecl; external SQLiteDLL name 'sqlite3_column_int';
++function SQLite3_ColumnText(hStmt: TSqliteStmt; ColNum: integer): pchar; cdecl; external SQLiteDLL name 'sqlite3_column_text';
++function SQLite3_ColumnType(hStmt: TSqliteStmt; ColNum: integer): integer; cdecl; external SQLiteDLL name 'sqlite3_column_type';
++function SQLite3_ColumnInt64(hStmt: TSqliteStmt; ColNum: integer): Int64; cdecl; external SQLiteDLL name 'sqlite3_column_int64';
+ function SQLite3_Finalize(hStmt: TSqliteStmt): integer; cdecl; external SQLiteDLL name 'sqlite3_finalize';
+ function SQLite3_Reset(hStmt: TSqliteStmt): integer; cdecl; external SQLiteDLL name 'sqlite3_reset';
+ 
+-//
++// 
+ // In the SQL strings input to sqlite3_prepare() and sqlite3_prepare16(),
+ // one or more literals can be replace by a wildcard "?" or ":N:" where
+ // N is an integer.  These value of these wildcard literals can be set
+ // using the routines listed below.
+-//
++// 
+ // In every case, the first parameter is a pointer to the sqlite3_stmt
+ // structure returned from sqlite3_prepare().  The second parameter is the
+ // index of the wildcard.  The first "?" has an index of 1.  ":N:" wildcards
+ // use the index N.
+-//
+- // The fifth parameter to sqlite3_bind_blob(), sqlite3_bind_text(), and
+- //sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
++// 
++// The fifth parameter to sqlite3_bind_blob(), sqlite3_bind_text(), and
++//sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
+ //text after SQLite has finished with it.  If the fifth argument is the
+ // special value SQLITE_STATIC, then the library assumes that the information
+ // is in static, unmanaged space and does not need to be freed.  If the
+ // fifth argument has the value SQLITE_TRANSIENT, then SQLite makes its
+ // own private copy of the data.
+-//
++// 
+ // The sqlite3_bind_* routine must be called before sqlite3_step() after
+ // an sqlite3_prepare() or sqlite3_reset().  Unbound wildcards are interpreted
+ // as NULL.
+-//
++// 
+ 
+-function SQLite3_Bind_Blob(hStmt: TSqliteStmt; ParamNum: integer;
+-  ptrData: pointer; numBytes: integer; ptrDestructor: pointer): integer;
+-  cdecl; external SQLiteDLL name 'sqlite3_bind_blob';
+-function SQLite3_Bind_Double(hStmt: TSqliteStmt; ParamNum: integer; Data: Double): integer;
++type
++  TSQLite3Destructor = procedure(Ptr: Pointer); cdecl;
++
++function sqlite3_bind_blob(hStmt: TSqliteStmt; ParamNum: integer;
++  ptrData: pointer; numBytes: integer; ptrDestructor: TSQLite3Destructor): integer;
++cdecl; external SQLiteDLL name 'sqlite3_bind_blob';
++function sqlite3_bind_text(hStmt: TSqliteStmt; ParamNum: integer;
++  Text: PChar; numBytes: integer; ptrDestructor: TSQLite3Destructor): integer;
++cdecl; external SQLiteDLL name 'sqlite3_bind_text';
++function sqlite3_bind_double(hStmt: TSqliteStmt; ParamNum: integer; Data: Double): integer;
+   cdecl; external SQLiteDLL name 'sqlite3_bind_double';
+-function SQLite3_BindInt(hStmt: TSqLiteStmt; ParamNum: integer; intData: integer): integer;
+-  cdecl; external 'sqlite3.dll' name 'sqlite3_bind_int';
+-function SQLite3_Bind_int64(hStmt: TSqliteStmt; ParamNum: integer; Data: int64): integer;
++function sqlite3_bind_int(hStmt: TSqLiteStmt; ParamNum: integer; Data: integer): integer;
++  cdecl; external SQLiteDLL name 'sqlite3_bind_int';
++function sqlite3_bind_int64(hStmt: TSqliteStmt; ParamNum: integer; Data: int64): integer;
+   cdecl; external SQLiteDLL name 'sqlite3_bind_int64';
+-function SQLite3_Bind_null(hStmt: TSqliteStmt; ParamNum: integer): integer;
++function sqlite3_bind_null(hStmt: TSqliteStmt; ParamNum: integer): integer;
+   cdecl; external SQLiteDLL name 'sqlite3_bind_null';
+-function SQLite3_Bind_text(hStmt: TSqliteStmt; ParamNum: integer;
+-  Data: PChar; numBytes: integer; ptrDestructor: pointer): integer;
+-  cdecl; external SQLiteDLL name 'sqlite3_bind_text';
+ 
+-function SQLite3_Bind_Parameter_Index(hStmt: TSqliteStmt; zName: PChar): integer;
++function sqlite3_bind_parameter_index(hStmt: TSqliteStmt; zName: PChar): integer;
+   cdecl; external SQLiteDLL name 'sqlite3_bind_parameter_index';
+ 
+-function sqlite3_enable_shared_cache(value: integer): integer; cdecl; external SQLiteDLL name 'sqlite3_enable_shared_cache';
++function sqlite3_enable_shared_cache(Value: integer): integer; cdecl; external SQLiteDLL name 'sqlite3_enable_shared_cache';
+ 
+ //user collate definiton
+-function sqlite3_create_collation(db: TSQLiteDB; Name: Pchar; eTextRep: integer;
++function SQLite3_create_collation(db: TSQLiteDB; Name: Pchar; eTextRep: integer;
+   UserData: pointer; xCompare: TCollateXCompare): integer; cdecl; external SQLiteDLL name 'sqlite3_create_collation';
+-
+ 
+ function SQLiteFieldType(SQLiteFieldTypeCode: Integer): AnsiString;
+ function SQLiteErrorStr(SQLiteErrorCode: Integer): AnsiString;
diff --git a/src/lib/SQLite/SQLiteTable3.pas b/src/lib/SQLite/SQLiteTable3.pas
index 8f33b115..ab465ef8 100644
--- a/src/lib/SQLite/SQLiteTable3.pas
+++ b/src/lib/SQLite/SQLiteTable3.pas
@@ -54,6 +54,7 @@ unit SQLiteTable3;
    Adapted by Tim Anderson (tim@itwriting.com)
    Originally created by Pablo Pissanetzky (pablo@myhtpc.net)
    Modified and enhanced by Lukas Gebauer
+   Modified and enhanced by Tobias Gunkel
 }
 
 interface
@@ -90,12 +91,13 @@ type
     valuedata: string;
   end;
 
+  THookQuery = procedure(Sender: TObject; SQL: String) of object;
+
   TSQLiteQuery = record
     SQL: String;
     Statement: TSQLiteStmt;
   end;
 
-
   TSQLiteTable = class;
   TSQLiteUniTable = class;
 
@@ -105,12 +107,14 @@ type
     fInTrans: boolean;
     fSync: boolean;
     fParams: TList;
+    FOnQuery: THookQuery;
     procedure RaiseError(s: string; SQL: string);
     procedure SetParams(Stmt: TSQLiteStmt);
     procedure BindData(Stmt: TSQLiteStmt; const Bindings: array of const);
     function GetRowsChanged: integer;
   protected
     procedure SetSynchronised(Value: boolean);
+    procedure DoQuery(value: string); 
   public
     constructor Create(const FileName: string);
     destructor Destroy; override;
@@ -129,6 +133,7 @@ type
     function GetTableValue(const SQL: string; const Bindings: array of const): int64; overload;
     function GetTableString(const SQL: string): string; overload;
     function GetTableString(const SQL: string; const Bindings: array of const): string; overload;
+    procedure GetTableStrings(const SQL: string; const Value: TStrings);
     procedure UpdateBlob(const SQL: string; BlobData: TStream);
     procedure BeginTransaction;
     procedure Commit;
@@ -152,7 +157,7 @@ type
     //database rows that were changed (or inserted or deleted) by the most recent SQL statement
     property RowsChanged : integer read getRowsChanged;
     property Synchronised: boolean read FSync write SetSynchronised;
-
+    property OnQuery: THookQuery read FOnQuery write FOnQuery;
   end;
 
   TSQLiteTable = class
@@ -194,7 +199,7 @@ type
     property Row: cardinal read fRow;
     function MoveFirst: boolean;
     function MoveLast: boolean;
-    function MoveTo(position:Integer): boolean;
+    function MoveTo(position: cardinal): boolean;
     property Count: integer read GetCount;
     // The property CountResult is used when you execute count(*) queries.
     // It returns 0 if the result set is empty or the value of the
@@ -493,7 +498,7 @@ begin
       RaiseError('Error executing SQL', SQL);
     if (Stmt = nil) then
       RaiseError('Could not prepare SQL statement', SQL);
-
+    DoQuery(SQL);
     SetParams(Stmt);
     BindData(Stmt, Bindings);
 
@@ -545,6 +550,7 @@ begin
 
   if (Result.Statement = nil) then
     RaiseError('Could not prepare SQL statement', SQL);
+  DoQuery(SQL);
 end;
 {$WARNINGS ON}
 
@@ -604,6 +610,7 @@ begin
 
     if (Stmt = nil) then
       RaiseError('Could not prepare SQL statement', SQL);
+    DoQuery(SQL);
 
     //now bind the blob data
     iSize := BlobData.size;
@@ -701,6 +708,23 @@ begin
   end;
 end;
 
+procedure TSQLiteDatabase.GetTableStrings(const SQL: string;
+  const Value: TStrings);
+var
+  Table: TSQLiteUniTable;
+begin
+  Value.Clear;
+  Table := self.GetUniTable(SQL);
+  try
+    while not table.EOF do
+    begin
+      Value.Add(Table.FieldAsString(0));
+      table.Next;
+    end;
+  finally
+    Table.Free;
+  end;
+end;
 
 procedure TSQLiteDatabase.BeginTransaction;
 begin
@@ -853,6 +877,12 @@ begin
  Result := SQLite3_Changes(self.fDB);
 end;
 
+procedure TSQLiteDatabase.DoQuery(value: string);
+begin
+  if assigned(OnQuery) then
+    OnQuery(Self, Value);
+end;
+
 //------------------------------------------------------------------------------
 // TSQLiteTable
 //------------------------------------------------------------------------------
@@ -889,7 +919,7 @@ begin
       DB.RaiseError('Error executing SQL', SQL);
     if (Stmt = nil) then
       DB.RaiseError('Could not prepare SQL statement', SQL);
-
+    DB.DoQuery(SQL);
     DB.SetParams(Stmt);
     DB.BindData(Stmt, Bindings);
 
@@ -1152,15 +1182,19 @@ begin
   Result := '';
   MemStream := self.FieldAsBlob(I);
   if MemStream <> nil then
-    if MemStream.Size > 0 then
-    begin
-      MemStream.position := 0;
-      Buffer := stralloc(MemStream.Size + 1);
-      MemStream.readbuffer(Buffer[0], MemStream.Size);
-      (Buffer + MemStream.Size)^ := chr(0);
-      SetString(Result, Buffer, MemStream.size);
-      strdispose(Buffer);
-    end;
+    try
+      if MemStream.Size > 0 then
+      begin
+        MemStream.position := 0;
+        Buffer := stralloc(MemStream.Size + 1);
+        MemStream.readbuffer(Buffer[0], MemStream.Size);
+        (Buffer + MemStream.Size)^ := chr(0);
+        SetString(Result, Buffer, MemStream.size);
+        strdispose(Buffer);
+      end;
+    finally
+      MemStream.free;
+    end; 
 end;
 
 
@@ -1259,7 +1293,7 @@ begin
 end;
 
 {$WARNINGS OFF}
-function TSQLiteTable.MoveTo(position: Integer): boolean;
+function TSQLiteTable.MoveTo(position: cardinal): boolean;
 begin
   Result := False;
   if (self.fRowCount > 0) and (self.fRowCount > position) then
@@ -1296,7 +1330,7 @@ begin
     DB.RaiseError('Error executing SQL', SQL);
   if (fStmt = nil) then
     DB.RaiseError('Could not prepare SQL statement', SQL);
-
+  DB.DoQuery(SQL);
   DB.SetParams(fStmt);
   DB.BindData(fStmt, Bindings);
 
@@ -1349,14 +1383,18 @@ begin
   Result := '';
   MemStream := self.FieldAsBlob(I);
   if MemStream <> nil then
-    if MemStream.Size > 0 then
-    begin
-      MemStream.position := 0;
-      Buffer := stralloc(MemStream.Size + 1);
-      MemStream.readbuffer(Buffer[0], MemStream.Size);
-      (Buffer + MemStream.Size)^ := chr(0);
-      SetString(Result, Buffer, MemStream.size);
-      strdispose(Buffer);
+    try
+      if MemStream.Size > 0 then
+      begin
+        MemStream.position := 0;
+        Buffer := stralloc(MemStream.Size + 1);
+        MemStream.readbuffer(Buffer[0], MemStream.Size);
+        (Buffer + MemStream.Size)^ := chr(0);
+        SetString(Result, Buffer, MemStream.size);
+        strdispose(Buffer);
+      end;
+    finally
+      MemStream.Free;
     end;
 end;
 
diff --git a/src/lib/SQLite/SQLiteTable3.patch b/src/lib/SQLite/SQLiteTable3.patch
new file mode 100644
index 00000000..bee8f498
--- /dev/null
+++ b/src/lib/SQLite/SQLiteTable3.patch
@@ -0,0 +1,472 @@
+--- D:/daten/SQLiteTable3.pas	Mon Oct 13 12:38:52 2008
++++ D:/daten/Projekte/ultrastardx/linuxtrunk/src/lib/SQLite/SQLiteTable3.pas	Mon Oct 13 12:56:30 2008
+@@ -54,12 +54,20 @@
+    Adapted by Tim Anderson (tim@itwriting.com)
+    Originally created by Pablo Pissanetzky (pablo@myhtpc.net)
+    Modified and enhanced by Lukas Gebauer
++   Modified and enhanced by Tobias Gunkel
+ }
+ 
+ interface
+ 
++{$IFDEF FPC}
++  {$MODE Delphi}{$H+}
++{$ENDIF}
++
+ uses
+-  Windows, SQLite3, Classes, SysUtils;
++  {$IFDEF WIN32}
++  Windows,
++  {$ENDIF}
++  SQLite3, Classes, SysUtils;
+ 
+ const
+ 
+@@ -102,23 +110,29 @@
+     FOnQuery: THookQuery;
+     procedure RaiseError(s: string; SQL: string);
+     procedure SetParams(Stmt: TSQLiteStmt);
+-    function getRowsChanged: integer;
++    procedure BindData(Stmt: TSQLiteStmt; const Bindings: array of const);
++    function GetRowsChanged: integer;
+   protected
+     procedure SetSynchronised(Value: boolean);
+     procedure DoQuery(value: string); 
+   public
+     constructor Create(const FileName: string);
+     destructor Destroy; override;
+-    function GetTable(const SQL: string): TSQLiteTable;
++    function GetTable(const SQL: string): TSQLiteTable; overload;
++    function GetTable(const SQL: string; const Bindings: array of const): TSQLiteTable; overload;
+     procedure ExecSQL(const SQL: string); overload;
++    procedure ExecSQL(const SQL: string; const Bindings: array of const); overload;
+     procedure ExecSQL(Query: TSQLiteQuery); overload;
+     function PrepareSQL(const SQL: string): TSQLiteQuery;
+     procedure BindSQL(Query: TSQLiteQuery; const Index: Integer; const Value: Integer); overload;
+     procedure BindSQL(Query: TSQLiteQuery; const Index: Integer; const Value: String); overload;
+     procedure ReleaseSQL(Query: TSQLiteQuery);
+-    function GetUniTable(const SQL: string): TSQLiteUniTable;
+-    function GetTableValue(const SQL: string): int64;
+-    function GetTableString(const SQL: string): string;
++    function GetUniTable(const SQL: string): TSQLiteUniTable; overload;
++    function GetUniTable(const SQL: string; const Bindings: array of const): TSQLiteUniTable; overload;
++    function GetTableValue(const SQL: string): int64; overload;
++    function GetTableValue(const SQL: string; const Bindings: array of const): int64; overload;
++    function GetTableString(const SQL: string): string; overload;
++    function GetTableString(const SQL: string; const Bindings: array of const): string; overload;
+     procedure GetTableStrings(const SQL: string; const Value: TStrings);
+     procedure UpdateBlob(const SQL: string; BlobData: TStream);
+     procedure BeginTransaction;
+@@ -128,7 +142,7 @@
+     function GetLastInsertRowID: int64;
+     function GetLastChangedRows: int64;
+     procedure SetTimeout(Value: integer);
+-    function version: string;
++    function Version: string;
+     procedure AddCustomCollate(name: string; xCompare: TCollateXCompare);
+     //adds collate named SYSTEM for correct data sorting by user's locale
+     Procedure AddSystemCollate;
+@@ -139,7 +153,7 @@
+     procedure AddParamNull(name: string);
+     property DB: TSQLiteDB read fDB;
+   published
+-    property isTransactionOpen: boolean read fInTrans;
++    property IsTransactionOpen: boolean read fInTrans;
+     //database rows that were changed (or inserted or deleted) by the most recent SQL statement
+     property RowsChanged : integer read getRowsChanged;
+     property Synchronised: boolean read FSync write SetSynchronised;
+@@ -163,7 +177,8 @@
+     function GetCount: integer;
+     function GetCountResult: integer;
+   public
+-    constructor Create(DB: TSQLiteDatabase; const SQL: string);
++    constructor Create(DB: TSQLiteDatabase; const SQL: string); overload;
++    constructor Create(DB: TSQLiteDatabase; const SQL: string; const Bindings: array of const); overload;
+     destructor Destroy; override;
+     function FieldAsInteger(I: cardinal): int64;
+     function FieldAsBlob(I: cardinal): TMemoryStream;
+@@ -196,7 +211,6 @@
+   private
+     fColCount: cardinal;
+     fCols: TStringList;
+-    fColTypes: TList;
+     fRow: cardinal;
+     fEOF: boolean;
+     fStmt: TSQLiteStmt;
+@@ -207,10 +221,12 @@
+     function GetFieldByName(FieldName: string): string;
+     function GetFieldIndex(FieldName: string): integer;
+   public
+-    constructor Create(DB: TSQLiteDatabase; const SQL: string);
++    constructor Create(DB: TSQLiteDatabase; const SQL: string); overload;
++    constructor Create(DB: TSQLiteDatabase; const SQL: string; const Bindings: array of const); overload;
+     destructor Destroy; override;
+     function FieldAsInteger(I: cardinal): int64;
+     function FieldAsBlob(I: cardinal): TMemoryStream;
++    function FieldAsBlobPtr(I: cardinal; out iNumBytes: integer): Pointer;
+     function FieldAsBlobText(I: cardinal): string;
+     function FieldIsNull(I: cardinal): boolean;
+     function FieldAsString(I: cardinal): string;
+@@ -227,8 +243,10 @@
+ 
+ procedure DisposePointer(ptr: pointer); cdecl;
+ 
++{$IFDEF WIN32}
+ function SystemCollate(Userdta: pointer; Buf1Len: integer; Buf1: pointer;
+     Buf2Len: integer; Buf2: pointer): integer; cdecl;
++{$ENDIF}
+ 
+ implementation
+ 
+@@ -238,12 +256,14 @@
+     freemem(ptr);
+ end;
+ 
++{$IFDEF WIN32}
+ function SystemCollate(Userdta: pointer; Buf1Len: integer; Buf1: pointer;
+     Buf2Len: integer; Buf2: pointer): integer; cdecl;
+ begin
+   Result := CompareStringW(LOCALE_USER_DEFAULT, 0, PWideChar(Buf1), Buf1Len,
+     PWideChar(Buf2), Buf2Len) - 2;
+ end;
++{$ENDIF}
+ 
+ //------------------------------------------------------------------------------
+ // TSQLiteDatabase
+@@ -347,7 +367,126 @@
+   end;
+ end;
+ 
++procedure TSQLiteDatabase.BindData(Stmt: TSQLiteStmt; const Bindings: array of const);
++var
++  BlobMemStream: TCustomMemoryStream;
++  BlobStdStream: TStream;
++  DataPtr: Pointer;
++  DataSize: integer;
++  AnsiStr: AnsiString;
++  AnsiStrPtr: PAnsiString;
++  I: integer;
++begin
++  for I := 0 to High(Bindings) do
++  begin
++    case Bindings[I].VType of
++      vtString,
++      vtAnsiString, vtPChar,
++      vtWideString, vtPWideChar,
++      vtChar, vtWideChar:
++      begin
++        case Bindings[I].VType of
++          vtString: begin // ShortString
++            AnsiStr := Bindings[I].VString^;
++            DataPtr := PChar(AnsiStr);
++            DataSize := Length(AnsiStr)+1;
++          end;
++          vtPChar: begin
++            DataPtr := Bindings[I].VPChar;
++            DataSize := -1;
++          end;
++          vtAnsiString: begin
++            AnsiStrPtr := PString(@Bindings[I].VAnsiString);
++            DataPtr := PChar(AnsiStrPtr^);
++            DataSize := Length(AnsiStrPtr^)+1;
++          end;
++          vtPWideChar: begin
++            DataPtr := PChar(UTF8Encode(WideString(Bindings[I].VPWideChar)));
++            DataSize := -1;
++          end;
++          vtWideString: begin
++            DataPtr := PChar(UTF8Encode(PWideString(@Bindings[I].VWideString)^));
++            DataSize := -1;
++          end;
++          vtChar: begin
++            DataPtr := PChar(String(Bindings[I].VChar));
++            DataSize := 2;
++          end;
++          vtWideChar: begin
++            DataPtr := PChar(UTF8Encode(WideString(Bindings[I].VWideChar)));
++            DataSize := -1;
++          end;
++          else
++            raise ESqliteException.Create('Unknown string-type');
++        end;
++        if (sqlite3_bind_text(Stmt, I+1, DataPtr, DataSize, SQLITE_STATIC) <> SQLITE_OK) then
++          RaiseError('Could not bind text', 'BindData');
++      end;
++      vtInteger:
++        if (sqlite3_bind_int(Stmt, I+1, Bindings[I].VInteger) <> SQLITE_OK) then
++          RaiseError('Could not bind integer', 'BindData');
++      vtInt64:
++        if (sqlite3_bind_int64(Stmt, I+1, Bindings[I].VInt64^) <> SQLITE_OK) then
++          RaiseError('Could not bind int64', 'BindData');
++      vtExtended:
++        if (sqlite3_bind_double(Stmt, I+1, Bindings[I].VExtended^) <> SQLITE_OK) then
++          RaiseError('Could not bind extended', 'BindData');
++      vtBoolean:
++        if (sqlite3_bind_int(Stmt, I+1, Integer(Bindings[I].VBoolean)) <> SQLITE_OK) then
++          RaiseError('Could not bind boolean', 'BindData');
++      vtPointer:
++      begin
++        if (Bindings[I].VPointer = nil) then
++        begin
++          if (sqlite3_bind_null(Stmt, I+1) <> SQLITE_OK) then
++            RaiseError('Could not bind null', 'BindData');
++        end
++        else
++          raise ESqliteException.Create('Unhandled pointer (<> nil)');
++      end;
++      vtObject:
++      begin
++        if (Bindings[I].VObject is TCustomMemoryStream) then
++        begin
++          BlobMemStream := TCustomMemoryStream(Bindings[I].VObject);
++          if (sqlite3_bind_blob(Stmt, I+1, @PChar(BlobMemStream.Memory)[BlobMemStream.Position],
++              BlobMemStream.Size-BlobMemStream.Position, SQLITE_STATIC) <> SQLITE_OK) then
++          begin
++            RaiseError('Could not bind BLOB', 'BindData');
++          end;
++        end
++        else if (Bindings[I].VObject is TStream) then
++        begin
++          BlobStdStream := TStream(Bindings[I].VObject);
++          DataSize := BlobStdStream.Size;
++
++          GetMem(DataPtr, DataSize);
++          if (DataPtr = nil) then
++            raise ESqliteException.Create('Error getting memory to save blob');
++
++          BlobStdStream.Position := 0;
++          BlobStdStream.Read(DataPtr^, DataSize);
++
++          if (sqlite3_bind_blob(stmt, I+1, DataPtr, DataSize, @DisposePointer) <> SQLITE_OK) then
++            RaiseError('Could not bind BLOB', 'BindData');
++        end
++        else             
++          raise ESqliteException.Create('Unhandled object-type in binding');
++      end
++      else 
++      begin
++        raise ESqliteException.Create('Unhandled binding');
++      end;
++    end;
++  end;
++end;
++
+ procedure TSQLiteDatabase.ExecSQL(const SQL: string);
++begin
++  ExecSQL(SQL, []);
++end;
++
++procedure TSQLiteDatabase.ExecSQL(const SQL: string; const Bindings: array of const);
+ var
+   Stmt: TSQLiteStmt;
+   NextSQLStatement: Pchar;
+@@ -361,6 +500,8 @@
+       RaiseError('Could not prepare SQL statement', SQL);
+     DoQuery(SQL);
+     SetParams(Stmt);
++    BindData(Stmt, Bindings);
++
+     iStepResult := Sqlite3_step(Stmt);
+     if (iStepResult <> SQLITE_DONE) then
+       begin
+@@ -417,7 +558,7 @@
+ procedure TSQLiteDatabase.BindSQL(Query: TSQLiteQuery; const Index: Integer; const Value: Integer);
+ begin
+   if Assigned(Query.Statement) then
+-    Sqlite3_BindInt(Query.Statement, Index, Value)
++    sqlite3_Bind_Int(Query.Statement, Index, Value)
+   else
+     RaiseError('Could not bind integer to prepared SQL statement', Query.SQL);
+ end;
+@@ -514,17 +655,32 @@
+   Result := TSQLiteTable.Create(Self, SQL);
+ end;
+ 
++function TSQLiteDatabase.GetTable(const SQL: string; const Bindings: array of const): TSQLiteTable;
++begin
++  Result := TSQLiteTable.Create(Self, SQL, Bindings);
++end;
++
+ function TSQLiteDatabase.GetUniTable(const SQL: string): TSQLiteUniTable;
+ begin
+   Result := TSQLiteUniTable.Create(Self, SQL);
+ end;
+ 
++function TSQLiteDatabase.GetUniTable(const SQL: string; const Bindings: array of const): TSQLiteUniTable;
++begin
++  Result := TSQLiteUniTable.Create(Self, SQL, Bindings);
++end;
++
+ function TSQLiteDatabase.GetTableValue(const SQL: string): int64;
++begin
++  Result := GetTableValue(SQL, []);
++end;
++
++function TSQLiteDatabase.GetTableValue(const SQL: string; const Bindings: array of const): int64;
+ var
+   Table: TSQLiteUniTable;
+ begin
+   Result := 0;
+-  Table := self.GetUniTable(SQL);
++  Table := self.GetUniTable(SQL, Bindings);
+   try
+     if not Table.EOF then
+       Result := Table.FieldAsInteger(0);
+@@ -534,11 +690,16 @@
+ end;
+ 
+ function TSQLiteDatabase.GetTableString(const SQL: string): String;
++begin
++  Result := GetTableString(SQL, []);
++end;
++
++function TSQLiteDatabase.GetTableString(const SQL: string; const Bindings: array of const): String;
+ var
+   Table: TSQLiteUniTable;
+ begin
+   Result := '';
+-  Table := self.GetUniTable(SQL);
++  Table := self.GetUniTable(SQL, Bindings);
+   try
+     if not Table.EOF then
+       Result := Table.FieldAsString(0);
+@@ -609,7 +770,7 @@
+   SQLite3_BusyTimeout(self.fDB, Value);
+ end;
+ 
+-function TSQLiteDatabase.version: string;
++function TSQLiteDatabase.Version: string;
+ begin
+   Result := SQLite3_Version;
+ end;
+@@ -622,7 +783,9 @@
+ 
+ procedure TSQLiteDatabase.AddSystemCollate;
+ begin
++  {$IFDEF WIN32}
+   sqlite3_create_collation(fdb, 'SYSTEM', SQLITE_UTF16LE, nil, @SystemCollate);
++  {$ENDIF}
+ end;
+ 
+ procedure TSQLiteDatabase.ParamsClear;
+@@ -709,7 +872,7 @@
+ end;
+ 
+ //database rows that were changed (or inserted or deleted) by the most recent SQL statement
+-function TSQLiteDatabase.getRowsChanged: integer;
++function TSQLiteDatabase.GetRowsChanged: integer;
+ begin
+  Result := SQLite3_Changes(self.fDB);
+ end;
+@@ -725,6 +888,11 @@
+ //------------------------------------------------------------------------------
+ 
+ constructor TSQLiteTable.Create(DB: TSQLiteDatabase; const SQL: string);
++begin
++  Create(DB, SQL, []);
++end;
++
++constructor TSQLiteTable.Create(DB: TSQLiteDatabase; const SQL: string; const Bindings: array of const);
+ var
+   Stmt: TSQLiteStmt;
+   NextSQLStatement: Pchar;
+@@ -753,6 +921,8 @@
+       DB.RaiseError('Could not prepare SQL statement', SQL);
+     DB.DoQuery(SQL);
+     DB.SetParams(Stmt);
++    DB.BindData(Stmt, Bindings);
++
+     iStepResult := Sqlite3_step(Stmt);
+     while (iStepResult <> SQLITE_DONE) do
+     begin
+@@ -1122,6 +1292,7 @@
+   end;
+ end;
+ 
++{$WARNINGS OFF}
+ function TSQLiteTable.MoveTo(position: cardinal): boolean;
+ begin
+   Result := False;
+@@ -1131,13 +1302,18 @@
+     Result := True;
+   end;
+ end;
+-
++{$WARNINGS ON}
+ 
+ 
+ 
+ { TSQLiteUniTable }
+ 
+ constructor TSQLiteUniTable.Create(DB: TSQLiteDatabase; const SQL: string);
++begin
++  Create(DB, SQL, []);
++end;
++
++constructor TSQLiteUniTable.Create(DB: TSQLiteDatabase; const SQL: string; const Bindings: array of const);
+ var
+   NextSQLStatement: Pchar;
+   thisColType: pInteger;
+@@ -1156,36 +1332,14 @@
+     DB.RaiseError('Could not prepare SQL statement', SQL);
+   DB.DoQuery(SQL);
+   DB.SetParams(fStmt);
++  DB.BindData(fStmt, Bindings);
+ 
+   //get data types
+   fCols := TStringList.Create;
+-  fColTypes := TList.Create;
+   fColCount := SQLite3_ColumnCount(fstmt);
+   for i := 0 to Pred(fColCount) do
+     fCols.Add(AnsiUpperCase(Sqlite3_ColumnName(fstmt, i)));
+-  for i := 0 to Pred(fColCount) do
+-  begin
+-    new(thisColType);
+-    DeclaredColType := Sqlite3_ColumnDeclType(fstmt, i);
+-    if DeclaredColType = nil then
+-      thisColType^ := Sqlite3_ColumnType(fstmt, i) //use the actual column type instead
+-    //seems to be needed for last_insert_rowid
+-    else
+-      if (DeclaredColType = 'INTEGER') or (DeclaredColType = 'BOOLEAN') then
+-        thisColType^ := dtInt
+-      else
+-        if (DeclaredColType = 'NUMERIC') or
+-          (DeclaredColType = 'FLOAT') or
+-          (DeclaredColType = 'DOUBLE') or
+-          (DeclaredColType = 'REAL') then
+-          thisColType^ := dtNumeric
+-        else
+-          if DeclaredColType = 'BLOB' then
+-            thisColType^ := dtBlob
+-          else
+-            thisColType^ := dtStr;
+-    fColTypes.Add(thiscoltype);
+-  end;
++
+   Next;
+ end;
+ 
+@@ -1197,10 +1351,6 @@
+     Sqlite3_Finalize(fstmt);
+   if Assigned(fCols) then
+     fCols.Free;
+-  if Assigned(fColTypes) then
+-    for i := 0 to fColTypes.Count - 1 do
+-      dispose(fColTypes[i]);
+-  fColTypes.Free;
+   inherited;
+ end;
+ 
+@@ -1217,6 +1367,12 @@
+     Result.writebuffer(ptr^, iNumBytes);
+     Result.Position := 0;
+   end;
++end;
++
++function TSQLiteUniTable.FieldAsBlobPtr(I: cardinal; out iNumBytes: integer): Pointer;
++begin
++  iNumBytes := Sqlite3_ColumnBytes(fstmt, i);
++  Result := Sqlite3_ColumnBlob(fstmt, i);
+ end;
+ 
+ function TSQLiteUniTable.FieldAsBlobText(I: cardinal): string;
-- 
cgit v1.2.3