Why does one statement work and one not - ios

I have a table in a database which I access like this:
+(NSMutableArray *) queryDatabaseWithSQL:(NSString *)sql params:(NSArray *)params {
sqlite3 *database;
NSMutableArray *rtn = [[NSMutableArray alloc] init];
int index = 0;
NSString *filepath = [self copyDatabaseToDocumentsWithName:#"database"];
if (sqlite3_open([filepath UTF8String], &database) == SQLITE_OK) {
const char *sqlStatement = [sql cStringUsingEncoding:NSASCIIStringEncoding];
sqlite3_stmt *compiledStatement;
if (sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
if ([params count]) {
for (int i = 0; i < [params count]; i++) {
NSString *obj = [params objectAtIndex:i];
sqlite3_bind_blob(compiledStatement, i + 1, [obj UTF8String], -1, SQLITE_TRANSIENT);
}
}
while (sqlite3_step(compiledStatement) == SQLITE_ROW) {
NSMutableArray *arr = [[NSMutableArray alloc] init];
index = 0;
const char *s = (char *)sqlite3_column_text(compiledStatement, index);
while (s) {
[arr addObject:[NSString stringWithUTF8String:s]];
index++;
s = (char *)sqlite3_column_text(compiledStatement, index);
}
if (![rtn containsObject:arr]) {
[rtn addObject:arr];
}
}
}
sqlite3_finalize(compiledStatement);
}
NSLog(#"ERROR: %s", sqlite3_errmsg(database));
sqlite3_close(database);
return rtn;
}
This works fine when I call the function like this:
NSLog(#"%#", [database queryDatabaseWithSQL:#"SELECT * FROM FRIENDSUSERS WHERE USER = ?" params:#[[delegate->user objectForKey:#"username"]]]);
Then when I call the function using a string like this it doesn't return any rows:
NSLog(#"%#", [database queryDatabaseWithSQL:#"SELECT * FROM FRIENDSUSERS WHERE USER = ?" params:#[#"username"]]);
I haven't got a clue what is going one with but I have checked the strings match and they do so I'm now stuck
Can anyone see any reason why this would not work
I have run error checks as well and every time it returns no error, or rows :(
Thanks in advance

Related

How to use Lock/Unlock?

Here is the code that using SQLite.
This function will be call from some threads.
I don't know well, following code is correct one or not.
There are lock/unlock code.
Please advice me whether I used lock/unlock correctly.
- (NSMutableArray*) Query:(NSString *)query_str forColumn:(NSString*)mycolumn
{
sqlite3_stmt *statement;
const char *query_stmt = [query_str UTF8String];
[dbLock lock];
if (sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL) != SQLITE_OK) {
[dbLock unlock];
return nil;
}
NSMutableArray *queryResult = [NSMutableArray array];
while (sqlite3_step(statement) == SQLITE_ROW) {
NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
int num_of_fields = sqlite3_column_count(statement);
for (int i = 0; i < num_of_fields; i++) {
NSString * col_name = [[NSString alloc] initWithUTF8String:sqlite3_column_name(statement, i)];
const char * value = (const char *)sqlite3_column_text(statement, i);
NSString * col_text;
if (value)
col_text = [[NSString alloc] initWithUTF8String:value];
else
col_text = #"";
if (col_name && col_text) {
if ([col_text isEqualToString:#"--"] == NO && [col_text isEqualToString:#""] == NO)
[dict setObject:col_text forKey:col_name];
}
}
if (mycolumn == nil) {
[queryResult addObject:dict];
} else {
NSString *tmp = [dict objectForKey:mycolumn];
if (tmp != nil) {
[queryResult addObject:tmp];
}
}
}
sqlite3_finalize(statement);
[dbLock unlock];
return queryResult;
}
The locking is around all the database access functions, so as long as all the other database access code also does similar locking, the database is protected.
The query_str access is outside the lock, so it is not protected against concurrent modifications. Whether that could happen in your program is something only you can decide.

Facing an issue while fetching data in sqlite in iOS

- (NSMutableArray*)getAllDataFromTableUSERINFO:(NSString *)fetchQuery {
NSMutableArray *resultArray1 =[[NSMutableArray alloc]init];
#autoreleasepool {
if (sqlite3_open([[self getDBPath]UTF8String],&database)==SQLITE_OK){
sqlite3_stmt *stmt;
const char *sqlfetch=[fetchQuery UTF8String];
if (sqlite3_prepare(database, sqlfetch, -1,&stmt, NULL)==SQLITE_OK) {
while (sqlite3_step(stmt)==SQLITE_ROW){
RM_USER_INFO *UserInfo = [[RM_USER_INFO alloc]init];
UserInfo.uid=[NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt,0)];
UserInfo.username=[NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt,1)];
UserInfo.password=[NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt,2)];
UserInfo.fname=[NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt,3)];
UserInfo.mname=[NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt,4)];
[resultArray1 addObject:UserInfo];
}
}
sqlite3_finalize(stmt);
stmt=nil;
sqlite3_close(database);
sqlite3_release_memory(120);
}
}
return resultArray1;
}
Get always EXE_BAD_ACCESS after fews operations
Try this function:
static NSInteger DBBUSY;
+(NSMutableArray *)executeQuery:(NSString*)str{
sqlite3_stmt *statement= nil;
sqlite3 *database;
NSString *strPath = Your Database path here;
while(DBBUSY);
DBBUSY = 1;
NSMutableArray *allDataArray = [[NSMutableArray alloc] init];
if (sqlite3_open([strPath UTF8String],&database) == SQLITE_OK) {
if (sqlite3_prepare_v2(database, [str UTF8String], -1, &statement, NULL) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
NSInteger i = 0;
NSInteger iColumnCount = sqlite3_column_count(statement);
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
while (i< iColumnCount) {
NSString *str = [self encodedString:(const unsigned char*)sqlite3_column_text(statement, i)];
NSString *strFieldName = [self encodedString:(const unsigned char*)sqlite3_column_name(statement, i)];
if(!str)
str = #"";
[dict setObject:str forKey:strFieldName];
i++;
}
[allDataArray addObject:dict];
}
}
DBBUSY = 0;
sqlite3_finalize(statement);
}
sqlite3_close(database);
return allDataArray;
}
This may help you :)

saving json data into sqlite database in iOS

My question is how to insert a fetched JSON array data into sqlite database.
I have fetched JSON data which is an array of dictionaries.
My code to save JSON result looks like this:
-(BOOL) saveApiResults: (NSString *)tableName : (NSArray *)data
{
BOOL saveSuccess = NO;
#try {
const char *dbPath = [databasePath UTF8String];
if(sqlite3_open(dbPath,&database)==SQLITE_OK) {
sqlite3_exec(database, "BEGIN", 0, 0, 0);
//pass an array containing json dictionary to below line
NSDictionary *rowData=[data objectAtIndex:0];
NSArray *keyArray = [rowData allKeys];
NSLog(#"key array %#",keyArray);
NSString *insertSQL=#"INSERT INTO ";
insertSQL=[insertSQL stringByAppendingString:#"moodsdata"];
insertSQL=[insertSQL stringByAppendingString:#" VALUES("];
for(int j=0;j<[keyArray count];j++)
{
insertSQL=[insertSQL stringByAppendingString:#"?"];
if(j<[keyArray count]-1)
insertSQL=[insertSQL stringByAppendingString:#","];
}
insertSQL=[insertSQL stringByAppendingString:#");"];
NSLog(#"query : %# ",insertSQL);
const char *sqlstatement = [insertSQL UTF8String];
sqlite3_stmt *compiledstatement;
if(sqlite3_prepare_v2(database,sqlstatement , -1, &compiledstatement, NULL)==SQLITE_OK) {
for (NSUInteger i = 0; i < [data count]; i++) {
NSDictionary *rowData=[data objectAtIndex:0];
for(int j=0;j<[keyArray count];j++) {
NSString *val = #"";
NSString *value=(NSString *)[rowData objectForKey:[keyArray objectAtIndex:j]];
if((value != nil) && (![value isEqual:[NSNull null]]))
val=[NSString stringWithFormat:#"%#",value];
NSLog(#"values %#",val);
sqlite3_bind_text(compiledstatement,j+1,[val UTF8String], -1, SQLITE_TRANSIENT);
}
if(sqlite3_step(compiledstatement) != SQLITE_DONE) {
NSLog(#"ERROR");
}
sqlite3_clear_bindings(compiledstatement);
sqlite3_reset(compiledstatement);
}
sqlite3_exec(database, "COMMIT", 0, 0, 0);
saveSuccess = YES;
NSLog(#"RESULTS SAVED SUCCESSFULLY!");
} else {
NSLog(#"StatemenT FAILED (%s)", sqlite3_errmsg(database));
}
sqlite3_finalize(compiledstatement);
} else {
NSLog(#"Statement FAILED (%s)", sqlite3_errmsg(database));
}
}
#catch (NSException *exception) {
NSLog(#"NSException : %#",exception.description);
}
#finally {
sqlite3_close(database);
}
return saveSuccess;
}
My question is when I try to pass the JSON array to this method it only saves the value for first array object . i.e. only first dictionary values get saved. Please tell me what I am doing wrong.
You primary issue is that you mistakenly access data[0] instead of data[i] in your loop that does the actual inserting.
But there are lots of other little issues with this code. Here's your code all cleaned up:
-(BOOL) saveApiResults:(NSString *)tableName data:(NSArray *)data
{
BOOL saveSuccess = NO;
const char *dbPath = [databasePath UTF8String];
if (sqlite3_open(dbPath,&database) == SQLITE_OK) {
sqlite3_exec(database, "BEGIN", 0, 0, 0);
//pass an array containing json dictionary to below line
NSDictionary *rowData = data[0];
NSArray *keyArray = [rowData allKeys];
NSLog(#"key array %#",keyArray);
NSMutableString *insertSQL = #"INSERT INTO moods data VALUES(";
for (NSInteger j = 0; j < [keyArray count]; j++)
{
if (j) {
[insertSQL appendString:#","];
}
[insertSQL appendString:#"?"];
}
[insertSQL appendString:#");"];
NSLog(#"query : %# ",insertSQL);
const char *sqlstatement = [insertSQL UTF8String];
sqlite3_stmt *compiledstatement;
if (sqlite3_prepare_v2(database, sqlstatement, -1, &compiledstatement, NULL) == SQLITE_OK) {
for (NSDictionary *rowData in data) {
for (NSInteger j = 0; j < [keyArray count]; j++) {
NSString *val = #"";
NSString *value = rowData[keyArray[j];
if (value && ![value isEqual:[NSNull null]]) {
val = [NSString stringWithFormat:#"%#",value];
}
NSLog(#"values %#",val);
sqlite3_bind_text(compiled statement, j + 1, [val UTF8String], -1, SQLITE_TRANSIENT);
}
if (sqlite3_step(compiledstatement) != SQLITE_DONE) {
NSLog(#"ERROR");
}
sqlite3_reset(compiledstatement);
}
sqlite3_exec(database, "COMMIT", 0, 0, 0);
sqlite3_finalize(compiledstatement);
saveSuccess = YES;
NSLog(#"RESULTS SAVED SUCCESSFULLY!");
} else {
NSLog(#"StatemenTtFAILED (%s)", sqlite3_errmsg(database));
}
sqlite3_close(database);
} else {
NSLog(#"Statement FAILED (%s)", sqlite3_errmsg(database));
}
return saveSuccess;
}
There is no need for try/catch. Just do proper error checking.
Use NSMutableString to build up a string piece by piece.
Only finalize a statement if you successfully prepare it.
Be sure to close a database if you open it.
Use modern syntax for accessing values from dictionaries and arrays. It's easier to read and type.
Use modern loops when possible.
Use whitespace. It makes the code easier to read.
Give all of your method parameters a name.
But your SQLite code was actually better than most posts here. You actually use sqlite_bind_xxx to bind values to your query. Too few people do that.
In your code where you're grabbing the values, you are grabbing the row data with:
NSDictionary *rowData=[data objectAtIndex:0];
I suspect you mean:
NSDictionary *rowData=[data objectAtIndex:i];

how to fetch data from sqlite into an array

This is my code.
It is only returning the first row from database. I know something is really wrong but don't know what. Please help.
if(sqlite3_open([databasePath UTF8String],&texttalkdb)==SQLITE_OK)
{
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(texttalkdb, [sql UTF8String], -1,&statement, NULL)==SQLITE_OK)
{
if(sqlite3_step(statement)==SQLITE_ROW)
{
for(int i=0;i<=20;i++)
{
char *pass=(char*)sqlite3_column_text(statement,i);
NSString *passStr = [NSString stringWithFormat:#"%s",pass];
NSString *msg=[[NSString alloc]initWithUTF8String:pass];
[arr addObject:msg];
}
}
sqlite3_finalize(statement);
}
sqlite3_close(texttalkdb);
}
NSLog(#"%#",arr);
return arr;
Try this
if(sqlite3_prepare_v2(texttalkdb, [sql UTF8String], -1,&statement, NULL)==SQLITE_OK)
{
while( sqlite3_step(statement) == SQLITE_ROW )
{
//get records
}
}
Step 1: This is for check the getting values is empty or not
+(NSString*)charToString:(char*)chart
{
NSString *string = #" ";
if(string)
{
chart = [self checkEmptyChar:chart];
string=[NSString stringWithUTF8String:chart];
}
return string;
}
Step 2: This is for checking character
+(char *)checkEmptyChar:(char *)check
{
NSString *string = #" ";
if (check == NULL)
check = string;
return check;
}
Step 3: To fetch SQLite Coding
if (sqlite3_prepare_v2(database, [query UTF8String], -1, &stment, nil) == SQLITE_OK)
{
while (sqlite3_step(stment) == SQLITE_ROW)
{
for(int i=0;i<=20;i++)
{
NSString *msg = [self charToString: (char *)sqlite3_column_text(stment, i)];
[array addObject:msg];
}
}
sqlite3_reset(stment);
}
sqlite3_finalize(stment);
}
sqlite3_close(database);

NSMutableArray losing all of its objects

I am making a function which allows you to read from a database and then puts the data into a NSMutableArray which it later returns for the user. Though for some reason when it is about to return the data the data is deleted from the array. Here is the code for the function:
+(NSMutableArray *) readFromDataBaseWithName:(NSString *)name withSqlStatement:(NSString *)sql {
sqlite3 *database;
NSMutableArray *rtn = [[NSMutableArray alloc] init];
NSMutableArray *new = [[NSMutableArray alloc] init];
int index = 0;
NSString *filePath = [self copyDatabaseToDocumentsWithName:name];
if (sqlite3_open([filePath UTF8String], &database) == SQLITE_OK) {
const char *sqlStateMent = [sql cStringUsingEncoding:NSASCIIStringEncoding];
sqlite3_stmt *compiledStatement;
if (sqlite3_prepare(database, sqlStateMent, -1, &compiledStatement, NULL) == SQLITE_OK) {
while (sqlite3_step(compiledStatement) == SQLITE_ROW) {
// loop through elements in row and put them into array
const char *s = (char *)sqlite3_column_text(compiledStatement, index);
while (s) {
[new addObject:[NSString stringWithUTF8String:s]];
index++;
s = (char *)sqlite3_column_text(compiledStatement, index);
}
[rtn addObject:new];
[new removeAllObjects];
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
return rtn;
}
Any advice would be much appreciated.
You keep reusing new. You need to create individual arrays each time.
+(NSMutableArray *) readFromDataBaseWithName:(NSString *)name withSqlStatement:(NSString *)sql {
sqlite3 *database;
NSMutableArray *rtn = [[NSMutableArray alloc] init];
int index = 0;
NSString *filePath = [self copyDatabaseToDocumentsWithName:name];
if (sqlite3_open([filePath UTF8String], &database) == SQLITE_OK) {
const char *sqlStateMent = [sql cStringUsingEncoding:NSASCIIStringEncoding];
sqlite3_stmt *compiledStatement;
if (sqlite3_prepare(database, sqlStateMent, -1, &compiledStatement, NULL) == SQLITE_OK) {
while (sqlite3_step(compiledStatement) == SQLITE_ROW) {
// loop through elements in row and put them into array
NSMutableArray *new = [[NSMutableArray alloc] init];
const char *s = (char *)sqlite3_column_text(compiledStatement, index);
while (s) {
[new addObject:[NSString stringWithUTF8String:s]];
index++;
s = (char *)sqlite3_column_text(compiledStatement, index);
}
[rtn addObject:new];
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
return rtn;
}

Resources