room-rawquery-readonly-vacuum
Raw queries take a reader connection
An ORM picks the connection for a statement by deciding whether that statement writes. When the
statement is a parsed, annotated query the generator can read it and see a DELETE, so it asks for a
writer. When the statement arrives as an opaque string through a raw-query escape hatch, the
generator cannot know — and it defaults to read-only.
In Room specifically (as of Room 2.8), KSP generates a @RawQuery method as
performSuspending(__db, true, false) — positional booleans, in order isReadOnly,
inTransaction. Room then takes a reader
connection, and readers are opened with PRAGMA query_only = 1. Under that pragma VACUUM fails
outright with "attempt to write a readonly database".
Where compaction belongs
On the database class, not the DAO — the DAO has no way to ask for a writer connection at all: