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
Related
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)
In my andoid application's database directory (/data/data/com.me.myApp/databases), for every sqlite database I create there is a corresponding database of the same name with "-journal" appended to it's name.
e.g: myDatabase, myDatabase-journal, myOtherDatabase.db, myOtherDatabase.db-journal
What is this?
and,
If I'm providing pre-filled databases for my app (as per: http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/) do I need to include these as well?'
Such -journal files do not need to (and should not) be distributed.
This is because the various journal files represent temporary data (ref. SQLite's Use Of Temporary Disk Files) used by SQLite. In particular a -journal file is a rollback journal.
A rollback journal is a temporary file used to implement atomic commit and rollback capabilities in SQLite. (For a detailed discussion of how this works, see the separate document titled Atomic Commit In SQLite.) The rollback journal is always located in the same directory as the database file and has the same name as the database file except with the 8 characters "-journal" appended.
The rollback journal is usually created when a transaction is first started and is usually deleted when a transaction commits or rolls back. The rollback journal file is essential for implementing the atomic commit and rollback capabilities of SQLite. Without a rollback journal, SQLite would be unable to rollback an incomplete transaction, and if a crash or power loss occurred in the middle of a transaction the entire database would likely go corrupt without a rollback journal.
In general these -journal files should only exist when there is an open SQLite database - or rather, a running transaction - but can be controlled via PRAGMA journal_mode. With default pragma settings the -journal files will be deleted.
The DELETE journaling mode is the normal behavior. In the DELETE mode, the rollback journal is deleted at the conclusion of each transaction. Indeed, the delete operation is the action that causes the transaction to commit.
Make sure to only copy the actual database files when the database is not opened and all journals have been deleted (or cleared) by SQLite itself; this implies all transactions have been completed and the database is in a consistent state.
A DB-JOURNAL file is a temporary database file created by SQLite database management systems during a transaction between an application and a database. It contains a rollback journal, which is a temporary database that stores the most recent state of the database.
Is the problem solved in this? I have a case where I can not copy the .db I want to copy on my local machine from the android device. I have to manually delete the -journal on the device to successfully copy the .db. This is my code written in C#
var devices = MediaDevice.GetDevices();
using (var device = devices.First(d => d.Description == "PM67"))
{
device.Connect();
var photoDir = device.GetDirectoryInfo(#"\Internal Shared Storage\Databases");
var files = photoDir.EnumerateFiles("database.db", SearchOption.AllDirectories);
foreach (var file in files)
{
MemoryStream memoryStream = new System.IO.MemoryStream();
device.DownloadFile(file.FullName, memoryStream);
memoryStream.Position = 0;
try
{
device.DeleteFile(#"\Internal Storage\Databases\database.db-journal");//this is the part where I'd like to delete the -journal but it's not working
}
catch
{
}
try
{
if (File.Exists(result) == true)
{
File.Delete(result);
}
}
catch
{
}
WriteSreamToDisk(result, memoryStream);
}
device.Disconnect();
}
I have an sqlite3 database in Android. There is a thread that works with
the db. From another thread, I'd like to copy the sql file to a different location. I do not know whether the db is closed at the moment, or maybe there is a transaction going on at precisely the same moment. Can I assume that the copy of a file will always be a valid sqlite database?
Since the transactions in sqlite are atomic, this looks reasonable but I'd like to be sure.
The db is opened using DatabaseHelper and data is inserted time to time with SQLiteDatabase.insert. Some times the db is closed and then reopened.
Database transactions are atomic, but copying a file is, by itself, not a database transaction.
To ensure that no other SQLiteDatabase object can access the database file, execute BEGIN EXCLUSIVE first.
As long as you do not change the database inside this transaction, the database file is in a consistent state.
This question has been asked just out of curiosity!! I have implemented a database DB1 on android. But when I call method this.databaselist in main activity I am shown that two databases exist DB1 and DB-journal. Why is second database created by android automatically? Do we need to take care of these journal databse too while working on multiple databases??
The manner in which SQLite uses temporary files is not considered part of the contract that SQLite makes with applications.
A journal is a temporary file used to implement atomic commit and rollback capabilities in SQLite. The journal is always located in the same directory as the database file and has the same name as the database file except with the 8 characters "-journal" appended.
The journal is usually created when a transaction is first started and is usually deleted when a transaction commits or rolls back. The journal file is essential for implementing the atomic commit and rollback capabilities of SQLite. Without a journal, SQLite would be unable to rollback an incomplete transaction, and if a crash or power loss occurred in the middle of a transaction the entire database would likely go corrupt without a rollback journal.
The journal is usually created and destroyed at the start and end of a transaction, respectively. But there are exceptions to this rule.
If a crash or power loss occurs in the middle of a transaction, then the journal file is left on disk. The next time another application attempts to open the database file, it notices the presence of the abandoned rollback journal (we call it a "hot journal" in this circumstance) and uses the information in the journal to restore the database to its state prior to the start of the incomplete transaction. This is how SQLite implements atomic commit.
If an application puts SQLite in exclusive locking mode using the pragma:
PRAGMA locking_mode=EXCLUSIVE;
For more details Check
you can elect to keep the journal in memory so that no -journal file is created:
pragma journal_mode=memory;
Note that you need to run this each time you open the database.
credit goes here: How to disable Android SQLite Journal file?
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.