sqlite error :/* SQL error or missing database */ - iphone

I have a project in which I stored sqlite database file "data.sqlite3" to
'Group'&files'-'resource'
Below are my viewcontroller source codes
//-myviewcontroller.h
#import "sqlite3.h"
#define kFilename #"data.sqlite3"
//myviewcontroller.m
-(NSString *)dataFilePath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:kFilename];
}
-(void)f
{
if (sqlite3_open([[self dataFilePath] UTF8String],&database)!=SQLITE_OK)
//dataFilePath returns
///Users/interdev/Library/Application Support/iPhone Simulator/User/Applications/095C6E05-4EAE-4817-883E-A72E39D439E0/Documents/data.sqlite3
{
sqlite3_close(database);
NSAssert(0,#"Failed to open database");//no problem
}
NSString *query = #"SELECT * FROM table1 ORDER BY ROW";//table1 is table name
sqlite3_stmt *statement;
NSInteger v=sqlite3_prepare_v2( database, [query UTF8String],
-1, &statement, nil);
NSString *zs= [NSString stringWithFormat:#"%d",v];
NSLog(#" The buttontitile is %# ",zs);
if ( v == SQLITE_OK) { // ...
}
I checked value of v in log, it always is 1
#define SQLITE_ERROR 1 /* SQL error or missing database */
I do not know why this happened.

It looks like your code is looking for your database in the 'Documents' folder of your application.
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
Thus, if the data.sqlite3 file is in your Resources folder, the applicaiton is not going to find the database. It's probably best to create and store the sqlitedatabase in the 'Documents' folder of the applicaiton. E.g /Users/interdev/Library/Application Support/iPhone Simulator/User/Applications/095C6E05-4EAE-4817-883E-A72E39D439E0/Documents/data.sqlite3

Related

unable to omit #".DS_Store" file while fetching contents of Document Drectory

I am working on storing a list of audio files into my document directory and then fetching them.
It gives me a list of audio files along with this it gives me a file with name #".DS_Store". While fetching content I want to leave this file of documents directory.
Is there any way I can get rid of this while fetching the audio list other than removing this from array or apply a #".DS_Store" check.
What exactly is the reason for this.?
#pragma mark - Saving Audio in Document Directory
-(void)saveAudioinDocumentDirectory:(ASIHTTPRequest *)theRequest
{
/*save the Audio file in Document Directory */
NSFileManager *fileManager=[NSFileManager defaultManager];
NSLog(#"GOT THE SIZe OF AUDIO %d",[[theRequest responseData] length]);
NSLog(#"AUDIO ID IS %#",[[theRequest userInfo] valueForKey:#"audioIndex"]);
/*Get the Path to Application Documents Directory*/
NSArray *docDir=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
/*append the neccessary file extension */
NSString *filepathStr=[NSString stringWithFormat:#"/%#/%#.mp3",docDir,[NSString stringWithFormat:#"%#",[[theRequest userInfo] valueForKey:#"audioIndex"]]];
/*Check if my crrent file exists in the Documents Directory*/
if(![fileManager fileExistsAtPath:filepathStr])
{
/* file doesnt exists */
/*create a NSdata of File*/
NSData *data=[NSData dataWithData:[theRequest responseData]];
NSLog(#"%#",filepathStr);
if ([data length] >0 ){
/*write the File at the Location in Documents Directory */
[data writeToFile:filepathStr atomically:YES];
NSLog(#"Successfully saved the file to %#", filepathStr);
}
else if([data length] == 0)
{
NSLog(#"Nothing was downloaded.");
}
}
/*After saving fetch the path til documents Directory*/
NSArray *folders = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
/*Get the Path for Files */
NSString *s=[folders objectAtIndex:0];
/*Fetch the list of Files stored in Documents Directory*/
NSArray *contents = [fileManager contentsOfDirectoryAtPath:s error:NULL];
NSLog(#"TOTAL NUMBER OF AUDIO FILES %d %#",[contents count],[contents objectAtIndex:0]);
if([Audiolistforstr isEqualToString:#"AudioListForIntro"])
{
// NSLog(#"Audiolistforstr#"IntroThirdRow" in reading audio from document Intro IS %#",Audiolistforstr);
/*Intro*/
[AudioListArrForIntro removeAllObjects];
[AudioListArrForIntro addObjectsFromArray:contents];
if([AudioListArrForIntro containsObject:#".DS_Store"])
{
[AudioListArrForIntro removeObject:#".DS_Store"];
}
NSLog(#"FINAL LIST %#",AudioListArrForIntro);
}
else if([Audiolistforstr isEqualToString:#"AudioListForCredits"])
{
// NSLog(#"Audiolistforstr#"IntroThirdRow" in reading audio from document credit IS %#",Audiolistforstr);
/*credits*/
[AudioListArrForCredits removeAllObjects];
[AudioListArrForCredits addObjectsFromArray:contents];
if([AudioListArrForCredits containsObject:#".DS_Store"])
{
[AudioListArrForCredits removeObject:#".DS_Store"];
}
NSLog(#"FINAL LIST %#",AudioListArrForCredits);
}
/* Did we find anything? */
if([Audiolistforstr isEqualToString:#"AudioListForIntro"])
{
// NSLog(#"Audiolistforstr#"IntroThirdRow" in reading audio fromRELOADNG TABLE Intro IS %#",Audiolistforstr);
/*Intro*/
if ([AudioListArrForIntro count] == 0)
{
}
else
{
UIView *vw=(UIView *)[self.view viewWithTag:ViewAddAudioIntroTag];
[(UITableView *)[vw viewWithTag:tblIntroAudioListTag] reloadData];
}
}
else if([Audiolistforstr isEqualToString:#"AudioListForCredits"])
{
// NSLog(#"Audiolistforstr#"IntroThirdRow" in reading audio fromRELOADNG TABLE Intro IS %#",Audiolistforstr);
/*Credits*/
if ([AudioListArrForCredits count] == 0)
{
}
else
{
/*AudioListForCredits*/
UIView *vw=(UIView *)[self.view viewWithTag:ViewAddAudioCreditsTag];
[(UITableView *)[vw viewWithTag:tblCreditsAudioListTag] reloadData];
}
}
}
Any help would be appreciated.
Thanks
Vikas
You can check for .DS_Store after NSArray *docDir=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; line........that is,
NSMutableArray * dirContents = [[NSMutableArray alloc] initWithArray:docDir];
if([docDir containsObject:#".DS_Store"])
{
[dirContents removeObject:#".DS_Store"];
}
By this, dirContents removes the entry of .DS_Store.
Filter your document directory contents. For example, if you are having audio files with extension of .mp3, then you can get all the mp3 files as below:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *directoryContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:NULL];
directoryContent = [directoryContent filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:#"pathExtension ==[c] %#", #"mp3"]];
This will omit all other files than the mp3 files..
All the best!!!
The API you're using:
NSArray *contents = [fileManager contentsOfDirectoryAtPath:s error:NULL];
returns all files found at the path, which would include the ".DS_Store" file.
I'd recommend assigning "contents" to a mutable array, e.g.:
NSMutableArray * contents =
[[NSMutableArray alloc] initWithArray: [fileManager contentsOfDirectoryAtPath:s error:NULL]];`
and iterate through the array to find and removing any and all files that don't have ".mp3" as a path extension.
I'd also recommend not starting any variable with an upper case letter (e.g. instead of "Audiolistforstr", use "audiolistforstr" or even better, "arrayofAudioFiles"). Objective C best practice is to start all variables and methods with lower case letters.
Its Working well..
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *imageFilenames = [manager contentsOfDirectoryAtPath:documentsDirectory error:nil];
for (int i = 0; i < [imageFilenames count]; i++)
{
NSString *imageName = [NSString stringWithFormat:#"%#/%#",documentsDirectory,[imageFilenames objectAtIndex:i] ];
if (![[imageFilenames objectAtIndex:i]isEqualToString:#".DS_Store"])
{
UIImage *myimage = [UIImage imageWithContentsOfFile:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:_myimage];
}
}

How to update a table in SQLite database in objective C?

I created a table named "dept" in sqlite manually that has username (as Varchar) and Password (as Integer).
I used the following code to update a table
NSString *database2=[[NSBundle mainBundle]pathForResource:#"deptDatabase" ofType:#"sqlite"];
NSString *databasePath2=[NSString stringWithFormat:#"%#",database2];
const char *dbPath=[databasePath2 UTF8String];
if (sqlite3_open(dbPath, &dbHandler)==SQLITE_OK) {
NSLog(#"database Opened");
const char* updateQuery="update dept set password=1234 where username='suren'";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(dbHandler, updateQuery, -1, &stmt, NULL)==SQLITE_OK) {
NSLog(#"Query Executed");
}
}
sqlite3_close(dbHandler);
but the table seems to be not updating.
Can anyone pls tell me how to update the table by altering the above code.
Thanks in advance
You can't not update fils in the mainBundle, these files are readonly.
To make changes to the database, you will have to copy it to the document directory.
And use the database in the document directory and not the one in the main bundle.
Only use the one in the main bundle as a payload file to be copied to the document directory if there is not file there.
Why do you create a new string here:
NSString *database2=[[NSBundle mainBundle]pathForResource:#"deptDatabase" ofType:#"sqlite"];
NSString *databasePath2=[NSString stringWithFormat:#"%#",database2];
The database2 is same as databasePath2. You are only using up memory here.
copy file from bundle to documents directory
NSString *databaseName = #"YOUR DB NAME WITH EXTENSION";
// Get the path to the documents directory and append the databaseName
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL success=[fileManager fileExistsAtPath:databasePath];
if (!success) {
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
// Copy the database from the package to the users filesystem
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
}
then u can work in the path databasePath (documents directory)
const char *dbPath=[databasePath UTF8String];
if (sqlite3_open(dbPath, &dbHandler)==SQLITE_OK) {
NSLog(#"database Opened");
const char* updateQuery="update dept set password=1234 where username='suren'";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(dbHandler, updateQuery, -1, &stmt, NULL)==SQLITE_OK) {
NSLog(#"Query Executed");
}
}
sqlite3_close(dbHandler);
hope it helps.. happy coding :)

initialization from incompatible pointer type

-(void)initializeTableData
{
sqlite3 *db=[DatabaseTestAppDelegate getNewDBConnection];
sqlite3_stmt *statement=nil;
const char *sql="select * from WhereTo";
if (sqlite3_prepare_v2(db, sql, -1, &statement, NULL)!=SQLITE_OK)
NSAssert1(0,#"error in preparing staement",sqlite3_errmsg(db));
else {
while(sqlite3_step(statement)==SQLITE_ROW)
[tableData addObject:[NSString stringWithFormat:#"%s",(char*)sqlite3_column_text(statement,1)]];
}
sqlite3_finalize(statement);
}
at sqlite3 *db=[DatabaseTestAppDelegate getNewDBConnection]; <--- it says, DatabaseTestAppDelegate may not respond to '+getNewDbConnection'
and here is my getNewDbConnection
+(sqlite3 *) getNewDBConnection{
sqlite3 *newDBconnection;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Malacca-lah.sqlite"];
// Open the database. The database was prepared outside the application.
if (sqlite3_open([path UTF8String], &newDBconnection) == SQLITE_OK) {
NSLog(#"Database Successfully Opened :)");
}
else {
NSLog(#"Error in opening database :(");
}
return newDBconnection;
}
im new to XCode and also SQLite... been learning this for the past few weeks now, trying to get a hang on it... anyways, pls help me out with this problem. I understand the whole code but i dont understand why the inheritance has an issue.
Thanks in advance
If it says that a class may not respond to a selector, it means that it can not able to find the method declaration of the selector. Have you declared the method +(sqlite3 *)getNewDBConnection in DatabaseTestAppDelegate's header(".h") file?

iPHONE SDK- sqlite , how do i do an insert statement

i have a database that is in the documents directorys of the
Application/iPhoneSimulator/3.2/Applications/etc/Documents
I have this code under my method
databaseName = #"database.sql";
NSArray *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory.NSUserDomainMask,YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
How do i do an insert with a variable/ array .
Something like
"INSERT INTO TABLE (COLUMN) VALUES ('%#'),[appDelegate.variable objectAtIndex:0];
I insist you to go through this question.
First of all copy the database from main bundle to your application's document dir.
You can follow below code to implement it.
NSString *databaseFile=[[NSBundle mainBundle] pathForResource:kDataBaseName ofType:kDataBaseExt];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSString *dbPath=[basePath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.%#",kDataBaseName,kDataBaseExt]];
NSFileManager *fm=[NSFileManager defaultManager];
if(![fm fileExistsAtPath:dbPath]){
[fm copyItemAtPath:databaseFile toPath:dbPath error:nil];
}
[fm release];
self.dataBasePath=dbPath;
I am supplying you directly my project code. Please add comment if any doubts.
I have added comments for the explanation.
// function with multiple arguments which is going to be used for inserting into table.
+(void)insertBuilding:(NSString*)BName streetNo:(NSInteger)streetNo streetName:(NSString*)streetName streetDir:(NSString*)streetDir muni:(NSString*)muni province:(NSString*)province bAccess:(NSString*)bAccess bType:(NSString*)bType amnity:(NSString*)amnity latitude:(NSString*)latitude longitude:(NSString*)longitude imageName:(NSString*)imageName {
// application delegate where I have saved my database path.
BuildingLocatorAppDelegate *x=(BuildingLocatorAppDelegate *)[[UIApplication sharedApplication]delegate];
sqlite3 *database; // database pointer
// verifying if database successfully opened from path or not.
// you must open database for executing insert query
// i have supplied database path in argument
// opened database address will be assigned to database pointer.
if(sqlite3_open([[x dataBasePath] UTF8String],&database) == SQLITE_OK) {
// creating a simple insert query string with arguments.
NSString *str=[NSString stringWithFormat:#"insert into buildingDtl(b_name,streetNo,streetName,streetDir,muni,province,b_access,b_type,aminity,latitude,longitude,b_image) values('%#',%i,'%#','%#','%#','%#','%#','%#','%#','%#','%#','%#')",BName,streetNo,streetName,streetDir,muni,province,bAccess,bType,amnity,latitude,longitude,imageName];
// converting query to UTF8string.
const char *sqlStmt=[str UTF8String];
sqlite3_stmt *cmp_sqlStmt;
// preparing for execution of statement.
if(sqlite3_prepare_v2(database, sqlStmt, -1, &cmp_sqlStmt, NULL)==SQLITE_OK) {
int returnValue = sqlite3_prepare_v2(database, sqlStmt, -1, &cmp_sqlStmt, NULL);
((returnValue==SQLITE_OK) ? NSLog(#"Success") : NSLog(#"UnSuccess") );
// if NSLog -> unsuccess - that means - there is some problem with insert query.
sqlite3_step(cmp_sqlStmt);
}
sqlite3_finalize(cmp_sqlStmt);
}
sqlite3_close(database);
// please don't forget to close database.
}
+(NSString *)stringWithFormat:(NSString *)format parameters:...];
NSString sql = [NSString stringWithFormat:#"INSERT INTO table VALUES('%#')", #"Hello, world!"];
sqlite3_....
Use either prepared statements in combination with the bind_*() functions (e.g. bind_text()) or the mprintf() function to insert strings, see this question for details.
To get a raw C-string you can pass to these functions use -UTF8String or -cStringUsingEncoding: on a NSString.

NSArray writeToFile fails

I am trying to save an array, which has some dictionaries inside, to a plist file but it fails. I don't get any errors. I do exactly the same few lines above in the code just with another array and that works.. I can't figure out why it does not save the file.
This is where I save the file: (see some debugger output below)
// When built parse through dictionary and save to file
for ( NSString *keys in [dicByCountry allKeys] )
{
NSArray *arrr = [[NSArray alloc] initWithArray:[dicByCountry objectForKey:keys]];
NSString *fname = [self filePath:[NSString stringWithFormat:#"regions.cid%#.plist",keys]];
if (![arrr writeToFile:fname atomically:YES])
NSLog(#"Could not write file regions.cid%#.plist",keys);
}
Here some GDB Output
(gdb) po fname
/Users/chris/Library/Application Support/iPhone Simulator/4.0/Applications/44A9FF9E-5715-4BF0-9BE2-525883281420/Documents/regions.cid0.plist
(gdb) po arrr
<__NSArrayI 0x8022b30>(
{
countryID = "<null>";
region = "?\U00e2vora";
regionID = 16;
},
{
countryID = "<null>";
region = Vicenza;
regionID = 14;
},
{
countryID = "<null>";
region = Wales;
regionID = 23;
}
)
If you read the documentation closely, writeToFile:atomically: expects the array to contain only objects which can be written into a plist file.
Only objects of type:
NSString
NSData
NSDate
NSNumber
NSArray
NSDictionary
are permitted. If you have arrays or dictionaries within the array you're saving, their values will be examined by the same criteria.
This is somewhat more restrictive than what's usually allowed in NSArrays. In particular, the value [NSNull null] is not acceptable.
I convert NSArray or NSDictionary to NSData before serializing. Following is a category on nsarray for serializing and deserializing. This comfortableby handles some data being nsnull
#implementation NSArray(Plist)
-(BOOL)writeToPlistFile:(NSString*)filename{
NSData * data = [NSKeyedArchiver archivedDataWithRootObject:self];
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDirectory = [paths objectAtIndex:0];
NSString * path = [documentsDirectory stringByAppendingPathComponent:filename];
BOOL didWriteSuccessfull = [data writeToFile:path atomically:YES];
return didWriteSuccessfull;
}
+(NSArray*)readFromPlistFile:(NSString*)filename{
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDirectory = [paths objectAtIndex:0];
NSString * path = [documentsDirectory stringByAppendingPathComponent:filename];
NSData * data = [NSData dataWithContentsOfFile:path];
return [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
#end //needs to be set for implementation