Copying New Database

Bill Norris

Active Member
Licensed User
Longtime User
When my app is completed, I will be periodically sending a new database to the devices via push. I've got that all figured out so no problems. What I am wondering is are there any concerns or issues I may encounter by overwriting the database while the device is in use. The database interaction is read-only, so I don't have to worry about interrupting a database update. What happens if the new database is copied to dir.defaultexternal at the same time the app is reading data. I know this all occurs almost instantaneously, but I suppose it could happen. Is there a way to detect if a cursor is open on the database before copying over the new one? Any thoughts or suggestions appreciated.
 

mc73

Well-Known Member
Licensed User
Longtime User
I think you can use a boolean flag set to true whenever your database is under process. This way, you will wait until this flag turns to false, and then you will proceed with the update. Just a thought.
 
Upvote 0

Bill Norris

Active Member
Licensed User
Longtime User
RE:

Unless you are accessing the database from two different applications, this issue cannot happen as your code runs in the main thread.
Since the push notification is running as a service, I assume that it executes its code asynchronously in the background. I am not really up to speed on the concept of "threads". Might you explain a bit more.


It is recommended to close the SQL object before replacing the database.


I have several activities in the app, and each has its own sql.initialize and subsequent cursor=sql.execute....... statements. I execute a cursor.close statement in each activity whenever a new activity is called. I didn't know about closing the sql also. When should sql be closed .. immediately after the cursor=sql.execute... statement?
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Since the push notification is running as a service, I assume that it executes its code asynchronously in the background.
The service code runs in the same thread. You can safely overwrite the database.

It is better to have a single SQL object. It can be a process global variable so you can access it from other modules.
You should then close SQL, copy the new database and reopen it.
 
Upvote 0

Bill Norris

Active Member
Licensed User
Longtime User
this project got set aside for a short time but I am back on it. Is possible to verify that I am closing the sql (Main.sql_main.Close) at the proper place, or should it be closed before the out=File.OpenOutput..... line?


B4X:
If HttpUtils.IsSuccess(FileUrl) Then 
            Dim database As InputStream
            database=HttpUtils.GetInputStream(FileUrl)
            Dim out As OutputStream
            out = File.OpenOutput(File.DirDefaultExternal,"WINE_TABLET.DB",False)
            Main.sql_main.Close
            File.Copy2(HttpUtils.GetInputStream(FileUrl), out)
            out.Close
            ToastMessageShow("Database Download Complete", True)   
         End If

One other issue. Note that the database name "WINE_TABLET.DB" is uppercase. For some reason, the name of the downloaded database is showing in file manager as uppercase. The file name as it exists on the server is lower case. I cannot figure out where the uppercase is coming from. I didn't even realize this until I started getting the following fatal error.
B4X:
java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.io.FileNotFoundException: /mnt/sdcard/Android/data/wine_tablet.pss/files/wine_tablet.db: open failed: ENOENT (No such file or directory)
 
Upvote 0

Bill Norris

Active Member
Licensed User
Longtime User
RE:

Please advise if you want a new thread here. Does "Open the database" mean the same a "initialize the database"? I have declared the sql object globally in main activity. Then, in all of the other activities when I need to read the database, I initialize that sql object each time time just before the cursor=sql..... statement. Is that necessary, or can I simply initialize sql object one time in main activity.
 
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
Please advise if you want a new thread here. Does "Open the database" mean the same a "initialize the database"? I have declared the sql object globally in main activity. Then, in all of the other activities when I need to read the database, I initialize that sql object each time time just before the cursor=sql..... statement. Is that necessary, or can I simply initialize sql object one time in main activity.

You can check whether it is already initialized and if not, initialize it:
B4X:
If yourSQL.IsInitialized = False Then
     yourSQL.Initialize(yourDir, "yourDB.db", False)
End If
I think that since you've already initialized it in your main activity, you don't have to worry about that. But, if you close it for some reason elsewhere, the above if condition will probably do its job.
 
Upvote 0

Penko

Active Member
Licensed User
Longtime User
Just to add a little to @mc73's post. On my Android 2.2 device, the connection to my DB was killed in very strange situations so i was getting errors. I was searching for a solution but no one really told me my phone is kiling resources from apps even if they are not fully closed. Now that i dont have any problems anymore, i can conclude "lazy initialization is best". You may add initialization to your first activity but also add it anywhere else you have DB logic. Do it like this:

Sub init()
If(sql1.isInitialized = True) Then
Return
End if

Sql1.Initialize()

End sub

Call this anywhere before sql logic and you are safe. You just loose time for a single boolean operation but i think it is worth doing it compared to having a big chance of DB not initialized errors.

Sent from my Next7P12 using Tapatalk 2
 
Upvote 0
Top