Database not being found... iOS/SQLite - ios

I working on an app that takes input from a text field and puts it into a string. I have a table with a field in it that I want to check the value of the string from the input against the value in the field in the database. I'm new to iOS and fairly new to SQLite.
Code:
-(IBAction)setInput:(id)sender
{
NSString *strStoreNumber;
NSString *strRegNumber;
strStoreNumber = StoreNumber.text;
strRegNumber = RegNumber.text;
lblStoreNumber.text = strStoreNumber;
lblRegNumber.text = strRegNumber;
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths lastObject];
// NSString* databasePath = [documentsDirectory stringByAppendingPathComponent:#"tblStore.sqlite"];
NSString* databasePath = [[NSBundle mainBundle] pathForResource:#"tblStore" ofType:#"sqlite"];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
NSLog(#"Opened sqlite database at %#", databasePath);
//...stuff
}
else
{
NSLog(#"Failed to open database at %# with error %s", databasePath, sqlite3_errmsg(database));
sqlite3_close (database);
}
NSString *querystring;
// create your statement
querystring = [NSString stringWithFormat:#"SELECT strStore FROM tblStore WHERE strStore = %#;", strStoreNumber];
const char *sql = [querystring UTF8String];
NSString *szStore = nil;
NSString *szReg = nil;
if (sqlite3_prepare_v2(database, sql, -1, &databasePath, NULL)!=SQLITE_OK) //queryString = Statement
{
NSLog(#"sql problem occured with: %s", sql);
NSLog(#"%s", sqlite3_errmsg(database));
}
else
{
// you could handle multiple rows here
while (sqlite3_step(databasePath) == SQLITE_ROW) // queryString = statement
{
szStore = [NSString stringWithUTF8String:(char*)sqlite3_column_text(databasePath, 0)];
szReg = [NSString stringWithUTF8String:(char*)sqlite3_column_text(databasePath, 1)];
} // while
}
sqlite3_finalize(databasePath);
// Do something with data...
}
It gets to the line "NSLog(#"Opened sqlite database at %#", databasePath);", so it appears as though it has access to the database. However, when I run the app, I get the "NSLog(#"sql problem occured with: %s", sql);" error, which I can see in the console. Additionally, in the console, it says "No such table: tblStore".
I created the table using the Firefox add-on SQLite Manager. I added the sqlite3 library to the project. I dragged and dropped the database table I created in SQLite manager into my project, above my two AppDelegate files and my two ViewController files.
Any help or input would be greatly appreciated. Thanks!
EDIT: I have properly added the file to the project, and it appears as though the table is found now. Now I have some strange warnings, though:
"Incompatible pointer types passing 'const char *' to parameter of type 'sqlite3_stmt *' (aka 'struct sqlite3_stmt *')"
This warning appears on the following lines of code:
if (sqlite3_prepare_v2(database, sql, -1, &databasePath, NULL)!=SQLITE_OK)
while (sqlite3_step(sql) == SQLITE_ROW)
szStore = [NSString stringWithUTF8String:(char*)sqlite3_column_text(sql, 0)];
szReg = [NSString stringWithUTF8String:(char*)sqlite3_column_text(sql, 1)];
sqlite3_finalize(sql);
It's got something to do with "sql", but I'm unsure of what. Any suggestions?

Your code seems ok - did you copy the db to the ressource folder of your project?
EDIT
Make sure you access your db file with something like that:
- (void) initializeDB {
// Get the database from the application bundle
NSString* path = [[NSBundle mainBundle] pathForResource:#"tblStore" ofType:#"sqlite"];
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
{
NSLog(#"Opening Database");
}
else
{
// Call close to properly clean up
sqlite3_close(database);
NSAssert1(0, #"Error: failed to open database: '%s'.",
sqlite3_errmsg(database));
}
}

The database file you add to the project will be embedded in the main NSBundle (see [NSBundle mainBundle]).
In order to do what you want, you need to copy the database from the main bundle to the documents folder before trying to access it. Otherwise, as you are experiencing, you will not be able to find the SQLite DB on the document's folder.

You can copy your database, click finder and write this address(/Users/administrator/Library/Application Support/iPhone Simulator/6.1/Applications/) in finder click ok.
You will get documentary path.
Open your project document file and paste your database....

Related

sqlite3 "unable to open database file" - ios

I am using sqlite3 in my project.
I am getting error after couple(50-60) of transaction that "unable to open
database file",So check my database file path but path is correct and
file is there.
I tried each and every solution discussed on stack overflow, but with no
luck.
I check my "DocumentDirectory" path, done all necessary step before to close database. Like:
sqlite3_finalize(selectStatement);
sqlite3_close(database);
I don't know how to tackle this problem.can I check that my sqlite3 database is open or not.
====================== 1============================
+(NSMutableArray*)executeDataSet:(NSString*)query
{
NSMutableArray *arryResult = [[NSMutableArray alloc] initWithCapacity:0];
const char *sql = [query UTF8String];
sqlite3_stmt *selectStatement;
sqlite3 *database = [DataBaseClass openDataBase];
//prepare the select statement
int returnValue = sqlite3_prepare_v2(database, sql, -1, &selectStatement, NULL);
if(returnValue == SQLITE_OK)
{
//my code
}
}
//sqlite3_reset(selectStatement);
// NILOBJECT(selectStatement);
// NILOBJECT(selectStatement);
sqlite3_finalize(selectStatement);
sqlite3_close(database);
return arryResult;
}
==================== 2 =================================
+(sqlite3 *) openDataBase {
sqlite3 * edenAdultDatabase;
NSString * databasePath =[DataBaseClass pathForDatabase];
if(sqlite3_open([databasePath UTF8String], &edenAdultDatabase) == SQLITE_OK) {
NSLog(#"Yes database is open");
return edenAdultDatabase;
}
else
{
NSLog(#"do something %s",sqlite3_errmsg(edenAdultDatabase));
}
return edenAdultDatabase;
}
====================== 3 ===========================
+(NSString *) pathForDatabase {
NSString *libraryDir = [FileManager pathForPrivateDocumentsFolder];
NSFileManager *fileMgr = [NSFileManager defaultManager];
NSError *error;
NSString *privateFolderPath = [libraryDir stringByAppendingPathComponent:#"DataBase"];
if (![fileMgr fileExistsAtPath:privateFolderPath])
{
[fileMgr createDirectoryAtPath:privateFolderPath withIntermediateDirectories:NO attributes:nil error:&error];
}
/*
// My database in library private folder ..this is just for test.
// I copied databae to document dir but no luck.
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
privateFolderPath = [documentsDir stringByAppendingPathComponent:kDatabaseName];
*/
privateFolderPath = [privateFolderPath stringByAppendingPathComponent:kDatabaseName];
return privateFolderPath;
}
There is a weird issue in database connectivity, sometime it does not connect. Therefore it is recommended by people that your application should open a database once (during in initialisation phase) and close the connection when application is terminating.
Reference: Sqlite opening issue
Regarding checking database connectivity, Sqlite3 does not provide any method to check that either database is open or not.
By using Shared instance of database manager, you can achieve it. Define a boolean at class level and set it's value when you open the database:
// .h file
BOOL isDatabaseOpen;
// .m file
-(void) openDatabase
{
if(![self isDatabaseExist])
{
// copy database to library
[self copyDatabaseFile];
}
NSString *sqLiteDb = [self getDatabaseLibraryPath];
if (sqlite3_open([sqLiteDb UTF8String], &_databaseHandler) != SQLITE_OK) {
NSLog(#"Database --> Failed to open");
isDatabaseOpen = NO;
}
else
{
isDatabaseOpen = YES;
}
}
and then you can use the following method to check is database opened or not.
-(BOOL) isDatabaseOpen
{
return isDatabaseOpen;
}
Let me know if it worked :).
check out this kind of solution
first of all create function like below:
-(void)checkDBAndCopy{
NSArray *dirPath=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *connectionPath=[dirPath objectAtIndex:0];
strDBPath=[connectionPath stringByAppendingPathComponent:#"database.sqlite"];
NSLog(#"%#",strDBPath);
NSFileManager *filemanager=[[NSFileManager alloc]init];
if (![filemanager fileExistsAtPath:strDBPath]) {
NSString *databasePathFromApp=[[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:#"database.sqlite"];
[filemanager copyItemAtPath:databasePathFromApp toPath:strDBPath error:nil];
}
}
and call this function like below method:-
-(NSMutableArray *)RetriveSharedspots:(NSString *)Query{
[self checkDBAndCopy];
if (sqlite3_open([strDBPath UTF8String], &contactDB)==SQLITE_OK) {
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(contactDB, [Query UTF8String],-1,&statement,NULL)==SQLITE_OK)
{
while (sqlite3_step(statement)==SQLITE_ROW) {
// Your code
}
}
sqlite3_finalize(statement);
}
sqlite3_close(databaseName);
return array;
}
Above this worked for me great. try this.
Just sharing my case with this issue.
I have a project that uses databaseFile1.sqlite and I am not sure if there was a build of it installed on my simulator.
Then I changed the database file, say databaseFile2.sqlite different contents, different filename. Then this issue came up. As I read the solutions and comments, I realized that the issue shouldn't be so biggie.
Welp, I deleted the build and restarted Xcode. Voila. It's okay now. Later on, I will revert back to databaseFile1.sqlite the database, and I'll see if this issue can be reproduced.

how to scroll a uiwebview using uiscrollview

i have a UIWebView over a UIScrollView. i use some js files to draw some graph like line that will update when the time value changes.
The Problem
Im not able to scroll when the points goes out of the screen.
I'm new to IOS Development so please help me.
thank in advance
After Completion the QUERY, You need to close transaction.
Here's the sample code for you...
// 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: #"YOURDB.db"]];
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &DB) == SQLITE_OK)
{
NSString *query=[NSString stringWithFormat:#"insert into studentDetails (NAME,Email,adressL1,adressL2,phone,landline,department,DoB,fatherName) values (\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\")",
name.text,
email.text,
addressLine1.text,
addressLine2.text,
phone.text,
Landline.text,
Department.text,
DoB.text,
fname.text];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(YOURDB, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(#" Successfully added");
} else {
NSLog(#" Failed added");
NSLog(#"Error %s",sqlite3_errmsg(ExplorejaipurDB));
}
}
sqlite3_finalize(statement);
sqlite3_close(YOURDB);
}
The database could be locked because of several reasons:
Multiple queries running
multiple threads running
opened the database multiple times
Check your code and see if you have closed the connections to the database sqlite3_close(). A good idea would also be to use sqlite3_finalize() after each SQL statement when you are done with it.
So try try to match all your sqlite3_open() with sqlite3_close() and sqlite3_prepare() (if you are using it) with sqlite3_finalize()

(Objective C) Save changes in sqlite database

I'm creating an app for my school project that has to write data to my sqlite database. It works, as long as the app is running active but as soon as the app closes, my added data is gone and when I want to read this data this will not work off course. I included both my loadData and saveData methods. The two database paths are the same in both functions so it's not that I'm writing my data elsewhere. I really can't find the solution or the problem. I even get the insert success in my output, so the insert is successful.
- (void) saveData:(id)sender{
NSString *sqldb = [[NSBundle mainBundle] pathForResource:#"PXLate" ofType:#"sqlite3"];
sqlite3_stmt *stmt;
NSString *queryInsert = #"INSERT INTO assignments (name, lesson, dueDate, notification, start, at) VALUES ('abc','abc', 'abc', 1, 'abc', 'abc')";
NSLog(#"%#",sqldb);
NSLog(#"%#",queryInsert);
if(sqlite3_open([sqldb UTF8String], &_PXLate) == SQLITE_OK)
{
sqlite3_prepare_v2(_PXLate, [queryInsert UTF8String], -1, &stmt, NULL);
if(sqlite3_step(stmt)==SQLITE_DONE)
{
NSLog(#"insert success");
}
else
{
NSLog(#"insert un success");
NSAssert1(0, #"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(_PXLate));
}
int success=sqlite3_step(stmt);
if (success == SQLITE_ERROR)
{
NSAssert1(0, #"Error: failed to insert into the database with message '%s'.", sqlite3_errmsg(_PXLate));
//[_PXLate save:&error];
} sqlite3_finalize(stmt);
}
sqlite3_close(_PXLate);
}
and my loadData function
- (void) loadData:(id)sender
{
//path for database
NSString *sqldb = [[NSBundle mainBundle] pathForResource:#"PXLate" ofType:#"sqlite3"];
//check if present
NSFileManager*fm=[NSFileManager defaultManager];
NSLog(#"path: %#", sqldb);
const char *dbpath = [sqldb UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &_PXLate) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"SELECT * FROM assignments WHERE name='abc'", _label.text];
const char *query_stmt = [querySQL UTF8String];
NSLog(#"name");
NSLog(querySQL);
int response = sqlite3_prepare_v2(_PXLate, query_stmt, -1, &statement, NULL);
NSLog(#"response %d", response);
if (response == SQLITE_OK)
{
NSLog(#"name");
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *namefield = [[NSString alloc]
initWithUTF8String:
(const char *) sqlite3_column_text(
statement, 0)];
NSLog(#"name:%#", namefield);
_label.text = namefield;
} else {
_label.text = #"Match not found";
}
sqlite3_finalize(statement);
}
sqlite3_close(_PXLate);
}
}
You have to copy your sqlite to the documents directory and then work with that. Example:
self.databaseName = #"databasename.sqlite";
// Get the path to the documents directory and append the databaseName
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
self.databasePath = [[NSString alloc]init];
self.databasePath = [documentsDir stringByAppendingPathComponent:self.databaseName];
[self checkAndCreateDatabase];
And the create method:
-(void)checkAndCreateDatabase
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:self.databaseName];
[fileManager copyItemAtPath:databasePathFromApp toPath:self.databasePath error:nil];
}
A couple of observations:
As Retterdesdialogs said, you should
Check for existence of database in Documents;
If not there, copy from bundle to Documents; and
Open database from Documents.
You should not open database from bundle, because on the device that folder is read-only.
In your INSERT statement you are not checking the response of sqlite3_prepare_v2, which is a very common source of errors. If this is not SQLITE_OK, you should immediately log sqlite3_errmsg, before you call sqlite3_step.
You are performing sqlite3_step twice in the INSERT statement.
In loadData, you are not logging sqlite3_errmsg if sqlite3_prepare_v2 failed. Always look at sqlite3_errmsg upon any error.

ios - sqlite prepare statement

I am trying to read data from a sqlite database in an ios app. When I run the app, it is able to open the database but in the log file it shows the message - "Problem with the prepare statement". I don't know what is wrong with my prepare statement Here's my code -
-(NSString *)dataFilePath{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:kFilename];
}
In the viewDidLoad I have -
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
myarray = [[NSMutableArray alloc]init];
sqlite3 *database;
if(sqlite3_open([[self dataFilePath]UTF8String], &database)!=SQLITE_OK){
sqlite3_close(database);
NSAssert(0, #"Failed to open database");
}
const char *createSQL = #"SELECT ID, TITLE FROM FIRST ORDER BY TITLE;"; //first is the table in the database
sqlite3_stmt *sqlStmt;
if(sqlite3_prepare_v2(database, [createSQL UTF8String], -1, &sqlStmt, nil)!=SQLITE_OK){
NSLog(#"Problem with prepare statement"); //this is where the code gets stuck and I don't know why
}else{
while(sqlite3_step(sqlStmt)==SQLITE_ROW){
NSInteger number = sqlite3_column_int(sqlStmt, 0);
NSString *title = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStmt, 1)];
[myarray addObject:title];
}
sqlite3_finalize(sqlStmt);
}
sqlite3_close(database);
}
If your prepare statement fails, rather than just reporting "Problem with prepare statement", try retrieving the error message, e.g.,
NSLog(#"%s Prepare failure '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(database), sqlite3_errcode(database));
This might give you a better indication of the problem.
A problem I've seen in the past is that the database might not be found (because it wasn't included in the bundle, typo in the name, etc.) but the standard sqlite3_open function will create it if it's not there, and thus the sqlite3_open will succeed, but the table in question won't be found in the blank, newly created database. Better than sqlite3_open would be:
sqlite3 *database;
if (sqlite3_open_v2([[self dataFilePath] UTF8String], &database, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) {
sqlite3_close(database); // not sure you need to close if the open failed
NSAssert(0, #"Failed to open database");
}
That way you get a warning if the database is not found. But if you've done sqlite3_open already, you might have a blank database, so you might want to reset your simulator and/or remove the app from your device, before trying it with sqlite3_open_v2.
Several things you can try.
Clean your app, Remove from simulator or device & try installing a fresh copy again and see if it works.
Open your DB in Terminal & try to run your sql statement at there. Check wether you are getting desired output.
Try changing the nil to NULL. Also, try defining the SQL statement as a const char.
....
const char *sql = "SELECT ID, TITLE FROM FIRST ORDER BY TITLE";
sqlite3_stmt *sqlStmt;
if(sqlite3_prepare_v2(database, sql, -1, &sqlStmt, NULL)!=SQLITE_OK){
....

iPad SQLite3 fails INSERT query

I am currently trying to simply insert a new row into my SQLite3 database on my iPad. I have done it multiple times before in other apps and just copied the code. The copied SELECT queries work fine, but if I try to INSERT, it fails at == SQLITE_DONE
This is how I try to insert into the database:
NSString *databaseName = #"Waypoints.sql";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
sqlite3 *database;
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
NSString *statement = [NSString stringWithFormat:
#"INSERT INTO Waypoints (id, name, alt, ias, temp, tas, wd, ws, gs, mt, mh, dist, time, fuel, fuelrate) VALUES (%d,'New...','','','','','','','','','','','','','');", [self numberOfWaypoints]];
NSLog(#"Statement: %#", statement);
const char *sqlStatement = [statement cStringUsingEncoding:NSASCIIStringEncoding];
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK)
{
if(sqlite3_step(compiledStatement) == SQLITE_DONE)
NSLog(#"DATABASE: Adding: Success");
else
NSLog(#"DATABASE: Adding: Failed");
}
else
NSLog(#"Error. Could not add Waypoint.");
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
If I run this code on the press of a button, it outputs DATABASE: Adding: Failed in the console.
The NSLogged statement looks like this:
INSERT INTO Waypoints (id, name, alt, ias, temp, tas, wd, ws, gs, mt, mh, dist, time, fuel, fuelrate) VALUES (2,'New...','','','','','','','','','','','','','');
Which works perfectly fine if I paste it in the terminal (connected to same database file).
This brings me to the conclusion: what could be causing this problem?
I thought of maybe write permissions to the file. Could be it, but it's not in the bundle but already copied to the documents folder on the device.
Please help to how I can get this to work?
Try using NSUTF8StringEncoding for your cStringUsingEncoding or printing
NSLog(#"%#", [NSString stringWithUTF8String:(char*)sqlite3_errmsg(database)]);
Glad to see you could find your error with this.
By following the tip from #IgnacioInglese by printing out the error with NSLog(#"%#", [NSString stringWithUTF8String:(char*)sqlite3_errmsg(database)]); I found that the database is locked.
I found that I made a rookie-error by return a value in a method before closing the database. Fixing that solved my problem.

Resources