Saltar al contenido

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.

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.

Terminal window
npm install @capgo/capacitor-fast-sql
npx cap sync

Agrega lo siguiente a tu Info.plist para permitir redes locales:

ios/App/App/Info.plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>

Si es necesario, agrega a tu AndroidManifest.xml:

android/app/src/main/AndroidManifest.xml
<application
android:usesCleartextTraffic="true">
...
</application>

Para soporte de plataforma web, instala sql.js:

Terminal window
npm install sql.js
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 una tabla
await 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 una sola fila
const 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 con parámetros
const 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 }]
const result = await db.run(
'UPDATE users SET email = ? WHERE id = ?',
['newemail@example.com', 1]
);
console.log('Filas actualizadas:', result.rowsAffected);
const result = await db.run(
'DELETE FROM users WHERE id = ?',
[1]
);
console.log('Filas eliminadas:', result.rowsAffected);

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
}
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 rendimiento
  • ReadCommitted - Previene lecturas sucias
  • RepeatableRead - Previene lecturas no repetibles
  • Serializable - Aislamiento más alto, previene todas las anomalías

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');

Almacena y recupera datos binarios usando Uint8Array:

// Almacenar datos binarios
const imageData = new Uint8Array([0xFF, 0xD8, 0xFF, 0xE0, /* ... */]);
await db.run(
'INSERT INTO images (name, data) VALUES (?, ?)',
['photo.jpg', imageData]
);
// Recuperar datos binarios
const rows = await db.query('SELECT data FROM images WHERE name = ?', ['photo.jpg']);
const retrievedData = rows[0].data; // Uint8Array

Habilita la encriptación SQLCipher para almacenamiento seguro:

const db = await FastSQL.connect({
database: 'secure_db',
encrypted: true,
encryptionKey: 'your-secure-encryption-key'
});

Abre bases de datos en modo de solo lectura para prevenir modificaciones:

const db = await FastSQL.connect({
database: 'myapp',
readOnly: true
});

Siempre cierra las conexiones de base de datos cuando hayas terminado:

await FastSQL.disconnect('myapp');

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 Authorization
const 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();
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);
}
}
const result = await db.query(
"SELECT name FROM sqlite_master WHERE type='table' AND name=?",
['users']
);
const tableExists = result.length > 0;
const schema = await db.query('PRAGMA table_info(users)');
console.log('Columnas:', schema);
const result = await db.query('SELECT COUNT(*) as count FROM users');
const count = result[0].count;
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]
);
  1. Usa transacciones para múltiples operaciones: significativamente más rápido que confirmaciones individuales
  2. Usa operaciones por lotes para inserciones masivas: más eficiente que bucles
  3. Crea índices en columnas consultadas frecuentemente
  4. Usa sentencias preparadas con parámetros (?): previene inyección SQL y mejora el rendimiento
  5. Usa el protocolo HTTP directamente para conjuntos de resultados muy grandes
  6. Cierra conexiones cuando no estén en uso para liberar recursos

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