I have a table and 3 records.
and I have the code;
-(void) readScoreFromDatabase {
sqlite3 *database;
scores = [[NSMutableArray alloc] init];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
const char *sqlStatement = "select name,score from game";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
// Loop through the results and add them to the feeds array
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
//if(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
NSString *aName =[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
NSString *aScore =[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
DatabaseClass *dbOBJ = [[DatabaseClass alloc] initWithName:aName score:aScore];
[scores addObject:dbOBJ];
[dbOBJ release];
}
}
sqlite3_finalize(compiledStatement);
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"No Connection"
delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
}
sqlite3_close(database);
}
and I am using that code to show records;
-(IBAction)refreshClick:(id)sender {
// Navigation logic -- create and push a new view controller
IDRGameAppDelegate *appDelegate = (IDRGameAppDelegate *)[[UIApplication sharedApplication] delegate];
DatabaseClass *dbOBJ = (DatabaseClass *)[appDelegate.scores objectAtIndex:1];
game1NameLabel.text = dbOBJ.name;
score1Label.text = dbOBJ.score;
}
I have 3 records, but I can take only one record. I mean changed that line "DatabaseClass *dbOBJ = (DatabaseClass *)[appDelegate.scores objectAtIndex:1];"
objectAtIndex:1 when I change this value 1 or 2 or 3 etc. the result doesn't change. It is always showing one record from 3 records. I don't understand the reason.
Thank you.
Are you able to see the table rows, when you go to the SQLite manager (from Firefox) and run the below query:
select name,score from game;
If you are able to see 3 records, then:
Go to the iPhone simulator and reset settings
(which will clear all the temp caches, database, and build files).
Go to Xcode and do a Build and GO.
This will get you latest database; put it in the Build folder.
This may not be the answer you want, but you should really consider using Core Data now that it's in iPhone OS 3.0. It handles most of this for you and is very easy to use.
Maybe you forgot to set score to your delegate?
scores = [[NSMutableArray alloc] init];
....
//I don't see this in your code
((IDRGameAppDelegate *)[[UIApplication sharedApplication] delegate]).score = score;
Related
i want to select data from the table but those data which has same question id in the questions table and answers table.
Now it selects all the data from answers the code is shown below
+ (void) getAnswers:(NSString*)dbPath{
CereniaAppDelegate *appDelegate = (CereniaAppDelegate *)[[UIApplication sharedApplication] delegate];
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
const char *sql = "select *from answers";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
Answers *coffeeObj = [[Answers alloc] initWithPrimaryKey:primaryKey];
coffeeObj.answer_text = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 3)];
NSString*testString=coffeeObj.answer_text;
NSLog(testString);
[appDelegate.answerArray addObject:coffeeObj];
int mycount=[appDelegate.answerArray count];
NSLog(#"This is int of latest %d",mycount);
[coffeeObj release];
}
}
}
else
sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.
}
I suggest avoiding c level code for calling a SQLite DB - try a simple wrapper over SQLite - see https://github.com/JohnGoodstadt/EasySQLite
This will allow:
DataTable* result = [_db ExecuteQuery:#"SELECT * FROM answers"];
It feels like you need to use a LEFT JOIN statement to answer your actual query - if you add info about your table definitions and what data you are trying to get out I can help more.
I have a massive problem with SQLite in my iPhone app, that needs to be fixed for a client soon! Basically i'm pulling a column from a database and loading it into a table view on viewWillAppear. It works fine, for the first few times the view is loaded but then suddenly it starts return empty (null) values. Upon inspection it appears that there is an issue with opening the database maybe but this is my first SQLite project so it's hard to figure out what's going on.
Here is the code I use to pull the SQL information:
+ (void) getInitialDataToDisplay:(NSString *)dbPath {
NSLog(#"INCOME CALLED 1");
NavTabAppDelegate *appDelegate = (NavTabAppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.incomeArray = [[NSMutableArray alloc] init];
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
NSLog(#"INCOME CALLED 2");
const char *sql = "select IncomeID, IncomeName from Income ORDER BY IncomeName asc";
//const char *sql2 = "select categoryID, Size from coffee";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
NSLog(#"INCOME CALLED 3");
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
NSLog(#"INCOME CALLED 4");
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
Income *incomeObj = [[Income alloc] initWithPrimaryKey:primaryKey];
//This is how I pull info from the database using the above select statement and setting it in the coffeeObj property of Coffee class
incomeObj.incomeName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
//coffeeObj.coffeeSize = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)];
incomeObj.isDirty = NO;
[appDelegate.incomeArray addObject:incomeObj];
[incomeObj release];
NSLog(#"INCOME OBJECTS %#", incomeObj.incomeName);
//NSLog(#"CALLED");
}
}
}
else{
sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory
NSLog(#"INCOME CALLED 5");
}
NSLog(#"INCOME CALLED 6");
}
I am calling the code in viewWillAppear as follows:
[Income getInitialDataToDisplay:[appDelegate getDBPath]];
Also this is the output from my console when the error occurs:
2011-06-17 12:21:48.307 CashCal[318:707] GET DB PATH CALLED
2011-06-17 12:21:48.310 CashCal[318:707] /var/mobile/Applications/2BD7CA1D-C7AB-4425-B5C1-974C4F4D057C/Documents/SQL.sqlite
2011-06-17 12:21:48.312 CashCal[318:707] INCOME CALLED 1
2011-06-17 12:21:48.314 CashCal[318:707] INCOME CALLED 5
2011-06-17 12:21:48.318 CashCal[318:707] INCOME CALLED 6
It appears the problem is with the first if statement opening the database. I really need help on this one
You should always destroy prepared statements by calling sqlite3_finalize(your_stmt). And you should always close youre connection not only if it sqlite3_open() failed.
Also do something like this:
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
//your code here
} else {
//print error
NSLog(#"sql-error: %s", sqlite3_errmsg(database));
}
for clarification, here a interface for your db, that should avoid opening the db when its allready open, and makes code cleaner
DBi.h
#import <Foundation/Foundation.h>
#import <sqlite3.h>
#interface DBi : NSObject {
sqlite3* db;
}
- (void)opendDB;
- (void)closeDB;
- (NSArray*)getIcons;
#end
DBi.m
#import "DBi.h"
#import "Income.h"
static DBi *sharedDBi = nil;
#implementation DBi
- (void)dealloc {
sqlite3_close(db);
[super dealloc];
}
+ (DBi*)sharedManager {
if (sharedDBi == nil) {
sharedDBi = [[super allocWithZone:NULL] init];
[sharedDBi opendDB];
}
return sharedDBi;
}
+ (id)allocWithZone:(NSZone *)zone {
return [[self sharedManager] retain];
}
- (void)opendDB {
NSString *dbPath = [[NSBundle mainBundle]pathForResource:#"path_to_db_file"ofType:#"sqlite"];
//open the database
if(!sqlite3_open([dbPath UTF8String], &db) == SQLITE_OK) {
NSLog(#"connection to db failed");
sqlite3_close(db);
}
}
- (void)closeDB {
sqlite3_close(db);
}
- (NSArray*)getIncoms {
NSMutableArray rArray = [[[NSMutableArray alloc] init] autorelease];
const char *sql = "select IncomeID, IncomeName from Income ORDER BY IncomeName asc";
//const char *sql2 = "select categoryID, Size from coffee";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(db, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
Income *incomeObj = [[Income alloc] initWithPrimaryKey:primaryKey];
incomeObj.incomeName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
incomeObj.isDirty = NO;
[rArray addObject:incomeObj];
[incomeObj release];
}
} else {
NSLog(#"sql-error in getIncoms: %s", sqlite3_errmsg(db));
}
sqlite3_finalize(selectstmt);
return rArray;
}
Now you could do something like that.
DBi *dbi = [[DBi alloc] init];
NSArray *incoms = [dbi getIncoms];
[dbi release];
hope, that should help
use this code
sqlite3 *database;
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
////your Code
if(sqlite3_prepare_v2(database, [sqlStatement cStringUsingEncoding:NSUTF8StringEncoding], -1, &compiledStatement, NULL) == SQLITE_OK)
{
NSLog(#"%#",sqlStatement);
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
//your code
}
}
sqlite3_finalize(compiledStatement);
sqlite3_close(database);
}
}
Use FMDB for you sqlite tasks. It's a bad practice to use sqlite calls everywhere in the application. Just search on google for FMDB Example you will find one. FMDB is much easier to implement then SQLIte because FMDB handles all the things.
It turns out I was calling the same SQL method in two different places in very quick succession before the statements had a chance to be finalised each time. I guess this caused some sort of overlap eventually leading to the statements becoming invalid. Thanks for all the help. I will definitely be using CoreData or FMDB next time.
i have multiple view controllers, registrationviewcontroller , contactsviewcontroller , addnewcontactsviewcontroller, etc.
i have the below code in registrationviewcontroller
DatabaseCRUD *database = [[DatabaseCRUD alloc] init];
NSMutableString *registrationquery=[NSMutableString stringWithFormat:#"insert into BARvalues values ('%#','%#','%#','%#','%#','%#')",[name text],[emailAddress text],[mobileNumber text],[password text],[country text],#"0"];
NSLog(#"registrationquery is %#",registrationquery);
[database updatenewregistration:registrationquery];
[database release];
DatabaseCRUD *database1 = [[DatabaseCRUD alloc] init];
NSMutableString *registrationquery1=[NSMutableString stringWithFormat:#"insert into contacts values ('1234','1234')"];
NSLog(#"registrationquery is %#",registrationquery1);
[database1 updatenewregistration:registrationquery1];
[database1 release];
DatabaseCRUD *database2 = [[DatabaseCRUD alloc] init];
NSMutableString *registrationquery2=[NSMutableString stringWithFormat:#"insert into contacts values ('abcd','abcd')"];
NSLog(#"registrationquery is %#",registrationquery2);
[database2 addcontacts:registrationquery2];
[database2 release];
the above code works fine . it inserts the values into the sqlite database. Here is the problem , i have the almost same code in a different viewcontroller(contacts, addcontacts) and the values dont get inserted into the sqlite database.Here is the code.
DatabaseCRUD *database = [[DatabaseCRUD alloc] init];
NSMutableString *registrationquery=[NSMutableString stringWithFormat:#"insert into contacts values ('raja','shekar')"];
NSLog(#"registrationquery is %#",registrationquery);
[database updatenewregistration:registrationquery];
[database release];
DatabaseCRUD *database1 = [[DatabaseCRUD alloc] init];
NSMutableString *registrationquery1=[NSMutableString stringWithFormat:#"insert into contacts values ('rajesh','neelam')"];
NSLog(#"registrationquery is %#",registrationquery1);
[database1 addcontacts:registrationquery1];
[database1 release];
i dont see any reason why the database object would insertin in one viewcontroller and doesnt in the other viewcontroller. Any help will be greatly appreciated. i have tried to figure where the error is all day long and i dont want to waste anymore time. any help please????
I put breakpoints at every method of database object to see if its inserting, there is no error at all . it seems to be passing through the sqlstatment, but no insertion happens. Here is the code of saving the values in databaseHere is the code for database insertion.
-(void) addcontacts :(NSString *)query
{
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
NSLog(#"query is %#",query);
sqlStatement=[query cStringUsingEncoding:NSASCIIStringEncoding];
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK)
{
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
NSLog(#"new contact updated");
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
}
This is somewhere between an answer and a comment - interpret as necessary.
I assume that the insert statements return some error code, correct? What are their values? This will send you a long ways towards your solution.
hye all,
i have built a SQLite database and wanna to add into iphone app. already i have add it resource->add->x.sqlite and also add libsqlite3.0.dylib.framework but i don't know what is the showing code. I wanna to show the data in the db when user pressed button.
Can anyone help me to give an example on how the db can be view when button is press??
Here's some basic code to query the database:
-(NSArray*)names
{
NSString* query = [[NSString alloc] initWithString:#"SELECT name FROM sometablename;"];
sqlite3_stmt* statement;
int retval = sqlite3_prepare_v2(yourDatabaseHandle, [query UTF8String], -1, &statement, nil);
[query release];
if (retval != SQLITE_OK)
{
sqlite3_close(yourDatabaseHandle);
NSAssert1(0, #"Error querying table: %i", (retval ^ SQLITE_ERROR));
return nil;
}
NSMutableArray* values = [[[NSMutableArray alloc] init] autorelease];
while (sqlite3_step(statement) == SQLITE_ROW)
{
const char* value = (const char*)sqlite3_column_text(statement, 0);
NSString* s = [[NSString alloc] initWithUTF8String:value];
[values addObject:s];
[s release];
}
sqlite3_finalize(statement);
return values;
}
You might want to present this in a table view. There are plenty of questions & answers here on Stack Overflow already to explain how to do that, as well as plenty of Apple sample code.
i have a problem for some time which i can't solve:
In the applicationDidFinishLaunching i have this code:
[self checkAndCreateDatabase];
[self readCharsFromDatabase];// which stores into an array some objects
[self readGlyphsFromDatabaseAtId:#"a"];// idem
The second array i'm using into a secondary ViewController and i'm getting the array in the viewDidLoad with:
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
self.array = delegate.array2;
All perfect till now, just that i want to run a new query before getting the array2. I'm trying with this:
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[delegate readGlyphsFromDatabaseAtId:#"b"];// which is supposed to override my array2 with new values
self.array = delegate.array2;
This stops my application without error. I get this message only:
GNU gdb 6.3.50-20050815 (Apple version gdb-966) (Tue Mar 10 02:43:13 UTC 2009)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin".sharedlibrary apply-load-rules all
Attaching to process 4736.
My method is called till this point, after it i don't get a NSLog neither in the if, neither in the else:
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
Can someone help? Or if the logic is wrong to point me to the correct way of doing it?
If it's not to large for the memory i can store all the database in some arrays, it has 400kb
Thanks!
EDIT: This is how my function looks:
-(void) readGlyphsFromDatabaseAtId:(NSString *)charId {
NSLog(#"reading glyphs for id %#", charId);
// Setup the database object
sqlite3 *database;
// Init the animals Array
glyphs = [[NSMutableArray alloc] init];
NSLog(#"1");
// Open the database from the users filessytem
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
NSLog(#"reading row");
// Setup the SQL Statement and compile it for faster access
NSString *query = [NSString stringWithFormat:#"SELECT nr,title,description FROM `glyphs` WHERE `id`='%#'", charId];
NSLog(#"%#", query);
//const char *sqlStatement = "SELECT nr,title,description FROM `glyphs` WHERE `id`='b'";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, [query UTF8String], -1, &compiledStatement, nil) == SQLITE_OK) {
NSLog(#"prepared OK");
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
//NSLog(#"reading row");
NSString *aNr = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
NSString *aTitle = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSString *aDescription = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
//NSLog(#"glyph: %# %# %#", aNr, aTitle, aDescription);
Glyph *g = [[Glyph alloc] initWithCharId:charId glyphNr:aNr glyphTitle:aTitle glyphDescription:aDescription];
[glyphs addObject:g];
[g release];
}
}
else {
NSLog(#"not prepared");
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
else{
NSLog(#"sqlite not ok");
}
sqlite3_close(database);
NSLog(#"fin reading database2");
}
Ok, seems that the databasePath wasn't accessible, so i re-inited it and now works. If someone can enlighten a bit about why....
databasePath was inited in applicationDidFinishLaunching
Are you calling sqlite3_open() in each invocation of readGlyphsFromDatabaseAtId? If you're doing that with the database already open, that may cause issues.