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.

Standard Library · std.db.postgres · 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

Letzte Aktualisierung: 2026-06-05