Database error when testing on device

Hello everyone. I have the following problem. I have an application that queries a database in sqlite. When I run the app in xcode on my mac I give it the path to the database to make it work. So far so good. But when I want to test this application on a physical device (iPhone 11), I get the error that the application cannot find the database. My question or problem is where I have to store the database on the iPhone so that the application can make the queries. Thank you.

I am putting my db on app group directory so that the app and app widgets can access it:

let dbName = "my-db.sqlite"
let documentsDirectory = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.org.org-name.app-name")
let databaseURL = documentsDirectory?.appendingPathComponent(dbName)

Where do you want that database to be? Possible locations depending upon your use case: Document folder, Temporary folder (could be deleted by OS on a whim), Caches folder (ditto, but less aggressively), Application Support folder (don't remember off-hand if this one is writeable), App bundle (read-only). And if it is a pre-populated DB (rather than the one created from scratch) you'd need to copy it to the target location first (e.g. from your app bundle).

Tera, thank.First of all, thank you very much for answering me.I want the database to go with the application. That is, I have created the application on my mac and now I am testing it on my iphone. The problem is that I DON'T KNOW WHERE TO SAVE the database so that when I run the application on the iPhone it works. My application works perfectly on the iPhone, except when it has to perform a query, because it doesn't know where the database is, and that is my question, where do I have to put the database on the iPhone so that, when the application, you can make the query, because now, when you want to make the query, the application gives me an error and it doesn't work.

Thanks for the reply. But I have a question. When you say . "I am putting my db on app group directory so that the app and app widgets can access it:" I don't quite understand, do I have to put the database inside the application's file group in Xcode? As if it were a view?

Tera, thank.First of all, thank you very much for answering me.I want the database to go with the application. That is, I have created the application on my mac and now I am testing it on my iphone. The problem is that I DON'T KNOW WHERE TO SAVE the database so that when I run the application on the iPhone it works. My application works perfectly on the iPhone, except when it has to perform a query, because it doesn't know where the database is, and that is my question, where do I have to put the database on the iPhone so that, when the application, you can make the query, because now, when you want to make the query, the application gives me an error and it doesn't work.

If I understand your task correctly - your database is writeable (not just used for read-only queries). If that's the case I'd do something like this:

  1. put your DB file in Xcode project normally, make sure it gets into the resulting binary (check Target Membership property of that file).
  2. on app startup check Documents folder location (e.g. .../Documents/database.db)
    2.a if the file is not there - copy it from your bundle location
    2.b if the file is already there - it was already copied (on previous app launches), do nothing
  3. after that point your code to use DB in the document folder location.
extension URL {
    static var documentsDir: URL {
        let array = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
        let path = array.first.unwrap()
        return URL(fileURLWithPath: path)
    }
    var fileExists: Bool {
        FileManager.default.fileExists(atPath: path)
    }
}

var dbFile: URL!

func onLaunch() {
    dbFile = URL.documentsDir.appendingPathComponent("database.db")
    if !dbFile.fileExists {
        let sourceFile = Bundle.main.url(forResource: "database.db", withExtension: nil)!
        try! FileManager.default.copyItem(at: sourceFile, to: dbFile)
    }
}

In addition to that if you specify "Application supports iTunes file sharing: true" in the project's plist file you'll be able to import / export that file from your app when you connect your iPhone to the computer (Devices → your device → Your app → Files tab) - might be convenient for debugging, or as a user feature.

Thanks again for answering me. I tell you. The database is READ ONLY, depending on the option chosen by the user, the application performs a query with the database (sqlite) and it returns some data. This the first.The second thing I don't understand about itunes. I beg your patience because I am new to this and I have no idea, for me this is completely new. Could you explain to me step by step how to do what you say? I beg your patience and thank you very much for everything.

hanks again for answering me. I tell you. The database is READ ONLY, depending on the option chosen by the user, the application performs a query with the database (sqlite) and it returns some data. This the first.The second thing I don't understand about itunes. I beg your patience because I am new to this and I have no idea, for me this is completely new. Could you explain to me step by step how to do what you say? I beg your patience and thank you very much for everything.

Then, assuming SQLite can work with the DB from a readonly location †, just place the DB in Xcode's project:

And use in the app like so:

let dbFile = Bundle.main.url(forResource: "database.db", withExtension: nil)!
... use dbFile ...

Change the DB file name accordingly.

(† and if SQLite can't work with a read-only file then follow the approach I outlined in the previous post).

Please note that questions like these are out of scope on this forum and better asked on stackoverflow or apple dev forums.

1 Like

I am reading json files delivered within the app using this approach, so I'd assume reading (read only) SQLite database files would work too. Haven't tried though.

1 Like

Good morning. Sorry for replying so late. I have had the flu and I have not been able to recover until today. I have tried what you indicate in the image and I have used the code

var Database: OpaquePointer?
let dbFile = Bundle.main.url(forResource: "Database.sqlite", withExtension: nil)!

    if sqlite3_open(dbFile.path, &DataBase) != SQLITE_OK
     {
         //Error opening the database
        
         print("Error opening the database")
         let alertController = UIAlertController(title: "Information", message: "Error. Database not found.", preferredStyle: .alert)
         alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Default Action"), style: .default, handler: {_ in NSLog("OK")}))
         self.present(alertController, animated: true, completion: nil)
        
         //                        //We went out
         return
     }
     else {
         // We perform query

I have tried to run the application on an iPhone physically, and the database cannot be found.

And I'm desperate because I don't know what to do, I just have to try on physical devices to upload the application, if it works, to the apple store... but it keeps giving me the error, and it's only on the physical device.

PLEASE HELP TO TEST THE APPLICATION ON THE IPHONE. AND LET IT FIND THE DATABASE!!

I have not used the C API to SQLite, only through Swift library.

But if the db is read only and in a read only location, have you tried passing the read only flag?

https://www.sqlite.org/c3ref/open.html

Also have you tried checking with File Manager API that the file is really on the device?

What is the error code returned from open?

1 Like

Should be easy to debug such things, build those skills.
E.g. put "precondition(FileManager.default.fileExists(atPath: dbFile.path)))" before opening the file and step through those lines in debugger.

1 Like

Hello again. I have already managed to open the database. But, when I do a query, it always tells me that it can't find the tables. this is my code

let queryString = ("SELECT * FROM TipoCoche")
var stmt:OpaquePointer?
if sqlite3_prepare(BaseDatos, queryString, -1, &stmt, nil) != SQLITE_OK
{
let errmsg = String(cString: sqlite3_errmsg(BaseDatos)!)
print("error: (errmsg)")
return

And it always tells me the same error, can't find the table.
My question is, if it finds the database and opens it (in the above code), why does it tell me that it can't find the table? Any table that it puts in the database... I don't understand! .Any help please?. All this is when running the app on the physical device, which is an iphone 11. If I run it on an iphone 11 emulator in xcode, it finds the tables... Any help, please??

Hello again. I have already managed to open the database. But, when I do a query, it always tells me that it can't find the tables. this is my code

let queryString = ("SELECT * FROM TipoCoche")
var stmt:OpaquePointer?
if sqlite3_prepare(BaseDatos, queryString, -1, &stmt, nil) != SQLITE_OK
{
let errmsg = String(cString: sqlite3_errmsg(BaseDatos)!)
print("error: (errmsg)")
return

(code)

And it always tells me the same error, can't find the table.
My question is, if it finds the database and opens it (in the above code), why does it tell me that it can't find the table? Any table that it puts in the database... I don't understand! .Any help please?. All this is when running the app on the physical device, which is an iphone 11. If I run it on an iphone 11 emulator in xcode, it finds the tables... Any help, please??

This is getting too far from the subject area of this forum - swift language itself. You may try luck elsewhere (e.g. stackoverflow). As mentioned your issue seems to be relates to read-only DB (on the phone) and read-write DB on the simulator, hard to tell anything else. Be prepared to not get the ready answer - that's part of developer's job to resolve issues like these, one by one.

1 Like

One last question, please.
When I display the path of the database, I get something like this
/var/mobile/Containers/Data/Application/C2D370B0-E8B4-4DBD-BC5C-82A63FA27C92/Documents/

However, I go to that folder and it doesn't exist on the iphone!!..

Any help please?

What do you mean, "go to that folder"? Unless you have rooted your iPhone (from which I'd discourage you as it is by far not needed for your task) you cannot access it. Applications are sandboxed on the iPhone, so while you "see" a certain folder from within your app (and that path looks it is in your app's sandbox), from other apps (the "Files" app, for example) you will not see it.

All in all: You should probably really try to address this elsewhere, this all is fundamentals of iOS specifically and not Swift generally. We're not trying to discourage you (quite the contrary!), these forums are simply not a good fit. :slight_smile:

This is really not Swift programming language question but Xcode / iOS / general tool question so, as said above, should discuss this on Apple Developer Forums or Stackoverflow. But anyways.

See the attached screenshot. I just created an empty iOS project, added a SQLite db file to it I created at terminal and then executed it on my phone. As you can see from the log, the app prints that the file is there.

Make sure you include the database file in Copy Bundle Resources Build phase.