Skip to content
This repository has been archived by the owner on Mar 11, 2022. It is now read-only.

Commit

Permalink
Allow queries combining $not and $size operators
Browse files Browse the repository at this point in the history
- Added recursion logic to handle size operator in negated clause
- Added tests in CDTQQueryExecutorTests and CDTQQuerySqlTranslatorTests
  • Loading branch information
emlaver committed Mar 20, 2017
1 parent c608264 commit b7ae4d4
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 1 deletion.
5 changes: 5 additions & 0 deletions CDTDatastore/query/CDTQQuerySqlTranslator.m
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,11 @@ + (BOOL)isOperator:(NSString *)operator inClause:(NSArray *)clause
NSDictionary *predicate = (NSDictionary *) term.allValues[0];
if (predicate[operator]) {
found = YES;
} else {
found = [self isOperator:operator inClause:[NSArray arrayWithObjects:predicate, nil]];
}

if (found) {
break;
}
}
Expand Down
65 changes: 65 additions & 0 deletions CDTDatastoreTests/CDTQQueryExecutorTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -1861,6 +1861,12 @@
expect(result.documentIds).to.containsInAnyOrder(@[ @"mike12", @"fred34", @"bill34" ]);
});

it(@"works when array count does not match", ^{
NSDictionary* query = @{ @"pet" : @{ @"$not" : @{ @"$size" : @2 } } };
CDTQResultSet* result = [im find:query];
expect(result.documentIds).to.containsInAnyOrder(@[ @"mike24", @"john44", @"fred72", @"john12", @"fred11" ]);
});

it(@"correctly returns empty result set when array count does not match", ^{
NSDictionary* query = @{ @"pet": @{ @"$size": @3 } };
CDTQResultSet* result = [im find:query];
Expand All @@ -1880,6 +1886,33 @@
expect(result.documentIds).to.containsInAnyOrder(@[ @"fred11" ]);
});

it(@"correctly returns a result set when argument is negative in negated clause", ^{
NSDictionary* query = @{ @"pet": @{ @"$not" : @{ @"$size": @-1 }} };
CDTQResultSet* result = [im find:query];
expect(result).toNot.beNil();
expect(result.documentIds.count).to.equal(8);
});

it(@"correctly returns a result set when argument is not a whole number in negated clause", ^{
NSDictionary* query = @{ @"pet": @{ @"$not" : @{ @"$size": @1.6 }} };
CDTQResultSet* result = [im find:query];
expect(result).toNot.beNil();
expect(result.documentIds.count).to.equal(8);
});

it(@"correctly returns a result set when argument is string in negated clause", ^{
NSDictionary* query = @{ @"pet": @{ @"$not" : @{ @"$size": @"dog" }} };
CDTQResultSet* result = [im find:query];
expect(result).toNot.beNil();
expect(result.documentIds.count).to.equal(8);
});

it(@"correctly returns nil when argument is invalid in negated clause", ^{
NSDictionary* query = @{ @"pet": @{ @"$not" : @{ @"$size": @[ @1 ] }} };
CDTQResultSet* result = [im find:query];
expect(result).to.beNil();
});

it(@"correctly returns empty result set when argument is negative", ^{
NSDictionary* query = @{ @"pet": @{ @"$size": @-1 } };
CDTQResultSet* result = [im find:query];
Expand Down Expand Up @@ -1914,6 +1947,13 @@
expect(result.documentIds).to.containsInAnyOrder(@[ @"mike12" ]);
});

it(@"correctly performs compound AND query with negated $size clause", ^{
NSDictionary* query = @{ @"$and": @[ @{ @"pet": @{@"$not" : @{ @"$size": @2 } }},
@{ @"name": @"mike" } ] };
CDTQResultSet* result = [im find:query];
expect(result.documentIds).to.containsInAnyOrder(@[ @"mike24" ]);
});

it(@"correctly performs compound AND query on same field with single $size clause", ^{
NSDictionary* query = @{ @"$and": @[ @{ @"pet": @{ @"$size": @2 } },
@{ @"pet": @"dog" } ] };
Expand All @@ -1931,6 +1971,17 @@
@"john44" ]);
});

it(@"correctly performs compound OR query with negated $size clause", ^{
NSDictionary* query = @{ @"$or": @[ @{ @"pet": @{@"$not" : @{ @"$size": @2 } }},
@{ @"name": @"john" } ] };
CDTQResultSet* result = [im find:query];
expect(result.documentIds).to.containsInAnyOrder(@[ @"mike24",
@"fred72",
@"john12",
@"john44",
@"fred11"]);
});

it(@"correctly performs compound OR query with multiple $size clauses on same field", ^{
NSDictionary* query = @{ @"$or": @[ @{ @"pet": @{ @"$size": @1 } },
@{ @"pet": @{ @"$size": @2 } } ] };
Expand All @@ -1942,6 +1993,20 @@
@"bill34" ]);
});

it(@"correctly performs compound OR query with multiple negated $size clauses on same field", ^{
NSDictionary* query = @{ @"$or": @[ @{ @"pet": @{@"$not" : @{ @"$size": @1 }} },
@{ @"pet": @{@"$not" : @{ @"$size": @2 }} } ] };
CDTQResultSet* result = [im find:query];
expect(result.documentIds).to.containsInAnyOrder(@[ @"mike12",
@"mike24",
@"fred11",
@"fred34",
@"fred72",
@"john12",
@"john44",
@"bill34" ]);
});

it(@"returns empty result set for compound AND, multiple $size clauses, same field", ^{
NSDictionary* query = @{ @"$and": @[ @{ @"pet": @{ @"$size": @1 } },
@{ @"pet": @{ @"$size": @2 } } ] };
Expand Down
34 changes: 33 additions & 1 deletion CDTDatastoreTests/CDTQQuerySqlTranslatorTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,16 @@
expect(idx).to.beNil();
});

it(@"does not select an index for negated $size queries", ^{
NSDictionary *indexes = @{ @"named": @{ @"name": @"named",
@"type": @"json",
@"fields": @[ @"name", @"pet", @"age" ] } };
NSString *idx =
[CDTQQuerySqlTranslator chooseIndexForAndClause:@[ @{ @"pet": @{ @"$not" : @{ @"$size": @2 }} } ]
fromIndexes:indexes];
expect(idx).to.beNil();
});

it(@"does not select an index for multi-field queries containing $size", ^{
NSDictionary *indexes = @{ @"named": @{ @"name": @"named",
@"type": @"json",
Expand All @@ -629,6 +639,17 @@
fromIndexes:indexes];
expect(idx).to.beNil();
});

it(@"does not select an index for multi-field queries containing $size in negated clause", ^{
NSDictionary *indexes = @{ @"named": @{ @"name": @"named",
@"type": @"json",
@"fields": @[ @"name", @"pet", @"age" ] } };
NSString *idx =
[CDTQQuerySqlTranslator chooseIndexForAndClause:@[ @{ @"name": @{ @"$eq": @"mike" } },
@{ @"pet": @{ @"$not" : @{ @"$size": @2 }} } ]
fromIndexes:indexes];
expect(idx).to.beNil();
});

it(@"selects an index for multi-field queries", ^{
NSDictionary *indexes = @{
Expand Down Expand Up @@ -978,7 +999,6 @@
expect(parts.placeholderValues).to.equal(@[ @2, @1 ]);
});
});

});

describe(@"when multiple conditions on one field", ^{
Expand Down Expand Up @@ -1278,12 +1298,24 @@
expect(actual).to.equal(@{ @"$and": @[ @{ @"pet": @{ @"$size": @2 } } ] });
});

it(@"correctly normalizes query with NOT and SIZE operator", ^{
NSDictionary *actual =
[CDTQQueryValidator normaliseAndValidateQuery:@{@"pet": @{ @"$not" : @{ @"$size": @2 } } } ];
expect(actual).to.equal(@{ @"$and": @[ @{ @"pet": @{ @"$not" : @{ @"$size": @2 } } } ] });
});

it(@"returns nil when SIZE argument is invalid", ^{
NSDictionary *actual =
[CDTQQueryValidator normaliseAndValidateQuery:@{@"pet": @{ @"$size": @[ @2 ] } } ];
expect(actual).to.beNil();
});

it(@"returns nil when SIZE argument is invalid in negated clause", ^{
NSDictionary *actual =
[CDTQQueryValidator normaliseAndValidateQuery:@{@"pet": @{ @"$not" : @{ @"$size": @[ @2 ] } } } ];
expect(actual).to.beNil();
});

});

describe(@"when normalizing text search queries", ^{
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

- [IMPROVED] Significant reduction in memory usage during large pull replications.
- [FIXED] Issue querying indexed fields when combining the `$not` and `$size` operators.

## 1.2.0 (2016-12-07)

Expand Down

0 comments on commit b7ae4d4

Please sign in to comment.