# zsqlite - SQLite Wrapper para Zig > **Ultima actualizacion**: 2025-12-08 > **Lenguaje**: Zig 0.15.2 > **Estado**: v0.3 - Fase 2B 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.3 (Fase 2B 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` | | **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 | ✅ | | **Total** | **20** | ✅ | --- ## Roadmap ### Fase 1 - Core (COMPLETADO) - [x] Estructura proyecto - [x] Compilar SQLite amalgamation - [x] Abrir/cerrar bases de datos - [x] Ejecutar SQL simple (exec) - [x] Prepared statements basicos - [x] Bind de parametros (int, text, blob, null, float) - [x] Iterador de resultados - [x] Transacciones basicas ### Fase 2A - Paridad CGo Core (COMPLETADO) - [x] SAVEPOINT support - [x] Named parameters (:name, @name, $name) - [x] Busy timeout - [x] WAL mode helpers - [x] Statement metadata (sql, isReadOnly, parameterCount) - [x] Boolean bind/column - [x] Error codes (errorCode, extendedErrorCode) - [x] Database info (isReadOnly, filename) - [x] interrupt() ### Fase 2B - Paridad CGo Avanzada (COMPLETADO) - [x] Backup API completo - [x] User-defined functions (scalar) - [x] Collations personalizadas - [x] ATTACH/DETACH databases - [ ] Batch bind con tuples/structs - [ ] Row iterator idiomatico ### Fase 3 - Avanzado (EN PROGRESO) - [ ] Blob streaming (para archivos grandes) - [ ] User-defined functions (aggregate) - [ ] Authorizer callback - [ ] Progress handler - [ ] Update/Commit hooks - [ ] 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 ```zig 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 ```zig 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 ```zig 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) ```zig 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 ```zig 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 ```zig 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) ```zig 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) ```zig 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 ```zig try db.setForeignKeys(true); ``` --- ## Comandos ```bash # 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 normas - `NORMAS_TRABAJO_CONSENSUADAS.md` - Metodologia fundamental - `QUICK_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 ```bash # 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 1. Blob streaming (para archivos grandes) 2. User-defined aggregate functions 3. Update/Commit hooks 4. Batch bind con comptime structs ### Lecciones Aprendidas - SQLite amalgamation compila limpiamente con Zig build system - `@cImport` funciona bien para headers SQLite - SQLITE_TRANSIENT necesario para strings/blobs que Zig puede mover - En Zig 0.15 usar `std.fmt.allocPrint` + `\x00` manual en lugar de `allocPrintZ` - Named parameters funcionan con el prefijo incluido (":name", no "name") - Callbacks C requieren `callconv(.c)` y estructuras wrapper para pasar estado - `std.ArrayListUnmanaged` en Zig 0.15 (no `ArrayList.init`) - UDFs y Collations usan page_allocator interno para simplicidad --- **© zsqlite - Wrapper SQLite para Zig** *2025-12-08 - En desarrollo activo*