Android Room has method void clearAllTables() and according to docs it makes the following:
Deletes all rows from all the tables that are registered to this database as entities().
This does NOT reset the auto-increment value generated by autoGenerate().
After deleting the rows, Room will set a WAL checkpoint and run VACUUM. This means that the data is completely erased. The space will be reclaimed by the system if the amount surpasses the threshold of database file size.
I checked it in my project and looks like db has no data after that call, but when I pulled
*.db file from my device and opened it in sqlite viewer I've seen that all the data exists, the tables are filled and nothing has been erased.
How can that be? I consider this as a potential flaw in my app. Please provide a reliable approach of cleaning room database
looks like db has no data after that call
It means the method worked.
when I pulled *.db file from my device and opened it in sqlite viewer
I've seen that all the data exists
Most probably the transactions are not moved to the original database from the WAL file yet.
Solution
You can force a checkpoint using the wal_checkpoint pragma. Query the following statement against the database.
pragma wal_checkpoint(full)
Related
How can I set the id (which is my #PrimaryKey(autogenerate = true)) back to 0 after I have deleted all data in Room Database Table? For the moment my delete works but the new inserted data increment where the last ID has been.
#Dao
interface MyDao {
#RawQuery
fun vacuumDb(supportSQLiteQuery: SupportSQLiteQuery): Int
}
When all of the content is deleted, execute this statement,
MyDao.vacuumDb(SimpleSQLiteQuery("VACUUM"))
VACUUM command does not change the content of your database but changes rowids. This will reset the rowids.
How VACUUM works?
The VACUUM command works by copying the contents of the database into a temporary database file and then overwriting the original with the contents of the temporary file. When overwriting the original, a rollback journal or write-ahead log WAL file is used just as it would be for any other database transaction. This means that when VACUUMing a database, as much as twice the size of the original database file is required in free disk space.
The VACUUM INTO command works the same way except that it uses the file named on the INTO clause in place of the temporary database and omits the step of copying the vacuumed database back over top of the original database.
The VACUUM command may change the ROWIDs of entries in any tables that do not have an explicit INTEGER PRIMARY KEY.
A VACUUM will fail if there is an open transaction on the database connection that is attempting to run the VACUUM. Unfinalized SQL statements typically hold a read transaction open, so the VACUUM might fail if there are unfinalized SQL statements on the same connection. VACUUM (but not VACUUM INTO) is a write operation and so if another database connection is holding a lock that prevents writes, then the VACUUM will fail.
An alternative to using the VACUUM command to reclaim space after data has been deleted is auto-vacuum mode, enabled using the auto_vacuum pragma. When auto_vacuum is enabled for a database free pages may be reclaimed after deleting data, causing the file to shrink, without rebuilding the entire database using VACUUM. However, using auto_vacuum can lead to extra database file fragmentation. And auto_vacuum does not compact partially filled pages of the database as VACUUM does.
More info: SQLite VACUUM
I have an android application that relies on a sqlite database, and use OrmLite to access my DB.
Instead of OrmLite creating the tables I rely on downloading the database from a central server as the user will often want to "sync" things. Currently I don't have the fancy sync code written so the app replaces the db. The steps are:
1 Download the latest SQLite db file from the server, as a zip
2 Expand the file to produce a database.sqlite file in a temporary folder
3 Deletes the contents of a data folder, which contains the live database.sqlite file
4 Move the database.sqlite file from the temporary folder to the data folder.
The problem is that the new database file seems to get ignored and DAO queries I run return old data. The only way to show data from the new version of the DB is to restart the application.
To test things I created a table with a timestamp that records when the database was generated, each time you request a new copy of the sqlite db from the server this is updated. I have a fragment that displays this time so you know how fresh your data is. In the fragments onResume method I make a call to the DAO to get the timestamp and put value on screen. I've stepped through this and I see the call to the DAO but the value that comes back is from the old, now deleted, db. Restart the app and the correct value is shown.
So my question is, if I replace the underlying sqlite db file that stores my database, how can I tell ormlite to pick it up or refresh the connection or whatever it has to do???
I tried calling clearObjectCache on the DAO, made no difference.
I've created an empty table in a sqlite database, DB, via a database adapter.
Since I have a lot of data (10,000+ rows) to be inserted and I don't want to do it in the activities so I pull the sqlite database out of data/data/package-name/databases and inserted the rows via sqlite browser software. I then reinserted/push the updated DB it back into the eclipse DDMS and all was fine at first.
The DB has an inflated size of 800kb from the original 22kb.
But after running the emulator again, I noticed that the DB shrunk back to 22kb and upon pulling it out and inspecting it, the rows I inserted is no longer there.
Strange enough, the DB journal file in the same folder is now inflated to 800kb, but I can not open that file (sqlite browser says the file is either corrupt or encrypted but not a valid Sqlite file). Can someone explain what happened?
Did you commit changes after updating database? Also check if database is not dropped when Eclipse uninstall old version of the application before new one is deployed on target.
I want to save a table file in database, which have many tables in it, but, I don't want to save the database, because I will restore the table file if needed and other tables files keep original state. Is there a way?
Some ideas:
Copy the original database and only use the copy. This approach is simple and doesn't require the code to do anything "special" to not leave changes. However, it makes it hard to persist any data back to the original -- but see below for a nifty trick!
Use an attached database. Only update tables in the attached database. The code has to be modified to only use tables from the attached database. Modifications to tables in the primary database will still be saved. The attached database can be deleted (or left alone) as needed. Attached databases are a good way to move data between different SQLite data files!
Use a temporary table (and see this SO post). Then delete the table when done (or let SQLite delete it). Again, this requires the code to play nice and not modify other tables.
Just don't put the data in the DB :-)
An SQLite database can also be opened "read only", but this has other implications as well.
Happy coding!
I have an app which stores data in a SQLite database, when the app is just installed it uses 8kb of data and when I start inserting data obviously the size increases. The weird thing is when I start cleaning my database tables, I empty completely the database but I will never recover the first 8kb of data but much more, in some cases more than 100kb, where this data come from?
A database is not like a filesystem, so when you delete data from a database, you do not recover the space you previously used. The database driver will tend to prefer to keep the old allocated space.
You can compact your database, which will recover this space by manually executing the SQLite VACUUM command.
It may be possible to enable auto_vacuum mode, but this needs to be done before database creation.