I have these codes that retrieve value from the SQLite database and comparing it to a NSString declared in the header file.
Retrieving from database:
NSString *sql = [[NSString alloc] initWithFormat:#"SELECT TESTONE, TESTTWO, TESTTHREE, TESTFOUR FROM STUDENTS WHERE NAME='%#'",Name];
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil)== SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW){
char *one = (char *) sqlite3_column_text(statement,0);
tOne = [[NSString alloc] initWithUTF8String:one];
char *two = (char *) sqlite3_column_text(statement,1);
tTwo = [[NSString alloc] initWithUTF8String:two];
char *three = (char *) sqlite3_column_text(statement,2);
tThree = [[NSString alloc] initWithUTF8String:three];
char *four = (char *) sqlite3_column_text(statement,3);
tFour = [[NSString alloc] initWithUTF8String:four];
}
}
Comparing string:
if(tOne == #"Yes")
{
//blablabla
}
else if(tOne == #"No")
{
//blablabla
}
It doesn't seem to go into the 'IF' at all.
I have double-checked the field in the database and its TEXT datatype.
I made a UILabel to display the tOne value and it shows "Yes".
May i know what or where went wrong during the comparison?
You can't compare strings like this, you have to use isEqualToString:
if([tOne isEqualToString:#"Yes"])
{
//blablabla
}
else if([tOne isEqualToString:#"No"])
{
//blablabla
}
You are currently comparing the address of the NSString object, not its contents. Use the compare: or isEqualToString: family of methods to compare the content of the string.
Reference.
Related
I have a project in Objective-c in which I am trying to find a way of saving the attributedText from a UITextView to a SQLite3 table.
My Project Target OS is 12.1.
I am using an object called "MMItem" with a NSData property called "notesAttributed".
In my viewController Class I am using NSKeyedArchiver to encode the AttributedText into a NSdata format then copying to the object property.
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.itemNotes.attributedText requiringSecureCoding:YES error:Nil];
self.item.notesAttributed = data;
I then call a method in my model to save the object
NSString *resultStr = [self.meetingModel saveAttributedItemNote:item];
In the model I'm attempting to save the attributed string to a field in the Item table setup as type 'blob'
- (NSString *)saveAttributedItemNote:(MMItem *)item{
NSString *errorMessage;
NSString *sql;
NSInteger result = 0;
if (item) {
//create blob encoded data for Attributed notes
NSInteger itemID = item.itemID;
sql = [NSString stringWithFormat:
#"UPDATE Item set noteAttributed = %# WHERE itemID = %ld",item.notesAttributed, (long)itemID];
char *err;
// open DB and save
if ([self openDB]){
//NSLog(#"%#", NSStringFromSelector(_cmd));
result = sqlite3_exec(db, [sql UTF8String], NULL, NULL, &err);
sqlite3_close(db);
}
if (result != SQLITE_OK)
{
errorMessage = #"Error";
}
else
{
//NSLog(#"Table updated");
errorMessage = #"OK";
[self saveAttributedItemNote:item];
}
}
item = nil;
return errorMessage;
}
The SQL Execute statement fails with error 1.
I suspect I'm meant to insert the blob into the table using 'binding' and not an Execute statement but I just find how to put this all together using Objective-c.
Any help would be great thanks.
With acknowledgement to the following post iOS SQLite Blob data is saving NULL
I managed to get a working solution. It's apparent that to save a blob into an SQLite you must use a Prepare statement with a sqlite3_bind_blob to insert the blob parameters into the statement, then to use sqlite3_step to deploy it.
This then allows the bytes and length parameters to also be passed into the statement, which I don't think can be done using the execute method I was originally trying.
Here is the code that works perfectly.
- (NSString *)saveAttributedItemNote:(MMItem *)item{
NSString *errorMessage;
if (item) {
//create blob encoded data for Attributed notes
int itemID = (int)item.itemID;
if ([self openDB]) {
const char *insert_stmt = "UPDATE Item set notesAttributed = ? WHERE itemID = ?";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, insert_stmt, -1, &statement, NULL) == SQLITE_OK) {
sqlite3_bind_blob(statement, 1, item.notesAttributed.bytes, (int)item.notesAttributed.length, SQLITE_TRANSIENT);
sqlite3_bind_int(statement, 2, itemID);
if (sqlite3_step(statement) == SQLITE_DONE) {
errorMessage = #"OK";
//update successfull
}else{
const char *err = sqlite3_errmsg(db);
NSString *error = [[NSString alloc] initWithUTF8String:err];
NSLog(#"Update error ID:%#",error);
errorMessage = #"Error";
}
sqlite3_finalize(statement);
}else{
errorMessage = #"Error";
NSLog(#"Unable to prepare stsement %s: %s",insert_stmt, sqlite3_errmsg(db));
}
sqlite3_close(db);
}
}
item = nil;
return errorMessage;
}
The following code then shows how the field was retrieved from sqlite. Column 11 is the blob.
if (sqlite3_prepare(db, [sql UTF8String], -1, &statement, nil)==SQLITE_OK)
{
//NSLog(#"SQL Select OK");
while (sqlite3_step(statement)==SQLITE_ROW) {
MMItem *item = [[MMItem alloc]init];
item.itemID = sqlite3_column_int(statement, 0);
item.topicID = sqlite3_column_int(statement, 1);
item.sequenceID = sqlite3_column_int(statement, 2);
char *description = (char *) sqlite3_column_text(statement, 3);
if(description) item.itemDescription = [[NSString alloc]initWithUTF8String:description];
char *notes = (char *) sqlite3_column_text(statement, 4);
if(notes) item.notes = [[NSString alloc]initWithUTF8String:notes];
char *actionBy = (char *) sqlite3_column_text(statement, 5);
if(actionBy) item.actionBy = [[NSString alloc]initWithUTF8String:actionBy];
char *requiredBy = (char *) sqlite3_column_text(statement, 6);
if (requiredBy) item.requiredBy = [[NSString alloc]initWithUTF8String:requiredBy];
item.completed = sqlite3_column_int(statement, 7);
char *proposedBy = (char *) sqlite3_column_text(statement, 8);
if (proposedBy) item.proposedBy = [[NSString alloc]initWithUTF8String:proposedBy];
char *secondedBy = (char *) sqlite3_column_text(statement, 9);
if (secondedBy) item.secondedBy = [[NSString alloc]initWithUTF8String:secondedBy];
item.carried = sqlite3_column_int(statement, 10);
NSData *attributedTextData = [[NSData alloc]initWithBytes:sqlite3_column_blob(statement,11) length:sqlite3_column_bytes(statement, 11)];
item.notesAttributed = attributedTextData;
[items addObject:item];
item = nil;
}
}
Then in the ViewController, the following was used to take the NSData property and decode this for the UITextView (self.itemNotes)
self.itemNotes.attributedText = [NSKeyedUnarchiver unarchivedObjectOfClass:([NSAttributedString class]) fromData:self.item.notesAttributed error:&error];
Weird how just posting the question lead me to finding the right solution. Thanks to El Tomato for your help bud.
Here is my code i am getting only the last value of the database in the array but i need the entire column values in my array...
//select the values from the db
NSString *sql = [NSString stringWithFormat:#"SELECT * FROM district_details"];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil)==SQLITE_OK)
{
while (sqlite3_step(statement)==SQLITE_ROW)
{
char *field2 = (char *)sqlite3_column_text(statement, 1);
field2Str = [[NSString alloc]initWithUTF8String:field2];
str = [NSString stringWithFormat:#"%#", field2Str]; NSLog(#"the value from thr field1 from the district name is %#...",field2Str);
myarray =[[NSMutableArray alloc]initWithObjects:#"--select the value--",nil];
[myarray addObject:field2Str];
NSLog(#"the value of the myarray is......%#",myarray);
}
}
Initiate your array object once before you use it, if you initiate it inside while loop like you do it loses the previous added objects and takes fresh allocation inside the heap memory.
Just put this code inside viewDidLoad method and remove from while loop:
- (void)viewDidLoad {
[super viewDidLoad];
// mutable array allocation do once here
myarray =[[NSMutableArray alloc]initWithObjects:#"--select the value--",nil];
}
Now use below code to fetch entire column from data base:
//select the values from the db
NSString *sql = [NSString stringWithFormat:#"SELECT * FROM district_details"];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil)==SQLITE_OK)
{
while (sqlite3_step(statement)==SQLITE_ROW)
{
char *field2 = (char *)sqlite3_column_text(statement, 1);
field2Str = [[NSString alloc]initWithUTF8String:field2];
// --------- myarray allocation removed from here -----------
[myarray addObject:field2Str];
NSLog(#"the value of the myarray is......%#",myarray);
}
sqlite3_finalize(statement);
}
sqlite3_close(db);
The problem is that you are instantiating a new mutable array in ever loop of your while statement. You want to instantiate it once, before the loop, and inside the loop merely addObject.
NSString *sql = [NSString stringWithFormat:#"SELECT * FROM district_details"];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil)==SQLITE_OK) {
myarray = [[NSMutableArray alloc] initWithObjects:#"--select the value--",nil];
while (sqlite3_step(statement)==SQLITE_ROW) {
char *field2 = (char *)sqlite3_column_text(statement, 1);
field2Str = [[NSString alloc] initWithUTF8String:field2];
[myarray addObject:field2Str];
}
sqlite3_finalize(statement); // remember to finalize to prevent SQLite leak
}
I have the below code that should populate the TableViewController with information from my sqlite file, it lets me add fine, and i can view the file and the information is there, but I'm getting the above error message, and failing miserably at fixing it....
-(NSMutableArray *) stockList
{
NSString *filePath = [self getWritableDBPath];
if(sqlite3_open([filePath UTF8String], &db) == SQLITE_OK)
{
const char *sql = "Select Description, Quantity from StockTable";
sqlite3_stmt *sqlStatement;
if(sqlite3_prepare(db, sql, -1, &sqlStatement, NULL) != SQLITE_OK)
{
NSLog(#"Problem with query: %s", sqlite3_errmsg(db));
}
else
{
while (sqlite3_step(sqlStatement)==SQLITE_ROW)
{
Stock * stock = [[Stock alloc] init];
stock.desc = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 1)];
stock.qty = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 2)];
[thestock addObject:stock];
stock = nil;
}
}
sqlite3_finalize(sqlStatement);
}
sqlite3_close(db);
return thestock;
}
thanks for any help, currently googling it myself..
connection strings as mentioned below: (reason being it causes a LINK error and states that MyDB is a duplicate in both views)
TableView:
NSString * MyDB2=#"StockDatabase.db";
AddingView:
NSString * MyDB=#"StockDatabase.db";
One (or both) of the columns you are fetching from the database is NULL:
stock.desc = [NSString stringWithUTF8String:(char *)sqlite3_column_text(sqlStatement, 1)];
stock.qty = [NSString stringWithUTF8String:(char *)sqlite3_column_text(sqlStatement, 2)];
Guard against that with:
const char *desc = sqlite3_column_text(sqlStatement, 1);
if (desc)
stock.desk = #(desc);
const char *qty = sqlite3_column_text(sqlStatement, 2);
if (qty)
stock.qty = #(qty);
I got this error too. How I solved it is by setting the first column text index to "0" instead of "1". And the error went away.
char *charPrice = (char*) sqlite3_column_text(stmt, 0);
NSString *price = [NSString stringWithUTF8String:charPrice];
char *charName = (char*) sqlite3_column_text(stmt, 1);
NSString *name = [NSString stringWithUTF8String:charName];
hello guys i am doing some database operations in iphone .. please can anyone explain me how to retrieve all rows from the table..here in this example it retreives only the latest entered data..
while(sqlite3_step(statement) == SQLITE_ROW)
{
char *field1 = (char *) sqlite3_column_text(statement,0);
NSString *field1Str = [[NSString alloc] initWithUTF8String: field1];
char *field2 = (char *) sqlite3_column_text(statement,1);
NSString *field2Str = [[NSString alloc] initWithUTF8String: field2];
NSString *str = [[NSString alloc] initWithFormat:#"%#::%#",field1Str, field2Str];
textv.text=str;
[field1Str release];
[field2Str release];
}
You were doing all right so far. Just keep adding the final formatted string (str) in an NSMutableArray and finally return it from the function.
// Take an array to store all string.
NSMutableArray *allRows = [[[NSMutableArray alloc] init] autorelease];
while(sqlite3_step(statement) == SQLITE_ROW)
{
char *field1 = (char *) sqlite3_column_text(statement,0);
NSString *field1Str = [[NSString alloc] initWithUTF8String: field1];
char *field2 = (char *) sqlite3_column_text(statement,1);
NSString *field2Str = [[NSString alloc] initWithUTF8String: field2];
NSString *str = [NSString stringWithFormat:#"%#::%#",field1Str, field2Str];
// textv.text=str; // I don't know why your are mixing your view controller stuff's in database function.
// Add the string in the array.
allRows addObject:str];
[field1Str release];
[field2Str release];
}
// Finally you can return your allRows
return allRows;
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