Read write access of sqlite in objective c - iphone

Hopefully this makes sense. I have a sqlite database in my documents folder. I also have a function that checks to see if that file exists in the directory, and if it doesn't, it is moved there from the main bundle. So I know that the database is in the correct place to access. However, when I run my app, I get the error: no such table: databaseName. Could the problem have to do with read write access of the sqlite database? If so, how to I check this and rectify the problem?
#define kFilename #"foods.sqlite"
- (NSString *)dataFilePath {
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* sqliteFile = [documentsPath stringByAppendingPathComponent:kFilename];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:sqliteFile];
if(fileExists)
return sqliteFile;
else {
NSString *sourcePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:kFilename];
NSString *folderPath = [documentsPath stringByAppendingPathComponent:kFilename];
NSError *error;
[[NSFileManager defaultManager] copyItemAtPath:sourcePath
toPath:folderPath
error:&error];
NSLog(#"Error description-%# \n", [error localizedDescription]);
NSLog(#"Error reason-%#", [error localizedFailureReason]);
}
return [documentsPath stringByAppendingPathComponent:kFilename];
}
-(void) viewWillAppear:(BOOL)animated{
sqlite3 *database;
if (sqlite3_open([[self dataFilePath] UTF8String], &database)
!= SQLITE_OK) {
sqlite3_close(database);
NSAssert(0, #"Failed to open database");
}
sqlite3_stmt *statement;
//why is this if statement failing?
if (sqlite3_prepare_v2(database, [sqlStatement UTF8String],
-1, &statement, nil) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
//int row = sqlite3_column_int(statement, 0);
char *rowData = (char *)sqlite3_column_text(statement, 1);
foodName = [[NSString alloc] initWithUTF8String:rowData];
[foodArray addObject:foodName];
}
sqlite3_finalize(statement);
}
else {
NSLog(#"%i", sqlite3_prepare_v2(database, [sqlStatement UTF8String],
-1, &statement, nil));
NSLog(#"Statement: %s", sqlite3_errmsg(database));
}
sqlite3_close(database);
}

Use this way instead. skip the intermediate directory steps, and talk right to the db.
- (void)checkAndCreateDB {
NSString *dbPath = [[[NSBundle mainBundle] bundlePath]stringByAppendingPathComponent:#"../Documents/yourDB.sqlite"];
// Check if the SQL database has already been saved to the users phone, if not then copy it over
BOOL success;
// Check if the database has already been created in the users filesystem
success = [[NSFileManager defaultManager] fileExistsAtPath:dbPath];
if(!success) {
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"yourDB.sqlite"];
[fileManager copyItemAtPath:databasePathFromApp toPath:dbPath error:nil];
NSLog(#"readandwrite is available");
}
if(!(sqlite3_open([dbPath UTF8String], &dB) == SQLITE_OK))
{
NSLog(#"An error has occurred.");
}
}

The error that you are getting says that the table 'databaseName' does not exist in your database file.
You are not getting an error that the database can not be opened, so that isn't the problem.
It looks like your sqlStatement is wrong.

Related

Not able to store data in database in iphone

I am new to iphone programming.Iam using Mac 10.7.3 in that i am not able to store data in database I am storing data inside database through textfield.Can any body tell me why its not adding data inside the database.What is mistake in this code
NSString *docsDir;
NSArray *dirPaths;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
// Build the path to the database file
databasePath = [docsDir stringByAppendingPathComponent: #"test.db"];
NSLog(#"%#",databasePath);
NSFileManager *fn=[NSFileManager defaultManager];
NSError *error;
BOOL success=[fn fileExistsAtPath:databasePath];
if(!success) {
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"test.db"];
success = [fn copyItemAtPath:defaultDBPath toPath:databasePath error:&error];
}
//NSLog(#"sdasdassd%#",databasePath);
NSLog(#"hai");
sqlite3_stmt *statement;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
NSLog(#"hai2");
NSString *insertSQL = [NSString stringWithFormat: #"insert into path(imagepath,audiopath) values (\"%#\",\"%#\")",name.text,email.text];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(#"details added");
} else {
NSLog(#"details not added");
}
sqlite3_finalize(statement);
sqlite3_close(contactDB);
}
}
Thanks
Aslam
First of all, when application load, then copy database into application folder
App Delegate file's Code ::
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSString *docsDir;
NSArray *dirPaths;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
//Build the path to the database file
databasePath = [docsDir stringByAppendingPathComponent: #"test.db"];
NSLog(#"%#",databasePath);
NSFileManager *fn=[NSFileManager defaultManager];
NSError *error;
BOOL success=[fn fileExistsAtPath:databasePath];
if(!success) {
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"test.db"];
success = [fn copyItemAtPath:defaultDBPath toPath:databasePath error:&error];
}
}
Then, on Save Button Click,
here, [app dbpath] is NSString accessed from delegate file.
Code ::
sqlite3_stmt *statement;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open([[app dbpath] UTF8String], &contactDB) == SQLITE_OK) {
{
NSString *insertSQL = [NSString stringWithFormat: #"insert into path(imagepath,audiopath) values (\"%#\",\"%#\")",name.text,email.text];
const char *insert_stmt = [insertSQL UTF8String];
if (sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL) == SQLITE_OK) {
NSLog(#"details added");
}
else {
NSLog(#"details not added");
}
sqlite3_finalize(statement);
sqlite3_close(contactDB);
}
It may be help to you.
Thanks.

Error trying to open DB in SQLite (iOS)

Am making an iOS apps with an embedded SQLite database. So I make my DB in a SQLite administrator and drag it to my Xcode project, like in the tutorial says.
When I try open my DataBase, I get this error: "out of memory". Dont know if it is a SQLite bug or something, but my file is really small to get a memory problem.
This is my code to init my DataBase:
- (id)initWithPath:(NSString *)path {
if (self = [super init]) {
BOOL success;
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dbPath = [documentsDirectory stringByAppendingPathComponent:#"SoundLib_DB.sqlite"];
if ([fileManager fileExistsAtPath:dbPath] == NO) {
NSString *resourcePath = [[NSBundle mainBundle] pathForResource:#"SoundLib_DB" ofType:#"sqlite"];
[fileManager copyItemAtPath:resourcePath toPath:dbPath error:&error];
}
success = [fileManager fileExistsAtPath:dbPath];
if(!success)
{
NSLog(#"Cannot locate database file '%#'.", dbPath);
}
sqlite3 *dbConnection;
//Here is when I get the error, at trying to open the DB
if (sqlite3_open_v2("SoundLib", &dbConnection, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) {
NSLog(#"[SQLITE] Unable to open database!");
NSLog(#"%s Prepare failure '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(database), sqlite3_errcode(database));
return nil;
}
database = dbConnection;
}
return self;
}
Error may be because you need to pass databasepath as UTF8String. I see you are passing "SoundLib". You can not directly pass like that.
if (sqlite3_open([dbPath UTF8String], &databaseHandle) == SQLITE_OK)
{
//dbPath is your full database path you getting above
}
P.S. Also have dbpath as const char
const char *dbpath
Change your opening process so that it looks like this... It works for me ;)
I guess your main mistake is that you forgot the UTF8String....
sqlite3 *database;
int result = sqlite3_open([dbPath UTF8String], &database);
if (result != SQLITE_OK) {
sqlite3_close(database);
NSLog(#"Error opening databse");
return;
}

Insert Values In SQLITE Database

I tried to insert values in sqlite3 database, but it cant work on my app.
I follow this code where all this values in table are varchar.
sqlite3_stmt *statement;
NSString *docsDir;
NSArray *dirPaths;
int ID;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
// Build the path to the database file
databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: #"weather.sqlite"]];
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat: #"INSERT INTO satish VALUES ('jodhpur','hazy1','68','7','700','30','28','10sept')"];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL);
{
NSLog(#"%#",statement);
sqlite3_bind_text(statement, 1, insert_stmt, -1, SQLITE_TRANSIENT );
if (sqlite3_step(statement) == SQLITE_ROW)
{
ID = sqlite3_last_insert_rowid(contactDB);
NSLog(#"Data inserted successfully ");
}
else{
NSLog(#"Failed to add contact");
}
}
sqlite3_finalize(statement);
sqlite3_close(contactDB);
}
//tyr this code
// you must give the column name to insert values in DB
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dbPath =[documentsDir stringByAppendingPathComponent:#"register.sqlite"];
BOOL success = [fileManager fileExistsAtPath:dbPath];
sqlite3_stmt *selectstmt;
if(!success)
{
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"register.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
//*************** insert value in database******************************\\
const char *sql = "insert into satish (firstname,lastname,email,company,phone) VALUES ('sdcbb','bbbb','bbbb','bbbb',1111122)";
sqlite3_prepare_v2(database,sql, -1, &selectstmt, NULL);
if(sqlite3_step(selectstmt)==SQLITE_DONE)
{
NSLog(#"insert successfully");
}
else
{
NSLog(#"insert not successfully");
}
sqlite3_finalize(selectstmt);
sqlite3_close(database);
}
I don't see where you copy your database from your bundle to the documents directory. If you do not copy a premade SQLite database, then your open call will create a new empty one. Since you did not create a table yet in your empty database, then the Insert call will fail. Solution 1: Write file routines to copy a premade SQLite database with a table named satish into your documents directory. Solution 2: If you don't want to premake a sqlite database, use a create statement in SQLite first to create the satish table.

Can't insert record in Sqlite Database

I m using below code to for sqlite DB, but I can not insert values with Execute query can any one tell me where i m wrong ?
- (void)createEditableCopyOfDatabaseIfNeeded {
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:DATABASE_NAME];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success) return;
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:DATABASE_NAME];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
Initialize Database
- (void)initializeDatabase {
// The database is stored in the application bundle.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:DATABASE_NAME];
// Open the database. The database was prepared outside the application.
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
{
//TRUE
}
else
{
// Even though the open failed, call close to properly clean up resources.
sqlite3_close(database);
NSAssert1(0, #"Failed to open database with message '%s'.", sqlite3_errmsg(database));
// Additional error handling, as appropriate...
}
}
Execute Sql Method
-(void)ExecuteSQL:(NSString*)SQL
{
#synchronized(self)
{
sqlite3_stmt *select_statement=nil;
if (sqlite3_prepare_v2(database, [SQL UTF8String], -1, &select_statement, NULL) != SQLITE_OK) {
NSString *errString = [NSString stringWithFormat:#"%#",
[NSLocalizedString(#"statementPrepareFailedKey",#"")
stringByReplacingOccurrencesOfString:#"#" withString:[NSString
stringWithCString:sqlite3_errmsg(database) encoding:NSUTF8StringEncoding] ]];
NSAssert1(0, #"%#", errString);
}
//int columncount=sqlite3_column_count(select_statement);
//NSMutableDictionary* dic;
if(sqlite3_step(select_statement) == SQLITE_DONE)
{
NSLog(#"Execute sql");
}
sqlite3_finalize(select_statement);
}
}
Thanks.

Error on Xcode 4.3.2 <Attempt to write a readonly database>

I am new on iphone programming..
I keep getting the error
and I have no idea how to change the permission for SQLite
Error while updating. attempt to write a readonly database
and the following is my coding
NSString *filePath = [[NSBundle mainBundle]pathForResource:#"card" ofType:#"sqlite"];
sqlite3_stmt *statement;
if(sqlite3_open([filePath UTF8String], &db) == SQLITE_OK)
{
  const char *query_stmt = "UPDATE card SET isActivate =?";
  if(sqlite3_prepare_v2(db, query_stmt, -1, &statement, NULL) != SQLITE_OK)
     {
         NSAssert1(0, #"Error while creating update statement. '%s'", sqlite3_errmsg(db));
     }
}
sqlite3_bind_int(statement, 1, 1);
if(SQLITE_DONE != sqlite3_step(statement))
   {
      NSLog(#"Error while updating. %s", sqlite3_errmsg(db));
    }
sqlite3_finalize(statement);
sqlite3_close(db);
Hope someone could help me because this really makes me feel frustrated..
You need to copy your sql file to your cache directory in order to use it correctly.
Here's some of my code:
NSString *sqlFile = #"database.sql";
NSArray *cachePath= NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cacheDir = [cachePathobjectAtIndex:0];
databasePath = [cacheDirstringByAppendingPathComponent:sqlFile];
NSFileManager *fileManager = [NSFileManager defaultManager];
// Copy the database sql file from the resourcepath to the documentpath
if (![fileManager fileExistsAtPath:databasePath]) {
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:sqlFile];
NSError *error;
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:&error];
if (error != nil) {
NSLog(#"[Database:Error] %#", error);
}
}