Permalink
Browse files

Support for getting specific keys from a view

Added support for issuing a POST request to a view and adding the structure {"keys": ["key1", "key2", ...]} to the body, as per http://wiki.apache.org/couchdb/HTTP_view_API

Original patch by alexanderedge: #21
Cleanup & unit test by snej.
  • Loading branch information...
1 parent 03f9a66 commit 19014f025758c1be1db50d3fda9e0c6b4c5b2ad6 @snej snej committed Jan 8, 2012
Showing with 40 additions and 6 deletions.
  1. +16 −2 Source/TDRouter+Handlers.m
  2. +1 −0 Source/TDView.h
  3. +14 −3 Source/TDView.m
  4. +9 −1 Source/TDView_Tests.m
View
@@ -636,15 +636,16 @@ - (TDStatus) do_DELETE: (TDDatabase*)db docID: (NSString*)docID attachment: (NSS
#pragma mark - VIEW QUERIES:
-- (TDStatus) do_GET: (TDDatabase*)db designDocID: (NSString*)designDoc view: (NSString*)viewName {
+- (TDStatus) queryDesignDoc: (NSString*)designDoc view: (NSString*)viewName keys: (NSArray*)keys {
viewName = $sprintf(@"%@/%@", designDoc, viewName);
- TDView* view = [db existingViewNamed: viewName];
+ TDView* view = [_db existingViewNamed: viewName];
if (!view)
return 404;
TDQueryOptions options;
if (![self getQueryOptions: &options])
return 400;
+ options.keys = keys;
TDStatus status;
NSArray* rows = [view queryWithOptions: &options status: &status];
@@ -659,6 +660,19 @@ - (TDStatus) do_GET: (TDDatabase*)db designDocID: (NSString*)designDoc view: (NS
}
+- (TDStatus) do_GET: (TDDatabase*)db designDocID: (NSString*)designDoc view: (NSString*)viewName {
+ return [self queryDesignDoc: designDoc view: viewName keys: nil];
+}
+
+
+- (TDStatus) do_POST: (TDDatabase*)db designDocID: (NSString*)designDoc view: (NSString*)viewName {
+ NSArray* keys = $castIf(NSArray, [self.bodyAsDictionary objectForKey: @"keys"]);
+ if (!keys)
+ return 400;
+ return [self queryDesignDoc: designDoc view: viewName keys: keys];
+}
+
+
- (TDStatus) do_POST_temp_view: (TDDatabase*)db {
if (![[_request valueForHTTPHeaderField: @"Content-Type"] hasPrefix: @"application/json"])
return 415;
View
@@ -29,6 +29,7 @@ typedef id (^TDReduceBlock)(NSArray* keys, NSArray* values, BOOL rereduce);
typedef struct TDQueryOptions {
__unsafe_unretained id startKey;
__unsafe_unretained id endKey;
+ __unsafe_unretained NSArray* keys;
unsigned skip;
unsigned limit;
unsigned groupLevel;
View
@@ -25,9 +25,9 @@
const TDQueryOptions kDefaultTDQueryOptions = {
- nil, nil,
- 0, UINT_MAX, 0, 0,
- NO, NO, NO, YES, NO, NO
+ .limit = UINT_MAX,
+ .inclusiveEnd = YES
+ // everything else will default to nil/0/NO
};
@@ -277,6 +277,17 @@ - (FMResultSet*) resultSetWithOptions: (const TDQueryOptions*)options
[sql appendString: @" FROM maps, revs, docs WHERE maps.view_id=?"];
NSMutableArray* args = $marray($object(_viewID));
+ if (options->keys) {
+ [sql appendString:@" AND key in ("];
+ NSString* item = @"?";
+ for (NSString * key in options->keys) {
+ [sql appendString: item];
+ item = @",?";
+ [args addObject: toJSONString(key)];
+ }
+ [sql appendString:@")"];
+ }
+
id minKey = options->startKey, maxKey = options->endKey;
BOOL inclusiveMin = YES, inclusiveMax = options->inclusiveEnd;
if (options->descending) {
View
@@ -190,7 +190,15 @@
rows = [view queryWithOptions: &options status: &status];
expectedRows = $array($dict({@"id", @"44444"}, {@"key", @"four"}));
CAssertEqual(rows, expectedRows);
-}
+
+ // Specific keys:
+ options = kDefaultTDQueryOptions;
+ options.keys = $array(@"two", @"four");
+ rows = [view queryWithOptions: &options status: &status];
+ expectedRows = $array($dict({@"id", @"44444"}, {@"key", @"four"}),
+ $dict({@"id", @"22222"}, {@"key", @"two"}));
+ CAssertEqual(rows, expectedRows);
+}
TestCase(TDView_AllDocsQuery) {

0 comments on commit 19014f0

Please sign in to comment.