diff options
author | tobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c> | 2008-10-13 12:04:24 +0000 |
---|---|---|
committer | tobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c> | 2008-10-13 12:04:24 +0000 |
commit | dc2616a471905229cebc6225c98264c737161825 (patch) | |
tree | 4ccd12524e6ac6f47c9108aeaa6af00c80d28faa | |
parent | 9ecbf3bb2d137e2c6f04ab615a34becb4b999abb (diff) | |
download | usdx-dc2616a471905229cebc6225c98264c737161825.tar.gz usdx-dc2616a471905229cebc6225c98264c737161825.tar.xz usdx-dc2616a471905229cebc6225c98264c737161825.zip |
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
-rw-r--r-- | src/lib/SQLite/SQLite3.patch | 252 | ||||
-rw-r--r-- | src/lib/SQLite/SQLiteTable3.pas | 86 | ||||
-rw-r--r-- | src/lib/SQLite/SQLiteTable3.patch | 472 |
3 files changed, 786 insertions, 24 deletions
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;
|