SQLite Writes Crashing App - But Only Selects in My App!?

My app is crashing with this error in the xCode Organizer Console:
deny file-write-data /private/var/mobile/Applications//.app/.db

I’m baffled because my application only selects / reads from SQLite, it never writes or modifies.

The sqlite file is in system.ResourceDirectory.

Thanks in advance for any help. [import]uid: 4621 topic_id: 2196 reply_id: 302196[/import]

Sounds like your not accessing the data file correctly. Have you looked at the SQLite sample app to compare how it’s doing the reads and writes?

-Tom [import]uid: 7559 topic_id: 2196 reply_id: 7069[/import]

Hi, Tom.

My code is based on the SQLite example yep.
I’m only doing reads though. No writes.

The only difference between the SQLite sample and mine is that the example creates the database file. I already had my SQLite database file ready, so the file is in, and read from, system.ResourceDirectory. [import]uid: 4621 topic_id: 2196 reply_id: 7103[/import]

Try taking the file created in the sample and move it into the same directory as your main.lua file. You can do this in the Corona Simulator and copy it from the sandbox /Documents folder.

Now try reading this from your app and see if it works. Maybe there’s an issue accessing the file from the Resource directory.

-Tom [import]uid: 7559 topic_id: 2196 reply_id: 7105[/import]

Hi, Tom, I just resumed (and completed) development of the application referenced in this thread. Per your advice (thank you), I made sure the .sqlite file is in the same directory as main.lua, and I am still getting this error, despite having no writes in my application – all reads.

"unknown sandboxd[4743] : T206(4744) deny file-write-data /private/var/mobile/Applications/66424D27-6893-426A-97DF-DBC9942052AB/T206.app/t206_gallery.db"

The database is only a few tables, all simple text/string data, and the largest one is only 524 rows.

Any other ideas?

Here’s how I handle the connections globally:
[lua]require "sqlite3"

path = system.pathForFile(“t206_gallery.db”, system.ResourceDirectory)
db = sqlite3.open( path )

– Handle Application Events

function onSystemEvent( event )
if( event.type == “applicationExit” ) then
– Close DB Connection
db:close()

– Clear any running timers
stopAllTimers()
end

if( event.type == “applicationSuspend” ) then
– Close DB Connection
db:close()

– Clear any running timers
stopAllTimers()
end

if( event.type == “applicationResume” ) then
– Open DB Connection
path = system.pathForFile(“t206_gallery.db”, system.ResourceDirectory)
db = sqlite3.open( path )
end
end[/lua]

Hopefully something jumps out as incorrect!?

Thank you! [import]uid: 4621 topic_id: 2196 reply_id: 21374[/import]

My guess is the sqlite is writing a pointer into the DB file when it’s opened or closed which is causing the violation because you are not allowed to change any file in the Resource directory.

I believe the solution is to copy the DB file in to the Documents directory and access it from there. You need to add a routine when your application starts to check to see if the file has been copied.

I did create some test code and had no problem reading a small DB file from the resource directory. I copied the data.db file created with our SQLite sample app.

require "sqlite3"  
  
--print the sqlite version to the terminal  
print( "version " .. sqlite3.version() )  
   
   
path = system.pathForFile("data.db", system.ResourceDirectory)  
db = sqlite3.open( path )  
  
print( tostring(db) )  
  
-- Handle Application Events  
   
function onSystemEvent( event )  
 if( event.type == "applicationExit" ) then  
 -- Close DB Connection  
 db:close()  
  
 -- Clear any running timers  
--t stopAllTimers()  
 end  
  
 if( event.type == "applicationSuspend" ) then  
 -- Close DB Connection  
 db:close()  
  
 -- Clear any running timers  
--t stopAllTimers()  
 end  
  
 if( event.type == "applicationResume" ) then  
 print( "Resume" )  
 -- Open DB Connection  
 path = system.pathForFile("data.db", system.ResourceDirectory)  
 db = sqlite3.open( path )  
  
 --print all the table contents  
 for row in db:nrows("SELECT \* FROM test") do  
 local text = row.content.." "..row.content2  
 local t = display.newText(text, 20, 120 + (20 \* row.id), native.systemFont, 16)  
 t:setTextColor(255,0,255)  
 end  
 end  
end  
  
Runtime:addEventListener( "system", onSystemEvent )  

I will ask around but I’m not sure why you getting the error unless there is something writing to the DB file.

-Tom [import]uid: 7559 topic_id: 2196 reply_id: 21761[/import]

Thanks, Tom, I took your advice, and it’s running well now!

[lua]-- See if Database File Already Exists in Documents Directory
path = system.pathForFile( “t206_gallery.db”, system.DocumentsDirectory )
file = io.open( path, “r” )

if( file == nil )then

– Doesn’t Already Exist, So Copy it In From Resource Directory

pathSource = system.pathForFile( “t206_gallery.db”, system.ResourceDirectory )
fileSource = io.open( pathSource, “r” )
contentsSource = fileSource:read( “*a” )

– Write Destination File in Documents Directory

pathDest = system.pathForFile( “t206_gallery.db”, system.DocumentsDirectory )
fileDest = io.open( pathDest, “w” )
fileDest:write( contentsSource )

– Done

io.close( fileSource )
io.close( fileDest )

end

– One Way or Another The Database File Exists Now
– So Open Database Connection

path = system.pathForFile(“t206_gallery.db”, system.DocumentsDirectory)
db = sqlite3.open( path )[/lua] [import]uid: 4621 topic_id: 2196 reply_id: 22521[/import]

Glad you got it working and thanks for posting your solution. I’m not sure why it doesn’t work in the Resource directory but the fact that it works in Documents directory means there is some file writes even when you are only reading the DB file.

Thanks,
Tom [import]uid: 7559 topic_id: 2196 reply_id: 22731[/import]

Well, poopy! I find this now after doing multiple searches and coming up with nada.

So I spent time last night figuring out how INSERTS work in Lua/SQLite and am copying my database a row at a time instead of the snazzy, clean way you’re doing it above.

On the plus side, I needed to dive more into Lua+SQLite anyway, but still… :slight_smile:

So in case anybody else is searching for this info, I’ll include the strings I was searching on so this can be found more easily.

copy files
filecopy
sqlite copy records
copy database

Thanks! :slight_smile:

Jay
[import]uid: 9440 topic_id: 2196 reply_id: 27100[/import]

Regarding post #6:

While this check may be a good solution, I think that it would cause significant problems if the developer updates the app and the user downloads the update.

In that scenario, you will have a new (maybe different) DB in the Resources directory but a used and modified one in the Documents directory. The app is going to start with using the Documents’ DB, since it exists, and the updated Resources’ DB is never going to be applied to the game.

Having said that, I think that beyond checking to see if Docs DB exists, one should also somehow compare the Resources and the Documents DBs, when the app starts, to find out if an update has been applied. If yes, the Docs DB has to be populated in a manner that user info in there (HighScores etc) is not deleted, while any updated or new info is being copied from the Resources’ DB to the Docs’ DB.

[import]uid: 7356 topic_id: 2196 reply_id: 46939[/import]

That’s a very good point. I hadn’t considered it since the database I’m using for the project I wrote that example for is read-only. [import]uid: 4621 topic_id: 2196 reply_id: 46959[/import]

@LiveToCollect

Your solution works nice for my project too. I have a read/write db involved so I’ll now have to find out a way to retain unlocked levels info when new updates are applied and the whole db has to be overwritten.

Thanks for sharing! [import]uid: 7356 topic_id: 2196 reply_id: 46960[/import]

Just for future reference:

ATTACH DATABASE doesn’t seem to work in Lua Sqlite. I ended up syncing the Resource and Documents databases row by row for any updated tables. [import]uid: 7356 topic_id: 2196 reply_id: 47069[/import]

My main take-away from this thread is that the ResourceDirectory in iOS is not meant for storing database files, even if you just intend to read from it. (This is different from Android, mind you.)

Always store the database file in the DocumentsDirectory. That will work for both iOS and Android.

Taking my own dog food now. Changing codes to read from DocumentsDirectory…then have to do regression test on all off them…which largely means playing my own games all over again! [import]uid: 58387 topic_id: 2196 reply_id: 63357[/import]