https://github.com/continuous-delphi/delphi-wrapper-sqlite3
Multi-platform SQLite3 class library for Delphi
https://github.com/continuous-delphi/delphi-wrapper-sqlite3
continuous-delphi delphi sqlite3 wrapper-library
Last synced: 2 days ago
JSON representation
Multi-platform SQLite3 class library for Delphi
- Host: GitHub
- URL: https://github.com/continuous-delphi/delphi-wrapper-sqlite3
- Owner: continuous-delphi
- License: mit
- Created: 2026-05-15T16:56:41.000Z (21 days ago)
- Default Branch: main
- Last Pushed: 2026-05-15T19:43:12.000Z (21 days ago)
- Last Synced: 2026-05-15T19:50:10.892Z (21 days ago)
- Topics: continuous-delphi, delphi, sqlite3, wrapper-library
- Language: Pascal
- Homepage: https://github.com/continuous-delphi
- Size: 43.9 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# delphi-wrapper-sqlite3

[](https://www.embarcadero.com/products/delphi)
[](https://docwiki.embarcadero.com/PlatformStatus/en/Main_Page)
[](assets/coverage/CodeCoverage_Summary.md)
[](https://opensource.org/licenses/MIT)
[](https://deepwiki.com/continuous-delphi/delphi-wrapper-sqlite3)
[](https://github.com/continuous-delphi)
Lightweight cross-platform Delphi wrapper for SQLite. Dynamically loads the platform-native SQLite library at runtime.
## Platform Support
| Platform | Library | Calling Convention | Availability |
|---|---|---|---|
| Windows Win32 | `winsqlite3.dll` | stdcall | Ships with Windows 10 1803+ |
| Windows Win64 | `winsqlite3.dll` | stdcall | Ships with Windows 10 1803+ |
| Linux x64 | `libsqlite3.so` | cdecl | `apt install libsqlite3-0` or equivalent |
| macOS x64/ARM | `libsqlite3.dylib` | cdecl | Ships with macOS |
| iOS ARM | `libsqlite3.dylib` | cdecl | Ships with iOS |
| Android ARM/x64 | `libsqlite.so` | cdecl | Ships with Android |
## Requirements
- Newer version of Delphi (uses inline variables, `PUTF8Char`)
- SQLite library available on the target platform (see table above)
## Quick Start
Add `Source\Delphi.SQLite3.pas` to your project (ensure `Source\` is in the include path for the `.inc` file).
```pascal
uses Delphi.SQLite3;
var DB := TSQLite3.Create('mydata.db');
try
DB.ExecSQL('CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY, name TEXT, price REAL)');
DB.ExecSQL('INSERT INTO items (name, price) VALUES (:n, :p)', ['Widget', 9.99]);
var Q := DB.Query('SELECT id, name, price FROM items');
try
while Q.Next do
WriteLn(Q.AsInteger(0), ' | ', Q.AsString(1), ' | ', Q.AsFloat(2):0:2);
finally
Q.Free;
end;
finally
DB.Free;
end;
```
## API Reference
### TSQLite3
Database connection. Opens (or creates) a SQLite database file.
```pascal
constructor Create(const ADbPath: string);
```
#### Execute
```pascal
// DDL or DML with no result set.
procedure ExecSQL(const ASQL: string);
procedure ExecSQL(const ASQL: string; const AParams: array of const);
// Query returning a result set. Caller must free the returned object.
function Query(const ASQL: string): TSQLite3Query;
function Query(const ASQL: string; const AParams: array of const): TSQLite3Query;
```
#### Scalar Helpers
Return the first column of the first row. Raise `ESQLite3Error` if the query returns no rows.
```pascal
function QueryValue(const ASQL: string): string;
function QueryValue(const ASQL: string; const AParams: array of const): string;
function QueryInt(const ASQL: string): Integer;
function QueryInt(const ASQL: string; const AParams: array of const): Integer;
```
#### Transactions
```pascal
procedure StartTransaction;
procedure Commit;
procedure Rollback;
```
#### Metadata
```pascal
function Changes: Integer; // rows affected by last INSERT/UPDATE/DELETE
function LastInsertRowId: Int64; // rowid of most recent INSERT
class function LibVersion: string; // e.g. '3.39.4'
class function IsAvailable: Boolean;// True if the platform SQLite library can be loaded
```
### TSQLite3Query
Forward-only cursor returned by `TSQLite3.Query`. Call `Next` to advance; read columns by 0-based index.
```pascal
function Next: Boolean; // advance to next row; False when done
function EOF: Boolean; // True after the last row
property ColumnCount: Integer;
function ColumnName(AIndex: Integer): string;
function IndexOf(const AName: string): Integer; // -1 if not found (case-insensitive)
function AsString(AIndex: Integer): string;
function AsInteger(AIndex: Integer): Integer;
function AsInt64(AIndex: Integer): Int64;
function AsFloat(AIndex: Integer): Double;
function AsBlob(AIndex: Integer): TBytes;
function IsNull(AIndex: Integer): Boolean;
```
### Parameter Binding
Parameters use `:name` placeholders in SQL and `array of const` values passed positionally. Supported Delphi types:
| Delphi type | SQLite binding |
|---|---|
| `Integer` | `sqlite3_bind_int` |
| `Int64` | `sqlite3_bind_int64` |
| `Double` / `Extended` | `sqlite3_bind_double` |
| `Currency` | `sqlite3_bind_double` |
| `string` | `sqlite3_bind_text` (UTF-8) |
| `Boolean` | `sqlite3_bind_int` (0 or 1) |
| `nil` | `sqlite3_bind_null` |
```pascal
DB.ExecSQL('INSERT INTO t (name, amount, active) VALUES (:n, :a, :f)', ['Bolt', 3.50, True]);
DB.ExecSQL('UPDATE t SET name = :n WHERE id = :id', ['Nut', 42]);
DB.ExecSQL('INSERT INTO t (optional) VALUES (:v)', [nil]); // NULL
```
### Error Handling
All errors raise `ESQLite3Error` with the SQLite error code:
```pascal
type
ESQLite3Error = class(Exception)
property ErrorCode: Integer read FErrorCode;
end;
```
```pascal
try
DB.ExecSQL('SELECT * FROM nonexistent');
except
on E: ESQLite3Error do
WriteLn('SQLite error ', E.ErrorCode, ': ', E.Message);
end;
```
## Examples
### Transactions
```pascal
DB.StartTransaction;
try
for var I := 1 to 1000 do
DB.ExecSQL('INSERT INTO items (name) VALUES (:n)', ['Item ' + I.ToString]);
DB.Commit;
except
DB.Rollback;
raise;
end;
```
### Auto-increment IDs
```pascal
DB.ExecSQL('INSERT INTO items (name) VALUES (:n)', ['New item']);
var NewId := DB.LastInsertRowId;
WriteLn('Inserted row ID: ', NewId);
```
### Column Lookup by Name
```pascal
var Q := DB.Query('SELECT id, name, price FROM items');
try
var ColPrice := Q.IndexOf('price');
while Q.Next do
WriteLn(Q.AsFloat(ColPrice):0:2);
finally
Q.Free;
end;
```
### Check Availability
```pascal
if TSQLite3.IsAvailable then
WriteLn('SQLite ', TSQLite3.LibVersion)
else
WriteLn('SQLite library not found on this platform');
```
## Technical Notes
### Calling Convention
The wrapper uses `stdcall` on Windows (matching `winsqlite3.dll`) and `cdecl` on all POSIX platforms. This is handled via the `Delphi.SQLite3.cc.inc` include file that expands to the correct convention for the target platform.
### String Encoding
All strings are converted to UTF-8 before passing to SQLite and converted back to Delphi `string` (UTF-16) on read. The conversions use `UTF8String` and `PUTF8Char` for type safety.
### Dynamic Loading
The library is loaded once on first use. On Windows this uses `LoadLibrary` / `GetProcAddress`; on POSIX platforms (Linux, macOS, iOS, Android) it uses `dlopen` / `dlsym` from `Posix.Dlfcn`. The module handle is freed in the unit `finalization` section.
If the library is not present, `TSQLite3.Create` raises `ESQLite3Error`. Use `TSQLite3.IsAvailable` to check without raising.
### Thread Safety
SQLite itself is thread-safe (serialized mode by default). However, a single `TSQLite3` instance and its associated `TSQLite3Query` objects should be used from one thread at a time, or the caller must serialize access. For multi-threaded applications, create a separate `TSQLite3` connection per thread.
## Demo Project
### APIBackup -- Todo List with Backup/Restore
A VCL application in `projects/APIBackup/` that demonstrates `TSQLite3` and `TSQLite3Backup` working together. The form has a `TStringGrid` showing todo entries from `todo.db3`, an edit control with an Add button to insert rows, and Backup/Restore buttons.
- **Create** -- opens (or creates) `todo.db3` on startup with WAL journal mode
- **Read** -- populates the grid from the `todos` table
- **Insert** -- adds a new row from the edit control
- **Backup** -- saves to `todo.backup.db3` via `TSQLite3Backup.BackupToFile` (single-file output, no WAL sidecars)
- **Restore** -- loads from the backup via `TSQLite3Backup.RestoreFromFile` and refreshes the grid
The backup unit (`Delphi.SQLite3.Backup.pas` in `source/`) also serves as a reference for extending `TSQLite3` via raw API access. It resolves `sqlite3_backup_init`/`step`/`finish`/`remaining`/`pagecount` at runtime using `TSQLite3.GetAPIProc` and `TSQLite3.Handle`, without modifying the core unit.
## Tests
The test suite uses DUnitX and covers 64 tests:
| Category | Tests |
|---|---|
| Availability and version | 2 |
| Open / close | 3 |
| DDL (CREATE TABLE) | 2 |
| INSERT / SELECT | 7 |
| Scalar query helpers | 5 |
| Result set navigation | 7 |
| UPDATE / DELETE | 3 |
| LastInsertRowId | 2 |
| Transactions | 2 |
| Open flags | 4 |
| Busy timeout | 2 |
| Pragmas | 6 |
| Progress handler | 3 |
| Error handling | 2 |
| Multiple queries | 1 |
| Type coercion | 2 |
| Blob read | 1 |
| NULL handling | 1 |
| Backup / restore | 9 |
### Running Tests
Open `Tests\Delphi.SQLite3.Tests.dpr` in the Delphi IDE and create a project file, or build from the command line:
```
dcc64 -Q -B -NSSystem;System.Win;Winapi ^
-I"Source" ^
-E"Tests\Win64\Debug" -N"Tests\Win64\Debug" ^
-U"\lib\Win64\release;\lib\Win64\debug" ^
Tests\Delphi.SQLite3.Tests.dpr
```
Run:
```
Tests\Win64\Debug\Delphi.SQLite3.Tests.exe --exit:Continue
```
### Project Layout
```
delphi-wrapper-sqlite3/
source/
Delphi.SQLite3.pas -- core wrapper (TSQLite3, TSQLite3Query)
Delphi.SQLite3.cc.inc -- calling convention include (stdcall/cdecl)
Delphi.SQLite3.Backup.pas -- online backup/restore via raw API access
test/
Delphi.SQLite3.Tests.dpr -- DUnitX test project (64 tests)
Delphi.SQLite3.Test.pas -- core wrapper tests
Delphi.SQLite3.Backup.Test.pas-- backup/restore tests
projects/
APIBackup/ -- VCL demo: todo list with backup/restore
```
------------------------------------------------------------------------

## Part of Continuous Delphi
This tool is part of the [Continuous-Delphi](https://github.com/continuous-delphi)
ecosystem, focused on improving engineering discipline for long-lived Delphi systems.