I am working on something using SQLite3 and I cant exactly figure out why I am getting an error. I have looked at other SO post and no one can actually quite put a finger on that error and I have tried a number of things. the code is failing on this line (sqlite3_open(dbPath, &itemDB)==SQLITE_OK).
I have tried:
commenting that line and saying sqlite3_open(dbPath, &itemDB), when i do that my code excecutes but nothing in the folder
Error from the NSLog was "unable to open database file" so i created the datbase and placed it in the path myself to see if that would help but no difference
Verified the path by using breakpoints, path is correct but the db is just never created.
-(void)openDatabase
{
NSArray *path=NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);
NSString *docPath=[path objectAtIndex:0];
// dbPathString=[docPath stringByAppendingPathComponent:#"items.db"];
dbPathString = [docPath stringByAppendingPathComponent:#"items.sqlite"];
char *error;
NSFileManager *fileManager=[NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:dbPathString]) {
const char *dbPath=[dbPathString UTF8String];
//Create DB
if (sqlite3_open(dbPath, &items)==SQLITE_OK)
// sqlite3_open(dbPath, &items);
{
const char *sql_stmt= " CREATE TABLE IF NOT EXIST PERSON (ID INTEGER PRIMARY KEY AUTOINCREMENT,NAME TEXT,PRICE INTEGER)";
sqlite3_exec(items, sql_stmt, NULL, NULL, &error);
sqlite3_close(items);
NSLog(#"Db Created");
}
NSLog(#"%s", sqlite3_errmsg(items));
}
}
You are trying to write to the documentation directory, not the document directory.
Replace NSDocumentationDirectory with NSDocumentDirectory.
Try this tutorial
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 = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: #"contacts.db"]];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: databasePath ] == NO) {
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK) {
char *errMsg;
const char *sql_stmt = "CREATE TABLE IF NOT EXISTS CONTACTS (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, ADDRESS TEXT, PHONE TEXT)";
if (sqlite3_exec(contactDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK) {
status.text = #"Failed to create table";
}
sqlite3_close(contactDB);
}
else {
status.text = #"Failed to open/create database";
}
}
This will help u
#import<sqlite3.h>
-(BOOL)createTable
{
NSArray *yourArray=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath=[yourArray objectAtIndex:0];
filePath =[filePath stringByAppendingPathComponent:#"yourdatabase.sqlite"];
NSFileManager *manager=[NSFileManager defaultManager];
BOOL success = NO;
if ([manager fileExistsAtPath:filePath])
{
success =YES;
}
if (!success)
{
NSString *path2=[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"yourdatabase.sqlite"];
success =[manager copyItemAtPath:path2 toPath:filePath error:nil];
}
createStmt = nil;
NSString *tableName=#"SecondTable";
if (sqlite3_open([filePath UTF8String], &database) == SQLITE_OK) {
if (createStmt == nil) {
NSString *query=[NSString stringWithFormat:#"create table (ID INTEGER PRIMARY KEY AUTOINCREMENT,NAME TEXT,PRICE INTEGER)];
if (sqlite3_prepare_v2(database, [query UTF8String], -1, &createStmt, NULL) != SQLITE_OK) {
return NO;
}
sqlite3_exec(database, [query UTF8String], NULL, NULL, NULL);
return YES;
}
}
return YES;
}
Related
I'm having some issue connecting to my sqlite database.. I'm using xcode version 4.4.1
here's my 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 = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: #"signature.db"]];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: databasePath ] == NO)
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
status.text = #"Connected..";
} else {
status.text = #"Failed to open/create database..";
}
}
[filemgr release];
Any suggestion..?
Thanks,
Boom
There is no need to check if the database exists; sqlite3_open_v2() (reference) will create the database, if it does not exist, if you pass the flag SQLITE_OPEN_CREATE:
NSString *dbPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPath:#"signature.db"];
if (sqlite3_open_v2([dbPath UTF8String], &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE) == SQLITE_OK)
{
status.text = #"Connected..";
// Check the schema and install if it doesn't exist
sqlite3_close(database);
} else {
status.text = #"Failed to open/create database..";
}
You may wish to check if the DB file is in place if you have one in your app's bundle that is pre-built so you can drop it into your documents folder. Of course, as you enhance your app, any schema changes will need to be done in code. Here is some code that I use (that works, but needs to updated a bit)
When opening/creating the DB I use this to specify where the DB file will be. I don't put it with the init because my location is different between iOS and Mac OS X and I want the DB code to work with both:
NSString *dbFilePath;
NSArray *searchPaths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentFolderPath = searchPaths[0];
dbFilePath = [documentFolderPath stringByAppendingPathComponent: #"MyDBFile.db"];
MyDB* appDB = [[EasySpendLogDB alloc] initWithFile:dbFilePath];
if(!appDB) {
// show error
return;
}
This is in my DB access class. It uses some wrapper classes I wrote:
- (id) initWithFile: (NSString*) filePathName {
if(!(self = [super init])) return nil;
BOOL myPathIsDir;
BOOL fileExists = [[NSFileManager defaultManager]
fileExistsAtPath: filePathName
isDirectory: &myPathIsDir];
NSString *backupDbPath = [[NSBundle mainBundle]
pathForResource:#"MyDBFile"
ofType:#"db"];
if (backupDbPath != nil && !fileExists) {
[[NSFileManager defaultManager]
copyItemAtPath:backupDbPath
toPath:filePathName
error:nil];
}
db = [[ABSQLiteDB alloc] init];
if(![db connect:filePathName]) {
return nil;
}
[self checkSchema]; // this is where schema updates are done (see project sample)
return self;
}
You may also want to check out this objective-c wrapper I wrote that has a sample project: https://github.com/AaronBratcher/ABSQLite
I'm trying to display a string of text in a text view. According to NSLog the database is found but, I cannot retrieve the data from the table. Could someone point out what is wrong with my query? (I may need this explained in very simple terms. I've been sing objective-c for only a few days.)
- (void)viewDidLoad {
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 = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent:#"trivia_game.db"]];
NSLog(#"Full DB path: %#", databasePath);
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: databasePath ] == NO)
{
const char *dbpath = [databasePath UTF8String];
NSLog(#"[SQLITE] DB not found");
} else {
NSLog(#"[SQLITE] trivia_game.db found");
}
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &questionsForGame) == SQLITE_OK)
{
NSLog(#"[SQLITE] db opened");
NSString *querySQL = [NSString stringWithFormat: #"SELECT question, answer0, answer1, answer2, answer3 FROM questions"];
NSLog(#"[SQLITE] string is: %#", querySQL);
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(questionsForGame, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#"[SQLITE] written!");
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *textField = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
questHolder.text = textField;
NSLog(#"[SQLITE] string is: %#",textField);
[textField release];
} else {
questHolder.text = #"query not found";
NSLog(#"[SQLITE] Unable to open database!");
}
sqlite3_finalize(statement);
sqlite3_close(questionsForGame);
} else {
NSLog(#"[SQLITE] Screwed up query!");
questHolder.text = #"query not found";
}
}
[filemgr release];
[super viewDidLoad];
}
log:
[Session started at 2012-05-28 12:27:19 -0300.]
2012-05-28 12:27:20.547 ans[9374:207] Full DB path: /Users/admin/Library/Application Support/iPhone Simulator/4.3/Applications/0B4C50FB-5A3F-4371-83D6-1A2AF95B9F66/Documents/trivia_game.db
2012-05-28 12:27:20.549 ans[9374:207] [SQLITE] trivia_game.db found
2012-05-28 12:27:20.550 ans[9374:207] [SQLITE] db opened
2012-05-28 12:27:20.551 ans[9374:207] [SQLITE] string is: SELECT question, answer0, answer1, answer2, answer3 FROM questions
2012-05-28 12:27:20.553 ans[9374:207] [SQLITE] Screwed up query!
I am not familiar with the SQLite library you're using but I would recommend to switch to Core Data. cf. http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/coredata/cdprogrammingguide.html
I try to insert only two integer variable to my sqlite database. I created a database which name is ups.sqlite, it has a one table (upssTable) and the table have two column. But when I open /Users/ds/Library/Application Support/iPhone Simulator/5.0/Applications/FCB4B455-4B7F-4C47-81B6-AC4121874596/SqliteDeneme.app/ups.sqlite there is no data in ups.sqlite. My code is here:
- (IBAction)buttonClick:(id)sender {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dbPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:dbPath];
if(!success) {
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"ups.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
NSLog(#"database path %#",dbPath);
if(!(sqlite3_open([dbPath UTF8String], &cruddb) == SQLITE_OK))
{
NSLog(#"An error has occured.");
}
if(sqlite3_open([dbPath UTF8String], &cruddb) ==SQLITE_OK){
NSString * str1 =#"1";
NSString * str2 =#"1";
const char *sql = "INSERT INTO upssTable (column1, column2) VALUES (?,?)";
NSInteger result = sqlite3_prepare_v2(cruddb,sql, -1, &stmt, NULL);
NSLog(#"upss %s\n", sqlite3_errmsg(cruddb));
if(result == SQLITE_OK)
{
sqlite3_bind_int(stmt, 1, [str1 integerValue]);
sqlite3_bind_int(stmt, 2, [str2 integerValue]);
}
else
{
NSAssert1(0, #"Error . '%s'", sqlite3_errmsg(cruddb));
}
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
sqlite3_close(cruddb);
}
}
- (NSString *) getDBPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:#"ups.sqlite"];
}
How can I solve this problem? Please help me. Thanks for your reply.
You havent used sqlite3_step() at all. Try this way...
sqlite3 *database;
dbPath=[self.databasePath UTF8String];
if(sqlite3_open(dbPath,&database)==SQLITE_OK)
{
const char *sqlstatement = "INSERT INTO upssTable (column1, column2) VALUES (?,?)";
sqlite3_stmt *compiledstatement;
if(sqlite3_prepare_v2(database,sqlstatement , -1, &compiledstatement, NULL)==SQLITE_OK)
{
NSString * str1 =#"1";
NSString * str2 =#"1";
sqlite3_bind_int(compiledstatement, 1, [str1 integerValue]);
sqlite3_bind_int(compiledstatement, 2, [str2 integerValue]);
if(sqlite3_step(compiledstatement)==SQLITE_DONE)
{
NSLog(#"done");
}
else NSLog(#"ERROR");
sqlite3_reset(compiledstatement);
}
else
{
NSAssert1(0, #"Error . '%s'", sqlite3_errmsg(cruddb));
}
sqlite3_close(database);
}
You are creating your sqlite3 statement, but you aren't actually executing it using sqlite3_step().
Also you appear to be opening the database twice?
Through the following code I am retrieving data from a Db, however I need to insert some data into a Sqlite3 database with this code before select statement. Can any one tell me where I need to put the insert query and how can I execute it.
I am selecting the datas through the following code:
sqlite3* database;
- (void)initializeDatabase
{
list=[[NSMutableArray alloc] init];
BOOL success;
NSFileManager *filemanager=[NSFileManager defaultManager];
NSError *error;
NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory= [paths objectAtIndex:0];
NSString *writablePath=[documentsDirectory stringByAppendingPathComponent:#"SymbolTalk.sqlite"];
success=[filemanager fileExistsAtPath:writablePath];
if(!success)
{
NSString *defaultDBPath=[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"SymbolTalk.sqlite"];
success=[filemanager copyItemAtPath:defaultDBPath toPath:writablePath error:&error];
if(!success)
{
NSAssert1(0,#"Failed to create writable databasefile withw message %#.",[error localizedDescription]);
}
}
//Specify where to get the database from
NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory= [paths objectAtIndex:0];
NSString *path=[documentsDirectory stringByAppendingPathComponent:#"SymbolTalk.sqlite"];
//Open the database
//might have to make database as property
if(sqlite3_open([path UTF8String], &dataBase) ==SQLITE_OK)
{
const char *sql="select filename from scenes";
sqlite3_stmt *statement;
if(sqlite3_prepare(dataBase, sql, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
//NSLog(#"%#",[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)]);
[list addObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)]];
}
}
}
}
sqlite3_stmt *insert_statement = nil;
const char *sql = "INSERT INTO scenes (filename) VALUES(?)";
if (sqlite3_prepare_v2(database, sql, -1, &insert_statement, NULL) != SQLITE_OK) {
NSAssert1(NO, #"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
sqlite3_bind_text(insert_statement, 1, [newFilename UTF8String], -1, SQLITE_TRANSIENT);
if (sqlite3_step(insert_statement) == SQLITE_DONE) {
// code if all ok
} else {
NSAssert1(NO, #"Error: failed to insert into the database with message '%s'.", sqlite3_errmsg(database));
}
sqlite3_reset(insert_statement);
sqlite3_finalize(insert_statement);
SQLite insert statement does not insert the new data
i am using this code
- (void) addN: (number *) theN
{
const char *sql = "insert into table (valueN) Values(?)";
sqlite3_stmt *addStmt = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString * docsDir = [paths objectAtIndex:0];
NSString * thePath = [docsDir stringByAppendingPathComponent: #"theDB.sqlite"];
sqlite3_open([thePath UTF8String], &database);
sqlite3_prepare_v2(database, sql, -1, &addStmt, NULL);
sqlite3_bind_int(addStmt, 1, theN.theNumber);
sqlite3_step(addStmt);
sqlite3_finalize(addStmt);
sqlite3_close(database);
}
and the method to insert the record is
- (IBAction) saveN: (id) sender
{
numbers *theNumbers = [[numbers alloc] init];
number *theNumber = [[number alloc] init];
theNumber.theNumber = newN;
[theNumbers addN:theNumber];
[theNumbers release];
[theNumber release];
}
the code is executed but no record is inserted in the DB.
can someone please point me where is the mistake - cause there obviously is a mistake :)
You're not checking the return values of any of the sqlite3 calls. There's a good chance one of them is failing.
this code seems to work:
- (void) addN: (number *) theN
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *thePath = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:#"theDB.sqlite"];
BOOL success = [fileManager fileExistsAtPath:thePath];
if (!success)
{
NSLog(#"Failed to find database file '%#'.", thePath);
}
if (!(sqlite3_open([thePath UTF8String], &database) == SQLITE_OK))
{
NSLog(#"An error opening database, normally handle error here.");
}
const char *sql = "insert into table (valueN) Values(?)";
sqlite3_stmt *addStmt = nil;
if (sqlite3_prepare_v2(database, sql, -1, &addStmt, NULL) != SQLITE_OK)
{
NSLog(#"Error, failed to prepare statement, normally handle error here.");
}
sqlite3_bind_int(addStmt, 1, theN.theNumber);
sqlite3_step(addStmt);
if(sqlite3_finalize(addStmt) != SQLITE_OK)
{
NSLog(#"Failed to finalize data statement, normally error handling here.");
}
if (sqlite3_close(database) != SQLITE_OK)
{
NSLog(#"Failed to close database, normally error handling here.");
}
}