IMPORTANT INCOMPATIBILITY CHANGE – please read carefully:
Up to this version, the sqlite3 type was an untyped Pointer. This worked fine when used correctly, but caused hard to identify errors when not. Incompatible variable types are usually detected by the compiler's type checking. But as a matter of fact, Delphi does not generate type errors for untyped Pointer. Code would compile happily if sqlite3 was used instead of sqlite3_stmt, and Delphi would not even object to TDISQLite3Database in place of sqlite3.
Instead, problems surfaced at runtime. They often materialized as access violations with no meaningful error message and could drive helpless developers into despair. When contacting support, some of them even attributed the problem to a bug in DISQLite3. Even though this was not correct, they certainly had a point. So after careful consideration I decided to change all untyped Pointer types to pointers to record structures.
For record pointers, Delphi can detect type conflicts at compile time, so the likelihood of critical runtime errors is greatly reduced. For most stringent type checking, I recommend to compile with "Typed @ operator" always enabled. This can be set as a project option or in code using {$T+} or {$TYPEDADDRESS ON}. With typed @ operator enabled, Delphi also detects incompatible output variable types passed to sqlite3_open(), sqlite3_prepare_v2(), and similar routines.
Unfortunately, the modified strong typing might ask to change existing code before it compiles. Luckily, however, with {$TYPEDADDRESS ON} Delphi now catches all type incompatibilities so they can be fixed easily. For smaller projects, this is a simple search and replace (older IDEs) or code refactoring (newer ones).
Automatic conversion for larger projects is at hand here:
DISQLite3_Type_Converter.zip contains a precompiled version of the JVCLConverter utility plus the conversion data file. It takes less than a minute to update the DISQLite3 Demos from previous versions: Run JVCLConverter.exe, select the source code folder, and convert. Converting other projects should be just as quickly.
Limit to auto-conversion: The PPointerArray type (mostly used in sqlite3_create_function() callbacks) is a standard Delphi type. Converting this automatically might cause unintended side effects if used outside the DISQLite3 context. Therefore PPointerArray must be manually changed to sqlite3_value_ptr_array_ptr.
This table lists all modified, renamed, or deleted type names and their new counterparts. Only those at the top of the list should be in frequent use:
| Old | New |
sqlite3_ptr | sqlite3_ptr_ptr |
sqlite3 | sqlite3_ptr |
TDISQLite3DatabaseHandle | sqlite3_ptr |
PDISQLite3DatabaseHandle | sqlite3_ptr_ptr |
sqlite3_stmt_ptr | sqlite3_stmt_ptr_ptr |
sqlite3_stmt | sqlite3_stmt_ptr |
TDISQLite3StatementHandle | sqlite3_stmt_ptr |
PDISQLite3StatementHandle | sqlite3_stmt_ptr_ptr |
sqlite3_blob | sqlite3_blob_ptr |
TDISQLite3BlobHandle | sqlite3_blob_ptr |
PDISQLite3BlobHandle | sqlite3_blob_ptr_ptr |
TSQLite3_Module | sqlite3_module |
Psqlite3_module | sqlite3_module_ptr |
Tsqlite3_tokenizer | sqlite3_tokenizer |
Psqlite3_tokenizer | sqlite3_tokenizer_ptr |
PPsqlite3_tokenizer | sqlite3_tokenizer_ptr_ptr |
Tsqlite3_tokenizer_module | sqlite3_tokenizer_module |
Psqlite3_tokenizer_module | sqlite3_tokenizer_module_ptr |
Tsqlite3_tokenizer_cursor | sqlite3_tokenizer_cursor |
Psqlite3_tokenizer_cursor | sqlite3_tokenizer_cursor_ptr |
PPsqlite3_tokenizer_cursor | sqlite3_tokenizer_cursor_ptr_ptr |
Tsqlite3_vtab | sqlite3_vtab |
Psqlite3_vtab | sqlite3_vtab_ptr |
PPsqlite3_vtab | sqlite3_vtab_ptr_ptr |
Tsqlite3_vtab_cursor | sqlite3_vtab_cursor |
Psqlite3_vtab_cursor | sqlite3_vtab_cursor_ptr |
PPsqlite3_vtab_cursor | sqlite3_vtab_cursor_ptr_ptr |
TSQLite3_index_info | sqlite3_index_info |
Psqlite3_index_info | sqlite3_index_info_ptr |
Tsqlite3_index_constraint | sqlite3_index_constraint |
Tsqlite3_index_constraint_array | sqlite3_index_constraint_array |
Psqlite3_index_constraint_array | sqlite3_index_constraint_array_ptr |
Tsqlite3_index_orderby | sqlite3_index_orderby |
Tsqlite3_index_orderby_array | sqlite3_index_orderby_array |
Psqlite3_index_orderby_array | sqlite3_index_orderby_array_ptr |
Tsqlite3_index_constraint_usage | sqlite3_index_constraint_usage |
Tsqlite3_index_constraint_usage_array | sqlite3_index_constraint_usage_array |
Psqlite3_index_constraint_usage_array | sqlite3_index_constraint_usage_array_ptr |
Bugs fixed in this version:
Problems that might cause incorrect query results:
Queries that have a WHERE clause of the form (x AND y) OR z where x and z come from one table of a join and y comes from a different table.
Queries where the use of the CAST operator in the WHERE clause could lead to incorrect results if the column being cast to a new datatype is also used in the same WHERE clause without being cast.
Expressions with different COLLATIONs could compare equal and lead to wrong query results.
When reusing an instance of TDISQLite3Database, the internal transaction counter was not reset when opening another database so its InTransaction property could return wrong results. Fixed.
Other minor bug fixes and performance enhancements, especially for the
FTS3 full text search.