Comenzando con Fast SQL
Esta guía te ayudará a instalar y configurar el plugin @capgo/capacitor-fast-sql para acceso de base de datos SQLite de alto rendimiento.
¿Por qué Fast SQL?
Section titled “¿Por qué Fast SQL?”Los plugins SQLite tradicionales para Capacitor dependen del puente JavaScript estándar para comunicarse entre tu código web y el código nativo. Aunque esto funciona bien para operaciones pequeñas, el puente se convierte en un cuello de botella significativo cuando necesitas transferir grandes cantidades de datos. Cada dato debe serializarse a JSON, enviarse a través del puente y luego deserializarse del otro lado. Esta sobrecarga de serialización hace que las operaciones con miles de filas o datos binarios grandes sean increíblemente lentas.
Fast SQL resuelve este problema estableciendo un servidor HTTP local en el dispositivo que se comunica directamente con la base de datos SQLite nativa. Este protocolo personalizado evita completamente el puente de Capacitor, eliminando la sobrecarga de serialización y habilitando:
- Hasta 25 veces más rendimiento para operaciones por lotes y grandes conjuntos de datos
- Transferencia eficiente de datos binarios sin codificación base64
- Transmisión de resultados grandes sin problemas de memoria
- Rendimiento óptimo para sistemas de sincronización como CRDTs y transformaciones operacionales
Esto hace que Fast SQL sea ideal para aplicaciones local-first, sistemas de sincronización sin conexión y escenarios donde necesitas reemplazar IndexedDB con una solución más confiable y de mejor rendimiento.
Instalación
Section titled “Instalación”npm install @capgo/capacitor-fast-sqlnpx cap syncConfiguración de plataforma
Section titled “Configuración de plataforma”Configuración de iOS
Section titled “Configuración de iOS”Agrega lo siguiente a tu Info.plist para permitir redes locales:
<key>NSAppTransportSecurity</key><dict> <key>NSAllowsLocalNetworking</key> <true/></dict>Configuración de Android
Section titled “Configuración de Android”Si es necesario, agrega a tu AndroidManifest.xml:
<application android:usesCleartextTraffic="true"> ...</application>Configuración Web
Section titled “Configuración Web”Para soporte de plataforma web, instala sql.js:
npm install sql.jsUso básico
Section titled “Uso básico”Conectarse a una base de datos
Section titled “Conectarse a una base de datos”import { FastSQL } from '@capgo/capacitor-fast-sql';
// Conectar a base de datos (crea archivo si no existe)const db = await FastSQL.connect({ database: 'myapp'});
console.log('Conectado a base de datos en puerto:', db.port);Crear tablas
Section titled “Crear tablas”// Crear una tablaawait db.execute(` CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT UNIQUE, created_at INTEGER DEFAULT (strftime('%s', 'now')) )`);Insertar datos
Section titled “Insertar datos”// Insertar una sola filaconst result = await db.run( 'INSERT INTO users (name, email) VALUES (?, ?)', ['John Doe', 'john@example.com']);
console.log('ID de fila insertada:', result.insertId);console.log('Filas afectadas:', result.rowsAffected);Consultar datos
Section titled “Consultar datos”// Consultar con parámetrosconst users = await db.query( 'SELECT * FROM users WHERE name LIKE ?', ['John%']);
console.log('Usuarios encontrados:', users);
// users es un array de objetos:// [{ id: 1, name: 'John Doe', email: 'john@example.com', created_at: 1234567890 }]Actualizar datos
Section titled “Actualizar datos”const result = await db.run( 'UPDATE users SET email = ? WHERE id = ?', ['newemail@example.com', 1]);
console.log('Filas actualizadas:', result.rowsAffected);Eliminar datos
Section titled “Eliminar datos”const result = await db.run( 'DELETE FROM users WHERE id = ?', [1]);
console.log('Filas eliminadas:', result.rowsAffected);Transacciones
Section titled “Transacciones”Las transacciones garantizan atomicidad: todas las operaciones tienen éxito o todas se revierten:
try { await db.transaction(async (tx) => { // Todas las operaciones en este bloque son parte de la transacción await tx.run('INSERT INTO accounts (name, balance) VALUES (?, ?)', ['Alice', 1000]); await tx.run('INSERT INTO accounts (name, balance) VALUES (?, ?)', ['Bob', 500]);
// Transferir dinero await tx.run('UPDATE accounts SET balance = balance - 100 WHERE name = ?', ['Alice']); await tx.run('UPDATE accounts SET balance = balance + 100 WHERE name = ?', ['Bob']); });
console.log('¡Transacción confirmada exitosamente!');} catch (error) { console.error('Transacción revertida:', error); // Todos los cambios se revierten automáticamente en caso de error}Niveles de aislamiento de transacciones
Section titled “Niveles de aislamiento de transacciones”import { FastSQL, IsolationLevel } from '@capgo/capacitor-fast-sql';
await db.transaction(async (tx) => { // Tus operaciones}, IsolationLevel.Serializable);Niveles de aislamiento disponibles:
ReadUncommitted- Aislamiento más bajo, mayor rendimientoReadCommitted- Previene lecturas suciasRepeatableRead- Previene lecturas no repetiblesSerializable- Aislamiento más alto, previene todas las anomalías
Operaciones por lotes
Section titled “Operaciones por lotes”Ejecuta múltiples sentencias eficientemente:
const results = await db.executeBatch([ { statement: 'INSERT INTO logs (message, level) VALUES (?, ?)', params: ['App started', 'INFO'] }, { statement: 'INSERT INTO logs (message, level) VALUES (?, ?)', params: ['User logged in', 'INFO'] }, { statement: 'INSERT INTO logs (message, level) VALUES (?, ?)', params: ['Error occurred', 'ERROR'] },]);
console.log('Ejecutadas', results.length, 'sentencias');Datos binarios (BLOBs)
Section titled “Datos binarios (BLOBs)”Almacena y recupera datos binarios usando Uint8Array:
// Almacenar datos binariosconst imageData = new Uint8Array([0xFF, 0xD8, 0xFF, 0xE0, /* ... */]);
await db.run( 'INSERT INTO images (name, data) VALUES (?, ?)', ['photo.jpg', imageData]);
// Recuperar datos binariosconst rows = await db.query('SELECT data FROM images WHERE name = ?', ['photo.jpg']);const retrievedData = rows[0].data; // Uint8ArrayEncriptación (iOS/Android)
Section titled “Encriptación (iOS/Android)”Habilita la encriptación SQLCipher para almacenamiento seguro:
const db = await FastSQL.connect({ database: 'secure_db', encrypted: true, encryptionKey: 'your-secure-encryption-key'});Modo de solo lectura
Section titled “Modo de solo lectura”Abre bases de datos en modo de solo lectura para prevenir modificaciones:
const db = await FastSQL.connect({ database: 'myapp', readOnly: true});Cerrar conexiones
Section titled “Cerrar conexiones”Siempre cierra las conexiones de base de datos cuando hayas terminado:
await FastSQL.disconnect('myapp');Protocolo HTTP directo
Section titled “Protocolo HTTP directo”Para máximo rendimiento con grandes conjuntos de datos, usa el protocolo HTTP directamente:
const { port, token } = await FastSQL.getServerInfo({ database: 'myapp' });
// Hacer solicitudes HTTP directas a localhost:port// Incluir token en encabezado Authorizationconst response = await fetch(`http://localhost:${port}/execute`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ statement: 'SELECT * FROM users', params: [] })});
const result = await response.json();Manejo de errores
Section titled “Manejo de errores”import { FastSQL } from '@capgo/capacitor-fast-sql';
try { const db = await FastSQL.connect({ database: 'myapp' });
await db.run('INSERT INTO users (name, email) VALUES (?, ?)', ['John', 'john@example.com']);
} catch (error) { if (error.message.includes('UNIQUE constraint failed')) { console.error('El email ya existe'); } else if (error.message.includes('no such table')) { console.error('La tabla no existe'); } else { console.error('Error de base de datos:', error); }}Patrones SQL comunes
Section titled “Patrones SQL comunes”Verificar si existe una tabla
Section titled “Verificar si existe una tabla”const result = await db.query( "SELECT name FROM sqlite_master WHERE type='table' AND name=?", ['users']);
const tableExists = result.length > 0;Obtener esquema de tabla
Section titled “Obtener esquema de tabla”const schema = await db.query('PRAGMA table_info(users)');console.log('Columnas:', schema);Contar filas
Section titled “Contar filas”const result = await db.query('SELECT COUNT(*) as count FROM users');const count = result[0].count;Paginación
Section titled “Paginación”const pageSize = 20;const page = 1;const offset = (page - 1) * pageSize;
const users = await db.query( 'SELECT * FROM users ORDER BY created_at DESC LIMIT ? OFFSET ?', [pageSize, offset]);Consejos de rendimiento
Section titled “Consejos de rendimiento”- Usa transacciones para múltiples operaciones: significativamente más rápido que confirmaciones individuales
- Usa operaciones por lotes para inserciones masivas: más eficiente que bucles
- Crea índices en columnas consultadas frecuentemente
- Usa sentencias preparadas con parámetros (?): previene inyección SQL y mejora el rendimiento
- Usa el protocolo HTTP directamente para conjuntos de resultados muy grandes
- Cierra conexiones cuando no estén en uso para liberar recursos
Siguientes pasos
Section titled “Siguientes pasos”Consulta el tutorial completo para patrones avanzados que incluyen:
- Arquitectura de servicio de base de datos
- Sistemas de migración
- Motores de sincronización
- Consultas complejas y uniones
- Optimización de rendimiento