Getting Started with Fast SQL
このガイドでは、高性能なSQLiteデータベースアクセスのための**@capgo/capacitor-fast-sql**プラグインをインストールして設定する方法を説明します。
Fast SQLとは?
Section titled “Fast SQLとは?”Capacitor用の従来のSQLiteプラグインは、標準的なJavaScriptブリッジに依存してWebコードとネイティブコード間の通信を行っています。小規模な操作では問題ありませんが、大量のデータを転送する必要がある場合、ブリッジが大きなボトルネックになります。すべてのデータはJSONにシリアル化され、ブリッジ経由で送信され、その後、相手側でデシリアル化されます。このシリアル化のオーバーヘッドにより、数千行のデータまたは大きなバイナリデータの操作は非常に遅くなります。
Fast SQLはこの問題を解決します。デバイス上にローカルHTTPサーバーを確立し、ネイティブSQLiteデータベースと直接通信します。このカスタムプロトコルはCapacitorのブリッジをバイパスし、シリアル化のオーバーヘッドを排除し、以下を実現します:
- バッチ操作と大規模データセットで最大25倍高速化
- base64エンコードなしの効率的なバイナリデータ転送
- メモリの問題のない大規模な結果のストリーミング
- CRDTとオペレーショナルトランスフォームのような同期システムの最適なパフォーマンス
これにより、Fast SQLはローカルファースト アプリケーション、オフライン同期システム、およびIndexedDBをより信頼性が高く高性能なソリューションに置き換える必要があるシナリオに最適です。
Installation
Section titled “Installation”npm install @capgo/capacitor-fast-sqlnpx cap syncPlatform Configuration
Section titled “Platform Configuration”iOS Configuration
Section titled “iOS Configuration”Add the following to your Info.plist to allow local networking:
<key>NSAppTransportSecurity</key><dict> <key>NSAllowsLocalNetworking</key> <true/></dict>Android Configuration
Section titled “Android Configuration”If needed, add to your AndroidManifest.xml:
<application android:usesCleartextTraffic="true"> ...</application>Web Configuration
Section titled “Web Configuration”For web platform support, install sql.js:
npm install sql.jsBasic Usage
Section titled “Basic Usage”Connecting to a Database
Section titled “Connecting to a Database”import { FastSQL } from '@capgo/capacitor-fast-sql';
// Connect to database (creates file if it doesn't exist)const db = await FastSQL.connect({ database: 'myapp'});
console.log('Connected to database on port:', db.port);Creating Tables
Section titled “Creating Tables”// Create a tableawait 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')) )`);Inserting Data
Section titled “Inserting Data”// Insert single rowconst result = await db.run( 'INSERT INTO users (name, email) VALUES (?, ?)', ['John Doe', 'john@example.com']);
console.log('Inserted row ID:', result.insertId);console.log('Rows affected:', result.rowsAffected);Querying Data
Section titled “Querying Data”// Query with parametersconst users = await db.query( 'SELECT * FROM users WHERE name LIKE ?', ['John%']);
console.log('Found users:', users);
// users is an array of objects:// [{ id: 1, name: 'John Doe', email: 'john@example.com', created_at: 1234567890 }]Updating Data
Section titled “Updating Data”const result = await db.run( 'UPDATE users SET email = ? WHERE id = ?', ['newemail@example.com', 1]);
console.log('Updated rows:', result.rowsAffected);Deleting Data
Section titled “Deleting Data”const result = await db.run( 'DELETE FROM users WHERE id = ?', [1]);
console.log('Deleted rows:', result.rowsAffected);Transactions
Section titled “Transactions”Transactions ensure atomicity - either all operations succeed or all are rolled back:
try { await db.transaction(async (tx) => { // All operations in this block are part of the transaction await tx.run('INSERT INTO accounts (name, balance) VALUES (?, ?)', ['Alice', 1000]); await tx.run('INSERT INTO accounts (name, balance) VALUES (?, ?)', ['Bob', 500]);
// Transfer money 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('Transaction committed successfully!');} catch (error) { console.error('Transaction rolled back:', error); // All changes are automatically rolled back on error}Transaction Isolation Levels
Section titled “Transaction Isolation Levels”import { FastSQL, IsolationLevel } from '@capgo/capacitor-fast-sql';
await db.transaction(async (tx) => { // Your operations}, IsolationLevel.Serializable);Available isolation levels:
ReadUncommitted- Lowest isolation, highest performanceReadCommitted- Prevent dirty readsRepeatableRead- Prevent non-repeatable readsSerializable- Highest isolation, prevents all anomalies
Batch Operations
Section titled “Batch Operations”Execute multiple statements efficiently:
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('Executed', results.length, 'statements');Binary Data (BLOBs)
Section titled “Binary Data (BLOBs)”Store and retrieve binary data using Uint8Array:
// Store binary dataconst imageData = new Uint8Array([0xFF, 0xD8, 0xFF, 0xE0, /* ... */]);
await db.run( 'INSERT INTO images (name, data) VALUES (?, ?)', ['photo.jpg', imageData]);
// Retrieve binary dataconst rows = await db.query('SELECT data FROM images WHERE name = ?', ['photo.jpg']);const retrievedData = rows[0].data; // Uint8ArrayEncryption (iOS/Android)
Section titled “Encryption (iOS/Android)”Enable SQLCipher encryption for secure storage:
const db = await FastSQL.connect({ database: 'secure_db', encrypted: true, encryptionKey: 'your-secure-encryption-key'});Read-Only Mode
Section titled “Read-Only Mode”Open databases in read-only mode to prevent modifications:
const db = await FastSQL.connect({ database: 'myapp', readOnly: true});Closing Connections
Section titled “Closing Connections”Always close database connections when done:
await FastSQL.disconnect('myapp');Direct HTTP Protocol
Section titled “Direct HTTP Protocol”For maximum performance with large datasets, use the HTTP protocol directly:
const { port, token } = await FastSQL.getServerInfo({ database: 'myapp' });
// Make direct HTTP requests to localhost:port// Include token in Authorization headerconst 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();Error Handling
Section titled “Error Handling”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 already exists'); } else if (error.message.includes('no such table')) { console.error('Table does not exist'); } else { console.error('Database error:', error); }}Common SQL Patterns
Section titled “Common SQL Patterns”Check if Table Exists
Section titled “Check if Table Exists”const result = await db.query( "SELECT name FROM sqlite_master WHERE type='table' AND name=?", ['users']);
const tableExists = result.length > 0;Get Table Schema
Section titled “Get Table Schema”const schema = await db.query('PRAGMA table_info(users)');console.log('Columns:', schema);Count Rows
Section titled “Count Rows”const result = await db.query('SELECT COUNT(*) as count FROM users');const count = result[0].count;Pagination
Section titled “Pagination”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]);パフォーマンスティップス
Section titled “パフォーマンスティップス”- 複数の操作にはトランザクションを使用 - 個別のコミットより大幅に高速
- バルク挿入にはバッチ操作を使用 - ループより効率的
- 頻繁にクエリされるカラムにインデックスを作成
- パラメータ (?) 付きの準備済みステートメントを使用 - SQLインジェクションを防止しパフォーマンスを向上
- 非常に大きな結果セットにはHTTPプロトコルを直接使用
- 使用しない場合は接続を閉じて リソースを解放
次のステップ
Section titled “次のステップ”完全なチュートリアルで以下を含む高度なパターンを確認してください:
- データベースサービスアーキテクチャ
- マイグレーションシステム
- 同期エンジン
- 複雑なクエリとジョイン
- パフォーマンス最適化