zcatsql/docs/API.md
reugenio c5e6cec4a6 refactor: rename zsqlite to zcatsql
Consistent naming with zcat ecosystem (zcatui, zcatgui, zcatsql).
All lowercase per Zig naming conventions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-09 02:19:52 +01:00

28 KiB

zcatsql - API Reference

Version: 0.6 Ultima actualizacion: 2025-12-08

Quick Reference

const sqlite = @import("zcatsql");

// Abrir base de datos
var db = try sqlite.openMemory();          // In-memory
var db = try sqlite.open("file.db");       // Archivo
var db = try sqlite.openUri("file:test.db?mode=ro");  // URI
defer db.close();

// Connection pool
var pool = try sqlite.ConnectionPool.init(alloc, "file:db?cache=shared", 10);
defer pool.deinit();
const conn = try pool.acquire();
defer pool.release(conn);

// SQL directo
try db.exec("CREATE TABLE ...");

// Prepared statement
var stmt = try db.prepare("SELECT * FROM users WHERE id = ?");
defer stmt.finalize();
try stmt.bindInt(1, 42);
while (try stmt.step()) {
    const name = stmt.columnText(1);
}

// Named parameters
var stmt = try db.prepare("INSERT INTO users VALUES (:name, :age)");
try stmt.bindTextNamed(":name", "Alice");
try stmt.bindIntNamed(":age", 30);

// Transacciones
try db.begin();
// ... operaciones ...
try db.commit();  // o db.rollback()

// Savepoints
try db.savepoint(allocator, "sp1");
try db.rollbackTo(allocator, "sp1");
try db.release(allocator, "sp1");

// Backup
try sqlite.backupToFile(&db, "backup.db");
var restored = try sqlite.loadFromFile("backup.db");

// User-defined functions
try db.createScalarFunction("double", 1, myDoubleFunc);
try db.createAggregateFunction("sum_squares", 1, stepFn, finalFn);
try db.createWindowFunction("running_sum", 1, stepFn, finalFn, valueFn, inverseFn);

// Custom collations
try db.createCollation("NOCASE2", myCaseInsensitiveCompare);

// Blob I/O
var blob = try sqlite.Blob.open(&db, "main", "table", "column", rowid, true);
defer blob.deinit();
try blob.write(data, 0);
try blob.read(&buffer, 0);

// Hooks
try db.setCommitHook(myCommitHook);
try db.setUpdateHook(myUpdateHook);
try db.setPreUpdateHook(myPreUpdateHook);
try db.setAuthorizer(myAuthorizer);
try db.setProgressHandler(1000, myProgress);

// Timestamp binding
try stmt.bindTimestamp(1, unix_timestamp);
try stmt.bindCurrentTime(1);

// Limits
const old = db.setLimit(.sql_length, 10000);
const current = db.getLimit(.sql_length);

// Pragmas adicionales
try db.setAutoVacuum(alloc, "full");
try db.setCacheSize(alloc, 10000);
try db.setLockingMode(alloc, "exclusive");

// Maintenance
try db.vacuum();
try db.optimize();
const result = try db.integrityCheck(alloc);

Funciones de Modulo

open

pub fn open(path: [:0]const u8) Error!Database

Abre una base de datos SQLite.

Parametros:

  • path: Ruta al archivo. Usar ":memory:" para base de datos en memoria.

Retorna: Database o error.


openMemory

pub fn openMemory() Error!Database

Abre una base de datos en memoria.


version / versionNumber

pub fn version() []const u8
pub fn versionNumber() i32

Retorna la version de SQLite como string ("3.47.2") o numero (3047002).


backupDatabase

pub fn backupDatabase(dest_db: *Database, source_db: *Database) Error!void

Copia una base de datos completa a otra.


backupToFile

pub fn backupToFile(source_db: *Database, path: [:0]const u8) Error!void

Guarda una base de datos a un archivo.


loadFromFile

pub fn loadFromFile(path: [:0]const u8) Error!Database

Carga una base de datos desde archivo a memoria.


Database

Apertura y Cierre

Funcion Descripcion
open(path) Abre conexion (read-write, create)
openWithFlags(path, flags) Abre con flags especificos
openUri(uri) Abre con URI (file:path?mode=ro&cache=shared)
openUriAlloc(alloc, uri) openUri con string runtime
close() Cierra la conexion

Ejecucion SQL

Funcion Descripcion
exec(sql) Ejecuta SQL sin resultados
execAlloc(alloc, sql) exec con string runtime
prepare(sql) Crea prepared statement
prepareAlloc(alloc, sql) prepare con string runtime

Transacciones

Funcion Descripcion
begin() Inicia transaccion (DEFERRED)
beginImmediate() Inicia con lock inmediato
beginExclusive() Inicia con lock exclusivo
commit() Confirma transaccion
rollback() Revierte transaccion

Savepoints

pub fn savepoint(self: *Database, allocator: Allocator, name: []const u8) !void
pub fn release(self: *Database, allocator: Allocator, name: []const u8) !void
pub fn rollbackTo(self: *Database, allocator: Allocator, name: []const u8) !void

Savepoints permiten transacciones anidadas.

Ejemplo:

try db.begin();
try db.savepoint(alloc, "sp1");
try db.exec("INSERT ...");
try db.rollbackTo(alloc, "sp1");  // Revierte INSERT
try db.release(alloc, "sp1");
try db.commit();

Configuracion

Funcion Descripcion
setForeignKeys(enabled) Habilita/deshabilita FKs
setBusyTimeout(ms) Timeout en ms para locks
setJournalMode(alloc, mode) "WAL", "DELETE", etc
setSynchronous(alloc, mode) "OFF", "NORMAL", "FULL"
enableWalMode(alloc) WAL + NORMAL sync
setAutoVacuum(alloc, mode) "none", "full", "incremental"
setCacheSize(alloc, size) Tamano de cache en KB
setCaseSensitiveLike(enabled) LIKE case-sensitive
setDeferForeignKeys(enabled) Diferir FK checks
setLockingMode(alloc, mode) "normal", "exclusive"
setQueryOnly(enabled) Solo lectura
setRecursiveTriggers(enabled) Triggers recursivos
setSecureDelete(enabled) Borrado seguro
setPageSize(alloc, size) Tamano de pagina
setMaxPageCount(alloc, count) Max paginas
setTempStore(alloc, mode) "default", "file", "memory"
setWalAutoCheckpoint(alloc, n) Checkpoint cada N paginas

Maintenance

Funcion Descripcion
vacuum() Compacta la base de datos
incrementalVacuum(alloc, pages) Vacuum incremental
optimize() Optimiza indices
integrityCheck(alloc) Verifica integridad
quickCheck(alloc) Verificacion rapida
walCheckpoint(alloc, mode) Checkpoint WAL

ATTACH/DETACH

pub fn attach(self: *Database, alloc: Allocator, path: []const u8, schema: []const u8) !void
pub fn attachMemory(self: *Database, alloc: Allocator, schema: []const u8) !void
pub fn detach(self: *Database, alloc: Allocator, schema: []const u8) !void
pub fn listDatabases(self: *Database, alloc: Allocator) ![][]const u8
pub fn freeDatabaseList(alloc: Allocator, list: [][]const u8) void

Ejemplo:

try db.attachMemory(alloc, "cache");
try db.exec("CREATE TABLE cache.items (...)");
// SELECT * FROM cache.items
try db.detach(alloc, "cache");

User-Defined Functions

pub fn createScalarFunction(
    self: *Database,
    name: [:0]const u8,
    num_args: i32,
    func: ScalarFn,
) !void

pub fn removeFunction(self: *Database, name: [:0]const u8, num_args: i32) Error!void

Ejemplo:

fn myDouble(ctx: FunctionContext, args: []const FunctionValue) void {
    if (args[0].isNull()) {
        ctx.setNull();
        return;
    }
    ctx.setInt(args[0].asInt() * 2);
}

try db.createScalarFunction("double", 1, myDouble);
// SELECT double(value) FROM table

Custom Collations

pub fn createCollation(self: *Database, name: [:0]const u8, func: CollationFn) !void
pub fn removeCollation(self: *Database, name: [:0]const u8) Error!void

Ejemplo:

fn reverseOrder(a: []const u8, b: []const u8) i32 {
    return -std.mem.order(u8, a, b);
}

try db.createCollation("REVERSE", reverseOrder);
// SELECT * FROM table ORDER BY name COLLATE REVERSE

Utilidades

Funcion Descripcion
lastInsertRowId() Ultimo rowid insertado
changes() Filas modificadas (ultimo stmt)
totalChanges() Total filas desde conexion
errorMessage() Mensaje de error reciente
errorCode() Codigo de error
extendedErrorCode() Codigo extendido
interrupt() Interrumpe operacion
isReadOnly(db_name) Si DB es readonly
filename(db_name) Ruta del archivo
getLimit(limit_type) Obtener limite actual
setLimit(limit_type, val) Establecer limite

Hooks y Callbacks

Funcion Descripcion
setCommitHook(fn) Hook al commit
setRollbackHook(fn) Hook al rollback
setUpdateHook(fn) Hook a INSERT/UPDATE/DELETE
setPreUpdateHook(fn) Hook ANTES de cambios
setAuthorizer(fn) Autorizar operaciones SQL
setProgressHandler(n, fn) Callback cada N operaciones
setBusyHandler(fn) Handler personalizado de busy
clearHooks() Eliminar todos los hooks

Statement

Ciclo de Vida

Funcion Descripcion
finalize() Libera el statement
reset() Resetea para re-ejecucion
clearBindings() Limpia parametros
step() Ejecuta un paso (true=hay fila)

Metadata

Funcion Descripcion
sql() Texto SQL del statement
isReadOnly() Si es SELECT
parameterCount() Numero de parametros
parameterIndex(name) Indice de parametro named
parameterName(index) Nombre de parametro

Bind Parameters (1-indexed)

Funcion Descripcion
bindNull(idx) NULL
bindInt(idx, val) i64
bindFloat(idx, val) f64
bindText(idx, val) []const u8
bindBlob(idx, val) []const u8
bindBool(idx, val) bool (como 0/1)
bindZeroblob(idx, size) Blob de ceros

Named Parameters

Funcion Descripcion
bindNullNamed(name) :name, @name, $name
bindIntNamed(name, val)
bindFloatNamed(name, val)
bindTextNamed(name, val)
bindBlobNamed(name, val)
bindBoolNamed(name, val)
bindTimestamp(idx, ts) Unix timestamp como ISO8601
bindTimestampNamed(name, ts)
bindCurrentTime(idx) Tiempo actual como ISO8601
bindCurrentTimeNamed(name)

Column Access (0-indexed)

Funcion Descripcion
columnCount() Numero de columnas
columnName(idx) Nombre
columnType(idx) ColumnType enum
columnInt(idx) i64
columnFloat(idx) f64
columnText(idx) ?[]const u8
columnBlob(idx) ?[]const u8
columnBool(idx) bool
columnIsNull(idx) bool
columnBytes(idx) Tamano en bytes
columnDeclType(idx) Tipo declarado
columnDatabaseName(idx) Nombre de la base de datos
columnTableName(idx) Nombre de la tabla
columnOriginName(idx) Nombre original de la columna

Statement Metadata Extended

Funcion Descripcion
expandedSql(allocator) SQL con parametros expandidos

Backup

pub const Backup = struct {
    pub fn init(dest: *Database, dest_name: [:0]const u8,
                source: *Database, source_name: [:0]const u8) Error!Backup
    pub fn initMain(dest: *Database, source: *Database) Error!Backup
    pub fn step(self: *Backup, n_pages: i32) Error!bool
    pub fn stepAll(self: *Backup) Error!void
    pub fn remaining(self: *Backup) i32
    pub fn pageCount(self: *Backup) i32
    pub fn progress(self: *Backup) u8  // 0-100
    pub fn finish(self: *Backup) Error!void
    pub fn deinit(self: *Backup) void
};

Ejemplo con progreso:

var backup = try Backup.initMain(&dest_db, &source_db);
defer backup.deinit();

while (try backup.step(100)) {
    std.debug.print("Progress: {}%\n", .{backup.progress()});
}

User-Defined Functions

FunctionContext

pub const FunctionContext = struct {
    pub fn setNull(self: Self) void
    pub fn setInt(self: Self, value: i64) void
    pub fn setFloat(self: Self, value: f64) void
    pub fn setText(self: Self, value: []const u8) void
    pub fn setBlob(self: Self, value: []const u8) void
    pub fn setError(self: Self, msg: []const u8) void
};

FunctionValue

pub const FunctionValue = struct {
    pub fn getType(self: Self) ColumnType
    pub fn isNull(self: Self) bool
    pub fn asInt(self: Self) i64
    pub fn asFloat(self: Self) f64
    pub fn asText(self: Self) ?[]const u8
    pub fn asBlob(self: Self) ?[]const u8
};

ScalarFn Type

pub const ScalarFn = *const fn (ctx: FunctionContext, args: []const FunctionValue) void;

Types

OpenFlags

pub const OpenFlags = struct {
    read_only: bool = false,
    read_write: bool = true,
    create: bool = true,
    uri: bool = false,
    memory: bool = false,
    no_mutex: bool = false,
    full_mutex: bool = false,
};

ColumnType

pub const ColumnType = enum {
    integer,
    float,
    text,
    blob,
    null_value,
};

CollationFn

pub const CollationFn = *const fn (a: []const u8, b: []const u8) i32;

Retorna: negativo si a < b, cero si a == b, positivo si a > b.

Error

Mapeo completo de codigos SQLite:

Error Descripcion
SqliteError Error generico
Busy Database bloqueada
Locked Tabla bloqueada
Constraint Violacion de constraint
OutOfMemory Sin memoria
IoError Error de I/O
Corrupt DB corrupta
CantOpen No se puede abrir
ReadOnly DB es readonly
Range Parametro fuera de rango
... (25+ errores mapeados)

Ejemplos Completos

CRUD con Named Parameters

var db = try sqlite.openMemory();
defer db.close();

try db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)");

// Insert con named params
var insert = try db.prepare("INSERT INTO users (name, age) VALUES (:name, :age)");
defer insert.finalize();

try insert.bindTextNamed(":name", "Alice");
try insert.bindIntNamed(":age", 30);
_ = try insert.step();

// Query
var query = try db.prepare("SELECT * FROM users WHERE age > :min_age");
defer query.finalize();

try query.bindIntNamed(":min_age", 25);
while (try query.step()) {
    const name = query.columnText(1) orelse "(null)";
    std.debug.print("User: {s}\n", .{name});
}

Backup con Progreso

var source = try sqlite.open("production.db");
defer source.close();

var dest = try sqlite.open("backup.db");
defer dest.close();

var backup = try sqlite.Backup.initMain(&dest, &source);
defer backup.deinit();

while (try backup.step(100)) {
    const pct = backup.progress();
    std.debug.print("\rBackup: {d}%", .{pct});
}
std.debug.print("\nBackup complete!\n", .{});

UDF: String Length

fn strLen(ctx: sqlite.FunctionContext, args: []const sqlite.FunctionValue) void {
    if (args.len != 1 or args[0].isNull()) {
        ctx.setNull();
        return;
    }
    if (args[0].asText()) |text| {
        ctx.setInt(@intCast(text.len));
    } else {
        ctx.setNull();
    }
}

try db.createScalarFunction("strlen", 1, strLen);
// SELECT strlen(name) FROM users

Collation: Case-Insensitive

fn caseInsensitive(a: []const u8, b: []const u8) i32 {
    var i: usize = 0;
    while (i < a.len and i < b.len) : (i += 1) {
        const ca = std.ascii.toLower(a[i]);
        const cb = std.ascii.toLower(b[i]);
        if (ca < cb) return -1;
        if (ca > cb) return 1;
    }
    if (a.len < b.len) return -1;
    if (a.len > b.len) return 1;
    return 0;
}

try db.createCollation("ICASE", caseInsensitive);
// SELECT * FROM users ORDER BY name COLLATE ICASE

Aggregate Function: Sum of Squares

const SumState = struct {
    total: i64 = 0,
};

fn sumSquaresStep(ctx: sqlite.AggregateContext, args: []const sqlite.FunctionValue) void {
    const state = ctx.getAggregateContext(SumState) orelse return;
    if (args.len > 0 and !args[0].isNull()) {
        const val = args[0].asInt();
        state.total += val * val;
    }
}

fn sumSquaresFinal(ctx: sqlite.AggregateContext) void {
    const state = ctx.getAggregateContext(SumState) orelse {
        ctx.setNull();
        return;
    };
    ctx.setInt(state.total);
}

try db.createAggregateFunction("sum_squares", 1, sumSquaresStep, sumSquaresFinal);
// SELECT sum_squares(value) FROM numbers => 1+4+9+16+25 = 55

Blob I/O: Incremental Read/Write

// Insert placeholder blob
try db.exec("INSERT INTO files (data) VALUES (zeroblob(1024))");
const rowid = db.lastInsertRowId();

// Open for writing
var blob = try sqlite.Blob.open(&db, "main", "files", "data", rowid, true);
defer blob.deinit();

// Write data
try blob.write("Hello, World!", 0);

// Read data
var buffer: [100]u8 = undefined;
try blob.read(&buffer, 0);

Hooks: Monitor Database Changes

fn onCommit() bool {
    std.debug.print("Transaction committed!\n", .{});
    return true; // Allow commit
}

fn onUpdate(op: sqlite.UpdateOperation, db_name: []const u8, table: []const u8, rowid: i64) void {
    std.debug.print("{s} on {s}.{s} row {d}\n", .{
        @tagName(op), db_name, table, rowid
    });
}

try db.setCommitHook(onCommit);
try db.setUpdateHook(onUpdate);
// ... operations will trigger hooks ...
db.clearHooks(); // Remove all hooks

Blob

pub const Blob = struct {
    pub fn open(db: *Database, schema: [:0]const u8, table: [:0]const u8,
                column: [:0]const u8, rowid: i64, writable: bool) Error!Blob
    pub fn openAlloc(db: *Database, allocator: Allocator, ...) !Blob
    pub fn close(self: *Blob) Error!void
    pub fn deinit(self: *Blob) void
    pub fn bytes(self: *Blob) i32
    pub fn read(self: *Blob, buffer: []u8, offset: i32) Error!void
    pub fn write(self: *Blob, data: []const u8, offset: i32) Error!void
    pub fn reopen(self: *Blob, rowid: i64) Error!void
    pub fn readAll(self: *Blob, allocator: Allocator) ![]u8
};

Hooks

Types

pub const ZigCommitHookFn = *const fn () bool;
pub const ZigRollbackHookFn = *const fn () void;
pub const ZigUpdateHookFn = *const fn (
    operation: UpdateOperation,
    db_name: []const u8,
    table_name: []const u8,
    rowid: i64
) void;

pub const UpdateOperation = enum(i32) {
    insert,
    update,
    delete,
};

Database Methods

Method Description
setCommitHook(fn) Called when transaction commits
setRollbackHook(fn) Called when transaction rolls back
setUpdateHook(fn) Called on INSERT/UPDATE/DELETE
clearHooks() Remove all hooks

Aggregate Functions

Types

pub const AggregateStepFn = *const fn (ctx: AggregateContext, args: []const FunctionValue) void;
pub const AggregateFinalFn = *const fn (ctx: AggregateContext) void;

AggregateContext

pub const AggregateContext = struct {
    pub fn getAggregateContext(self: Self, comptime T: type) ?*T
    pub fn setNull(self: Self) void
    pub fn setInt(self: Self, value: i64) void
    pub fn setFloat(self: Self, value: f64) void
    pub fn setText(self: Self, value: []const u8) void
    pub fn setBlob(self: Self, value: []const u8) void
    pub fn setError(self: Self, msg: []const u8) void
};

Database Method

pub fn createAggregateFunction(
    self: *Database,
    name: [:0]const u8,
    num_args: i32,
    step_fn: AggregateStepFn,
    final_fn: AggregateFinalFn,
) !void

Authorizer

Controla que operaciones SQL estan permitidas.

Types

pub const AuthAction = enum(i32) {
    create_index, create_table, create_temp_index, create_temp_table,
    create_temp_trigger, create_temp_view, create_trigger, create_view,
    delete, drop_index, drop_table, drop_temp_index, drop_temp_table,
    drop_temp_trigger, drop_temp_view, drop_trigger, drop_view,
    insert, pragma, read, select, transaction, update,
    attach, detach, alter_table, reindex, analyze,
    create_vtable, drop_vtable, function, savepoint, recursive,
};

pub const AuthResult = enum(i32) {
    ok,     // Permitir
    deny,   // Denegar con error
    ignore, // Tratar como NULL
};

pub const ZigAuthorizerFn = *const fn (
    action: AuthAction,
    arg1: ?[]const u8,  // tabla/indice
    arg2: ?[]const u8,  // columna/trigger
    arg3: ?[]const u8,  // nombre de database
    arg4: ?[]const u8,  // trigger/view
) AuthResult;

Ejemplo

fn myAuthorizer(action: AuthAction, arg1: ?[]const u8, _, _, _) AuthResult {
    if (action == .drop_table) {
        if (arg1) |table| {
            if (std.mem.eql(u8, table, "important")) return .deny;
        }
    }
    return .ok;
}

try db.setAuthorizer(myAuthorizer);
// Ahora DROP TABLE important fallara
try db.setAuthorizer(null); // Remover

Pre-Update Hook

Hook que se ejecuta ANTES de cambios, permitiendo acceso a valores antiguos y nuevos.

Types

pub const PreUpdateContext = struct {
    pub fn columnCount(self: Self) i32
    pub fn depth(self: Self) i32         // 0=directo, 1=trigger, etc
    pub fn oldValue(self: Self, col: u32) ?FunctionValue  // UPDATE/DELETE
    pub fn newValue(self: Self, col: u32) ?FunctionValue  // UPDATE/INSERT
};

pub const ZigPreUpdateHookFn = *const fn (
    ctx: PreUpdateContext,
    operation: UpdateOperation,
    db_name: []const u8,
    table_name: []const u8,
    old_rowid: i64,
    new_rowid: i64,
) void;

Ejemplo

fn auditHook(ctx: PreUpdateContext, op: UpdateOperation, _, table: []const u8, _, _) void {
    if (op == .update) {
        // Acceder a valor antes del cambio
        if (ctx.oldValue(0)) |old| {
            const old_val = old.asInt();
            // Acceder a nuevo valor
            if (ctx.newValue(0)) |new| {
                const new_val = new.asInt();
                std.debug.print("{s}: {d} -> {d}\n", .{table, old_val, new_val});
            }
        }
    }
}

try db.setPreUpdateHook(auditHook);

Progress Handler

Callback periodico para queries de larga duracion.

pub const ZigProgressFn = *const fn () bool;  // true=continuar, false=interrumpir

Ejemplo

var should_cancel = false;

fn checkCancel() bool {
    return !should_cancel;  // false interrumpe el query
}

try db.setProgressHandler(1000, checkCancel);  // Cada 1000 operaciones VM
// Para cancelar un query largo:
// should_cancel = true;

Busy Handler

Handler personalizado para cuando la base de datos esta bloqueada.

pub const ZigBusyHandlerFn = *const fn (count: i32) bool;  // true=reintentar

Ejemplo

fn myBusyHandler(count: i32) bool {
    if (count > 10) return false;  // Fallar despues de 10 reintentos
    std.time.sleep(100_000_000);   // Esperar 100ms
    return true;                    // Reintentar
}

try db.setBusyHandler(myBusyHandler);

Limits

Control de limites de SQLite.

Limit Types

pub const Limit = enum(i32) {
    length,              // Tamano maximo de string/blob
    sql_length,          // Longitud maxima de SQL
    column,              // Columnas por tabla/query
    expr_depth,          // Profundidad de expresiones
    compound_select,     // Terminos en SELECT compuesto
    vdbe_op,            // Operaciones de VM
    function_arg,        // Argumentos de funcion
    attached,            // Databases attached
    like_pattern_length, // Patron LIKE
    variable_number,     // Variables SQL
    trigger_depth,       // Profundidad de triggers
    worker_threads,      // Threads de trabajo
};

Ejemplo

// Obtener limite actual
const sql_limit = db.getLimit(.sql_length);

// Establecer nuevo limite (retorna el anterior)
const old_limit = db.setLimit(.sql_length, 10000);

Timestamp Binding

Bind de timestamps Unix como texto ISO8601 (YYYY-MM-DD HH:MM:SS).

Funciones

pub fn bindTimestamp(self: *Statement, index: u32, ts: i64) Error!void
pub fn bindTimestampNamed(self: *Statement, name: [:0]const u8, ts: i64) Error!void
pub fn bindCurrentTime(self: *Statement, index: u32) Error!void
pub fn bindCurrentTimeNamed(self: *Statement, name: [:0]const u8) Error!void

Ejemplo

var stmt = try db.prepare("INSERT INTO events (created_at) VALUES (?)");
try stmt.bindTimestamp(1, 1705314645);  // 2024-01-15 10:30:45 UTC
// O usar tiempo actual
try stmt.bindCurrentTime(1);

Window Functions

Funciones de ventana personalizadas para queries analiticos.

Types

pub const WindowValueFn = *const fn (ctx: AggregateContext) void;
pub const WindowInverseFn = *const fn (ctx: AggregateContext, args: []const FunctionValue) void;

Database Method

pub fn createWindowFunction(
    self: *Database,
    name: [:0]const u8,
    num_args: i32,
    step_fn: AggregateStepFn,    // Agrega valor a ventana
    final_fn: AggregateFinalFn,  // Retorna resultado final
    value_fn: WindowValueFn,     // Retorna valor actual
    inverse_fn: WindowInverseFn, // Remueve valor de ventana
) !void

Ejemplo: Running Sum

const SumState = struct { total: i64 = 0 };

fn runningSumStep(ctx: AggregateContext, args: []const FunctionValue) void {
    const state = ctx.getAggregateContext(SumState) orelse return;
    if (args.len > 0 and !args[0].isNull()) {
        state.total += args[0].asInt();
    }
}

fn runningSumFinal(ctx: AggregateContext) void {
    const state = ctx.getAggregateContext(SumState) orelse {
        ctx.setNull();
        return;
    };
    ctx.setInt(state.total);
}

fn runningSumValue(ctx: AggregateContext) void {
    // Igual que final para running sum
    runningSumFinal(ctx);
}

fn runningSumInverse(ctx: AggregateContext, args: []const FunctionValue) void {
    const state = ctx.getAggregateContext(SumState) orelse return;
    if (args.len > 0 and !args[0].isNull()) {
        state.total -= args[0].asInt();
    }
}

try db.createWindowFunction("running_sum", 1,
    runningSumStep, runningSumFinal, runningSumValue, runningSumInverse);

// SELECT running_sum(value) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
// FROM numbers

Connection Pool

Pool de conexiones para aplicaciones multi-hilo.

Struct

pub const ConnectionPool = struct {
    pub fn init(allocator: Allocator, path: [:0]const u8, max_size: usize) !ConnectionPool
    pub fn deinit(self: *ConnectionPool) void
    pub fn acquire(self: *ConnectionPool) !*Database
    pub fn release(self: *ConnectionPool, conn: *Database) void
    pub fn inUseCount(self: *ConnectionPool) usize
    pub fn openCount(self: *ConnectionPool) usize
    pub fn capacity(self: *ConnectionPool) usize
};

Ejemplo

var pool = try sqlite.ConnectionPool.init(allocator, "file:app.db?cache=shared", 10);
defer pool.deinit();

// En cada thread/request:
const conn = try pool.acquire();
defer pool.release(conn);

try conn.exec("INSERT INTO logs (msg) VALUES ('Hello')");

Notas

  • El pool usa mutex para thread-safety
  • Las conexiones se crean bajo demanda (lazy)
  • Las conexiones liberadas se reutilizan
  • Usar URI con cache=shared para compartir cache entre conexiones

URI Connection String

Conexion via URI con parametros.

Funciones

pub fn openUri(uri: [:0]const u8) Error!Database
pub fn openUriAlloc(allocator: Allocator, uri: []const u8) !Database

Sintaxis URI

file:path?param1=value1&param2=value2

Parametros Soportados

Parametro Valores Descripcion
mode ro, rw, rwc, memory Modo de apertura
cache shared, private Cache compartida
psow 0, 1 Power-safe overwrite
nolock 1 Sin locking
immutable 1 Base inmutable

Ejemplos

// Solo lectura
var db = try sqlite.openUri("file:data.db?mode=ro");

// Memoria compartida (para pools)
var db = try sqlite.openUri("file::memory:?cache=shared");

// Read-write, crear si no existe
var db = try sqlite.openUri("file:app.db?mode=rwc");

// Base inmutable (sin journal)
var db = try sqlite.openUri("file:static.db?immutable=1");

© zcatsql v0.6 - API Reference 2025-12-08