Cocoa sqlite db file - objective-c

I'm having a bit of trouble understanding why the below code is not working:
sqlite3_stmt *statement5;
NSString *databasePath2 = #"default-gameData.db";
NSInteger speed_int = 0;
const char *dbPath2 = [databasePath2 UTF8String];
if(sqlite3_open(dbPath2, &db)==SQLITE_OK){
NSString *getspeeds = #"SELECT * FROM planeInfo";
NSLog(#"%#",getspeeds);
const char *getspeed_stmt = [getspeeds UTF8String];
if(sqlite3_prepare_v2(db, getspeed_stmt, -1, &statement5, nil)==SQLITE_OK){
NSLog(#"%d",sqlite3_step(statement5));
NSString *org_plane_info_id = [[NSString alloc] init];
while(sqlite3_step(statement5) == SQLITE_ROW){
if((const char*)sqlite3_column_text(statement5, 1)==NULL){
org_plane_info_id = #"no";
}
else{
org_plane_info_id = [[NSString alloc] initWithUTF8String:(const char*)sqlite3_column_text(statement5, 1)];
}
NSLog(#"%#",org_plane_info_id);
if(org_plane_info_id==plane_info_id){
NSString *speed = [[NSString alloc] initWithUTF8String:(const char*)sqlite3_column_text(statement5, 2)];
NSLog(#"%#",speed);
speed_int = [speed integerValue];
return speed_int;
}
}
}
}
if(speed_int==0){
return 0;
}
sqlite3_close(db);
I've found the source of the problem being the database path, the file is stored where the .h and .m files are so I think that's where I am going wrong, but what do I have to do to get that to work?

Cocoa/Foundation doesn't know where your file is. You need to tell it that it's in the app bundle.
NSString *databasePath2 = [[NSBundle mainBundle] pathForResource:#"default-gameData" ofType:#"db"];

Related

Getting NSDate from database and assign it to object NSDate

I am doing a project that will load data from database and display it in tableView.
I am wondering... What is the right code to be executed for NSDate from database to be assigned into voucher.date
line of code asked=(voucher.date = [[NSNumber alloc](init with sqlite3 statement line);)
Responses will be a great help ! :)
NSMutableArray *vouchers = [[NSMutableArray alloc]init];
while (sqlite3_step(statement) == SQLITE_ROW)
{
searchAndClaim *voucher = [[searchAndClaim alloc]init];
voucher.inquiry_id = [[NSNumber alloc] initWithInt:sqlite3_column_int(statement, 0)];
voucher.name = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 1)];
voucher.date = [[NSNumber alloc](init with sqlite3 statement line);
voucher.branch = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 4)];
voucher.expDate = [[NSString alloc](init with sqlite3 statement line)];
[vouchers addObject:voucher];
}

Xcode - NSInvalidArgumentException', reason: '*** +[NSString stringWithUTF8String:]: NULL cString'

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];

call an array method

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.

iOS - object sent autorelease too many times

I have a method that is reading some information from a sqlite db and initialising a class called Achievement. When I analyse this code I am given the feedback 'object sent autorelease too many times'. I don't really understand where I am going wrong - why is the retval object released on line 225 and not at the return statement on line 229?
Can someone please explain where I have made a mistake in the code below and how I can fix it?
Function Code (so answerer can easily copy/paste):
- (Achievement *)getAchievement:(int)Id
{
Achievement *retval = [[Achievement alloc] autorelease];
NSString *query = [NSString stringWithFormat:#"SELECT * FROM Achievements where ID = %d", Id];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, nil)
== SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
int Id = sqlite3_column_int(statement, 0);
char *name = (char *) sqlite3_column_text(statement, 1);
char *title = (char *) sqlite3_column_text(statement, 2);
char *description = (char *) sqlite3_column_text(statement, 3);
Boolean Achieved;
char *com = (char *) sqlite3_column_text(statement, 4);
NSString *c1 = [[[NSString alloc] initWithUTF8String:com] autorelease];
Achieved = [c1 isEqualToString:#"1"];
NSDate *CompletedDate = (NSDate *) sqlite3_column_text(statement, 5);
char *icon = (char *) sqlite3_column_text(statement, 6);
int New = sqlite3_column_int(statement, 7);
NSString *Title = [[[NSString alloc] initWithUTF8String:title] autorelease];
NSString *Description = [[[NSString alloc] initWithUTF8String:description] autorelease];
NSString *Name = [[[NSString alloc] initWithUTF8String:name] autorelease];
NSString *Icon = [[[NSString alloc] initWithUTF8String:icon] autorelease];
retval = [retval initDetails:Id :Name :Title: Description : Achieved : CompletedDate: Icon: New];
}
sqlite3_finalize(statement);
}
return retval;
}
Analysis feedback image:
As always any feedback is greatly appreciated.
Achievement *retval = [[Achievement alloc] autorelease];
this is very bad idea to do that. You ALWAYS have to initialize object before using it.
Instead you're initializing it in a loop:
retval = [retval initDetails:Id :Name :Title: Description : Achieved : CompletedDate: Icon: New];
I don't really get why you need to initialize the same object multiple times. Maybe, you need to create multiple objects and init them with different values?
Rearrange this:
Achievement *retval = nil;
while (...) {
[retval release];
retval = [[Achievement alloc] initDetails: ...];
}
return [retval autorelease];
I guess you're confusing the compiler with the wrong sequence of alloc, init, autorelease. What you should be doing instead is the following (pseudocode):
Achievement *retval = nil;
while (...) {
retval = [[[Achievement alloc] initDetails: ...] autorelease];
}
return retval;

How do I retrieve all the rows from an SQLite table?

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;