From dc2616a471905229cebc6225c98264c737161825 Mon Sep 17 00:00:00 2001 From: tobigun 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/SQLiteTable3.patch | 472 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 472 insertions(+) create mode 100644 src/lib/SQLite/SQLiteTable3.patch (limited to 'src/lib/SQLite/SQLiteTable3.patch') 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