Escape special characters in FMDB iOS query - ios

I wrote a query with arguments in FMDB using ? mark symbol.I want to get details of users who has any of info in the list(hope i can give different info separated by commas in "in" statement in sql). Since my arguments having special symbols, It is throwing error. How to escape there special symbols. I tried different methods but none worked yet
My code is like:
FMResultSet *results = [db executeQuery:#"select details from user where info in(?)",infoList];
while([results next])
{...}
Info is a string combined by different string seperated by commas.For example:
'C-note','Cuban missile crisis, the','cubbyhole','I Love Lucy','I'm a Celebrity ... Get me Out of Here!','Iacocca, Lee','-iana','Ivy League, the'
Thanks in advance

You can't use a single ? with an in clause unless you only bind a single value. It doesn't work for a list of values.
Since infoList is an array of string values, one option is to add a ? for each value in the list.
NSMutableString *query = [NSMutableString stringWithString:#"select details from user where info in ("];
for (NSInteger i = 0; i < infoList.count; i++) {
if (i) {
[query appendString:#","];
}
[query appendString:#"?"];
}
[query appendString:#")"];
FMResultSet *results = [db executeQuery:query withArgumentsInArray:infoList];

Related

PFQuery constraints - exclude subquery

I have a table called "match". this table has several columns of type string.
I'm trying to create a query that queries for the string value "undefined" in column "player2". That works without problem. When I query for just that I get the results.
But I want to add a constraint so that it excludes the match objects where the current user's facebook id matches that of column "player1". I've stored the id in the PFUser object so i can easily retrieve it.
I'm creating a random player matching system where the query checks for an open spot in the match table's "player2" column. if it's "undefined" I know that there is an open slot in the match and the player can join it.
However it needs to exclude the matches the current player previously started himself. Otherwise it would join a match the current player started himself.
//check for objects that match the string "undefined"
PFQuery *query1 = [PFQuery queryWithClassName:#"match"];
[query1 whereKey:#"player2" containsString:#"UNDEFINED"];
//AND constraint to exclude the match of query1 if the current user id matches
PFQuery *query2 = [PFQuery queryWithClassName:#"match"];
[query2 whereKey:#"player1" notEqualTo:[[PFUser currentUser] objectForKey#"fbId"]];
PFQuery *mainQuery = [PFQuery orQueryWithSubqueries:#[query1,query2]];
Your player1 and player2 cols are strings containing user ids. I think this is going to cause other problems, but you can still do the query you're attempting as follows...
NSString *userId = [PFUser currentUser].objectId;
NSPredicate *predicate = [NSPredicate predicateWithFormat:
#"(player1 = 'UNDEFINED') AND (player2 != %#)", userId];
PFQuery *query = [PFQuery queryWithClassName:#"match" predicate:predicate];
EDIT - I changed fbId above to be the user's object id. That's what you're probably storing in the player string col. It's this kind of confusion that makes storing strings (instead of pointers) a problem for the design.

query not returning the latest objects

I'm using Parse within my app. i'm trying to do a query with a limit of 10 objects ordered by descending order of the createdAt property plus I'm using the nearGeopoint:WithinKilometers function. When i run the query, the receive the oldest objects in the database. when i remove the limit of number of objects to be returned, the query returns the latest objects from the newest to oldest (as expected). does the limit do that? isn't it a bug? here is the code, please let me know if there is anything wrong:
PFQuery *postsQuery = [PFQuery queryWithClassName:#"user_p"];
if (city)
{
[postsQuery whereKey:#"geoPoint" nearGeoPoint:[PFGeoPoint geoPointWithLatitude:[city[#"latitude"] doubleValue] longitude:[city[#"longitude"] doubleValue]] withinKilometers:[[[NSUserDefaults standardUserDefaults] valueForKey:#"distanceCovered"] doubleValue]];
}
[postsQuery orderByDescending:#"createdAt"];
[postsQuery includeKey:#"user_id"];
[postsQuery whereKeyExists:#"user_id"];
[postsQuery setLimit:10];

Bind parameter in FROM clause in SQLite

Is it possible to bind a parameter in the FROM clause of a query to SQLite? How?
If not, why? Any alternatives?
Here is what I want to do in my iOS application:
- (BOOL)existsColumn:(NSString *)column inTable:(NSString *)table ofDatabase:(FMDatabase *)database {
NSString *query = #"SELECT ? FROM ? LIMIT 0";
NSArray *queryParameters = #[column, table];
return (BOOL)[database executeQuery:query withArgumentsInArray:queryParameters];
}
Here is the error message I get:
near "?": syntax error
I understand that there are other ways to check if a column exists. I am specifically curious why I can't bind a parameter in the FROM clause (only binding a parameter in the SELECT clause above works so it must be an issue with the FROM clause).
The ? should only be used for binding actual values into the query such in the VALUES section of an INSERT or values in a WHERE clause.
For dynamically building the column and table names you should simply use a string format to build the query string before sending it to FMDB.
- (BOOL)existsColumn:(NSString *)column inTable:(NSString *)table ofDatabase:(FMDatabase *)database {
NSString *query = [NSString stringWithFormat:#"SELECT %# FROM %# LIMIT 0", column, table];
return (BOOL)[database executeQuery:query];
}
Please note that you should not use the string format in place of using ? and proper value binding for actual values (which you don't have in this case).

iOS/Parse query not finding string match in array

I am trying to query a PFObject that contains an array. I am looking to match a given NSString against any object within the PFObject's array of strings. According to http://blog.parse.com/2012/03/28/parse-supports-many-to-many-relations/, I can use whereKey:equalTo to look for matches within an array.
I have replaced the variable I would usually use with the string that I know to be in the array whose object I am querying. It is a character-for-character match. Yet the query returns no matches.
My code:
PFQuery *convosQuery = [PFQuery queryWithClassName:#"convo"];
PFObject *currentUserFacebookID = [NSString stringWithFormat:#"11808098"];
[convosQuery whereKey:#"nonUserFacebookIDs" equalTo:currentUserFacebookID];
[convosQuery findObjectsInBackgroundWithBlock:^(NSArray *convos, NSError *error) {
for (PFObject *convo in convos) {
NSLog(#"user/convo match found");
As I said, this returns no matches even though a PFObject of class "convo" contains for key "nonUserFacebookIDs" the value "[["11808098"]]".
What could be going on?
Does this object have any ACLs that might be restricting reads to a subset of users?
You mentioned "[["11808098"]]". Does this mean an array of array containing a string? If so, it would not match the string you specified.
And BTW, though not related to your question, why did use the below line? Why should you assign a string to a PFObject?
PFObject *currentUserFacebookID = [NSString stringWithFormat:#"11808098"];
~ Sunil Phani Manne

Problem with FMDB and insert value in the "executeQuery:" from a searchString

While building a Search for my app i ran into a problem whilst using the FMDB SQLite Wrapper (https://github.com/ccgus/fmdb).
When I search my database with this SQL Command, everything is fine. 13 objects are returned and I can use them.
FMResultSet *rs = [db executeQuery:#"SELECT * FROM ZARTICLE WHERE ZTITLEDE LIKE '%Daimler%'"];
But when i try to insert the searchQuery from the User Input like this:
FMResultSet *rs = [db executeQuery:#"SELECT * FROM ZARTICLE WHERE ZTITLEDE LIKE (?)", theSearchQuery];
... the value is dont be inserted into SQL Command. And I dont get any returned objects from the DB. even if the String (theSearchQuery) is the same written in the first example.
Additionaly I post a part from the documentation of FMDB for your convinience. :)
Data Sanitization
When providing a SQL statement to FMDB, you should not attempt to "sanitize" any values before insertion. Instead, you should use the standard SQLite binding syntax:
INSERT INTO myTable VALUES (?, ?, ?)
The ? character is recognized by SQLite as a placeholder for a value to be inserted. The execution methods all accept a variable number of arguments (or a representation of those arguments, such as an NSArray or a va_list), which are properly escaped for you.
Thus, you SHOULD NOT do this (or anything like this):
[db executeUpdate:[NSString stringWithFormat:#"INSERT INTO myTable VALUES (%#)", #"this has \" lots of ' bizarre \" quotes '"]];
Instead, you SHOULD do:
[db executeUpdate:#"INSERT INTO myTable VALUES (?)", #"this has \" lots of ' bizarre \" quotes '"];
All arguments provided to the -executeUpdate: method (or any of the variants that accept a va_list as a parameter) must be objects. The following will not work (and will result in a crash):
[db executeUpdate:#"INSERT INTO myTable VALUES (?)", 42];
The proper way to insert a number is to box it in an NSNumber object:
[db executeUpdate:#"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:42]];
Alternatively, you can use the -execute*WithFormat: variant to use NSString-style substitution:
[db executeUpdateWithFormat:#"INSERT INTO myTable VALUES (%d)", 42];
Internally, the -execute*WithFormat: methods are properly boxing things for you. The following percent modifiers are recognized: %#, %c, %s, %d, %D, %i, %u, %U, %hi, %hu, %qi, %qu, %f, %g, %ld, %lu, %lld, and %llu. Using a modifier other than those will have unpredictable results. If, for some reason, you need the % character to appear in your SQL statement, you should use %%.
NSString *search_text = [NSString stringWithFormat:#"%%%#%%", theSearchQuery];
FMResultSet *rs = [db executeQuery:#"SELECT * FROM ZARTICLE WHERE ZTITLEDE LIKE ?", search_text];
I would highly recommend to avoid creating queries with stringWithFormat:! There is a good reason why FMDB tries to force you to use their data sanitization. However, since FMDB is boxing your input, surrounding parenthesis in the following code are not needed and may cause your problem.
[db executeQuery:#"SELECT * FROM ZARTICLE WHERE ZTITLEDE LIKE (?)", theSearchQuery];
Simple add arguments without any parenthisis because you never know how FMDB boxes your argument internally.
[db executeQuery:#"SELECT * FROM ZARTICLE WHERE ZTITLEDE LIKE ?", theSearchQuery];
If this still doesn't work try to use the suggested executeQueryWithFormat: method of FMDB:
[db executeQueryWithFormat:#"SELECT * FROM ZARTICLE WHERE ZTITLEDE LIKE %#", theSearchQuery];

Resources