how to get NULL from sqlite in xcode - ios

I want one application that has sqlite DB.
in my sqlite DB exist 5 records that any record has 2 column. (Name,ID,key)
one of all ID is NULL and I want get this. (ID is INTEGER variable)
this is my code but when run it application is crashed.
do
{
sqlite3 *database2;
if(sqlite3_open([[self dataFilePath] UTF8String], &database2) == SQLITE_OK)
{
NSString *sqlStatement_userInfo2 =[NSString stringWithFormat:#"Select * from table1 where Name = %# and ID = %#",p,p2];
sqlite3_stmt *compiledStatement2;
if(sqlite3_prepare_v2(database2, [sqlStatement_userInfo2 UTF8String], -1, &compiledStatement2, NULL) == SQLITE_OK)
{
// Loop through the results and add them to the feeds array
while(sqlite3_step(compiledStatement2) == SQLITE_ROW)
{
NSMutableDictionary *_dataDictionary=[[NSMutableDictionary alloc] init];
// Init the Data Dictionary
childID = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement2, 1)];
childName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement2, 0)];
b = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement2, 2) ];
p = childID;
p2 = b;
[_dataDictionary setObject:[NSString stringWithFormat:#"%#",childName] forKey:#"Name"];
[array addObject:_dataDictionary];
}
}
else
{
NSLog(#"No Data Found");
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement2);
}
sqlite3_close(database2);
} while (b != NULL);
this code not work and I get this error :
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSString stringWithUTF8String:]: NULL cString'
*** First throw call stack:
(0x2092012 0x119fe7e 0x2091deb 0xb97480 0x35b7 0x2e08 0x1c8817 0x1c8882 0x1c8b2a 0x1dfef5 0x1dffdb 0x1e0286 0x1e0381 0x1e0eab 0x1e0fc9 0x1e1055 0x2e63ab 0x13792d 0x11b36b0 0x268efc0 0x268333c 0x268eeaf 0x1d68cd 0x11f1a6 0x11dcbf 0x11dbd9 0x11ce34 0x11cc6e 0x11da29 0x120922 0x1cafec 0x117bc4 0x117dbf 0x117f55 0x120f67 0xe4fcc 0xe5fab 0xf7315 0xf824b 0xe9cf8 0x1feddf9 0x1fedad0 0x2007bf5 0x2007962 0x2038bb6 0x2037f44 0x2037e1b 0xe57da 0xe765c 0x2b6d 0x2a95)
libc++abi.dylib: terminate called throwing an exception
(lldb)

You need to add a check as to whether sqlite3_column_text(compiledStatement2, 1) returns a NULL byte before you try to create the NSString with it.

if ID is integer then use this :
if( [ NSString stringWithFormat:#"%#", sqlite3_column_int(compiledStatement2, 1)]==nil)
{
childID = #"0";
}
else
{
childID = [ NSString stringWithFormat:#"%#", sqlite3_column_int(compiledStatement2, 1)];
}

Related

cannot fetch value from sqlite in IOS

Table values:
ID=1 CUSTOMERID=1 NAME=John EMAIL=email USERNAME=usernaeme
I am using this code to fetch customerId from Usertable with this code
#try {
//CustomerIdField=#"admin";
// customerUsername=#"admin";
NSLog(#"the value of customerusername is %#",customerUsername);
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths objectAtIndex:0];
NSLog(#"inside function");
databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: #"EBook.db" ]];
const char *dbpath;
#try {
dbpath = [databasePath UTF8String];
NSLog(#"the const char is %s",dbpath);
}
#catch (NSException *exception) {
NSLog(#"the exception3 is %#",exception);
}
if (sqlite3_open(dbpath, &Ebookreaderdb) == SQLITE_OK)
{
NSString *selectSQL = [NSString stringWithFormat: #"SELECT CUSTOMERID FROM Usertable WHERE EMAIL=\"%#\"",customerUsername];
sqlite3_stmt *selstatement;
const char *select_stmt = [selectSQL UTF8String];
//NSMutableArray *resultArray = [[NSMutableArray alloc]init];
if (sqlite3_prepare_v2(Ebookreaderdb,
select_stmt, -1, &selstatement, NULL ) == SQLITE_OK)
{
NSLog(#"inside sqlite OK"); //this prints in log
if (sqlite3_step(selstatement) == SQLITE_ROW)
{
NSLog(#"inside sqlite ROW"); // this is also printing in log
NSString *userInfoStr = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selstatement,1)];
NSLog(#"val is %#",userInfoStr);
char *tmp = sqlite3_column_text(selstatement,1);
if (tmp == NULL)
CustomerIdField = nil;
else
CustomerIdField = [[NSString alloc] initWithUTF8String:tmp];
CustomerIdField = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(selstatement,1)];
NSLog(#"inside customer is %#",CustomerIdField);
// [resultArray addObject:name];
}
else{
NSLog(#"Not found");
// return nil;
}
sqlite3_reset(selstatement);
}
But i am getting this exception Newpjtonfriday[2165:84017] the exception is 2 *** +[NSString stringWithUTF8String:]: NULL cString
I googled with the above result and everywhere it is saying that the value is null that is why the exception occurs. but in my case the value is there.
Because the code
NSLog(#"inside sqlite ROW");
is coming in log meaning that a row exists in table. But cannot fetch it.
Please help
I think it's a typo:
#"SELECT CUSTOMERID FROM Usertable WHERE EMAIL=\"%#\"",customerUsername;
You are passing the username instead of the e-mail? Or maybe you meant to SELECT ... WHERE USERNAME=?
Also there is no need for any of those #try/#catch blocks as I cannot see how an Objective-C exception can be thrown by that code.
One last thing; in order to avoid SQL Injection attacks you should bind the values into your statements, rather than formatting them as a string, as you have done here.
Little advise if you are just starting to develop on iOS, try to use some library(FMDB to easy work with SQLite) to make some task more straight forward.
Answer to your Question
Try the "SELECT * FROM Usertable" if it has any row in your table.
Second you should check if the value in your row is not NULL.
To get easy solution use something like Datum SQLite Free(Mac os X) OR you could use SELECT COUNT to ensure you have any rows in table.
Try your select and if the app return the rows but there is no value in your column that's mean you have problems with write to DB logic but not in read logic and you are trying to fetch row with have null value on column you want.That's why this method is not working:
[NSString stringWithUTF8String:]: NULL cString
its thrown an exception because you have no string and trying to send NULL to method.
The sqlite3_column_text index number is zero-based, not one-based. Thus, this line:
char *tmp = sqlite3_column_text(selstatement, 1);
Should be:
char *tmp = sqlite3_column_text(selstatement, 0);
By the way, your handling of this tmp variable is a prudent way of checking to make sure it's not NULL before you use it. Unfortunately, elsewhere in this same routine you use sqlite3_column_text value directly (which is why your app crashed, rather than gracefully reporting the error). You have several redundant calls to sqlite3_column_text here. I would suggest employing the pattern you used with this tmp variable.
Let me give you my suggestion I tried what you just did and I also got the error. Then I did some googling and found this link
http://www.raywenderlich.com/913/sqlite-tutorial-for-ios-making-our-app
just modify you codes from these
char *tmp = sqlite3_column_text(selstatement,1);
if (tmp == NULL)
CustomerIdField = nil;
else
CustomerIdField = [[NSString alloc] initWithUTF8String:tmp];
CustomerIdField = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(selstatement,1)];
NSLog(#"inside customer is %#",CustomerIdField);
to
int tmp = sqlite3_column_int(selstatement,0);// my case it is int
char *nameChars = (char *) sqlite3_column_text(selstatement, 1);// here is the change occuring please refer this
NSString *name = [[NSString alloc] initWithUTF8String:nameChars]; // there are two steps first fetch as char, then change to String
NSLog(#"customerid is %d",tmp);
NSLog(#"customer name is %#",name);
Try this, It worked for me..
I think the problem is that you are fetching the coustomerId as String directly
In you case just try this
char *custId = (char *) sqlite3_column_text(selstatement, 0);
NSString *customerId = [[NSString alloc] initWithUTF8String:custId];
:-)

[__NSCFString objectForKey:]: unrecognized selector sent to instance 0xa6a2750

I converted my database value to JSON format. It's showing in URL as JSON. Then i'm fetching value from JSON URL then store to local database. But i'm getting below error: [__NSCFString objectForKey:]: unrecognized selector sent to instance 0xa6a2750 and *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0xa6a2750'
JSON value in URL:
[{"cat_id":"196","category_name":"Performance Parts"},{"cat_id":"212","category_name":"Car Care"}]
Getting value and insert to local:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Mdb.sqlite"];
NSLog(#"filepath %#",path);
//NSDictionary *jsonDict = [stringFromFileAtURL JSONValue];
//array
NSArray *userData = [str JSONValue];
// NSLog(#"userData is %#", userData);
BOOL notExist = TRUE;
sqlite3_stmt *statement, *addStmt;
for (NSArray *skarray in userData) {
NSLog(#"test");
for (NSDictionary *tuser in skarray) {
NSLog(#"test1");
//write all this in the table
//if already exists in data base id then overwrite the name
//category table
//NSLog(#"CategoryId is %#",[tuser objectForKey:#"cat_id"]);
//NSLog(#"CategoryName is %#",[tuser objectForKey:#"cat_name"]);
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) {
NSLog(#"test2");
const char *sql = [[NSString stringWithFormat:#"SELECT cat_id FROM categories where cat_id = '%#'",[tuser objectForKey:#"cat_id"]] cStringUsingEncoding:NSUTF8StringEncoding];
NSLog(#"test3");
NSLog(#"check category is %s", sql);
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
notExist = TRUE;
while (sqlite3_step(statement) == SQLITE_ROW) {
notExist = FALSE;
}
}
if(notExist){
//NSLog(#"cat id does not exist");
const char *sqlInsert = [[NSString stringWithFormat:#"insert into categories (cat_id, category_name) values ('%#', '%#')", [tuser objectForKey:#"cat_id"], [tuser objectForKey:#"category_name"]] cStringUsingEncoding:NSUTF8StringEncoding];
NSLog(#"Insert category is %s", sqlInsert);
if(sqlite3_prepare_v2(database, sqlInsert, -1, &addStmt, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating add statement. '%s'", sqlite3_errmsg(database));
if(SQLITE_DONE != sqlite3_step(addStmt))
NSAssert1(0, #"Error while inserting data. '%s'", sqlite3_errmsg(database));
}
}
}
}
Remove for (NSArray *skarray in userData) { loop and use
for (NSDictionary *tuser in userData) {
NSLog(#"test1");
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) {
const char *sql = [[NSString stringWithFormat:#"SELECT cat_id FROM categories where cat_id = '%#'",[tuser objectForKey:#"cat_id"]] cStringUsingEncoding:NSUTF8StringEncoding];
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
notExist = TRUE;
while (sqlite3_step(statement) == SQLITE_ROW) {
notExist = FALSE;
}
}
You're trying to get data from NSDictionary (or mutable) but in your case, somehow it converts to NSString (NSCFString) and which don't have objectForKey property. Take a look into steps you're compiling where you using objectForKey.

I want to judge the param datatype when insert into sqlite ,How to do? On the ios development

I want to write a generate function which for inserting the data to sqlite database in the ios development,the codes are here:
-(NSInteger)executeUpdateWithSql:(NSString *)sql params:(NSMutableArray *)params
{
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(_database, [sql UTF8String], -1, &stmt, NULL) == SQLITE_OK) {
for (int i = 1; i <= params.count; i++) {
id param = [params objectAtIndex:i];
sqlite3_bind_text(stmt, i, [param UTF8String], -1, SQLITE_TRANSIENT);
}
}
NSInteger result =sqlite3_step(stmt);
if (result != SQLITE_DONE){
PBLog(#"error!");
}
return result;
}
But, if there is a int param in the params, the error message is "-[__NSCFNumber UTF8String]: unrecognized selector sent to instance 0x1dd1ea60".
I want to judge the param datatype,How to do? The datatype maybe int/float/double/bealoon/string.
then you should do something like this:
id param = [params objectAtIndex:i];
if([param isKindOfClass:[NSNumber class]])
{
NSString *tmp = [param stringValue]
}
else
{
NSString *tmp = param
}
the id can be any object type and not runt time safe.

How to read one column from SQLite and store in Array

I have SQLite database with 5 columns named: Name, ID, ChildID, ParentID, BrotherID.
In this database I have many records and I want to store one of all columns value in array and return this array. For example I want to get all value in ParentID column. I use this query code:
Select ParentID from Table1 (Table1 is name of table)
This is my code for get array from certain column :
/*==================================================================
METHOD FOR GETTING MIDIFIED FROM DATABASE
==================================================================*/
- (NSMutableArray*)readingModified
{
ModiArray = [[NSMutableArray alloc] init];
// Setup the database object
sqlite3 *database2;
// Open the database from the users filessytem
if(sqlite3_open([[self DatabaseSqlite] UTF8String], &database2) == SQLITE_OK)
{
// Setup the SQL Statement and compile it for faster access
//SQLIte Statement
NSString *sqlStatement_userInfo =[NSString stringWithFormat:#"Select ParentID from Table1"];
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database2, [sqlStatement_userInfo UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK)
{
// Loop through the results and add them to the feeds array
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
// Init the Data Dictionary
NSMutableDictionary *_dataDictionary2=[[NSMutableDictionary alloc] init];
NSString *_recordParentID = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
[_dataDictionary2 setObject:[NSString stringWithFormat:#"%#",_recordModified] forKey:#"ParentID"];
[array addObject:_dataDictionary2];
}
}
else
{
NSLog(#"No Data Found");
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database2);
return ModiArray;
}
please tell me my mistake.
my friend a few be careful.
this code is right but in line you mistake :
[array addObject:_dataDictionary2];
instead array put ModiArray
/*==================================================================
METHOD FOR GETTING MIDIFIED FROM DATABASE
==================================================================*/
- (NSMutableArray*)readingModified
{
ModiArray = [[NSMutableArray alloc] init];
// Setup the database object
sqlite3 *database2;
// Open the database from the users filessytem
if(sqlite3_open([[self DatabaseSqlite] UTF8String], &database2) == SQLITE_OK)
{
// Setup the SQL Statement and compile it for faster access
//SQLIte Statement
NSString *sqlStatement_userInfo =[NSString stringWithFormat:#"Select ParentID from Table1"];
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database2, [sqlStatement_userInfo UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK)
{
// Loop through the results and add them to the feeds array
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
// Init the Data Dictionary
NSMutableDictionary *_dataDictionary2=[[NSMutableDictionary alloc] init];
NSString *_recordParentID = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
[_dataDictionary2 setObject:[NSString stringWithFormat:#"%#",_recordModified] forKey:#"ParentID"];
[ModiArray addObject:_dataDictionary2];
}
}
else
{
NSLog(#"No Data Found");
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database2);
return ModiArray;
}
You are adding object to array and allocating and returning ModiArray.

App crashes when attempting to make an SQLite connection/statement

I'm having an issue with SQLite where my app crashes at run time while I'm trying to make a connection to an SQLite database and grab some of its contents. Here's my code:
-(IBAction)setInput:(id)sender
{
NSString *strStoreNumber;
NSString *strRegNumber;
strStoreNumber = StoreNumber.text;
strRegNumber = RegNumber.text;
lblStoreNumber.text = strStoreNumber;
lblRegNumber.text = strRegNumber;
NSString* databasePath = [[NSBundle mainBundle] pathForResource:#"tblStore" ofType:#"sqlite"];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
NSLog(#"Opened sqlite database at %#", databasePath);
//...stuff
}
else
{
NSLog(#"Failed to open database at %# with error %s", databasePath, sqlite3_errmsg(database));
sqlite3_close (database);
}
NSString *querystring;
querystring = [NSString stringWithFormat:#"SELECT strStore FROM tblStore WHERE strStore = %#;", strStoreNumber];
const char *sql = [querystring UTF8String];
NSString *szStore = nil;
NSString *szReg = nil;
sqlite3_stmt *statement = nil;
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL)!=SQLITE_OK) //queryString = Statement
{
NSLog(#"sql problem occured with: %s", sql);
NSLog(#"%s", sqlite3_errmsg(database));
}
else
{
// you could handle multiple rows here
while (sqlite3_step(statement) == SQLITE_ROW) // queryString = statement
{
szStore = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 0)];
szReg = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 1)];
} // while
}
sqlite3_finalize(statement);
// go on with putting data where you want
}
The errors I'm getting in console:
2012-05-07 09:39:33.619 CCoDBTry[962:f803] Opened sqlite database at /Users/*******/Library/Application Support/iPhone Simulator/5.1/Applications/5DB7A218-A0F6-485F-B366-91FD2F9BC062/CCoDBTry.app/tblStore.sqlite
2012-05-07 09:39:33.623 CCoDBTry[962:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSString stringWithUTF8String:]: NULL cString'
*** First throw call stack:
(0x1593022 0x1724cd6 0x153ba48 0x153b9b9 0x9d4973 0x27c9 0x1594e99 0xd714e 0xd70e6 0x17dade 0x17dfa7 0x17d266 0xfc3c0 0xfc5e6 0xe2dc4 0xd6634 0x147def5 0x1567195 0x14cbff2 0x14ca8da 0x14c9d84 0x14c9c9b 0x147c7d8 0x147c88a 0xd4626 0x1f82 0x1ef5)
terminate called throwing an exception(lldb)
Any help is greatly appreciated!
EDIT: Note the values I'm looking for in the database are of type VARCHAR. I'm not sure if knowing that makes a difference.
+[NSString stringWithUTF8String:]: NULL cString
It's complaining that you've fed a null value into stringWithUTF8String:. Your code has two calls to this method, each feeding a value in from the query results. Looking at your query, you are only selecting a single column, strStore. I would assume that the line that assigns to szReg is failing because you are trying to retrieve a value that you haven't selected in your query.
For accessing values that may be null and we are not sure about it I generally prefer checking it before hand
char *sk = (char *)sqlite3_column_text(statement, 0);
if (sk != nil) {
szStore = [NSString stringWithUTF8String:sk];
}
This will stop the app from crashing.

Resources