Question

I'm implementing an image dao that selects images based on a client_type (eg dropbox, facebook, etc), as follows:

Return results from any enabled client matching the supplied list of client types:

//clientTypes is an array of NSNumber objects - there's an enum for each client type
- (NSArray*)listByClientTypes:(NSArray*)clientTypes
{
    __block NSArray* results;

    [[self.manager queue] inDatabase:^(FMDatabase* database)
    {
        NSMutableArray* mappedResults = [[NSMutableArray alloc] init];
        NSString* sql = @"SELECT IMAGE_ADDRESS, CLIENT_TYPE, CREATED, FK_LOCATIONS_UNIQUE_COORD, PLACE_NAME, CITY, COUNTRY, IMAGE "
            "FROM IMAGES LEFT JOIN LOCATIONS ON IMAGES.FK_LOCATIONS_UNIQUE_COORD = LOCATIONS.UNIQUE_COORD "
            "WHERE CLIENT_TYPE IN (SELECT CLIENT_TYPE FROM CLIENT_STATE WHERE ENABLED = 1) "
            "AND CLIENT_TYPE IN (%@)"; // <------- THIS IS THE LIST OF CLIENTS
        FMResultSet* resultSet = [database executeQuery:sql];
        while ([resultSet next])
        {
            [mappedResults addObject:[self extractImageFrom:resultSet]];
        }
        results = [mappedResults copy];
    }];
    return results;
}

What's the best way to pass the 'IN' clause?

Normally I would use parameter binding (eg '?'), but I don't know how to do this for an unknown number of parameters. Is this possible?

For want of a better way, I was planning on just substituting a comma-separating list into the SQL query. . this would be quite safe given they're just integers.

Was it helpful?

Solution

If you're using a non-integer data-type its important to use SQL binding, as described in @MartinR's answer here. This is to:

  • Avoid problems with quotes an SQL that isn't properly escaped.
  • Avoid SQL-injection vulnerabilities.

Given, that in your case you have a list of integers, you could try something like this:

NSString *sql =
[NSString stringWithFormat:@"SELECT IMAGE_ADDRESS, CLIENT_TYPE, CREATED, FK_LOCATIONS_UNIQUE_COORD, PLACE_NAME, CITY, COUNTRY, IMAGE "
            "FROM IMAGES LEFT JOIN LOCATIONS ON IMAGES.FK_LOCATIONS_UNIQUE_COORD = LOCATIONS.UNIQUE_COORD "
            "WHERE CLIENT_TYPE IN (SELECT CLIENT_TYPE FROM CLIENT_STATE WHERE ENABLED = 1) "
            "AND CLIENT_TYPE IN (%@)",[clientTypes componentsJoinedByString:@"','"]];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top