I am try to fetch image from Gallery and save it to SQLite Database. so that i will use this image in other part of my Application. I am get image from Gallery and show it in imageView it works fine but when i try to save it in Database application crash. I am using following code to convert image in NSData and then save it to Database field which is BLOB in type.
NSData * imageData;
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
[picker dismissModalViewControllerAnimated:YES];
ImageView.image= img;
imageData= UIImagePNGRepresentation(_ImageView.image);
}
and My SQLite insert method is:
-(void) CreateGoal:(NSString *)Title :(NSString *) Description :(NSString *)NextStep :(NSString *) Date :(NSData *)image{
//Get list of directories in Document path
NSArray * dirPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//Define new path for database
NSString * documentPath = [[dirPath objectAtIndex:0] stringByAppendingPathComponent:#"GoalBook.db"];
if(!(sqlite3_open([documentPath UTF8String], &db) == SQLITE_OK))
{
NSLog(#"An error has occured.");
return;
}else{
NSString *insertSQL = [NSString stringWithFormat:
#"INSERT INTO createGoal(title, description, nextstep, date, image) VALUES ('%#','%#','%#', '%#', '%#')",
Title, Description, NextStep, Date, image];
const char *sql = [insertSQL UTF8String];
sqlite3_stmt *sqlStatement;
if(sqlite3_prepare_v2(db, sql, -1, &sqlStatement, NULL) != SQLITE_OK)
{
NSLog(#"Problem with prepare statement");
return;
}else{
if(sqlite3_step(sqlStatement)==SQLITE_DONE){
sqlite3_finalize(sqlStatement);
sqlite3_close(db);
}
}
}
}
I use use this method for save my Data like this:
[self.database CreateGoal:_Goaltitle.text :_goaldescription.text :_goalnext.text :getGoaldate :imageData];
I googled a lot to find an answer, but after experimenting a lot I gave up.
Can any one suggest what is wrong with this Please ?
Thanks in advance
Related
Using MacOS Terminal I created a database name database.sql and inserted some records. Using iOS I can retrive the inserted values.
But using iOS code I tried to insert the record to the database and it does not enter the record in the database.
Should I set the need to set some permission? This is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
[self openDB];
}
-(IBAction)save:(id)sender{
[self insertRecordIntoTableNamed:#"Contacts"
field1Value:fname.text
field2Value:lname.text
field3Value:comp.text
field4Value:email.text
field5Value:pnumber.text
field6Value:mnumber.text
field7Value:add.text
field8Value:city.text
field9Value:state.text];
}
-(void)openDB{
NSString *sqlfile=[[NSBundle mainBundle]pathForResource:#"database" ofType:#"sql"];
if(sqlite3_open([sqlfile UTF8String], &db)!= SQLITE_OK){
sqlite3_close(db);
NSLog(#"Database connected");
NSAssert(0,#"Database failed to open");
}
else
{
NSLog(#"Database connected");
}
}
-(void) insertRecordIntoTableNamed:(NSString *) tableName
field1Value:(NSString *) field1Value
field2Value:(NSString *) field2Value
field3Value:(NSString *) field3Value
field4Value:(NSString *) field4Value
field5Value:(NSString *) field5Value
field6Value:(NSString *) field6Value
field7Value:(NSString *) field7Value
field8Value:(NSString *) field8Value
field9Value:(NSString *) field9Value {
NSString *sql = [NSString stringWithFormat:#"INSERT INTO %# VALUES ('%#','%#','%#','%#',%#,%#,'%#','%#','%#');",tableName, field1Value, field2Value,field3Value,field4Value,field5Value,field6Value,field7Value ,field8Value,field9Value];
NSLog(#"%#",sql);
// char *err;
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil)== SQLITE_OK)
{
if (SQLITE_DONE!=sqlite3_step(statement))
{
sqlite3_close(db);
NSAssert(0, #"Error updating table.");
}
else{
NSLog(#"Success");
NSLog(#"%#",sql);
}
}
sqlite3_finalize(statement);
}
#end
Here is what i have done:
change the folder and path permissions using CHMOD
split the sqlite3_exec() into sqlite3_prepare(), sqlite3_step() and sqlite3_finalize() - I get the same output - query is created but record is not created in database
I am able to retrieve record information
You can't write to a database in the resource bundle. You need to copy it and then use it.
Here's some code I've successfully used to do that (key is ensureDatabasePrepared where it is copied from resources):
- (BOOL)ensureDatabaseOpen: (NSError **)error
{
// already created db connection
if (_contactDb != nil)
{
return YES;
}
NSLog(#">> ContactManager::ensureDatabaseOpen");
if (![self ensureDatabasePrepared:error])
{
return NO;
}
const char *dbpath = [_dbPath UTF8String];
if (sqlite3_open(dbpath, &_contactDb) != SQLITE_OK &&
error != nil)
{
*error = [[[NSError alloc] initWithDomain:#"ContactsManager" code:1000 userInfo:nil] autorelease];
return NO;
}
NSLog(#"opened");
return YES;
}
- (BOOL)ensureDatabasePrepared: (NSError **)error
{
// already prepared
if ((_dbPath != nil) &&
([[NSFileManager defaultManager] fileExistsAtPath:_dbPath]))
{
return YES;
}
// db in main bundle - cant edit. copy to library if !exist
NSString *dbTemplatePath = [[NSBundle mainBundle] pathForResource:#"contacts" ofType:#"db"];
NSLog(#"%#", dbTemplatePath);
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
_dbPath = [libraryPath stringByAppendingPathComponent:#"contacts.db"];
NSLog(#"dbPath: %#", _dbPath);
// copy db from template to library
if (![[NSFileManager defaultManager] fileExistsAtPath:_dbPath])
{
NSLog(#"db not exists");
NSError *error = nil;
if (![[NSFileManager defaultManager] copyItemAtPath:dbTemplatePath toPath:_dbPath error:&error])
{
return NO;
}
NSLog(#"copied");
}
return YES;
}
If you are interacting with the database only from the code you posted - you are missing a sqlite3_close. Most likely the changes are not getting flushed onto disk
I have a simple program that update a record of a table
The table is "person" with two columns "name" and "age";
some records have been inserted, as follows:
name age
tom 20
andy 30
han 25
Now I am writing a program to update a row in the table:
NSString *database=[[NSBundle mainBundle] pathForResource:#"mytable" ofType:#"sqlite"];
sqlite3_open([database UTF8String],&contactDB);
NSString *text=#"andy";
NSString *query=[NSString stringWithFormat:#"UPDATE person SET age=%d WHERE name='%#'",30,text];
sqlite3_stmt *statement;
sqlite3_prepare_v2(contactDB,[query UTF8String],-1,&statement,NULL);
sqlite3_finalize(statement);
sqlite3_close(contactDB);
The program works fine, but the database is not updated (I am using SQLite Manager to browser the database)
When I try reading from database, it works well:
NSString *database=[[NSBundle mainBundle] pathForResource:#"mytable" ofType:#"sqlite"];
sqlite3_open([database UTF8String],&contactDB);
NSString *query1=[NSString stringWithFormat:#"SELECT * FROM person WHERE age=%d;",30];
sqlite3_stmt *statement;
sqlite3_prepare_v2(contactDB,[query1 UTF8String],-1,&statement,NULL);
sqlite3_step(statement);
NSString *result=[[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 0)];
label.text=result;
sqlite3_finalize(statement);
sqlite3_close(contactDB);
-(void)updateSetting:(NSArray *)arr
{
if(sqlite3_open([databasePath UTF8String],&myDatabase)==SQLITE_OK)
{
sqlite3_stmt *compiledStmt;
NSString *sqlStmt=[NSString stringWithFormat:#"UPDATE setting SET flow='%#',formate='%#' WHERE primaryKey=%i;",[arr objectAtIndex:0],[arr objectAtIndex:1],1];
if(sqlite3_prepare_v2(myDatabase, [sqlStmt UTF8String],-1,&compiledStmt, NULL)==SQLITE_OK)
{
NSLog(#"Successful update");
}
sqlite3_step(compiledStmt);
sqlite3_close(myDatabase);
}
}
I already faced this issues. Whats the problem behind this is you passed the query as a string format so you have to use the ; at the end of the query statement.
NSString *query=[NSString stringWithFormat:#"UPDATE questionbank SET age=%d WHERE name='%#';",30,text];
Please make a checking like below before you perform your sqlite3_step method.
const char *sqlQuery = "UPDATE SETTINGS SET someFlag = 0";
sqlite3_stmt *insertStatement = nil;
int success = 0;
if(sqlite3_prepare_v2(sqliteDatabase, sqlQuery, -1, &insertStatement, NULL) == SQLITE_OK)
{
success = sqlite3_step(insertStatement);
if(insertStatement)
{
sqlite3_finalize(insertStatement);
}
if(success == SQLITE_ERROR)
{
return NO;
}
return YES;
}
return NO;
So that you can figure out, where the problem is.
You need to check whether you could access and open the database or not. Simply place your update segment in a if-statement like this: if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK).
Also try to add NSLog(#"%s", sqlite3_errmsg(database)); after your prepare to see if there was any errors.
The answer for this problem is that the database in the main bundle is read-only
I can not insert data into sqlite3 file on XCode
I searched a lot in google but not able to get the answer required. I am choosing photos from the image gallery and I want to store it in my application. If I have to store it in database(As BLOB), then I have to enter the name of the file(which I am not getting as I have chosen from the gallery). Can I store it anywhere else? please help. I am stuck in this from a long time. I need to extract the image and show it in map calloutview.
I am using the below code to choose photo from gallery and insert into the database
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)dictionary {
[picker dismissModalViewControllerAnimated:YES];
tempImg.image = image;
NSData *imgData = UIImagePNGRepresentation(tempImg.image);
NSLog(#"the img data %#",imgData);
sql = [NSString stringWithFormat:#"update latlng set image = '%#' where placeName = '%#'",imgData,pName.text];
The below code excuting the sql statement mentioned above
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
const char *sqlStatement;
sqlStatement = [sql UTF8String];;
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK)
{
if (sqlite3_step(compiledStatement))
{
NSLog(#"YES");
}
}
else
{
printf( "could not prepare statemnt: %s\n", sqlite3_errmsg(database));
}
sqlite3_finalize(compiledStatement);
}sqlite3_close(database);
The below code to extract from database
NSData *data = [[NSData alloc] initWithBytes:sqlite3_column_blob(compiledStatement, 5) length:sqlite3_column_bytes(compiledStatement, 5)];
the below code to display the image in callout
UIImageView *mapImg = [[UIImageView alloc] initWithImage [UIImageimageWithData:imgData]];
pinView.leftCalloutAccessoryView = mapImg;
Convert the image obtained for photo gallery to NSData and then save it in database as a Blob,So you can easily retrieve the nsdata from database when ever you needed.
NSData *image1Data = UIImagePNGRepresentation(image1.image);
sqlite3_bind_blob(init_statement, 1, [image1Data bytes], [image1Data length], NULL);
image1 is the ImageView where i am displaying the image from the photo gallery.
All the best.
You can use this to retrieve the path to a directory writable by your application:
NSString *directory = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
There are various ways to access that directory, including NSData's writeToFile: methods, the NSFileManager class, the NSFileHandle class, and even C stdio functions.
In my case i searching lots of google and then finaly got solution that below code its work's for me i hope its work for you
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
NSLog(#"info: %#",info);
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);
}
if(sqlite3_step(addStmt) != SQLITE_DONE){
NSLog(#"error %s",sqlite3_errmsg(database));
}
else {
NSLog(#"Insert row Id = %d",sqlite3_last_insert_rowid(database));
}
sqlite3_finalize(addStmt);
}
sqlite3_close(database);
[picker dismissModalViewControllerAnimated:YES];
}
thank you
How to use sqlite3_column_blob with NSData what parameter I need to pass
In my iPhone App I want to retrive image stored in NSData format in sqlite database in BLOB datatype
for retriving it
//select query
NSString *selectQuery = [NSString stringWithFormat:#"select image_column from tbl_image where id=1"];
NSArray *arraySelect = [database executeQuery:selectQuery];
//displaying image
NSData *imageData = [[arraySelect objectAtIndex:0] valueForKey:#"image_column"];
self.img3=[UIImage imageWithData:imageData];
imageView.image=img3;
from above code I am not able to display image
so please help and suggest
thanks
sqlite *database;
sqlite3_stmt *Stmt;
sqlite3_open([[self getDBPath] UTF8String],&database)
- (NSString *) getDBPath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:#"XXX.sqlite"];
}
NSData*thumbnailData;
//Inserting Thumbnail Data
NSString *lSQL = [NSString stringWithFormat:#"insert into Table(Thumbnail1) values(?)"];
if(sqlite3_prepare_v2(database, [lSQL UTF8String], -1, &Stmt, NULL) == SQLITE_OK)
{
sqlite3_bind_blob(Stmt, 1,[thumbnailData bytes], [thumbnailData length], NULL);
sqlite3_step(Stmt);
sqlite3_reset(Stmt);
if(Stmt)
sqlite3_finalize(Stmt);
}
//Fetching Thumbnail Data
NSString *lSQL = [NSString stringWithFormat:#"select Thumbnail1 from table"];
if(sqlite3_prepare_v2(database, [lSQL UTF8String], -1, &Stmt, NULL) == SQLITE_OK)
{
while(sqlite3_step(Stmt) == SQLITE_ROW)
{
NSString *myColNameNSString = [NSString stringWithFormat:#"%s", sqlite3_column_name(Stmt)];
if ([myColNameNSString isEqualToString:#"Thumbnail1"])
{
thumbnailData = [[NSData alloc] initWithBytes:sqlite3_column_blob(Stmt) length:sqlite3_column_bytes(Stmt)];
}
}
}
Hey, I don't what are your project requirements. I would not use BLOB unless it's required to.
reason is you are storing image file into sqlite, everytime you have to use the file you have access the database, process the file and use. which will be fairly easy and simple in terms of number of threads you are running if you use images directly form the disk. give a thought about it. Good Luck
I was successfully accessing my database to get a list of cities on the App launch. I tried running a second query against it right afterward to get the list of States but all that happens is that my app blows up with no usable error in the console (simply says "Program received signal: EXEC_BAD_ACCESS" and nothing more).
Here is the code, I was hoping someone could potentially explain to me what I'm doing wrong:
-(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:#"mydatabase.sqlite"];
// Open the database. The database was prepared outside the application.
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK){
[self initializeCities:database];
[self initializeStates:database];
} 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...
}
}
-(void) initializeCities:(sqlite3 *)db {
NSMutableArray *cityArray = [[NSMutableArray alloc] init];
self.cities = cityArray;
[cityArray release];
// Get the primary key for all cities.
const char *sql = "SELECT id FROM my_table ORDER BY state";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, sql, -1, &statement, NULL) == SQLITE_OK){
while (sqlite3_step(statement) == SQLITE_ROW){
int primaryKey = sqlite3_column_int(statement, 0);
City *city = [[City alloc] initWithPrimaryKey:primaryKey database:db];
[cities addObject:city];
[city release];
}
}
// "Finalize" the statement - releases the resources associated with the statement.
sqlite3_finalize(statement);
}
-(void) initializeStates:(sqlite3 *)db {
NSMutableArray *statesArray = [[NSMutableArray alloc] init];
self.states = statesArray;
[statesArray release];
// Get the primary key for all cities.
const char *sql = "SELECT DISTINCT state FROM my_table ORDER BY state";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, sql, -1, &statement, NULL) == SQLITE_OK){
// We "step" through the results - once for each row
while (sqlite3_step(statement) == SQLITE_ROW){
NSString *state;
state = (NSString *)sqlite3_column_text(statement, 0);
[states addObject:state];
[state release];
}
}
// "Finalize" the statement - releases the resources associated with the statement.
sqlite3_finalize(statement);
}
I can't debug this code as the debugger never hits my breakpoints at all.
If I remove the initializeStates method the app works as expected (albiet without a list of states).
You are releasing "state" without having allocated it. Try something like this:
while (sqlite3_step(statement) == SQLITE_ROW){
NSString *state = [[NSString alloc] initWithCString:(char*)sqlite3_column_text(statement, 0) encoding:NSASCIIStringEncoding];
//state = (NSString *)sqlite3_column_text(statement, 0);
[states addObject:state];
[state release];
}
Update: add cast above to fix compiler warning
Your problem is this:
NSString *state = (NSString *)sqlite3_column_text(statement, 0);
According to the documentation, sqlite3_column_text() returns a char*, not an NSString*.
Edit: You wouldn't have had this problem if you'd have used a wrapper ;)