Skip to content

Commit 03a02e8

Browse files
committed
Bug fix for YapDatabaseQuery: didn't properly handle empty arrays or multiple arrays in parameter list.
Now also supports NSNull in parameter list.
1 parent c428950 commit 03a02e8

3 files changed

Lines changed: 51 additions & 17 deletions

File tree

Testing/UnitTesting/TestYapDatabaseQuery.m

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ - (void)test1
4141
expectedArguments = @[@"test", @(1), @(5)];
4242
XCTAssertTrue([query.queryString isEqualToString:@"WHERE col2 <> ? AND col IN (?,?)"], @"Incorrect queryString");
4343
XCTAssertTrue([query.queryParameters isEqualToArray:expectedArguments], @"Incorrect queryParameters");
44+
45+
query = [YapDatabaseQuery queryWithFormat:@"WHERE col1 IN (?) AND col2 IN (?)", @[@(1), @(2)], @[@(3), @(4)]];
46+
expectedArguments = @[@(1), @(2), @(3), @(4)];
47+
XCTAssertTrue([query.queryString isEqualToString:@"WHERE col1 IN (?,?) AND col2 IN (?,?)"], @"Incorrect queryString: %@", query.queryString);
48+
XCTAssertTrue([query.queryParameters isEqualToArray:expectedArguments], @"Incorrect queryParameters");
49+
50+
query = [YapDatabaseQuery queryWithFormat:@"WHERE col1 IN (?)", @[]];
51+
expectedArguments = @[ [NSNull null] ];
52+
XCTAssertTrue([query.queryString isEqualToString:@"WHERE col1 IN (?)"], @"Incorrect queryString: %@", query.queryString);
53+
XCTAssertTrue([query.queryParameters isEqualToArray:expectedArguments], @"Incorrect queryParameters");
4454
}
4555

4656
@end

YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,10 @@ - (BOOL)_enumerateRowidsMatchingQuery:(YapDatabaseQuery *)query
11301130

11311131
sqlite3_bind_text(statement, bind_idx, [cast UTF8String], -1, SQLITE_TRANSIENT);
11321132
}
1133+
else if ([value isKindOfClass:[NSNull class]])
1134+
{
1135+
sqlite3_bind_null(statement, bind_idx);
1136+
}
11331137
else
11341138
{
11351139
YDBLogWarn(@"Unable to bind value for with unsupported class: %@", NSStringFromClass([value class]));

YapDatabase/Utilities/YapDatabaseQuery.m

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -101,39 +101,59 @@ + (instancetype)queryWithFormat:(NSString *)format arguments:(va_list)args
101101

102102
@try
103103
{
104-
NSMutableDictionary *paramIndexToElementCountMap = [NSMutableDictionary dictionary];
104+
NSMutableDictionary *paramIndexToArrayCountMap = [NSMutableDictionary dictionary];
105105
for (NSUInteger i = 0; i < paramCount; i++)
106106
{
107107
id param = va_arg(args, id);
108108
if ([param isKindOfClass:[NSArray class]])
109109
{
110-
paramIndexToElementCountMap[@(i)] = @([param count]);
111-
[queryParameters addObjectsFromArray:param];
110+
NSUInteger arrayCount = [param count];
111+
if (arrayCount == 0)
112+
{
113+
[queryParameters addObject:[NSNull null]];
114+
}
115+
else
116+
{
117+
paramIndexToArrayCountMap[@(i)] = @([param count]);
118+
[queryParameters addObjectsFromArray:param];
119+
}
120+
112121
}
113122
else
114123
{
115124
[queryParameters addObject:param];
116125
}
117126
}
118127

119-
if (paramIndexToElementCountMap.count > 0)
128+
if (paramIndexToArrayCountMap.count > 0)
120129
{
121-
NSUInteger unpackingOffset = 0;
122-
NSString *queryString = [format copy];
123-
NSRange range;
124-
for (NSNumber *index in paramIndexToElementCountMap)
130+
NSMutableString *queryString = [format mutableCopy];
131+
132+
__block NSUInteger unpackingOffset = 0;
133+
134+
[paramIndexToArrayCountMap enumerateKeysAndObjectsUsingBlock:
135+
^(NSNumber *paramIndexNum, NSNumber *arrayCountNum, BOOL *stop)
125136
{
126-
NSInteger elementCount = [paramIndexToElementCountMap[index] intValue];
127-
NSMutableArray *unpackedParams = [NSMutableArray array];
128-
for (NSInteger i = 0; i < elementCount; i++)
137+
NSUInteger arrayCount = [arrayCountNum unsignedIntegerValue];
138+
139+
NSMutableString *unpackedParamsStr = [NSMutableString stringWithCapacity:(arrayCount * 2)];
140+
for (NSUInteger i = 0; i < arrayCount; i++)
129141
{
130-
[unpackedParams addObject:@"?"];
142+
if (i == 0)
143+
[unpackedParamsStr appendString:@"?"];
144+
else
145+
[unpackedParamsStr appendString:@",?"];
131146
}
132-
NSString *unpackedParamsStr = [unpackedParams componentsJoinedByString:@","];
133-
range = NSMakeRange([paramLocations[[index intValue]] intValue] + unpackingOffset, 1);
134-
queryString = [queryString stringByReplacingCharactersInRange:range
135-
withString:unpackedParamsStr];
136-
}
147+
148+
NSUInteger paramIndex = [paramIndexNum unsignedIntegerValue];
149+
NSUInteger paramLocation = [paramLocations[paramIndex] unsignedIntegerValue];
150+
151+
NSRange range = NSMakeRange(paramLocation + unpackingOffset, 1);
152+
unpackingOffset += [unpackedParamsStr length] - 1;
153+
154+
[queryString replaceCharactersInRange:range withString:unpackedParamsStr];
155+
156+
}];
137157

138158
format = [queryString copy];
139159
}

0 commit comments

Comments
 (0)