mirror of
https://github.com/mirkobrombin/raven.git
synced 2026-11-01 21:45:06 +00:00
Windows has carried SQLite as winsqlite3.dll since Windows 10, and programs such as winget keep their package index in it. scripts/provision-sqlite.py builds the pinned public-domain amalgamation (3.54.1, SHA3-256 checked) with MinGW, exporting the unsuffixed sqlite3_* interface; the runtime places it in the system directory like its other components. Only the 64-bit library for now: Windows' 32-bit winsqlite3 uses the standard calling convention for its interface and callbacks, which the published amalgamation does not declare. Assisted-by: Claude Code:claude-opus-5-5 AI-Scope: provisioning script, CMake wiring, license records and the sqlite_client test
66 lines
3.6 KiB
C
66 lines
3.6 KiB
C
#define WIN32_LEAN_AND_MEAN
|
|
#include <windows.h>
|
|
|
|
/* The interface of winsqlite3.dll this client uses. */
|
|
typedef struct sqlite3 sqlite3;
|
|
typedef struct sqlite3_stmt sqlite3_stmt;
|
|
typedef int (*open_function)(const char *, sqlite3 **, int, const char *);
|
|
typedef int (*close_function)(sqlite3 *);
|
|
typedef int (*exec_function)(sqlite3 *, const char *, void *, void *, char **);
|
|
typedef int (*prepare_function)(sqlite3 *, const char *, int, sqlite3_stmt **, const char **);
|
|
typedef int (*bind_function)(sqlite3_stmt *, int, int);
|
|
typedef int (*step_function)(sqlite3_stmt *);
|
|
typedef int (*statement_function)(sqlite3_stmt *);
|
|
typedef long long (*column_function)(sqlite3_stmt *, int);
|
|
typedef const char *(*version_function)(void);
|
|
|
|
#define SQLITE_OK 0
|
|
#define SQLITE_ROW 100
|
|
#define SQLITE_DONE 101
|
|
#define SQLITE_OPEN_READWRITE 0x2
|
|
#define SQLITE_OPEN_CREATE 0x4
|
|
|
|
/* SQLite as Windows ships it, found by name in the system directory: a database in a file is created, written in a transaction with
|
|
* bound parameters, closed, opened again and read back; a malformed statement is refused. */
|
|
int raven_entry(void)
|
|
{
|
|
HMODULE library = LoadLibraryW(L"winsqlite3.dll");
|
|
if (!library) return 1;
|
|
open_function open = (open_function)GetProcAddress(library, "sqlite3_open_v2");
|
|
close_function close = (close_function)GetProcAddress(library, "sqlite3_close_v2");
|
|
exec_function exec = (exec_function)GetProcAddress(library, "sqlite3_exec");
|
|
prepare_function prepare = (prepare_function)GetProcAddress(library, "sqlite3_prepare_v2");
|
|
bind_function bind = (bind_function)GetProcAddress(library, "sqlite3_bind_int");
|
|
step_function step = (step_function)GetProcAddress(library, "sqlite3_step");
|
|
statement_function reset = (statement_function)GetProcAddress(library, "sqlite3_reset");
|
|
statement_function finalize = (statement_function)GetProcAddress(library, "sqlite3_finalize");
|
|
column_function column = (column_function)GetProcAddress(library, "sqlite3_column_int64");
|
|
version_function version = (version_function)GetProcAddress(library, "sqlite3_libversion");
|
|
if (!open || !close || !exec || !prepare || !bind || !step || !reset || !finalize || !column || !version) return 2;
|
|
if (version()[0] != '3' || version()[1] != '.') return 3;
|
|
char path[MAX_PATH];
|
|
DWORD length = GetTempPathA(MAX_PATH - 16, path);
|
|
if (!length) return 4;
|
|
lstrcpyA(path + length, "raven-sqlite.db");
|
|
DeleteFileA(path);
|
|
sqlite3 *database = NULL;
|
|
if (open(path, &database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK || !database) return 5;
|
|
if (exec(database, "CREATE TABLE numbers(value INTEGER NOT NULL); BEGIN", NULL, NULL, NULL) != SQLITE_OK) return 6;
|
|
sqlite3_stmt *insert = NULL;
|
|
if (prepare(database, "INSERT INTO numbers VALUES (?1)", -1, &insert, NULL) != SQLITE_OK || !insert) return 7;
|
|
for (int value = 1; value <= 100; ++value)
|
|
if (bind(insert, 1, value) != SQLITE_OK || step(insert) != SQLITE_DONE || reset(insert) != SQLITE_OK) return 8;
|
|
if (finalize(insert) != SQLITE_OK || exec(database, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) return 9;
|
|
sqlite3_stmt *broken = NULL;
|
|
if (prepare(database, "SELEKT 1", -1, &broken, NULL) == SQLITE_OK || broken) return 10;
|
|
if (close(database) != SQLITE_OK) return 11;
|
|
database = NULL;
|
|
if (open(path, &database, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) return 12;
|
|
sqlite3_stmt *query = NULL;
|
|
if (prepare(database, "SELECT count(*), sum(value) FROM numbers", -1, &query, NULL) != SQLITE_OK) return 13;
|
|
if (step(query) != SQLITE_ROW || column(query, 0) != 100 || column(query, 1) != 5050 || step(query) != SQLITE_DONE) return 14;
|
|
if (finalize(query) != SQLITE_OK || close(database) != SQLITE_OK) return 15;
|
|
if (!DeleteFileA(path)) return 16;
|
|
return 0;
|
|
}
|