Skip to content

Commit

Permalink
Buffing up SBCouchEnumerator's itemAtIndex
Browse files Browse the repository at this point in the history
- Adding query options to SBCouchDatabase
- Adding support for setting the queryStrings startkey value when limit is set.
- Added integration tests for itmeAtIndex.
  • Loading branch information
objectiveous committed Mar 10, 2009
1 parent cf38c7f commit ab21525
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 18 deletions.
4 changes: 3 additions & 1 deletion Classes/SBCouchDatabase.m
Expand Up @@ -84,8 +84,10 @@ -(NSEnumerator*) getViewEnumerator:(NSString*)viewId{
}

-(NSEnumerator*)allDocsInBatchesOf:(NSInteger)count{
SBCouchQueryOptions *queryOptions = [SBCouchQueryOptions new];
SBCouchQueryOptions *queryOptions = [SBCouchQueryOptions new];
queryOptions.limit = count;
SBCouchView *view = [[SBCouchView alloc] initWithName:@"_all_docs" andQueryOptions:queryOptions];
view.couchDatabase = self;
SBCouchEnumerator *enumerator = [[[SBCouchEnumerator alloc] initWithView:view] autorelease];
return (NSEnumerator*)enumerator;
}
Expand Down
65 changes: 48 additions & 17 deletions Classes/SBCouchEnumerator.m
Expand Up @@ -10,6 +10,13 @@
#import "SBCouchDatabase.h"
#import "CouchObjC.h"

@interface SBCouchEnumerator (Private)

-(BOOL)shouldFetchNextBatch;

@end


@implementation SBCouchEnumerator

@synthesize couchView;
Expand All @@ -21,8 +28,7 @@ @implementation SBCouchEnumerator
@synthesize sizeOfLastFetch;


-(id)initWithView:(SBCouchView*)aCouchView{

-(id)initWithView:(SBCouchView*)aCouchView{
self = [super init];
if(self != nil){
// Setting the currentIndex to -1 is used to indicate that we don't have an index yet.
Expand All @@ -40,27 +46,48 @@ -(void) dealloc{
[super dealloc];

}
-(id)itemAtIndex:(NSInteger)idx{
// trying to access something outside our range of options.
if(idx > totalRows)
return nil;

-(id)itemAtIndex:(NSInteger)idx{
if(self.currentIndex == -1)
[self fetchNextPage];

if([self.rows count] >= idx){
NSDictionary *row = [self.rows objectAtIndex:idx];
return [[SBCouchDocument alloc] initWithNSDictionary:row couchDatabase:self.couchView.couchDatabase];
}else{
self.currentIndex = self.currentIndex + self.queryOptions.limit;
}

// trying to access something that has not yet been fetched
if(idx >= [rows count]){

BOOL noMoreDataToFetch = self.sizeOfLastFetch < self.queryOptions.limit;
BOOL needMoreData = idx > self.currentIndex;
while(needMoreData && !noMoreDataToFetch ){
[self logIndexes];
[self fetchNextPage];
if( [self itemAtIndex:idx]){
// TODO might want to autorelase this
SBCouchDocument *doc = [[SBCouchDocument alloc] initWithNSDictionary:[rows objectAtIndex:idx] couchDatabase:self.couchView.couchDatabase];
return doc;
}else{
return nil;
}
self.currentIndex = self.currentIndex + self.queryOptions.limit;

if(self.sizeOfLastFetch < self.queryOptions.limit)
noMoreDataToFetch = TRUE;
}
if(idx > self.currentIndex)
return nil;

// TODO Might want to autorelease this.
SBCouchDocument *doc = [[SBCouchDocument alloc] initWithNSDictionary:[rows objectAtIndex:idx] couchDatabase:self.couchView.couchDatabase];
NSDictionary *row = [self.rows objectAtIndex:idx];
SBCouchDocument *doc = [[SBCouchDocument alloc] initWithNSDictionary:row couchDatabase:self.couchView.couchDatabase];
return doc;
}

-(void)logIndexes{
NSLog(@"----------------------------------------------- \n");
NSLog(@"sizeOfLastFetch = %i", self.sizeOfLastFetch);
NSLog(@"limit = %i", self.queryOptions.limit);
NSLog(@"currentIndex = %i", self.currentIndex);

}


-(BOOL)shouldFetchNextBatch{
if(self.currentIndex == -1)
return YES;
Expand Down Expand Up @@ -88,7 +115,7 @@ - (id)nextObject{

// If the call to fetchNextPage did not expand the number of rows to a number
// greater than currentIndex
if(currentIndex >= [rows count]){
if(currentIndex >= [self.rows count]){
//[rows release], rows = nil;
return nil;
}
Expand All @@ -108,6 +135,7 @@ - (NSArray *)allObjects{
-(void)fetchNextPage{
// contruct a new URL using our own copy of the query options
NSString *contructedUrl = [NSString stringWithFormat:@"%@?%@", self.couchView.name, [self.queryOptions queryString]];
NSLog(contructedUrl);
//NSString *viewUrl = [self.couchView urlString];
NSDictionary *etf = [self.couchView.couchDatabase get:contructedUrl];

Expand All @@ -116,7 +144,7 @@ -(void)fetchNextPage{
self.totalRows = [[etf objectForKey:@"total_rows"] integerValue];
self.offset = [[etf objectForKey:@"offset"] integerValue];
self.currentIndex = 0;
// Since this is not our first fetch, set the skip value to 1
// Since this is our first fetch, set the skip value to 1
// XXX This should be moved someplace where its only ever called
// once. No need to set this on every fetch.
self.queryOptions.skip=1;
Expand All @@ -128,6 +156,9 @@ -(void)fetchNextPage{
self.sizeOfLastFetch = -1;
}else{
self.sizeOfLastFetch = [newRows count];
NSString *lastObjectsID = [[self.rows lastObject] objectForKey:@"id"];
if(self.queryOptions.limit > 0)
self.queryOptions.startkey = lastObjectsID;
}
}

Expand Down
19 changes: 19 additions & 0 deletions Tests/SBEnumeratorIntegrationTest.m
Expand Up @@ -11,6 +11,7 @@ -(void)simpleAllDocsEnumeration;
-(void)simplestThingThatWillWork;
-(void)simpleDesignDocsEnumerator;
-(void)ensureSkipIsWorkingAndThereAreNoDuplicates;
-(void)itemAtIndexCallsWorkProperly;
@end

@implementation SBEnumeratorIntegrationTest
Expand All @@ -37,6 +38,24 @@ -(void)testANumberOfThingsWithASingleSetup{
[self simpleAllDocsEnumeration];
[self simpleDesignDocsEnumerator];
[self ensureSkipIsWorkingAndThereAreNoDuplicates];
[self itemAtIndexCallsWorkProperly];
}


-(void)itemAtIndexCallsWorkProperly{
SBCouchQueryOptions *queryOptions = [SBCouchQueryOptions new];
queryOptions.limit = 6;

SBCouchView *view = [[SBCouchView alloc] initWithName:@"_all_docs" andQueryOptions:queryOptions];
view.couchDatabase = self.couchDatabase;
// subtract 1 becuase the index is 0th based.
NSInteger totalNumberOfDocs = (self.numberOfViewsToCreate + self.numberOfDocumentsToCreate) -1 ;

SBCouchEnumerator *resultEnumerator = (SBCouchEnumerator*)[view getEnumerator];
id object = [resultEnumerator itemAtIndex:0];
STAssertNotNil(object, @"Jumping ahead several windows is not working");
object = [resultEnumerator itemAtIndex:totalNumberOfDocs];
STAssertNotNil(object, @"Jumping ahead several windows is not working");
}

-(void)ensureSkipIsWorkingAndThereAreNoDuplicates{
Expand Down

0 comments on commit ab21525

Please sign in to comment.