====== std.db.sqlite ======
SQLite3-Binding via FFI (''libsqlite3.so.0''). Alle Verbindungs- und Statement-Handles werden als ''int64''-Pointer dargestellt. Das API folgt dem Prepared-Statement-Muster: ''SQLiteStmtPrepare'' → Bind → ''SQLiteStmtStep'' → Column-Accessoren → ''SQLiteStmtFinalize''.
→ [[lyx_-_programmiersprache:units|Standard Library]] · [[lyx_-_programmiersprache:units:db:postgres|std.db.postgres]] · [[lyx_-_programmiersprache:units:db:mysql|std.db.mysql]]
----
===== Konstanten =====
==== Rückgabecodes ====
^ Konstante ^ Wert ^ Beschreibung ^
| ''SQLITE_OK'' | 0 | Erfolg |
| ''SQLITE_ERROR'' | 1 | Allgemeiner Fehler |
| ''SQLITE_BUSY'' | 5 | Datenbank ist gesperrt |
| ''SQLITE_NOTFOUND'' | 12 | Nicht gefunden |
| ''SQLITE_CONSTRAINT'' | 19 | Constraint-Verletzung (UNIQUE, NOT NULL …) |
| ''SQLITE_MISUSE'' | 21 | Falsche Verwendung der API |
| ''SQLITE_NOMEM'' | 7 | Kein Speicher verfügbar |
| ''SQLITE_ROW'' | 100 | ''SQLiteStmtStep'' liefert eine Zeile |
| ''SQLITE_DONE'' | 101 | ''SQLiteStmtStep'' hat alle Zeilen verarbeitet |
==== Spalten-Typkodes ====
^ Konstante ^ Wert ^ SQLite-Typ ^
| ''SQLITE_INTEGER'' | 1 | Ganzzahl |
| ''SQLITE_FLOAT'' | 2 | Gleitkommazahl |
| ''SQLITE_TEXT'' | 3 | Text |
| ''SQLITE_BLOB'' | 4 | Binärdaten |
| ''SQLITE_NULL'' | 5 | NULL |
==== Destruktor-Sentinels ====
^ Konstante ^ Wert ^ Beschreibung ^
| ''SQLITE_STATIC'' | 0 | SQLite kopiert die Daten nicht — Puffer muss bis Step/Reset gültig bleiben |
| ''SQLITE_TRANSIENT'' | -1 | SQLite macht eine interne Kopie sofort |
----
===== Typen =====
==== SQLiteDB (24 Bytes) ====
Verbindungs-Handle. Immer über ''SQLiteOpen'' erstellen und über ''SQLiteClose'' freigeben.
==== SQLiteStmt (24 Bytes) ====
Prepared-Statement-Handle. Immer über ''SQLiteStmtPrepare'' erstellen und über ''SQLiteStmtFinalize'' freigeben.
----
===== Funktionen =====
==== Verbindung ====
Funktionen für Verbindungsaufbau und -verwaltung:
^ Signatur ^ Beschreibung ^
| ''SQLiteOpen(path: pchar): int64'' | Öffnet oder erstellt eine SQLite-Datenbank. ''„:memory:"'' für In-Memory-DB. Gibt SQLiteDB-Pointer zurück; 0 bei Fehler |
| ''SQLiteClose(db: int64): void'' | Schließt Verbindung und gibt SQLiteDB-Speicher frei |
| ''SQLiteExec(db: int64, sql: pchar): bool'' | Führt SQL ohne Ergebnismenge aus (CREATE TABLE, INSERT ohne Bind, PRAGMA …). Gibt ''true'' bei Erfolg |
| ''SQLiteExecParam(db: int64, sql: pchar, params: int64, nparams: int64): bool'' | Führt parametrisiertes SQL mit String-Parametern aus. ''params'': Zeiger auf Array von ''nparams'' pchar-Pointern |
| ''SQLiteErrmsg(db: int64): pchar'' | Fehlermeldung der letzten Operation |
| ''SQLiteErrno(db: int64): int64'' | Fehlercode der letzten Operation |
==== Prepared Statements ====
Funktionen für Prepared Statements:
^ Signatur ^ Beschreibung ^
| ''SQLiteStmtPrepare(db: int64, sql: pchar): int64'' | Kompiliert SQL zu einem Prepared Statement. Gibt SQLiteStmt-Pointer zurück; 0 bei Fehler |
| ''SQLiteStmtStep(stmt: int64): int64'' | Führt einen Schritt aus. Gibt ''SQLITE_ROW'' (Zeile verfügbar), ''SQLITE_DONE'' (fertig) oder Fehlercode zurück |
| ''SQLiteStmtReset(stmt: int64): void'' | Setzt Statement zurück — Bindings bleiben erhalten, für Re-Execution mit neuen Werten |
| ''SQLiteStmtFinalize(stmt: int64): void'' | Gibt Statement-Speicher frei |
| ''SQLiteClearBindings(stmt: int64): void'' | Setzt alle Bindings auf NULL zurück |
==== Parameter-Binding (1-basierter Index) ====
^ Signatur ^ Beschreibung ^
| ''SQLiteBindInt(stmt: int64, i: int64, v: int64): bool'' | Bindet ''int64'' an Parameter ''i'' |
| ''SQLiteBindFloat(stmt: int64, i: int64, v: f64): bool'' | Bindet ''f64'' an Parameter ''i'' |
| ''SQLiteBindStr(stmt: int64, i: int64, v: pchar): bool'' | Bindet null-terminierten String an Parameter ''i'' (SQLITE_STATIC — Puffer bis Step/Reset gültig halten) |
| ''SQLiteBindNull(stmt: int64, i: int64): bool'' | Bindet NULL an Parameter ''i'' |
| ''SQLiteBindBlob(stmt: int64, i: int64, ptr: int64, len: int64): bool'' | Bindet Binärdaten an Parameter ''i'' (SQLITE_STATIC) |
==== Column-Accessoren (0-basierter Index) ====
^ Signatur ^ Beschreibung ^
| ''SQLiteColumnInt(stmt: int64, i: int64): int64'' | INTEGER-Spalte lesen |
| ''SQLiteColumnFloat(stmt: int64, i: int64): f64'' | REAL-Spalte lesen |
| ''SQLiteColumnText(stmt: int64, i: int64): pchar'' | TEXT-Spalte lesen — Pointer bis zum nächsten Step/Reset/Finalize gültig |
| ''SQLiteColumnBlob(stmt: int64, i: int64): int64'' | BLOB-Spalte — Rohzeiger auf Daten (0 wenn NULL) |
| ''SQLiteColumnBytes(stmt: int64, i: int64): int64'' | Länge der BLOB- oder TEXT-Spalte in Bytes |
| ''SQLiteColumnType(stmt: int64, i: int64): int64'' | Typ-Code (SQLITE_INTEGER / SQLITE_FLOAT / SQLITE_TEXT / SQLITE_BLOB / SQLITE_NULL) |
| ''SQLiteColumnIsNull(stmt: int64, i: int64): bool'' | Gibt ''true'' zurück wenn die Spalte NULL ist |
| ''SQLiteColumnCount(stmt: int64): int64'' | Anzahl Spalten im Ergebnis |
| ''SQLiteColumnName(stmt: int64, i: int64): pchar'' | Spaltenname (0-basiert) |
==== Transaktionen ====
Transaktionsverwaltung:
^ Signatur ^ Beschreibung ^
| ''SQLiteBegin(db: int64): bool'' | Startet eine Transaktion (BEGIN TRANSACTION) |
| ''SQLiteCommit(db: int64): bool'' | Schreibt die Transaktion fest (COMMIT) |
| ''SQLiteRollback(db: int64): bool'' | Macht die Transaktion rückgängig (ROLLBACK) |
| ''SQLiteBeginImmediate(db: int64): bool'' | Transaktion mit sofortigem Schreib-Lock |
| ''SQLiteBeginExclusive(db: int64): bool'' | Exklusive Transaktion (kein anderer Leser/Schreiber) |
| ''SQLiteInTransaction(db: int64): bool'' | Gibt ''true'' zurück wenn eine Transaktion aktiv ist |
==== Hilfsfunktionen & Metadaten ====
^ Signatur ^ Beschreibung ^
| ''SQLiteLastInsertId(db: int64): int64'' | Rowid des letzten erfolgreichen INSERT |
| ''SQLiteChanges(db: int64): int64'' | Anzahl betroffener Zeilen des letzten INSERT/UPDATE/DELETE |
| ''SQLiteTableExists(db: int64, table: pchar): bool'' | Gibt ''true'' zurück wenn die Tabelle in ''sqlite_master'' existiert |
| ''SQLiteDropTable(db: int64, table: pchar): bool'' | Führt ''DROP TABLE IF EXISTS'' aus (mit Identifier-Validierung) |
| ''SQLiteVacuum(db: int64): bool'' | Gibt ungenutzten Speicher in der DB-Datei frei |
| ''SQLiteSetJournalMode(db: int64, mode: pchar): bool'' | Setzt den Journal-Modus: ''„WAL"'', ''„DELETE"'', ''„TRUNCATE"'', ''„PERSIST"'', ''„MEMORY"'', ''„OFF"'' |
| ''SQLiteSetCacheSize(db: int64, pages: int64): bool'' | Setzt Cache-Größe in Seiten (PRAGMA cache_size) |
----
===== Verwendung =====
==== Tabelle erstellen und Daten einfügen ====
import std.db.sqlite;
import std.io;
fn SetupDB(): int64 {
var db := SQLiteOpen("/tmp/test.db");
if (db == 0) { return 0; }
SQLiteExec(db, "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)");
return db;
}
fn InsertUser(db: int64, name: pchar, age: int64): void {
var stmt := SQLiteStmtPrepare(db, "INSERT INTO users (name, age) VALUES (?, ?)");
SQLiteBindStr(stmt, 1, name);
SQLiteBindInt(stmt, 2, age);
SQLiteStmtStep(stmt);
SQLiteStmtFinalize(stmt);
}
==== SELECT mit Prepared Statement ====
import std.db.sqlite;
import std.io;
fn PrintUsers(db: int64): void {
var stmt := SQLiteStmtPrepare(db, "SELECT id, name, age FROM users ORDER BY name");
while (SQLiteStmtStep(stmt) == SQLITE_ROW) {
PrintLn(IntToStr(SQLiteColumnInt(stmt, 0)) + ": " + SQLiteColumnText(stmt, 1) + " (" + IntToStr(SQLiteColumnInt(stmt, 2)) + ")");
}
SQLiteStmtFinalize(stmt);
}
==== Transaktion mit Rollback ====
import std.db.sqlite;
fn BulkInsert(db: int64, names: int64, count: int64): bool {
SQLiteBegin(db);
var stmt := SQLiteStmtPrepare(db, "INSERT INTO users (name) VALUES (?)");
var i: int64 := 0;
var ok: bool := true;
while (i < count) {
var name: pchar := peek64(names + i * 8) as pchar;
SQLiteBindStr(stmt, 1, name);
var rc := SQLiteStmtStep(stmt);
if (rc != SQLITE_DONE) { ok := false; break; }
SQLiteStmtReset(stmt);
i := i + 1;
}
SQLiteStmtFinalize(stmt);
if (ok) {
SQLiteCommit(db);
} else {
SQLiteRollback(db);
}
return ok;
}
==== In-Memory-Datenbank ====
import std.db.sqlite;
fn TempDB(): int64 {
var db := SQLiteOpen(":memory:");
SQLiteExec(db, "CREATE TABLE tmp (k TEXT, v TEXT)");
SQLiteSetJournalMode(db, "OFF"); // kein Journal für In-Memory nötig
return db;
}
==== WAL-Modus für Concurrent Reads ====
import std.db.sqlite;
fn OpenWAL(path: pchar): int64 {
var db := SQLiteOpen(path);
SQLiteSetJournalMode(db, "WAL");
SQLiteSetCacheSize(db, 2000); // 2000 Seiten ≈ 8 MB bei 4096 Bytes/Seite
return db;
}
----
===== Hinweise =====
* Parameter-Indizes bei Binding sind **1-basiert**, Column-Indizes bei Accessoren sind **0-basiert**.
* ''SQLiteBindStr'' verwendet ''SQLITE_STATIC'' — der String-Puffer muss bis zum nächsten ''SQLiteStmtStep'', ''SQLiteStmtReset'' oder ''SQLiteStmtFinalize'' gültig bleiben.
* ''SQLiteColumnText'' gibt einen Pointer auf SQLite-internen Speicher zurück — nicht nach ''Step''/''Reset''/''Finalize'' verwenden.
* Für schreibintensive Workloads: WAL-Modus aktivieren (''SQLiteSetJournalMode(db, "WAL")'') und mehrere INSERT in Transaktionen bündeln.
* ''SQLiteDropTable'' validiert den Tabellennamen auf erlaubte Zeichen (A-Z, a-z, 0-9, _, .) — schützt vor SQL-Injection.
----
===== Verwandte Units =====
* ''[[lyx_-_programmiersprache:units:db:postgres|std.db.postgres]]'' — PostgreSQL (natives Wire-Protokoll)
* ''[[lyx_-_programmiersprache:units:db:mysql|std.db.mysql]]'' — MySQL/MariaDB
* ''[[lyx_-_programmiersprache:units:db:redis|std.db.redis]]'' — Redis Key-Value-Store
Letzte Aktualisierung: 2026-06-05