Iniziare con Fast SQL
Questa guida ti aiuterà a installare e configurare il plugin @capgo/capacitor-fast-sql per accesso database SQLite ad alte prestazioni.
Perché Fast SQL?
Section titled “Perché Fast SQL?”I plugin SQLite tradizionali per Capacitor si basano sul bridge JavaScript standard per comunicare tra il tuo codice web e il codice nativo. Anche se questo funziona bene per piccole operazioni, il bridge diventa un collo di bottiglia significativo quando devi trasferire grandi quantità di dati. Ogni pezzo di dati deve essere serializzato in JSON, inviato attraverso il bridge e quindi deserializzato dall’altra parte. Questo overhead di serializzazione rende le operazioni con migliaia di righe o dati binari grandi incredibilmente lente.
Fast SQL risolve questo problema stabilendo un server HTTP locale sul dispositivo che comunica direttamente con il database SQLite nativo. Questo protocollo personalizzato bypassa completamente il bridge di Capacitor, eliminando l’overhead di serializzazione e abilitando:
- Prestazioni fino a 25x più veloci per operazioni batch e grandi dataset
- Trasferimento efficiente di dati binari senza codifica base64
- Streaming di risultati grandi senza problemi di memoria
- Prestazioni ottimali per sistemi di sincronizzazione come CRDT e trasformazioni operazionali
Questo rende Fast SQL ideale per applicazioni local-first, sistemi di sincronizzazione offline e scenari in cui devi sostituire IndexedDB con una soluzione più affidabile e performante.
Installazione
Section titled “Installazione”npm install @capgo/capacitor-fast-sqlnpx cap syncConfigurazione Piattaforma
Section titled “Configurazione Piattaforma”Configurazione iOS
Section titled “Configurazione iOS”Aggiungi quanto segue al tuo Info.plist per consentire il networking locale:
<key>NSAppTransportSecurity</key><dict> <key>NSAllowsLocalNetworking</key> <true/></dict>Configurazione Android
Section titled “Configurazione Android”Se necessario, aggiungi al tuo AndroidManifest.xml:
<application android:usesCleartextTraffic="true"> ...</application>Configurazione Web
Section titled “Configurazione Web”Per il supporto della piattaforma web, installa sql.js:
npm install sql.jsUtilizzo Base
Section titled “Utilizzo Base”Connessione a un Database
Section titled “Connessione a un Database”import { FastSQL } from '@capgo/capacitor-fast-sql';
// Connetti al database (crea il file se non esiste)const db = await FastSQL.connect({ database: 'myapp'});
console.log('Connesso al database sulla porta:', db.port);Creazione Tabelle
Section titled “Creazione Tabelle”// Crea una tabellaawait 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')) )`);Inserimento Dati
Section titled “Inserimento Dati”// Inserisci singola rigaconst result = await db.run( 'INSERT INTO users (name, email) VALUES (?, ?)', ['John Doe', 'john@example.com']);
console.log('ID riga inserita:', result.insertId);console.log('Righe interessate:', result.rowsAffected);Query Dati
Section titled “Query Dati”// Query con parametriconst users = await db.query( 'SELECT * FROM users WHERE name LIKE ?', ['John%']);
console.log('Utenti trovati:', users);
// users è un array di oggetti:// [{ id: 1, name: 'John Doe', email: 'john@example.com', created_at: 1234567890 }]Aggiornamento Dati
Section titled “Aggiornamento Dati”const result = await db.run( 'UPDATE users SET email = ? WHERE id = ?', ['newemail@example.com', 1]);
console.log('Righe aggiornate:', result.rowsAffected);Eliminazione Dati
Section titled “Eliminazione Dati”const result = await db.run( 'DELETE FROM users WHERE id = ?', [1]);
console.log('Righe eliminate:', result.rowsAffected);Transazioni
Section titled “Transazioni”Le transazioni garantiscono l’atomicità - tutte le operazioni hanno successo o tutte vengono annullate:
try { await db.transaction(async (tx) => { // Tutte le operazioni in questo blocco fanno parte della transazione await tx.run('INSERT INTO accounts (name, balance) VALUES (?, ?)', ['Alice', 1000]); await tx.run('INSERT INTO accounts (name, balance) VALUES (?, ?)', ['Bob', 500]);
// Trasferisci denaro 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('Transazione committata con successo!');} catch (error) { console.error('Transazione annullata:', error); // Tutte le modifiche sono automaticamente annullate in caso di errore}Livelli di Isolamento Transazione
Section titled “Livelli di Isolamento Transazione”import { FastSQL, IsolationLevel } from '@capgo/capacitor-fast-sql';
await db.transaction(async (tx) => { // Le tue operazioni}, IsolationLevel.Serializable);Livelli di isolamento disponibili:
ReadUncommitted- Isolamento più basso, prestazioni più alteReadCommitted- Previeni letture sporcheRepeatableRead- Previeni letture non ripetibiliSerializable- Isolamento più alto, previene tutte le anomalie
Operazioni Batch
Section titled “Operazioni Batch”Esegui più istruzioni in modo efficiente:
const results = await db.executeBatch([ { statement: 'INSERT INTO logs (message, level) VALUES (?, ?)', params: ['App avviata', 'INFO'] }, { statement: 'INSERT INTO logs (message, level) VALUES (?, ?)', params: ['Utente loggato', 'INFO'] }, { statement: 'INSERT INTO logs (message, level) VALUES (?, ?)', params: ['Errore verificato', 'ERROR'] },]);
console.log('Eseguite', results.length, 'istruzioni');Dati Binari (BLOB)
Section titled “Dati Binari (BLOB)”Memorizza e recupera dati binari usando Uint8Array:
// Memorizza dati binariconst imageData = new Uint8Array([0xFF, 0xD8, 0xFF, 0xE0, /* ... */]);
await db.run( 'INSERT INTO images (name, data) VALUES (?, ?)', ['photo.jpg', imageData]);
// Recupera dati binariconst rows = await db.query('SELECT data FROM images WHERE name = ?', ['photo.jpg']);const retrievedData = rows[0].data; // Uint8ArrayCrittografia (iOS/Android)
Section titled “Crittografia (iOS/Android)”Abilita la crittografia SQLCipher per archiviazione sicura:
const db = await FastSQL.connect({ database: 'secure_db', encrypted: true, encryptionKey: 'your-secure-encryption-key'});Modalità Sola Lettura
Section titled “Modalità Sola Lettura”Apri database in modalità sola lettura per prevenire modifiche:
const db = await FastSQL.connect({ database: 'myapp', readOnly: true});Chiusura Connessioni
Section titled “Chiusura Connessioni”Chiudi sempre le connessioni database quando hai finito:
await FastSQL.disconnect('myapp');Protocollo HTTP Diretto
Section titled “Protocollo HTTP Diretto”Per prestazioni massime con grandi dataset, usa direttamente il protocollo HTTP:
const { port, token } = await FastSQL.getServerInfo({ database: 'myapp' });
// Effettua richieste HTTP dirette a localhost:port// Includi il token nell'header 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();Gestione Errori
Section titled “Gestione Errori”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('Email già esistente'); } else if (error.message.includes('no such table')) { console.error('La tabella non esiste'); } else { console.error('Errore database:', error); }}Pattern SQL Comuni
Section titled “Pattern SQL Comuni”Verifica se Tabella Esiste
Section titled “Verifica se Tabella Esiste”const result = await db.query( "SELECT name FROM sqlite_master WHERE type='table' AND name=?", ['users']);
const tableExists = result.length > 0;Ottieni Schema Tabella
Section titled “Ottieni Schema Tabella”const schema = await db.query('PRAGMA table_info(users)');console.log('Colonne:', schema);Conta Righe
Section titled “Conta Righe”const result = await db.query('SELECT COUNT(*) as count FROM users');const count = result[0].count;Paginazione
Section titled “Paginazione”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]);Suggerimenti per le Prestazioni
Section titled “Suggerimenti per le Prestazioni”- Usa Transazioni per operazioni multiple - significativamente più veloce dei commit individuali
- Usa Operazioni Batch per inserimenti massivi - più efficienti dei cicli
- Crea Indici sulle colonne frequentemente interrogate
- Usa Prepared Statement con parametri (?) - previene SQL injection e migliora le prestazioni
- Usa Protocollo HTTP Direttamente per set di risultati molto grandi
- Chiudi Connessioni quando non in uso per liberare risorse
Prossimi Passi
Section titled “Prossimi Passi”Consulta il tutorial completo per pattern avanzati inclusi:
- Architettura servizio database
- Sistemi di migrazione
- Motori di sincronizzazione
- Query e join complessi
- Ottimizzazione prestazioni