New features: - Blob I/O: Incremental read/write for large BLOBs - Blob.open(), close(), deinit() - Blob.read(), write() with offset support - Blob.bytes(), reopen(), readAll() - Hooks: Monitor database changes - setCommitHook() - called on transaction commit - setRollbackHook() - called on transaction rollback - setUpdateHook() - called on INSERT/UPDATE/DELETE - clearHooks() - remove all hooks - UpdateOperation enum (insert, update, delete) - Aggregate Functions: Custom multi-row aggregates - createAggregateFunction(name, num_args, step_fn, final_fn) - AggregateContext with getAggregateContext() for state management - Support for setNull/Int/Float/Text/Blob/Error results Documentation: - Updated docs/API.md to v0.4 with new features and examples - Updated docs/CGO_PARITY_ANALYSIS.md - Fase 3A marked complete - Updated CLAUDE.md to v0.4 with all new implementations Tests: 28 total (8 new tests for Fase 3A features) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
15 KiB
15 KiB
zsqlite - SQLite Wrapper para Zig
Ultima actualizacion: 2025-12-08 Lenguaje: Zig 0.15.2 Estado: v0.4 - Fase 3A completada Inspiracion: CGo go-sqlite3, SQLite C API
Descripcion del Proyecto
zsqlite es un wrapper idiomatico de SQLite para Zig que compila SQLite amalgamation directamente en el binario, resultando en un ejecutable unico sin dependencias externas.
Filosofia:
- Zero dependencias runtime
- API idiomatica Zig (errores, allocators, iteradores)
- Binario unico y portable
- Compatible con bases de datos SQLite existentes
- Calidad open source (doc comments, codigo claro)
Objetivo: Ser el pilar para trabajar con databases en Zig con codigo 100% propio, replicando toda la funcionalidad de wrappers maduros como CGo go-sqlite3.
Estado Actual del Proyecto
Implementacion v0.4 (Fase 3A Completada)
| Componente | Estado | Archivo |
|---|---|---|
| Core | ||
| Database open/close | ✅ | src/root.zig |
| Database open with flags | ✅ | src/root.zig |
| exec() SQL simple | ✅ | src/root.zig |
| execAlloc() runtime strings | ✅ | src/root.zig |
| Error mapping completo | ✅ | src/root.zig |
| Prepared Statements | ||
| prepare/finalize | ✅ | src/root.zig |
| prepareAlloc() runtime strings | ✅ | src/root.zig |
| reset/clearBindings | ✅ | src/root.zig |
| step() iteration | ✅ | src/root.zig |
| sql() / isReadOnly() | ✅ | src/root.zig |
| parameterCount/Index/Name | ✅ | src/root.zig |
| Bind Parameters | ||
| bindNull | ✅ | src/root.zig |
| bindInt (i64) | ✅ | src/root.zig |
| bindFloat (f64) | ✅ | src/root.zig |
| bindText | ✅ | src/root.zig |
| bindBlob | ✅ | src/root.zig |
| bindBool | ✅ | src/root.zig |
| bindZeroblob | ✅ | src/root.zig |
| Named Parameters | ||
| bindNullNamed | ✅ | src/root.zig |
| bindIntNamed | ✅ | src/root.zig |
| bindFloatNamed | ✅ | src/root.zig |
| bindTextNamed | ✅ | src/root.zig |
| bindBlobNamed | ✅ | src/root.zig |
| bindBoolNamed | ✅ | src/root.zig |
| Column Access | ||
| columnCount | ✅ | src/root.zig |
| columnName | ✅ | src/root.zig |
| columnType | ✅ | src/root.zig |
| columnInt | ✅ | src/root.zig |
| columnFloat | ✅ | src/root.zig |
| columnText | ✅ | src/root.zig |
| columnBlob | ✅ | src/root.zig |
| columnIsNull | ✅ | src/root.zig |
| columnBool | ✅ | src/root.zig |
| columnBytes | ✅ | src/root.zig |
| columnDeclType | ✅ | src/root.zig |
| Transacciones | ||
| begin/commit/rollback | ✅ | src/root.zig |
| beginImmediate | ✅ | src/root.zig |
| beginExclusive | ✅ | src/root.zig |
| Savepoints | ||
| savepoint(name) | ✅ | src/root.zig |
| release(name) | ✅ | src/root.zig |
| rollbackTo(name) | ✅ | src/root.zig |
| Pragmas/Config | ||
| setBusyTimeout | ✅ | src/root.zig |
| setJournalMode | ✅ | src/root.zig |
| setSynchronous | ✅ | src/root.zig |
| enableWalMode | ✅ | src/root.zig |
| setForeignKeys | ✅ | src/root.zig |
| ATTACH/DETACH | ||
| attach(file, schema) | ✅ | src/root.zig |
| attachMemory(schema) | ✅ | src/root.zig |
| detach(schema) | ✅ | src/root.zig |
| listDatabases() | ✅ | src/root.zig |
| Backup API | ||
| Backup.init/initMain | ✅ | src/root.zig |
| Backup.step/stepAll | ✅ | src/root.zig |
| Backup.finish/deinit | ✅ | src/root.zig |
| Backup.remaining/pageCount | ✅ | src/root.zig |
| Backup.progress | ✅ | src/root.zig |
| backupDatabase() | ✅ | src/root.zig |
| backupToFile() | ✅ | src/root.zig |
| loadFromFile() | ✅ | src/root.zig |
| User-Defined Functions | ||
| createScalarFunction() | ✅ | src/root.zig |
| removeFunction() | ✅ | src/root.zig |
| FunctionContext (setInt/Float/Text/etc) | ✅ | src/root.zig |
| FunctionValue (asInt/Float/Text/etc) | ✅ | src/root.zig |
| Custom Collations | ||
| createCollation() | ✅ | src/root.zig |
| removeCollation() | ✅ | src/root.zig |
| Aggregate Functions | ||
| createAggregateFunction() | ✅ | src/root.zig |
| AggregateContext | ✅ | src/root.zig |
| Blob I/O | ||
| Blob.open/openAlloc | ✅ | src/root.zig |
| Blob.read/write | ✅ | src/root.zig |
| Blob.bytes | ✅ | src/root.zig |
| Blob.reopen | ✅ | src/root.zig |
| Blob.readAll | ✅ | src/root.zig |
| Hooks | ||
| setCommitHook | ✅ | src/root.zig |
| setRollbackHook | ✅ | src/root.zig |
| setUpdateHook | ✅ | src/root.zig |
| clearHooks | ✅ | src/root.zig |
| Utilidades | ||
| lastInsertRowId | ✅ | src/root.zig |
| changes/totalChanges | ✅ | src/root.zig |
| errorMessage | ✅ | src/root.zig |
| errorCode/extendedErrorCode | ✅ | src/root.zig |
| interrupt | ✅ | src/root.zig |
| isReadOnly | ✅ | src/root.zig |
| filename | ✅ | src/root.zig |
| version/versionNumber | ✅ | src/root.zig |
Tests
| Categoria | Tests | Estado |
|---|---|---|
| Version | 1 | ✅ |
| Open/Close | 1 | ✅ |
| Create/Insert | 1 | ✅ |
| Prepared Statements | 1 | ✅ |
| Select Query | 1 | ✅ |
| Transaction Commit | 1 | ✅ |
| Transaction Rollback | 1 | ✅ |
| Foreign Keys | 1 | ✅ |
| Null Values | 1 | ✅ |
| Blob Data | 1 | ✅ |
| Named Parameters | 1 | ✅ |
| Savepoints | 1 | ✅ |
| Busy Timeout | 1 | ✅ |
| Statement Metadata | 1 | ✅ |
| Boolean bind/column | 1 | ✅ |
| Backup memory to memory | 1 | ✅ |
| Backup convenience | 1 | ✅ |
| ATTACH/DETACH | 1 | ✅ |
| User-defined functions | 1 | ✅ |
| Custom collations | 1 | ✅ |
| Blob I/O | 3 | ✅ |
| Hooks | 3 | ✅ |
| Aggregate functions | 2 | ✅ |
| Total | 28 | ✅ |
Roadmap
Fase 1 - Core (COMPLETADO)
- Estructura proyecto
- Compilar SQLite amalgamation
- Abrir/cerrar bases de datos
- Ejecutar SQL simple (exec)
- Prepared statements basicos
- Bind de parametros (int, text, blob, null, float)
- Iterador de resultados
- Transacciones basicas
Fase 2A - Paridad CGo Core (COMPLETADO)
- SAVEPOINT support
- Named parameters (:name, @name, $name)
- Busy timeout
- WAL mode helpers
- Statement metadata (sql, isReadOnly, parameterCount)
- Boolean bind/column
- Error codes (errorCode, extendedErrorCode)
- Database info (isReadOnly, filename)
- interrupt()
Fase 2B - Paridad CGo Avanzada (COMPLETADO)
- Backup API completo
- User-defined functions (scalar)
- Collations personalizadas
- ATTACH/DETACH databases
- Batch bind con tuples/structs
- Row iterator idiomatico
Fase 3A - Avanzado (COMPLETADO)
- Blob streaming (para archivos grandes)
- User-defined functions (aggregate)
- Update/Commit/Rollback hooks
Fase 3B - Avanzado (EN PROGRESO)
- Authorizer callback
- Progress handler
- Pre-update hook
- Window functions
- Busy handler (custom callback)
- Batch bind con tuples/structs
- Row iterator idiomatico
- Connection pooling
Fase 4 - Extras
- Connection URI parsing
- Virtual tables
- FTS5 helpers
- JSON1 helpers
- R-Tree helpers
Arquitectura
Estructura de Archivos
zsqlite/
├── CLAUDE.md # Este archivo - estado del proyecto
├── build.zig # Sistema de build
├── src/
│ └── root.zig # Wrapper principal (~1000 lineas)
├── vendor/
│ ├── sqlite3.c # SQLite 3.47.2 amalgamation
│ ├── sqlite3.h # Headers SQLite
│ ├── sqlite3ext.h # Extension headers
│ └── shell.c # SQLite shell (no usado)
├── examples/
│ └── basic.zig # Ejemplo basico funcional
└── docs/
├── ARCHITECTURE.md # Diseno interno
├── API.md # Referencia rapida API
└── CGO_PARITY_ANALYSIS.md # Analisis de paridad con go-sqlite3
SQLite Amalgamation
Version: SQLite 3.47.2
Flags de compilacion:
-DSQLITE_DQS=0 # Disable double-quoted strings
-DSQLITE_THREADSAFE=0 # Single-threaded (mas rapido)
-DSQLITE_DEFAULT_MEMSTATUS=0 # Disable memory tracking
-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS
-DSQLITE_OMIT_DEPRECATED
-DSQLITE_OMIT_SHARED_CACHE
-DSQLITE_ENABLE_FTS5 # Full-text search
-DSQLITE_ENABLE_JSON1 # JSON functions
-DSQLITE_ENABLE_RTREE # R-Tree geospatial
-DSQLITE_OMIT_LOAD_EXTENSION # No dynamic extensions
API Actual
Abrir Base de Datos
const sqlite = @import("zsqlite");
// In-memory
var db = try sqlite.openMemory();
defer db.close();
// Archivo
var db = try sqlite.open("test.db");
defer db.close();
// Con flags
var db = try sqlite.Database.openWithFlags("test.db", .{
.read_only = true,
.create = false,
});
defer db.close();
Ejecutar SQL Simple
try db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)");
try db.exec("INSERT INTO users (name) VALUES ('Alice')");
// Con string runtime
try db.execAlloc(allocator, sql_string);
Prepared Statements
var stmt = try db.prepare("INSERT INTO users (name, age) VALUES (?, ?)");
defer stmt.finalize();
try stmt.bindText(1, "Bob");
try stmt.bindInt(2, 30);
_ = try stmt.step();
// Reusar
try stmt.reset();
try stmt.clearBindings();
try stmt.bindText(1, "Charlie");
try stmt.bindInt(2, 25);
_ = try stmt.step();
Named Parameters (NUEVO v0.2)
var stmt = try db.prepare("INSERT INTO users (name, age) VALUES (:name, :age)");
defer stmt.finalize();
try stmt.bindTextNamed(":name", "Alice");
try stmt.bindIntNamed(":age", 30);
_ = try stmt.step();
// Tambien soporta @name y $name estilos
Queries
var stmt = try db.prepare("SELECT id, name FROM users ORDER BY id");
defer stmt.finalize();
while (try stmt.step()) {
const id = stmt.columnInt(0);
const name = stmt.columnText(1) orelse "(null)";
std.debug.print("User {}: {s}\n", .{ id, name });
}
Transacciones
try db.begin();
errdefer db.rollback() catch {};
try db.exec("INSERT INTO users (name) VALUES ('Alice')");
try db.exec("INSERT INTO users (name) VALUES ('Bob')");
try db.commit();
Savepoints (NUEVO v0.2)
const allocator = std.heap.page_allocator;
try db.begin();
try db.savepoint(allocator, "sp1");
try db.exec("INSERT INTO test VALUES (1)");
// Revertir al savepoint
try db.rollbackTo(allocator, "sp1");
// O confirmar el savepoint
try db.release(allocator, "sp1");
try db.commit();
WAL Mode (NUEVO v0.2)
const allocator = std.heap.page_allocator;
// Habilitar WAL mode con settings recomendados
try db.enableWalMode(allocator);
// O configurar individualmente
try db.setJournalMode(allocator, "WAL");
try db.setSynchronous(allocator, "NORMAL");
try db.setBusyTimeout(5000); // 5 segundos
Foreign Keys
try db.setForeignKeys(true);
Comandos
# Zig path
ZIG=/mnt/cello2/arno/re/recode/zig/zig-0.15.2/zig-x86_64-linux-0.15.2/zig
# Compilar
$ZIG build
# Tests
$ZIG build test
# Ejecutar ejemplo
$ZIG build basic && ./zig-out/bin/basic
Equipo y Metodologia
Normas de Trabajo Centralizadas
IMPORTANTE: Todas las normas de trabajo estan en:
/mnt/cello2/arno/re/recode/TEAM_STANDARDS/
Archivos clave a leer:
LAST_UPDATE.md- LEER PRIMERO - Cambios recientes en normasNORMAS_TRABAJO_CONSENSUADAS.md- Metodologia fundamentalQUICK_REFERENCE.md- Cheat sheet rapido
Estandares Zig Open Source (Seccion #24)
- Claridad: Codigo autoexplicativo, nombres descriptivos
- Doc comments:
///en todas las funciones publicas - Idiomatico: snake_case, error handling explicito
- Sin magia: Preferir codigo explicito sobre abstracciones complejas
Control de Versiones
# Remote
git remote: git@git.reugenio.com:reugenio/zsqlite.git
# Branches
main # Codigo estable
Referencias
CGo go-sqlite3 (Referencia principal)
- Repo: https://github.com/mattn/go-sqlite3
- Objetivo: Replicar toda su funcionalidad en Zig
- Analisis:
docs/CGO_PARITY_ANALYSIS.md
SQLite C API
- Docs: https://sqlite.org/c3ref/intro.html
- Objetivo: Wrapper completo de funciones relevantes
Otros Wrappers Zig (Referencia)
- zig-sqlite: https://github.com/vrischmann/zig-sqlite
- zqlite.zig: https://github.com/karlseguin/zqlite.zig
Historial de Desarrollo
2025-12-08 - v0.3 (Fase 2B Completada)
- Backup API completo:
- Backup struct con init/step/finish/remaining/pageCount/progress
- Funciones de conveniencia: backupDatabase, backupToFile, loadFromFile
- User-Defined Functions (Scalar):
- createScalarFunction() para registrar funciones Zig en SQL
- FunctionContext para retornar resultados
- FunctionValue para acceder a argumentos
- Cleanup automatico con destructores
- Custom Collations:
- createCollation() para orden personalizado de strings
- removeCollation() para eliminar collations
- ATTACH/DETACH Databases:
- attach(), attachMemory(), detach()
- listDatabases() para enumerar schemas adjuntos
- 20 tests pasando
- ~1700 lineas de codigo en root.zig
2025-12-08 - v0.2 (Fase 2A Completada)
- Named parameters (:name, @name, $name)
- Savepoints (savepoint, release, rollbackTo)
- WAL mode helpers (enableWalMode, setJournalMode, setSynchronous)
- Busy timeout (setBusyTimeout)
- Statement metadata (sql, isReadOnly, parameterCount, parameterIndex, parameterName)
- Boolean bind/column (bindBool, columnBool)
- Error codes (errorCode, extendedErrorCode)
- Database info (isReadOnly, filename, interrupt)
- bindZeroblob, columnBytes, columnDeclType
- 15 tests pasando
- Documentacion docs/ creada (ARCHITECTURE.md, API.md, CGO_PARITY_ANALYSIS.md)
2025-12-08 - v0.1 (Core Funcional)
- Estructura inicial del proyecto
- SQLite 3.47.2 amalgamation compilando
- Database, Statement, Error types
- Bind parameters completos (null, int, float, text, blob)
- Column access completo
- Transacciones basicas
- 10 tests unitarios pasando
- Ejemplo basic.zig funcional
Notas de Desarrollo
Proxima Sesion
- Blob streaming (para archivos grandes)
- User-defined aggregate functions
- Update/Commit hooks
- Batch bind con comptime structs
Lecciones Aprendidas
- SQLite amalgamation compila limpiamente con Zig build system
@cImportfunciona bien para headers SQLite- SQLITE_TRANSIENT necesario para strings/blobs que Zig puede mover
- En Zig 0.15 usar
std.fmt.allocPrint+\x00manual en lugar deallocPrintZ - Named parameters funcionan con el prefijo incluido (":name", no "name")
- Callbacks C requieren
callconv(.c)y estructuras wrapper para pasar estado std.ArrayListUnmanageden Zig 0.15 (noArrayList.init)- UDFs y Collations usan page_allocator interno para simplicidad
© zsqlite - Wrapper SQLite para Zig 2025-12-08 - En desarrollo activo