Skip to content

Commit

Permalink
New where syntax implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexDenisov committed Jun 3, 2012
1 parent 48f6080 commit edbaab1
Show file tree
Hide file tree
Showing 8 changed files with 288 additions and 72 deletions.
162 changes: 137 additions & 25 deletions UnitTests/ARLazyFetcherSpecs.h
Expand Up @@ -35,31 +35,7 @@ describe(@"LazyFetcher", ^{
expect([records count]).toEqual(10);
});

describe(@"where between", ^{
it(@"should fetch only records between two dates", ^{
[ActiveRecord clearDatabase];
NSDate *startDate = [NSDate dateWithTimeIntervalSinceNow:-MONTH];
NSDate *endDate = [NSDate dateWithTimeIntervalSinceNow:DAY];
User *john = [User newRecord];
john.name = @"John";
john.createdAt = [NSDate dateWithTimeIntervalSinceNow:-MONTH * 2];
expect([john save]).toEqual(YES);
User *alex = [User newRecord];
alex.name = @"Alex";
alex.createdAt = [NSDate dateWithTimeIntervalSinceNow:-DAY];
expect([alex save]).toEqual(YES);
ARLazyFetcher *fetcher = [User lazyFetcher];
[fetcher whereField:@"createdAt"
between:startDate
and:endDate];
NSArray *users = [fetcher fetchRecords];
expect(users.count).toEqual(1);
[alex release];
[john release];

});
});


describe(@"Limit/Offset", ^{
it(@"LIMIT should return limited count of records", ^{
NSInteger limit = 5;
Expand Down Expand Up @@ -137,7 +113,143 @@ describe(@"LazyFetcher", ^{
});
});

describe(@"New Where syntax", ^{
describe(@"where between", ^{
it(@"should fetch only records between two dates", ^{
[ActiveRecord clearDatabase];
NSDate *startDate = [NSDate dateWithTimeIntervalSinceNow:-MONTH];
NSDate *endDate = [NSDate dateWithTimeIntervalSinceNow:DAY];
User *john = [User newRecord];
john.name = @"John";
john.createdAt = [NSDate dateWithTimeIntervalSinceNow:-MONTH * 2];
expect([john save]).toEqual(YES);
User *alex = [User newRecord];
alex.name = @"Alex";
alex.createdAt = [NSDate dateWithTimeIntervalSinceNow:-DAY];
expect([alex save]).toEqual(YES);
ARLazyFetcher *fetcher = [User lazyFetcher];
[fetcher where:
@"createdAt BETWEEN %@ AND %@",
startDate,
endDate, nil];
NSArray *users = [fetcher fetchRecords];
expect(users.count).toEqual(1);
[alex release];
[john release];

});
});
describe(@"Simple where conditions", ^{
it(@"whereField equalToValue should find record", ^{
NSString *username = @"john";
User *john = [User newRecord];
john.name = username;
[john save];
ARLazyFetcher *fetcher = [User lazyFetcher];
[fetcher where:@"name == %@", username, nil];
User *founded = [[fetcher fetchRecords] first];
expect(founded.name).toEqual(username);
});
it(@"whereField notEqualToValue should not find record", ^{
NSString *username = @"john";
User *john = [User newRecord];
john.name = username;
[john save];
ARLazyFetcher *fetcher = [User lazyFetcher];
[fetcher where:@"name <> %@", username, nil];
User *founded = [[fetcher fetchRecords] first];
expect(founded.name).Not.toEqual(username);
});
it(@"WhereField in should find record", ^{
NSString *username = @"john";
NSArray *names = [NSArray arrayWithObjects:@"alex", username, @"peter", nil];
User *john = [User newRecord];
john.name = username;
[john save];
ARLazyFetcher *fetcher = [User lazyFetcher];
[fetcher where:@"name in %@", names, nil];
User *founded = [[fetcher fetchRecords] first];
expect(founded.name).toEqual(username);
});
it(@"WhereField notIn should not find record", ^{
NSString *username = @"john";
NSArray *names = [NSArray arrayWithObjects:@"alex", username, @"peter", nil];
User *john = [User newRecord];
john.name = username;
[john save];
ARLazyFetcher *fetcher = [User lazyFetcher];
[fetcher where:@"name not in %@", names, nil];
User *founded = [[fetcher fetchRecords] first];
expect(founded.name).Not.toEqual(username);
});
it(@"WhereField LIKE should find record", ^{
NSString *username = @"john";
User *john = [User newRecord];
john.name = username;
[john save];
ARLazyFetcher *fetcher = [User lazyFetcher];
[fetcher where:@"name like %@", @"%jo%", nil];
User *founded = [[fetcher fetchRecords] first];
expect(founded.name).toEqual(username);
});
});
describe(@"Complex where conditions", ^{
it(@"Two conditions should return actual values", ^{
NSArray *ids = [NSArray arrayWithObjects:
[NSNumber numberWithInt:1],
[NSNumber numberWithInt:15],
nil];
NSString *username = @"john";
User *john = [User newRecord];
john.name = username;
[john save];
ARLazyFetcher *fetcher = [User lazyFetcher];
[fetcher where:
@"'user'.'name' = %@ or 'user'.'id' in %@",
username, ids, nil];
[fetcher orderBy:@"id"];
NSArray *records = [fetcher fetchRecords];
BOOL idStatementSuccess = NO;
BOOL nameStatementSuccess = NO;
for(User *user in records){
if([ids containsObject:user.id]){
idStatementSuccess = YES;
}
if([user.name isEqualToString:username]){
nameStatementSuccess = YES;
}
}
expect(idStatementSuccess).toEqual(YES);
expect(nameStatementSuccess).toEqual(YES);
});
});
});

describe(@"Where conditions", ^{
describe(@"where between", ^{
it(@"should fetch only records between two dates", ^{
[ActiveRecord clearDatabase];
NSDate *startDate = [NSDate dateWithTimeIntervalSinceNow:-MONTH];
NSDate *endDate = [NSDate dateWithTimeIntervalSinceNow:DAY];
User *john = [User newRecord];
john.name = @"John";
john.createdAt = [NSDate dateWithTimeIntervalSinceNow:-MONTH * 2];
expect([john save]).toEqual(YES);
User *alex = [User newRecord];
alex.name = @"Alex";
alex.createdAt = [NSDate dateWithTimeIntervalSinceNow:-DAY];
expect([alex save]).toEqual(YES);
ARLazyFetcher *fetcher = [User lazyFetcher];
[fetcher whereField:@"createdAt"
between:startDate
and:endDate];
NSArray *users = [fetcher fetchRecords];
expect(users.count).toEqual(1);
[alex release];
[john release];

});
});
describe(@"Simple where conditions", ^{
it(@"whereField equalToValue should find record", ^{
NSString *username = @"john";
Expand Down
18 changes: 18 additions & 0 deletions iActiveRecord.xcodeproj/project.pbxproj
Expand Up @@ -186,6 +186,8 @@
CABB90B31520F60700E8D082 /* ARRelationHasManyThrough.m in Sources */ = {isa = PBXBuildFile; fileRef = CABB90B11520F60700E8D082 /* ARRelationHasManyThrough.m */; };
CABB90B41520F60700E8D082 /* ARRelationHasManyThrough.m in Sources */ = {isa = PBXBuildFile; fileRef = CABB90B11520F60700E8D082 /* ARRelationHasManyThrough.m */; };
CABB90B51520F60700E8D082 /* ARRelationHasManyThrough.m in Sources */ = {isa = PBXBuildFile; fileRef = CABB90B11520F60700E8D082 /* ARRelationHasManyThrough.m */; };
CAC022EB157B76C300208445 /* NSArray+toSql.m in Sources */ = {isa = PBXBuildFile; fileRef = CAC022EA157B76C300208445 /* NSArray+toSql.m */; };
CAC022EC157B76C300208445 /* NSArray+toSql.m in Sources */ = {isa = PBXBuildFile; fileRef = CAC022EA157B76C300208445 /* NSArray+toSql.m */; };
CADA6AEF154472D800CCE41D /* NSMutableDictionary+valueToArray.h in Headers */ = {isa = PBXBuildFile; fileRef = CADA6AED154472D800CCE41D /* NSMutableDictionary+valueToArray.h */; };
CADA6AF0154472D800CCE41D /* NSMutableDictionary+valueToArray.m in Sources */ = {isa = PBXBuildFile; fileRef = CADA6AEE154472D800CCE41D /* NSMutableDictionary+valueToArray.m */; };
CADA6AF1154472D800CCE41D /* NSMutableDictionary+valueToArray.m in Sources */ = {isa = PBXBuildFile; fileRef = CADA6AEE154472D800CCE41D /* NSMutableDictionary+valueToArray.m */; };
Expand Down Expand Up @@ -364,6 +366,9 @@
CABB90A11520E63200E8D082 /* ARRelationHasMany.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARRelationHasMany.m; sourceTree = "<group>"; };
CABB90B01520F60700E8D082 /* ARRelationHasManyThrough.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARRelationHasManyThrough.h; sourceTree = "<group>"; };
CABB90B11520F60700E8D082 /* ARRelationHasManyThrough.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARRelationHasManyThrough.m; sourceTree = "<group>"; };
CAC022DD1579477000208445 /* ARLazyFetcher_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ARLazyFetcher_Private.h; sourceTree = "<group>"; };
CAC022E9157B76C300208445 /* NSArray+toSql.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+toSql.h"; sourceTree = "<group>"; };
CAC022EA157B76C300208445 /* NSArray+toSql.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+toSql.m"; sourceTree = "<group>"; };
CADA6AED154472D800CCE41D /* NSMutableDictionary+valueToArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableDictionary+valueToArray.h"; sourceTree = "<group>"; };
CADA6AEE154472D800CCE41D /* NSMutableDictionary+valueToArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableDictionary+valueToArray.m"; sourceTree = "<group>"; };
CADA6AF5154473E500CCE41D /* ARBaseRelationship.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARBaseRelationship.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -633,6 +638,7 @@
25998EFE14BC2D4600CA2490 /* Extra */ = {
isa = PBXGroup;
children = (
CAC022E4157B767C00208445 /* NSArray */,
CADA6AF4154472DE00CCE41D /* NSMutableDictionary */,
CAAE32B515244BEB0080447D /* NSDate */,
CAF2480F151F375000120198 /* NSData */,
Expand Down Expand Up @@ -840,6 +846,15 @@
name = Relationships;
sourceTree = "<group>";
};
CAC022E4157B767C00208445 /* NSArray */ = {
isa = PBXGroup;
children = (
CAC022E9157B76C300208445 /* NSArray+toSql.h */,
CAC022EA157B76C300208445 /* NSArray+toSql.m */,
);
name = NSArray;
sourceTree = "<group>";
};
CADA6AF4154472DE00CCE41D /* NSMutableDictionary */ = {
isa = PBXGroup;
children = (
Expand All @@ -852,6 +867,7 @@
CAE051701574BFE100010AAE /* ARLazyFetcher */ = {
isa = PBXGroup;
children = (
CAC022DD1579477000208445 /* ARLazyFetcher_Private.h */,
CA3D18041519D5FA00FA3F3C /* ARLazyFetcher.h */,
CA3D18051519D5FA00FA3F3C /* ARLazyFetcher.m */,
);
Expand Down Expand Up @@ -1104,6 +1120,7 @@
CADA6AF9154473E600CCE41D /* ARBaseRelationship.m in Sources */,
CA1AF756155FEA3A00D0B17E /* ARColumn.m in Sources */,
CA1AF75D155FEA5600D0B17E /* ARSchemaManager.m in Sources */,
CAC022EC157B76C300208445 /* NSArray+toSql.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -1156,6 +1173,7 @@
CADA6AF8154473E600CCE41D /* ARBaseRelationship.m in Sources */,
CA1AF755155FEA3A00D0B17E /* ARColumn.m in Sources */,
CA1AF75C155FEA5600D0B17E /* ARSchemaManager.m in Sources */,
CAC022EB157B76C300208445 /* NSArray+toSql.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
2 changes: 2 additions & 0 deletions iActiveRecord/ARLazyFetcher.h
Expand Up @@ -78,6 +78,8 @@ typedef enum {
- (ARLazyFetcher *)orderBy:(NSString *)aField ascending:(BOOL)isAscending;
- (ARLazyFetcher *)orderBy:(NSString *)aField;// ASC by default

- (ARLazyFetcher *)where:(NSString *)aCondition, ... NS_REQUIRES_NIL_TERMINATION;

- (ARWhereStatement *)whereStatement;
- (ARLazyFetcher *)setWhereStatement:(ARWhereStatement *)aStatement;

Expand Down
81 changes: 37 additions & 44 deletions iActiveRecord/ARLazyFetcher.m
Expand Up @@ -14,50 +14,8 @@
#import "ARColumn.h"
#import "ActiveRecord.h"
#import "ActiveRecord_Private.h"

static const char *joins[] = {"LEFT", "RIGHT", "INNER", "OUTER"};

static NSString* joinString(ARJoinType type)
{
return [NSString stringWithUTF8String:joins[type]];
}

@interface ARLazyFetcher ()
{
@private
Class recordClass;
NSString *sqlRequest;
// order by
NSMutableDictionary *orderByConditions;
// select
NSMutableSet *onlyFields;
NSMutableSet *exceptFields;
// join
ARJoinType joinType;
Class joinClass;
NSString *recordField;
NSString *joinField;
BOOL useJoin;
// where
ARWhereStatement *whereStatement;
// limit/offset
NSNumber *limit;
NSNumber *offset;
}

- (NSSet *)recordFields;

- (void)buildSql;
- (NSString *)createOrderbyStatement;
- (NSString *)createWhereStatement;
- (NSString *)createLimitOffsetStatement;
- (NSString *)createSelectStatement;
- (NSString *)createJoinedSelectStatement;
- (NSString *)createJoinStatement;

- (NSSet *)fieldsOfRecord:(id)aRecord;

@end
#import "ARLazyFetcher_Private.h"
#import "ARWhereStatement_Private.h"

@implementation ARLazyFetcher

Expand Down Expand Up @@ -535,4 +493,39 @@ - (NSInteger)count {
return [[ARDatabaseManager sharedInstance] functionResult:sql];
}

- (ARLazyFetcher *)where:(NSString *)aCondition, ... {
va_list args;
NSMutableArray *sqlArguments = [NSMutableArray array];
NSString *argument = nil;
va_start(args, aCondition);
id value = nil;
while ((value = va_arg(args, id))) {
if([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSSet class]]){
argument = [value performSelector:@selector(toSql)];
}else{
argument = [[value performSelector:@selector(toSql)] quotedString];
}
[sqlArguments addObject:argument];
}
va_end(args);

char *argList = (char *)malloc(sizeof(NSString *) * [sqlArguments count]);
[sqlArguments getObjects:(id *)argList];
NSString* result = [[[NSString alloc] initWithFormat:aCondition
arguments:argList] autorelease];
free(argList);

ARWhereStatement *where = [ARWhereStatement statement:result];

if(self.whereStatement){
ARWhereStatement *currentWhere = self.whereStatement;
self.whereStatement = [ARWhereStatement concatenateStatement:currentWhere
withStatement:where
useLogicalOperation:ARLogicalAnd];
}else {
self.whereStatement = where;
}
return self;
}

@end

0 comments on commit edbaab1

Please sign in to comment.