Use of undeclared identifier - identifier is in "if statement" - objective-c

I have an alert Use of undeclared identifier 'sql3'.
If I delete the if statement, there 's no problem, but it seems it's not recognized when sql3 is inside the if statement.
Is there a way to fix it?
if ([typedepartie isEqual: #"ami"]) {
const char *sql3 =
[[NSString stringWithFormat:#"SELECT id
FROM tabledesquestions
WHERE pack = ? ORDER BY RANDOM() LIMIT 4"]
cStringUsingEncoding:NSUTF8StringEncoding];
}
listequestionmulti = [[NSMutableArray alloc]init];
sqlite3_stmt *sql1Statement;
if(sqlite3_prepare(database1, sql3, -1, &sql1Statement, NULL) != SQLITE_OK) {
NSLog(#"Problem with prepare statement: %s", sqlite3_errmsg(database1));
}

The identifier sql3 is defined inside curly braces. Therefore it is purely local to those curly braces. Therefore when you get past that to the next part of your code, it no longer exists.
if ([typedepartie isEqual: #"ami"]) {
const char *sql3 = // sql3 is born here...;
} // and dies here
What you want is more like this:
char *sql3 = // default value;
if ([typedepartie isEqual: #"ami"]) {
sql3 = // other value;
}

Related

How to set sslmode as allow in postgresql in Objective-C

I used the following code to connect to the postgresql database. It works good. But now I want to connect it with sslmode enabled. Can anyone help me to acheive this.
NSString* portS = [NSNumber numberWithInteger:port].stringValue;
headerPG = PQsetdbLogin(serverName.UTF8String,portS.UTF8String,NULL,NULL,databaseName.UTF8String,
userName.UTF8String, password.UTF8String);
BOOL result = [self connected];
NSString *resultString;
if(!result){
//Error connection
[self errorPG];
resultString = #"Connection Failed";
}
else{
resultString = #"Connected Successfully";
}
return resultString;
I dont know how to use the following function.
PGconn *PQconnectdbParams(const char **keywords, const char **values, int expand_dbname);
How to feed data in keywords, values, etc.
Thanks in advance.
I got the answer myself.
const char *const keywords[] = {[#"sslmode" UTF8String], [#"hostaddr" UTF8String], [#"port" UTF8String], [#"user" UTF8String], [#"password" UTF8String], [#"dbname" UTF8String]};
const char *const values[] = {[#"allow" UTF8String], [serverName UTF8String], [portS UTF8String],[userName UTF8String],[password UTF8String],[databaseName UTF8String]};
headerPG = PQconnectdbParams(keywords, values, 1);
Here the keyword array has the keywords of postgresql and value array has the values of particular key in keyword array.

sqlite fetch statement

Good day,
I need to fetch rows from my sqlite table, but I need to pass multiple parameters. This is my statement that does not work.
SELECT * FROM messages WHERE currentuser=\"%#\" AND (belongstouser=\"%#\" OR mymsgforuser=\"%#\") ORDER BY ID ASC
I need it to first check for the currentuser match, then out of those matches to check for either the belongstouser or mymsgforuser matches. Is it possible to nest a sqlite statement in this fashion? I tried removing the parenthesis and that didn't work either. I also searched the sqlite documentation and could not find a solution.
I can see wrong SQL syntax. string constants must be quoted with single quotes (') instead of (")
And as rmaddy said, you'd better avoid stringWithFormat. Use prepare statement technique.
- (BOOL)_prepareStatement:(sqlite3_stmt **)statement withSQL:(const char *)sql {
sqlite3_stmt *s = *statement;
//caDatabase is declared as sqlite3 *caDatabase object
if (nil == s && sqlite3_prepare_v2(caDatabase, sql, -1, &s, NULL)!= SQLITE_OK)
{
[self _showError];
*statement = nil;
return NO;
}
*statement = s;
return YES;
}
- (caObjectId)existObject:(caObjectId)objId withType:(caCacheObjectType)objType libraryID:(int)aLibraryID
{
#synchronized (self)
{
const char *caSQLexistObj = "SELECT id FROM objects WHERE objId = ? AND objType = ? AND libraryID = ?";
if(![self _prepareStatement:&ca_existObjectStatement withSQL:caSQLexistObj]) {
//produce some error message
return;
}
sqlite3_bind_int(ca_existObjectStatement, 1, objId);
sqlite3_bind_int(ca_existObjectStatement, 2, objType);
sqlite3_bind_int(ca_existObjectStatement, 3, aLibraryID);
NSInteger result = sqlite3_step(ca_existObjectStatement);
if (result != SQLITE_ROW)
{
sqlite3_reset(ca_existObjectStatement);
return caObjectIdNone;
}
caObjectId cacheId = sqlite3_column_int(ca_existObjectStatement, 0);
sqlite3_reset(ca_existObjectStatement);
return cacheId;
}
}

How to use value of a variable in ObjectiveC?

I just start to learn ObjectiveC and I have a problem.
I have a variable in a for loop , this variable change value at any iteration and I want get his value.
Here my problem the variable is "name":
for 1st iteration name='id'
for 2nd iteration name='city' ...
for (i = 0; i < count; i++) {
name = ivar_getName(ivars[i]);
encode = ivar_getTypeEncoding(ivars[i]);
type = decode_type_string(encode);
if (strncmp(encode, "#", 1) == 0)
{
printf(" '%s', ", [[obj name*]UTF8String]);
}
else
{
printf(" %s ", name);
}
}
My goal is that the variable is interpreted by its value. if in my iiteration variable name is set to "ID" I want to have: [obj name] => [id obj] (for the id of my instance) if in my iiteration variable name is set to "City" I want to have: [obj name] => [obj City] (for the city of my instance)
(sorry for my english)
I think you are badly confused about several things. First off, NSString objects do not begin with "#" as the first character of the string. Rather, the "#" character is used to differentiate between a C string literal (eg, "abc") and an Objective-C NSString literal (eg, #"abc"). Note that the "#" character is outside the quotes.
Second, if you have an object with a PROPERTY named "name" you may reference its value with either [myObj name] or myObj.name, and set it either with [myObj setName:newValue]; or with myObj.name = newValue;.
If you have an NSString object you wish to print for diagnostic purposes, you can print it using NSLog(#"Here is the string ->%#", theString);. The %# is a special Objective-C formatting code meaning "treat the next format parm as an object and invoke it's description method, then display that result".
(And if you're "just learning" Objective-C there's no reason to be mucking with ivar_getName and its ilk. Functions like that are very rarely needed.)
If you are printing an Objective-C string, use NSLog
NSLog(#" %# ", [obj name]);
To print a string in objective-c you can use NSLog. The call looks like
NSLog(#"%#",[obj name]);
Not sure I quite read your question right - but I think you want to dynamically fetch them.
See below for an example.
Dw.
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#interface Frob : NSObject;
#property (strong) NSString * name, * bar, * fred;
#end
#implementation Frob
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
Frob * frob = [[Frob alloc] init];
frob.name = #"aName value";
frob.bar = #"aBar value";
frob.fred = #"aFred value";
const char *lst[] = { "name", "bar", "fred" };
for(int i = 0; i < sizeof(lst)/sizeof(char*); i++)
{
const char * nameStr = lst[i];
SEL s = sel_getUid(nameStr);
if (s) {
NSString * val = [frob performSelector:s];
NSLog(#"%s --> %#\n", nameStr, val);
printf("%s --> %s", nameStr, [val UTF8String]);
}
}
}
return 0;
}

why does my sqlite sql return no results?

The follow is my db function:
+(NSArray*)searchWithKey:(NSString*)_key{
NSMutableArray* tmpArray = [NSMutableArray array];
static Statement* stmt = nil;
char* sql = "select * from Bookmarks where BMUrl like '%?%'";
if (stmt == nil) {
stmt = [DBConnection statementWithQuery:sql];
[stmt retain];
}
[stmt bindString:_key forIndex:1];
while ([stmt step] == SQLITE_ROW) {
BookMark* tmpBM = [[BookMark alloc] initWithStatement:stmt];
NSLog(#"tmpBM = %#",tmpBM);
[tmpArray addObject:tmpBM];
[tmpBM release];
}
[stmt reset];
return tmpArray;}
The keyword of sql is "like" which I use.But there are no results that the sqlite return.Anyone could tell me why?
I change the sql into "select * from Bookmarks where BMUrl like '%h%'",there are some results which are returned.So , I guess the mistake is the function "bindString:forIndex",the code is
- (void)bindString:(NSString*)value forIndex:(int)index{
sqlite3_bind_text(stmt, index, [value UTF8String], -1, SQLITE_TRANSIENT);}
which is the correct sqlite3 api that i will use? thank u!
Bindings aren't interpolated like that. If you put a quotation mark in a string, as in '%?%', it will be interpreted as a literal question mark.
You should instead modify your input _key:
Escape any instances of % and _ with a \
Add %s at the beginning and end
This prepares it to be used with a LIKE operator.
You also need to modify your SQL so that the ? represents a standalone parameter: ... where BMUrl like ?.
Here's an example for how to escape special characters and add %s at the beginning and end of _key:
NSString *escapedKey = [_key stringByReplacingOccurencesOfString:#"%"
withString:#"\\%"];
escapedKey = [escapedKey stringByReplacingOccurencesOfString:#"_"
withString:#"\\_"];
NSString *keyForLike = [NSString stringWithFormat:#"%%%#%%", escapedKey];
[stmt bindString:keyForLike forIndex:1];

Possibly bad memory access?

I am currently developing on Objective-C using sqlite3. The following code seems like a bad memory access.
-(sqlite3_stmt *)PrepareStmt:(NSString *)query
{
//...
const char *query_stmt = [query UTF8String];
sqlite3_stmt *stmt = nil;
int retval = 0;
if ((retval = sqlite3_prepare_v2(db, query_stmt, -1, &stmt, nil)) == SQLITE_OK)
{
return stmt;
}
else
{
//Error handling...
}
}
- (void)SomeFunc
{
NSString *query = #""; //Assume valid SQL statement
sqlite3_stmt *stmt = [self PrepareStmt:query];
//Use stmt, like step, etc.
sqlite3_finalize(stmt);
}
The sqlite3_stmt in PrepareStmt is set to nil and it will be an out parameter from sqlite3_prepare_v2(). The memory should be allocated in that function. Therefore, it should be released by calling sqlite3_finalize().
My question here is that if we return sqlite3_stmt from PrepareStmt(), it should be still valid right? The local pointer in PrepareStmt() is already popped off the stack, but the memory allocated by sqlite3_prepare_v2() should still be valid.
Is this thinking valid? Or do I need to pass in an address of an pointer to PrepareStmt()?
Thank you!
Yes it's valid in this case. But note that sqlite3_finalize() isn't just about releasing memory (i.e. dealloc). It also sends a message to the DB to tell it to drop it's precompiled SQL statement, etc...