I have an SQLite database with records being inserted into it for my Android app.
I am inserting the answers to on screen surveys, with one answer saved per row in my table.
My surveys have 20 questions, and it inserts the answers correctly to the database for the first survey, but then when I insert the answers for the second survey (programatically the same questions, just done again) it malforms the database, but never throws an exception or anything. I run an integrity check before and after and it always returns true.
The unusual thing is that it is only malformed when I try to look at the table on my computer. I tried using the SQLite Database Browser tool, TKSQLite tool, and then opening the DB from the supplied sqlite3.exe, and they all seem to show the DB as malformed. Although the TKSQLite tool notifies me that the table is malformed, I can get the data in other tables. The SQLite Database Browser just shows no data in the table, and sqlite3.exe won't open any tables.
The very unusual thing is if I query the table in the app and print the cursor rows out to log cat, or use the data within the app, all the data is there.
Has anyone seen only partial malformation without an exception being thrown? I would like my database to be pristine...but if my data is there can I hope that it won't get any more malformed?
I worked with SQLite databases for a few projects now doing similar things, and this is the first time I am seeing only partial malformation.
If it will help I am using the Acer a501 tablet programming on Honeycomb 3.2
Additionally, I am accessing the database using a static singleton, to avoid opening and closing the database too often for each insert, and originally inserted via SQL commands using execSQL(), but have also tried using the SQLiteDatabase method insert() to no avail.
We figured out why the database was malforming but not on the device. The tablet we are using is counted as a Portable Media Device according to Windows, and there was some issue when we copied it from the device to the computer. Using a thumb drive to copy to from the device and then from the thumb drive to Windows solved the problem.
Related
I'm working on an Android app where we need to migrate from some legacy SQLite code to a Room based implementation. But I've run into a couple of issues & I'm not sure how to solve them.
Environment:
Android 6.0+
SQLite implementation is in one database file
Room implementation is in a separate database file
Both will be in /data/user/0/.../databases/
What sorta works, but is slow:
We have a working test implementation to pull all the legacy SQLite tables' data into Kotlin objects, then do inserts into the Room based tables. But, it's fairly slow for our test cases (about 70 secs for 10k+ rows in at least one table). Real life cases could top 100k rows in at least one table. As far as I can tell, the select is one transaction and the inserts are wrapped in a transaction. So, I don't think it's transaction overhead slowing us down.
What we want to make work:
What I'm hoping to do is use SQLite's attach database and detach commands to load the legacy SQLite database into a Room DB connection. Then, I can do an insert into new_table.table_name select * from old_table.table_name. The actual SQL will be slightly different due to slight schema changes. But, the insert-select pattern will be the basic idea.
I'm using ContextWrapper to get the full database path for the legacy database file. That works fine.
What issues I'm seeing:
When I try to do the attach command, though, I was getting an IllegalStateException with something about not being able to enable/disable write-ahead logging while in a transaction or the db is open. But, the legacy DB is not open or in a transaction at that point.
So, I modified the approach to set the journal mode to TRUNCATE in the Room db connection setup. That allowed me to do the attach command. And the insert-select query seems to work as far as I can tell (I haven't fully tested that yet). BUT, when I tried the detach command, I got a SQLite 1 error about the database being locked.
For reference, my basic code for both above attach approaches is:
roomDb.execSQL("attach database '$fullLegacyDbPath' as old_db")
roomDb.execSQL($insertSelectQuery) // the "INSERT INTO ... SELECT ..." query
roomDb.execSQL("detach old_db")
Any ideas how I make this work (preferably without setting the journal mode to truncate)?
I'm currently developing an Application that uses a Database / ContentProvider to provide certain location data that's pulled from the network and stored locally in a database periodically.
I've verified that the database is created correctly in the Application, and the Tables are populated with data by exporting a copy of the app local database to the SD card for viewing in a SQL browser -- so the data not being present is not the issue here.
The odd behavior is probably better visualized through a couple of screen shots of my debugging process:
So, initially when I did my queries, all of my Cursor objects were returning -1 for the row count, even though I verified that a SELECT * FROM TABLE_NAME statement should return values, since the database I pulled off of the device contains row data. Here's a look at the debugger step:
Notice that when the cursor is initially returned, mCount displays as -1.
Out of curiosity, I added the cursor.moveToFirst(); call, and here's a screenshot from after that step:
Notice that the cursor count changed from -1 to 3, which corresponds to the correct number of rows (since the application only accounts for 3 continents atm). Unfortunately, this added line that should be unnecessary still doesn't fix my problem, since CursorAdapter.bindView() and CursorAdapter.newView() still fail to be called with the resulting cursor.
I'm confused as to what could be causing this issue, and how to fix it? If anyone could give any insight into what the problem could be, please let me know. Also, if any additional code is needed, such as the SQL create statements, etc let me know - however, as I've already mentioned the database is created fine and queries performed on the exported db copy outside of the Android application work just fine...
One last thing, the application is built for API levels 14+.
If you have an SQL query that are reading from the database you would want to delay reading that data until you are certain that you will use it.
So when you call rawQuery you get a reference to a Cursor object. But nothing is read yet. This is what themoveToFirst does. It is the first thing that tells the cursor that you are serious about running this SQL query and that you want a result.
But since you are using rawQuery nothing is passed on to the database before you try to fetch a result with moveToFirst.
Hope this answers your question.
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 have a really different situation while using same database file in android app
and web app. Hope someone has idea about this problem.
I have a web application that has a database with full of data. After that, I am exporting
the file to my PC and PC to android device in .sqlite format. At this point, Let's say the last primary key id of one table in database is 25.
Now, android app will use that database file to operate. In the same table more data will
be inserted. Let's say 10 more. Now the last primary key id will be 35(25+10).
At the mean time, if I insert some more data into the database from web app, let's say 3
more. Then, the last primary key id will be 28(25+3) in the database of web app.
Now, I am pulling database file from android device and importing to the web app to keep
records
for future. The database file in the web has most of the data same as newly
imported database from android device because it was exported to android app before.
Now I want to merge the both database files to make one single database file and show record in web app. For that, what I want to do is;
Filter data from both databases not to keep same records.
Manage to replace the primary key id of android app's database followed by the last
primary key id of web app's database. Like 28+10 = 38 Now the newly modified database file has 38 records.
Please someone give me some technical idea because it is even hard for me to google. I am sorry if it is unclear. If it unclear, do not hesitate to ask.
Sounds complicated, maybe you should consider moving your data handling entirely to a cloud database: A relational database shared by an android app and a website - the easy way.
Alternatively I would suggest having two id keys on the android device, namely (_id, _id_server). This way, when importing the database from the web, the _id_server is populated and known and any future updates, from phone to web, will be easily filtered as they either have no _id_server value (new insert) or if the value is there (update existing entry).
I do not like the idea of altering id's on the web, can see a lot of problematic scenarios if doing so.
I have been testing my app which uses the dbadapter from Reto Meir's earthquake example. Everything was going ok for several days but when debugging with the app on the device today I got the 'no such table' error. I changed the name of the database and all runs well again. This doesn't give me much confidence regarding potential other users.
Since it seems impossible to see the database on the phone, by design I suppose, I can't see how to find out what caused the problem and take steps to avoid it. The database appears to open ok at the start of the program but errors when handling a select query. Just changing the name of the table doesn't fix it, it has to be a new database name.
As the change of name allows it to run ok I can't see that the code is wrong. I wonder if the data becomes corrupted.
I've also found that after successfully inserting a row, then later getting a cursor to allitems sometimes produces a -1 error against a get for one of the column names. How can a column name drop out of the columns index?
I've googled this type of problem and whilst there are a lot of folks with the problem and a lot of replies I can't find anything which informs on the underlying reason for these problems - which is what I am after.
I was having the same problem with this. I was changing the version number, uninstalling application etc... in the end it was due to me not submitting the transaction of the sql call. It might be worth checking out the answer in the following for some clarity - https://stackoverflow.com/a/13568419/1634369
The database is available on the phone and if you can 'adb shell' to the phone, you can also use sqlite3 command line shell to connect, examine, query and modify your database. It's pretty much the same functionality as you'd get with oracle's or mysql's command line tools.
You can see some more details here for example:
http://www.infinitezest.com/articles/using-sqlite-from-shell-in-android.aspx
As for "no such table" case - it really depends on where you store your database. You can choose (at DB creation time) where the database is stored - it might be the internal /data/data (usually) folder where your application resides or you could (mistakenly) create it in cache space - cache can be cleaned at any time whenever Android's OS finds that it needs more space, so this might explain why your database disappeared.
Another possibility is that instead of reinstalling the application, you uninstalled it and installed in two steps. Uninstalling application also deletes all the private data for the application (on most phones, but not on all), whereas reinstalling application (For example by clicking Run in eclipse) does not delete the data. In any case - in you application's onCreate you should recreate the database including all tables - always if you find it has not been yet created - because you never know if you run application for the first or subsequent time.
Please explicitly link to the example you reference.
The way I understand it, you create your own database at launch, unless the database already exists on the device, in which case the database creation is skipped. Correct?
If that is correct, then the only thing you need to do is uninstall the application whenever you update the database design (to remove the old database, with the old table names, etc) and re-install, so the database is recreated with the new table names.
Otherwise you will have updated application code that tries to work with an outdated database.