I fixed the error of my last question but my code raise another EXC_BAD_ACCESS
at
const char *sqlStatement = [NewData UTF8String];
the complete code is
sqlite3 *database;
// Setup some globals
NSString *databaseName = #"test.sql";
// 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];
[databasePath retain];
sqlite3_stmt *compiledStatement;
NSString * TheNewText = self.animalDesciption.text;
[TheNewText retain];
NSString * the_user = AnimalName ;
[ the_user retain];
NSString *NewData = [NSString stringWithFormat:#"%#%#%#%#", #"Update animals set description = ",TheNewText , " Where name = ",the_user];
[NewData retain] ;
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
const char *sqlStatement = [NewData UTF8String];
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL)== SQLITE_OK) {
sqlite3_reset(sqlStatement);
}
Did you try to alloc and init NSString?
NSString *NewData = [[NSString alloc] initWithFormat:#"%#%#%#%#", #"Update animals set description = ",TheNewText , " Where name = ",the_user];
and don't retain it?
I'd bet the string is getting collected by an autorelease run. Look in the docs for UTF8String, they suggest copying the string to ensure it lasting beyond that point.
My real suggestion, after some thought, is to get rid of the assignment to a stepping stone variable.
I'd say use it like this:
if(sqlite3_prepare_v2(database, [NewData UTF8String], -1, &compiledStatement, NULL)== SQLITE_OK) {
sqlite3_reset(compiledStatement);
Note the change in the reset statement. That may be your real problem, your code is trying to execute a string instead of a prepared sqlite statement.
Related
I have this method, and I am trying to call that method doing [self getUsers ObjectAtIndex:0] but compiler won't compile that line at all and says it's unknown. How do I call an array method to display all the string in it?
- (NSArray*)getUsers
{
NSArray *getUsers = [[NSArray alloc] init];
NSString *databasepath;
NSString *docsDir;
NSArray *dirPaths;
//NSString *databasePath;
//get the document directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
//build the path to the database file
databasepath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent:
#"users.db"]];
const char *dbPath = [databasepath UTF8String];
sqlite3_stmt *statement;
sqlite3 *userdb;
if (sqlite3_open(dbPath, &userdb) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:#"SELECT * FROM USERS WHERE username = \"%#\"", txtUsername.text];
const char *sql_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(userdb, sql_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
char *field = (char*) sqlite3_column_text(statement, 1);
NSString *usernameField = [[NSString alloc]initWithUTF8String:field];
//NSLog(#"%#", usernameField);
getUsers = [NSArray arrayWithObject:usernameField];
}
}
sqlite3_finalize(statement);
}
sqlite3_close(userdb);
return getUsers;
}
Use [[self getUsers] objectAtIndex:0].
If you use the latest Xcode/clang version, you can also use [self getUsers][0], since arrays now support indexing.
Consider say you had a method -(id)someMethod, and then called it like this:
id myValue = [self someMethod];
Inside someMethod, there is a return statement - whatever is to the right of the return is what will be assigned to myValue in the calling method or function.
Just call like this:
NSArray *arrAllUsers = [self getUsers]; //As getUsers is method which returns nsarray.
can anybody tell me why i am unable to insert an image in sqlite. Some time i get error like:
1)(sqlite3_step(stm) == SQLITE_DONE) , getting value as 21.
2)gets stored in an array and not into databse.
I a fresher in objective c so if u could post back a code it would be sweet, as i searched almost evry site.
Thanks!
-(IBAction)submitDetails:(id)sender
{
sqlite3_stmt *stm;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &connectDB) == SQLITE_OK)
{
UIImage *contactImage = imageView.image;
NSData *imageData = UIImageJPEGRepresentation(contactImage, 100);
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:imageData forKey:#"image"];
[defaults synchronize];
NSLog(#"Data saved");
NSString *insertSQL = [NSString stringWithFormat: #"INSERT INTO STUDENTS (name,salary, gid,photo) VALUES (\"%#\", \"%#\", \"%#\",?)", name.text,salary.text,gid.text,imageData] ;
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(connectDB, insert_stmt, -1, &stm, NULL);
NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirec = [paths objectAtIndex:0];
NSString *imgePath = [documentsDirec stringByAppendingPathComponent:#"note.sqlite"];
if(sqlite3_open([imgePath UTF8String], &database) == SQLITE_OK){
const char *sql = "insert into images (images) values (?)";
if(sqlite3_prepare_v2(database, sql, -1, &addStmt, NULL) == SQLITE_OK){
UIImage *edtedImae = [info objectForKey:UIImagePickerControllerOriginalImage];
NSData *dataForImage = UIImagePNGRepresentation(edtedImae);
sqlite3_bind_blob(addStmt, 1, [dataForImage bytes], [dataForImage length], SQLITE_TRANSIENT);
NSLog(#"1st ..... %i",sqlite3_step(stm));
NSLog(#" 2nd.... %i",SQLITE_DONE);
if (sqlite3_step(stm) == SQLITE_DONE)
{
NSString* aName=name.text;
NSString* aSalary=salary.text;
NSString* aGid=gid.text;
UIImage* aPhoto=[UIImage imageWithData:imageData];
Person *person = [[Person alloc] initWithName:aName salary:aSalary gid:aGid photo:aPhoto];
[rootObject.list addObject:person];
[person release];
status.text = #"Contact added";
NSLog(#"contact added %# %#",name.text,gid.text);
NSLog(#"the count in person list is %i",[rootObject.list count]);
name.text = #"";
gid.text = #"";
salary.text = #"";
}
else
{
status.text = #"Failed to add contact";
}
sqlite3_finalize(stm);
sqlite3_close(connectDB);
}
}
Don't save the image in the database if you can avoid it. Instead, use columns to store the file name and any other attributes and then save the image as a document. I use a guid method to create file names. Don't forget to remove the document if you should remove the db entry.
I have a database. It has two tables in it. I want to call one table in an if condition. How do I call the second table in the else part if the if conditions fail?
This is the code I used:
{
NSArray *Paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *DocumentsDirectory = [Paths objectAtIndex:0];
NSString *Path = [DocumentsDirectory stringByAppendingPathComponent:#"StoreList.sqlite"];
// Open the database from the users filessytem.
if (sqlite3_open([Path UTF8String], &database) == SQLITE_OK) {
// Setup the SQL Statement and compile it for faster access
//*********const char *sqlStatement = "select * from Store where Zipcode ='%#'",inputTxt ;
NSString *sqlStatement = [NSString stringWithFormat:#"select * from Store where Zipcode ='%#' or Address = '%#' or CityName = '%#'",inputTxt, inputTxt, inputTxt];
NSLog(#" Query in if :%#",sqlStatement);
sqlite3_stmt *compiledStatement;
if (sqlite3_prepare_v2(database, [sqlStatement UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK) {
// Loop through the results and add them to the feeds array.
if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
NSString *latValue = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
NSLog(#"Latitude:%#",latValue);
NSString *longValue = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
NSLog(#"Longitude:%#",longValue);
//currentLocationLbl.text=[NSString stringWithFormat:#" %# , %#" ,latValue,longValue];
// delegate.latitudeVal=latValue;
// delegate.longitudeVal=longValue;
txtChangeLocation.text = #"";
isFromChangeLoc=TRUE;
//self.tabBarController.selectedIndex=3;
}
else {
NSLog(#"ELSE PART");
// Open the database from the user's filessytem.
if (sqlite3_open([Path UTF8String], &database) == SQLITE_OK) {
// Setup the SQL Statement and compile it for faster access
//*********const char *sqlStatement = "select * from Store where Zipcode ='%#'",inputTxt ;
NSString *sqlStatement = [NSString stringWithFormat:#"select * from zipcodes where zip ='35004'"];
NSLog(#" Query in if :%#",sqlStatement);
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, [sqlStatement UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK) {
// Loop through the results and add them to the feeds array
if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
NSString *latValue = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
NSLog(#"Latitude:%#",latValue);
NSString *longValue = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
NSLog(#"Longitude:%#",longValue);
//currentLocationLbl.text=[NSString stringWithFormat:#" %# , %#" ,latValue,longValue];
// delegate.latitudeVal=latValue;
// delegate.longitudeVal=longValue;
txtChangeLocation.text = #"";
isFromChangeLoc=TRUE;
}
}
}
}
sqlite3_finalize(compiledStatement);
sqlite3_close(database);
}
}
I'm getting the input from the text box. When I give the correct value, which is there in the database, it is working fine, the fetch of the data is correct. If I give the wrong data in the textbox it's not working fine - the else condition fails.
How can this issue be fixed?
When going on else you open the same database again, that's not needed (and might cause some problems as well, haven't tried it). Use a BOOL when running the first (select) statement and set it to YES or NO if it fails or not. After you finish with the first statement check the BOOL value and if ==NO run the second statement.
...
BOOL success = NO;
NSString *sqlStatement = [NSString stringWithFormat:#"select * from Store where Zipcode '%#' or Address = '%#' or CityName = '%#'",inputTxt, inputTxt, inputTxt];
NSLog(#" Query in if :%#",sqlStatement);
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, [sqlStatement UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK){
if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
NSString *latValue = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
NSLog(#"Latitude:%#",latValue);
NSString *longValue = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
NSLog(#"Longitude:%#",longValue);
//currentLocationLbl.text=[NSString stringWithFormat:#" %# , %#" ,latValue,longValue];
// delegate.latitudeVal=latValue;
// delegate.longitudeVal=longValue;
txtChangeLocation.text = #"";
isFromChangeLoc=TRUE;
//self.tabBarController.selectedIndex=3;
success=YES;
}
}
sqlite3_finalize(compiledStatement);
if(success){
//do the else from your code
NSString *sqlStatement = [NSString stringWithFormat:#"select * from zipcodes where zip ='35004'"];
NSLog(#" Query in if :%#",sqlStatement);
if(sqlite3_prepare_v2(database, [sqlStatement UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK){
// Loop through the results and add them to the feeds array
if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
NSString *latValue = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
NSLog(#"Latitude:%#",latValue);
NSString *longValue = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
NSLog(#"Longitude:%#",longValue);
//currentLocationLbl.text=[NSString stringWithFormat:#" %# , %#" ,latValue,longValue];
// delegate.latitudeVal=latValue;
// delegate.longitudeVal=longValue;
txtChangeLocation.text = #"";
isFromChangeLoc=TRUE;
}
}
sqlite3_finalize(compiledStatement);
}
I haven't run it, so it might contain some bugs.
In my app I am executing a query to get the count of images which are having same category and that category is passed by me as the parameter. Now when the query is executed I want to get two results either 1 or more than one. For that purpose I think I need to convert the string to integer. When I check the value of the String it is showing me 1 but when that value is returned to the method it is showing something like this:695842 and something else also. What could be the reason? Please help. I am posting the part of code:-
-(NSInteger)searchImagesInSameCategory:(NSString *)categoryName
{
NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory= [paths objectAtIndex:0];
NSString *path=[documentsDirectory stringByAppendingPathComponent:#"SymbolTalkLanguageElement.sqlite"];
//Open the database
//might have to make database as property
if(sqlite3_open([path UTF8String], &dataBase) ==SQLITE_OK)
{
sqlite3_stmt *statement;
NSString *strSQL = [[NSString alloc]init];
strSQL = #"select Count(ImageName) from tblLanguageElement where Category='";
strSQL = [[strSQL stringByAppendingString:categoryName] stringByAppendingString:#"'"];
const char *bar = [strSQL UTF8String];
if(sqlite3_prepare(dataBase, bar, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(#"%#",[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)]);
int k;
//NSString *string=[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)];
//NSLog(string);
k=[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)];
//NSLog([NSString stringWithFormat:#"Count for k:-%d",k]);
//[list addObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)]];
//return [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)];
return k;
}
}
}
return 1;
}
You should use intValue method to convert a NSString to int.
NSString *integerStr = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)];
k = [integerStr intValue];
The problem code:
NSString *query = #"SELECT Name FROM Category";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, nil)
== SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
char *row =(char *)sqlite3_column_text(statement,0);
char *rowData = (char *)sqlite3_column_text(statement,1);
NSString *fieldName = [[NSString alloc] initWithUTF8String:row];
NSString *fieldValue = [[NSString alloc] initWithUTF8String:rowData];
NSLog(#"%#",fieldName);
NSLog(#"%#",fieldValue);
[fieldName release];
[fieldValue release];
}
sqlite3_finalize(statement);
}
char *row =(char *)sqlite3_column_text(statement,0);
In the above code instead of 0 can't I just pass a column name?
How can I do that ?
You can't, not with the C bindings anyway. Instead, you may use this Objective-C wrapper over the standard C interface: FMDB