I tried importing db in my Supporting files folder and connected to db using:
NSString *sqliteDb = [[NSBundle mainBundle] pathForResource:#”person” ofType:#”sqlite”];
if(sqlite3_open([sqliteDb UTF8String], & database)!=SQLITE_OK)
I tried inserting values through code which got inserted but when I quit the program and check the db that values are not present. I don't know what's going wrong here.
Ok. Now copy that database to any local place which will be your data storage of the application. The code given below will do the same.
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *docDir = [docPaths objectAtIndex:0];
NSString *dbPath = [[docDir stringByAppendingPathComponent:#"person.rsd"] retain];
NSFileManager *fm = [NSFileManager defaultManager];
BOOL success = [fm fileExistsAtPath:dbPath];
if(success) return;
NSString *dbPathFromApp=[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent :#"person.rsd"];
[fm copyItemAtPath:dbPathFromApp toPath:dbPath error:nil];
After that, execute your query and you will get inserted data in your application simulator folder.
Files in the bundle are read-only. You can not edit them. You need to copy that database to the app's cache, document or temp directory to perform operations.
First copy your person.sqlite db into application's document directory and then open that db for operations.
Related
Hoping someone can help a new iOS developer out - I have a ready made sqlite database called teamresults.db that I added to the project using "Add Files..." but when I'm using the below code I seem to be connecting/referencing an empty database instead of the one that's added (on inspection through the terminal the database the simulator uses is 0mb in size where as the one I've added is around 3mb).
It seems like the application is creating an empty database but I can't work out why? Any thoughts?
For reference I don't get any error messages:
BOOL success;
dbName = #"teamresults.db";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
dbPath = [documentsDir stringByAppendingPathComponent:dbName];
NSFileManager *fileManager = [NSFileManager defaultManager];
success = [fileManager fileExistsAtPath:dbPath];
if(success) {
return;
}
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:dbName];
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePathFromApp error:nil];
There seems to be something wrong with this line of code:
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePathFromApp error:nil];
The correct one would be:
[fileManager copyItemAtPath:databasePathFromApp toPath:dbPath error:nil];
You should copy database to sandbox path instead of resources path !!
Do one thing. Delete the database added by right click on that and click delete instead of "Delete reference only". Then add it again and don't forget to click on "Copy into destination item". Hopefully that would help you.
I will try describe my problem as best as I can. I have created a sqlite database using the console on the mac. I've added the file to my project, by right clicking and hitting "add files to (projectname)" and it adds the database. I am able to read the database, however when I try and update the database, although my debugging has confirmed the statements (update statements) succeed, the data in the database is not updating. I am gathering this is because the pointer to the database file is pointing to the .sql file in my documents (which is where the original file that I added is located), however I thought by adding the file to the project, a copy of that file would go within the project folder.
My question is how can I add a .sql file to my project where it is not referenced from the desktop, and be able to update the information that is located within the database.
No the file is not the one on your desktop, the file be bundled in the .app bundle.
The database is located in the app bundle which is readonly, you will need to move the database to the document directory on first startup.
place something like this in the - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES) objectAtIndex:0];
NSString *sqlFile =[documentDirectory stringByAppendingPathComponent:#"yourdb.sql"];
if (![[NSFileManager defaultManager] fileExistsAtPath:sqlFile]) {
NSString *bundleSql = [[NSBundle mainBundle] pathForResource:#"yourdb" ofType:#"sql"];
NSError *error = nil;
[[NSFileManager defaultManager] copyItemAtPath:bundleSql toPath:sqlFile error:&error];
if (error) {
NSLog(#"Could not copy json file: %#", error);
}
}
Get your SQL file's directory path on your bundle by :
NSString *sqlFilePath = [[NSBundle mainBundle] pathForResource:#"YourSQLFileName" ofType:#"sql"];
Next copy the sql file to your sandbox directory using this command :
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *sandboxDirectoryPath = [documentPaths objectAtIndex:0];
NSString *newSQLFilePath = [NSString stringWithFormat:#"%#/YourSQLFileName.sql", sandboxDirectoryPath];
[[NSFileManager defaultManager] copyItemAtPath:sqlFilePath toPath:newSQLFilePath error:error]
I create database and put *.sqlite file in recources folder in Xcode. Before opening database I copy it to documents folder from resources.
This works fine on simulator, but does not work on iPhone.
For some reasons database file does not exists in iPhone device. This is my code:
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *databasePath = [documentsDir stringByAppendingPathComponent:databaseFileName];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL success = [fileManager fileExistsAtPath:databasePath];
if(!success) // all the time it's YES, even if I delete database
{
// copy database from application folder
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseFileName];
BOOL fileExists = [fileManager fileExistsAtPath:databasePathFromApp];
if (fileExists) { // It's NO, for some reasons database does not exist
[fileManager removeItemAtPath:databasePath error:nil];
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
}
[fileManager release];
}
return databasePath;
For some reasons this line returns NO all the time
BOOL fileExists = [fileManager fileExistsAtPath:databasePathFromApp];
the path in databasePathFromApp somthing like this
/var/alexander/xxx-xxx-xxx-xxx..../AppName.app/database.sqlite
The question is: why database does not exists in recources?
Finaly found the problem. iPhone device care about file name register, so "database.sqlite" and "DataBase.sqlite" is different files for device, but the same files for simulator. It's so weird.
I posed it in the blog
Can't open file in iPhone device, but can in iPhone simulator
Delete database from resource & add it once again &
check box appears at top with Copy items into destination group folder.
Clean targets & reset simulator.
I have an app leveraging Core Data SQLITE3 that works perfectly in the simulator. However i do not understand how to update the DB on the device, which i guess is the same as in app-store.
I update the DB from .txt files in the app and create the DB, this function is there only for creating the DB and will be removed in the final version. My idea is to create the DB in the simulator, lock the update part of the code and then distribute the package with an updated database.
However, when i rebuild my app on the device it still have the old data in the DB.
I have been looking around but i am afraid i do not fully understand how to solve this. I did find this thread: Can't refresh iphone sqlite3 database
I would very much appreciate if some nice person could share some light on this and help me to solve this.
Cheers
Have you copied the db file from the bundle directory (which is read only) to a writable one? (like the documents directory of each application?).
When trying to save in the device did you get a sqlite error like this?
SQLITE_READONLY 8 /* Attempt to write a readonly database */
EDIT:
All the files in the main bundle are read only, so if you need to modify one/some of them, you need to copy the files in a location that is writable. Assuming you have called the db mydb.sqlite here is some code that copies the db (only if it does not exists) to the documents directory.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDirectory = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSFileManager *fm = [NSFileManager defaultManager];
NSString *docPath = [docDirectory stringByAppendingPathComponent:#"mydb.sqlite"];
if (![fm fileExistsAtPath:docPath]) { // file does not exists, copy it
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:#"mydb" ofType:#"sqlite"];
NSError *error = nil;
BOOL res = [fm copyItemAtPath:bundlePath toPath:docPath error:&error];
if (!res) {
// do something with error
}
}
Actually to use .db file inside the Bundle - it's a very bad idea.
Every thime, when I am using .db file, i am checking, if it allready exists inside my Application document directory, and then I will rewrite it.
#define DB_SHOULD_BE_REWRITTEN YES //You should update database and change allready existing db file to file from bundle
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"db.sqlite"];
BOOL success = [fileManager fileExistsAtPath:writableDBPath];
if (!success || DB_SHOULD_BE_REWRITTEN)
{
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"db.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
dbPath = writableDBPath;
I've got the following iphone code, which seems to be failing:
sqlite3_stmt *dbps;
NSString *sql = #"delete from days where day=?1;insert into days(disabled,recipe_id,day) values(?2,?3,?1)";
int rc = sqlite3_prepare_v2(db, sql.UTF8String, -1, &dbps, NULL);
...
The 'rc' return code is 1, meaning SQLITE_ERROR (SQL error or missing database, according to the sqlite site). Not sure what i've done wrong? The database 'db' is indeed open, and other queries seem to work fine.
Thanks a lot guys
Remove the insert statement from your string. It is not compiled anyway since sqlite3_prepare_v2 will "only compile the first statement in zSql."
Perhaps you should use a trigger to do your (optional) delete, or use insert or replace.
Are you sure you have copied the database in Documents directory before opening it? iPhone OS only allow write permissions in documents directory. Here is the code for copying database to Documents directory -
//function to copy database in Documents dir.
-(void) checkAndCreateDatabase{
// Check if the SQL database has already been saved to the users phone, if not then copy it over
BOOL success;
// Create a FileManager object, we will use this to check the status
// of the database and to copy it over if required
NSFileManager *fileManager = [NSFileManager defaultManager];
// Check if the database has already been created in the users filesystem
success = [fileManager fileExistsAtPath:databasePath];
// If the database already exists then return without doing anything
if(success) return;
// If not then proceed to copy the database from the application to the users filesystem
// Get the path to the database in the application package
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
// Copy the database from the package to the users filesystem
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
[fileManager release];
}
// open the database and fire the delete query...
sqlite3 *database;
NSString *sqlStatement = #"";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
NSLog(#"%#",databasePath);
[serlf checkAndCreateDatabase];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
// here you can fire the delete query...
}
Silly me, i just had an old copy of the schema in my Documents folder, which didn't have the 'days' table in it. So i followed the instructions here: Cleaning up the iPhone simulator, and then it copied the new schema over, and it started working again.
Thanks for the help guys.