Given a Room database DAO like this:
import android.arch.persistence.room.Dao; import android.arch.persistence.room.Query; import java.util.Date; import java.util.List; @Dao public interface MyDao { @Query("SELECT * FROM MyTable") List<MyItem> all(); @Query("SELECT * FROM MyTable WHERE date = :date AND language = :language") MyItem byDate(Date date, String language); }
Is there a way to have a Logger or something like that added to MyDao
so that I could see which statements are being performed. This would be really helpful during development, because I could immediately check if the functions are transformed correctly to the expected SQL statement or not.
When you use the Room persistence library to store your app's data, you interact with the stored data by defining data access objects, or DAOs. Each DAO includes methods that offer abstract access to your app's database. At compile time, Room automatically generates implementations of the DAOs that you define.
Go To App Inspection . Then select the process. Database Inspector will now show the database contents. in 2021, with current Android Studio, this should be the only accepted answer.
Open the Database Inspector To fix the issue, follow these steps. Select View > Tool Windows > App Inspection from the menu bar. Select the Database Inspector tab. Select the running app process from the dropdown menu.
Assuming that Room uses framework's Sqlite as underlying database, the statements can be quite simply logged. The only limitation: this can be done only on emulator.
From SQLiteDebug.java:
/** * Controls the printing of SQL statements as they are executed. * * Enable using "adb shell setprop log.tag.SQLiteStatements VERBOSE". */ public static final boolean DEBUG_SQL_STATEMENTS = Log.isLoggable("SQLiteStatements", Log.VERBOSE);
By default, the log.tag.SQLiteStatements
's value is not set:
alex@mbpro:~$ adb shell getprop log.tag.SQLiteStatements
<-- BLANK LINE -->
According to the above documentation, to set the property we have to use:
alex@mbpro:~$ adb shell setprop log.tag.SQLiteStatements VERBOSE
alex@mbpro:~$ adb shell getprop log.tag.SQLiteStatements
VERBOSE
As we can see, the VERBOSE
value was successfully set. However, if we'll re-run our application - we won't see those statements printed. To make it work, we'll have to restart all the services using adb shell stop
and then adb shell start
.
If you'll try to do that with a regular device, you'll receive the following error (tried with Pixel XL / stock Android 9):
alex@mbpro:~$ adb shell start
start: must be root
alex@mbpro:~$ adb root
adbd cannot run as root in production builds
This is why we have to use the emulator:
alex@mbpro:~$ adb root
restarting adbd as root
alex@mbpro:~$ adb shell stop
alex@mbpro:~$ adb shell start
The emulator will restart.
Run your application and you'll see similar Sqlite statements in logcat:
<redacted..> V/SQLiteStatements: <redacted>/my_db: "BEGIN EXCLUSIVE;" V/SQLiteStatements: <redacted>/my_db: "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)" V/SQLiteStatements: <redacted>/my_db: "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, "3cb5664b6da264c13388292d98141843")" V/SQLiteStatements: <redacted>/my_db: "CREATE TABLE IF NOT EXISTS `MyTable` (`id` TEXT NOT NULL, `date` INTEGER, `language` TEXT, PRIMARY KEY(`id`))" <redacted..> V/SQLiteStatements: <redacted>/my_db: "BEGIN EXCLUSIVE;" V/SQLiteStatements: <redacted>/my_db: "PRAGMA temp_store = MEMORY;" V/SQLiteStatements: <redacted>/my_db: "PRAGMA recursive_triggers='ON';" V/SQLiteStatements: <redacted>/my_db: "CREATE TEMP TABLE room_table_modification_log(version INTEGER PRIMARY KEY AUTOINCREMENT, table_id INTEGER)" V/SQLiteStatements: <redacted>/my_db: "COMMIT;" <redacted..> V/SQLiteStatements: <redacted>/my_db: "SELECT * FROM MyTable" V/SQLiteStatements: <redacted>/my_db: "SELECT * FROM MyTable WHERE date = 1551562171387 AND language = 'en'"
To undo the changes, use these commands:
alex@mbpro:~$ adb shell setprop log.tag.SQLiteStatements ""
alex@mbpro:~$ adb shell getprop log.tag.SQLiteStatements
<-- BLANK LINE -->
alex@mbpro:~$ adb shell stop
alex@mbpro:~$ adb shell start
alex@mbpro:~$ adb unroot
restarting adbd as non root
There does not appear to be any hooks for that at the DAO level. There are callbacks related to database opens and upgrades, but not arbitrary stuff.
You could file a feature request, though. I agree that it could be useful. Even better would be an OkHttp-style generic interceptor framework.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With