dbinspect_sqflite

A sqflite adapter for dbinspect_bridge, so a desktop client can browse your app's SQLite database while it runs.

import 'package:dbinspect_bridge/dbinspect_bridge.dart';
import 'package:dbinspect_sqflite/dbinspect_sqflite.dart';

await startBridge(
  appName: 'example_app',
  adapters: [
    SqfliteAdapter(executor: db, id: 'app', displayName: 'app.db'),
  ],
);

Stores come from sqlite_master, schema from PRAGMA table_info, and paging from LIMIT/OFFSET. Blobs are truncated at 64 KB.

Written against DatabaseExecutor from sqflite_common rather than sqflite itself, which means it takes a Database or a Transaction, and that its tests run against real SQLite with no device and no plugin channel.

Reading only, unless you say otherwise

sql and edit are false by default, so the adapter browses and pages and does nothing else. Raw SQL is a separate opt-in:

SqfliteAdapter(executor: db, id: 'app', displayName: 'app.db',
    allowRawQuery: true);

That opens SELECT, WITH … SELECT and EXPLAIN, and nothing else. Adding allowWrite: true opens the row editor — insertRow, updateRow, deleteRow — and in the SQL console also permits INSERT, UPDATE, DELETE and REPLACE; ATTACH, DETACH, PRAGMA, VACUUM, extension loading, DDL and a second statement after a ; are refused whatever you turn on. The gate is an allow-list over a real tokenizer in dbinspect_bridge, not a keyword scan — ATTACH DATABASE '/path' reads any file this process can read, and it is not an UPDATE, a DELETE or a DROP.

A consequence worth knowing before you file it as a bug: a bare pragma, vacuum, attach, detach or load_extension is refused anywhere in a statement, so a column with one of those names must be quoted — "pragma", [pragma] or `pragma` all work. A bound parameter is not a bare word, so :pragma is fine.

watch is absent and always will be — sqflite has no change feed, and the client offers labelled polling instead of pretending otherwise.

A row editor addresses a row by the table's single-column primary key, which is the rowid when it is an INTEGER PRIMARY KEY. A table with no primary key, or with a composite one, refuses updateRow and deleteRow and says which case it is — a page is SELECT *, so a client has no rowid to send and any other addressing would be a guess. insertRow needs no key and works on such a table.

Store, sort-column and edited-column names coming off the wire are checked against the list SQLite itself reports, never interpolated into a statement.

Licence

Apache-2.0.

Libraries

dbinspect_sqflite
A sqflite adapter for dbinspect_bridge.