diff --git a/.changeset/gorgeous-scissors-drive.md b/.changeset/gorgeous-scissors-drive.md new file mode 100644 index 000000000..390dcc1f0 --- /dev/null +++ b/.changeset/gorgeous-scissors-drive.md @@ -0,0 +1,5 @@ +--- +'@powersync/common': patch +--- + +Fixed readTransaction method throwing "not allowed in read-only mode" errors diff --git a/packages/capacitor/README.md b/packages/capacitor/README.md index ab23df8c1..3a8ee4d17 100644 --- a/packages/capacitor/README.md +++ b/packages/capacitor/README.md @@ -82,7 +82,7 @@ const db = new PowerSyncDatabase({ - Encryption for native mobile platforms is not yet supported. - `PowerSyncDatabase.executeRaw` does not support results where multiple columns would have the same name in SQLite -- `PowerSyncDatabase.execute` has limited support on Android. The SQLCipher Android driver exposes queries and executions as separate APIs, so there is no single method that handles both. While `PowerSyncDatabase.execute` accepts both, on Android we treat a statement as a query only when the SQL starts with `select` (case-insensitive). +- `PowerSyncDatabase.execute` has limited support on Android. The SQLCipher Android driver exposes queries and executions as separate APIs, so there is no single method that handles both. While `PowerSyncDatabase.execute` accepts both, on Android we treat a statement as a query only when the SQL starts with `select` (case-insensitive). Queries such as `INSERT into customers (id, name) VALUES (uuid(), 'name') RETURNING *` do not work on Android. - Multiple tab support is not available for native Android and iOS targets. If you're not opening a second webview in your native app using something like `@jackobo/capacitor-webview`, you are unaffected by this. ## Examples diff --git a/packages/capacitor/src/adapter/CapacitorSQLiteAdapter.ts b/packages/capacitor/src/adapter/CapacitorSQLiteAdapter.ts index 7a4e64951..3081d8755 100644 --- a/packages/capacitor/src/adapter/CapacitorSQLiteAdapter.ts +++ b/packages/capacitor/src/adapter/CapacitorSQLiteAdapter.ts @@ -118,22 +118,31 @@ export class CapacitorSQLiteAdapter extends BaseObserver impl } protected generateLockContext(db: SQLiteDBConnection): LockContext { + const _query = async (query: string, params: any[] = []) => { + const result = await db.query(query, params); + const arrayResult = result.values ?? []; + return { + rowsAffected: 0, + rows: { + _array: arrayResult, + length: arrayResult.length, + item: (idx: number) => arrayResult[idx] + } + }; + }; + const _execute = async (query: string, params: any[] = []): Promise => { const platform = Capacitor.getPlatform(); + + if (db.getConnectionReadOnly()) { + return _query(query, params); + } + if (platform == 'android') { // Android: use query for SELECT and executeSet for mutations // We cannot use `run` here for both cases. if (query.toLowerCase().trim().startsWith('select')) { - const result = await db.query(query, params); - const arrayResult = result.values ?? []; - return { - rowsAffected: 0, - rows: { - _array: arrayResult, - length: arrayResult.length, - item: (idx: number) => arrayResult[idx] - } - }; + return _query(query, params); } else { const result = await db.executeSet([{ statement: query, values: params }], false); return { @@ -166,24 +175,9 @@ export class CapacitorSQLiteAdapter extends BaseObserver impl ? (sql: string, params?: any[]) => monitorQuery(sql, () => _execute(sql, params)) : _execute; - const _executeQuery = async (query: string, params?: any[]): Promise => { - let result = await db.query(query, params); - - let arrayResult = result.values ?? []; - - return { - rowsAffected: 0, - rows: { - _array: arrayResult, - length: arrayResult.length, - item: (idx: number) => arrayResult[idx] - } - }; - }; - const executeQuery = this.options.debugMode - ? (sql: string, params?: any[]) => monitorQuery(sql, () => _executeQuery(sql, params)) - : _executeQuery; + ? (sql: string, params?: any[]) => monitorQuery(sql, () => _query(sql, params)) + : _query; const getAll = async (query: string, params?: any[]): Promise => { const result = await executeQuery(query, params);