From 5da88e4b9b5ce9d1aee8611d03946e19bdfa5b65 Mon Sep 17 00:00:00 2001 From: zxu Date: Thu, 7 Dec 2017 15:36:15 -0500 Subject: Implement NSPredicate-based query (#531) * implement queryFilteredUsingPredicate in FIRQuery; * add unit test and integration test for queryFilteredUsingPredicate; * project change of adding the FIRQueryTests.m file; * refactoring queryFilteredUsingPredicate to split logic into two helpers; --- Firestore/CHANGELOG.md | 1 + .../Example/Firestore.xcodeproj/project.pbxproj | 4 + Firestore/Example/Tests/API/FIRQueryTests.m | 75 ++++++++++++++++++ .../Example/Tests/Integration/API/FIRQueryTests.m | 17 ++++ Firestore/Source/API/FIRQuery+Internal.h | 2 + Firestore/Source/API/FIRQuery.m | 92 ++++++++++++++++++++++ Firestore/Source/Public/FIRQuery.h | 13 +++ 7 files changed, 204 insertions(+) create mode 100644 Firestore/Example/Tests/API/FIRQueryTests.m (limited to 'Firestore') diff --git a/Firestore/CHANGELOG.md b/Firestore/CHANGELOG.md index 0c5bcdc..e6ecf11 100644 --- a/Firestore/CHANGELOG.md +++ b/Firestore/CHANGELOG.md @@ -4,6 +4,7 @@ with persistence enabled. - [fixed] Addressed race condition during the teardown of idle streams (#490). +- [feature] Queries can now be created from an NSPredicate. # v0.9.3 - [changed] Improved performance loading documents matching a query. diff --git a/Firestore/Example/Firestore.xcodeproj/project.pbxproj b/Firestore/Example/Firestore.xcodeproj/project.pbxproj index 437b661..5657b95 100644 --- a/Firestore/Example/Firestore.xcodeproj/project.pbxproj +++ b/Firestore/Example/Firestore.xcodeproj/project.pbxproj @@ -61,6 +61,7 @@ 6ED54761B845349D43DB6B78 /* Pods_Firestore_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 75A6FE51C1A02DF38F62FAAD /* Pods_Firestore_Example.framework */; }; 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */; }; 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */; }; + ABAEEF4F1FD5F8B100C966CB /* FIRQueryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = ABAEEF4E1FD5F8B100C966CB /* FIRQueryTests.m */; }; AFE6114F0D4DAECBA7B7C089 /* Pods_Firestore_IntegrationTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B2FA635DF5D116A67A7441CD /* Pods_Firestore_IntegrationTests.framework */; }; C4E749275AD0FBDF9F4716A8 /* Pods_SwiftBuildTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32AD40BF6B0E849B07FFD05E /* Pods_SwiftBuildTest.framework */; }; D5B2532E4676014F57A7EAB9 /* FSTStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D5B25C0D4AADFCA3ADB883E4 /* FSTStreamTests.m */; }; @@ -230,6 +231,7 @@ 8E002F4AD5D9B6197C940847 /* Firestore.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Firestore.podspec; path = ../Firestore.podspec; sourceTree = ""; }; 9D52E67EE96AA7E5D6F69748 /* Pods-Firestore_IntegrationTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_IntegrationTests/Pods-Firestore_IntegrationTests.debug.xcconfig"; sourceTree = ""; }; 9EF477AD4B2B643FD320867A /* Pods-Firestore_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_Example/Pods-Firestore_Example.debug.xcconfig"; sourceTree = ""; }; + ABAEEF4E1FD5F8B100C966CB /* FIRQueryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRQueryTests.m; sourceTree = ""; }; B2FA635DF5D116A67A7441CD /* Pods_Firestore_IntegrationTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_IntegrationTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CE00BABB5A3AAB44A4C209E2 /* Pods-Firestore_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_Tests/Pods-Firestore_Tests.debug.xcconfig"; sourceTree = ""; }; D3CC3DC5338DCAF43A211155 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; @@ -584,6 +586,7 @@ isa = PBXGroup; children = ( DE51B1841F0D48AC0013853F /* FIRGeoPointTests.m */, + ABAEEF4E1FD5F8B100C966CB /* FIRQueryTests.m */, ); path = API; sourceTree = ""; @@ -1161,6 +1164,7 @@ files = ( DE2EF0881F3D0B6E003D0CDC /* FSTTreeSortedDictionaryTests.m in Sources */, DE51B1FD1F0D492C0013853F /* FSTSpecTests.m in Sources */, + ABAEEF4F1FD5F8B100C966CB /* FIRQueryTests.m in Sources */, DE51B2001F0D493A0013853F /* FSTComparisonTests.m in Sources */, DE51B1CC1F0D48C00013853F /* FIRGeoPointTests.m in Sources */, DE51B1E11F0D490D0013853F /* FSTMemoryRemoteDocumentCacheTests.m in Sources */, diff --git a/Firestore/Example/Tests/API/FIRQueryTests.m b/Firestore/Example/Tests/API/FIRQueryTests.m new file mode 100644 index 0000000..bd0d860 --- /dev/null +++ b/Firestore/Example/Tests/API/FIRQueryTests.m @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import FirebaseFirestore; + +#import + +#import "Firestore/Source/API/FIRFirestore+Internal.h" +#import "Firestore/Source/API/FIRQuery+Internal.h" +#import "Firestore/Source/Core/FSTQuery.h" +#import "Firestore/Source/Model/FSTPath.h" + +#import "Firestore/Example/Tests/Util/FSTHelpers.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRQueryTests : XCTestCase +@end + +@implementation FIRQueryTests + +- (void)testFilteringWithPredicate { + // Everything is dummy for unit test here. Filtering does not require any app + // specific setting as far as we do not fetch data. + FIRFirestore *firestore = [[FIRFirestore alloc] initWithProjectID:@"abc" + database:@"abc" + persistenceKey:@"db123" + credentialsProvider:nil + workerDispatchQueue:nil + firebaseApp:nil]; + FSTResourcePath *path = [FSTResourcePath pathWithString:@"foo"]; + FIRQuery *query = [FIRQuery referenceWithQuery:[FSTQuery queryWithPath:path] + firestore:firestore]; + FIRQuery *query1 = [query queryWhereField:@"f" isLessThanOrEqualTo:@1]; + FIRQuery *query2 = [query queryFilteredUsingPredicate: + [NSPredicate predicateWithFormat:@"f<=1"]]; + FIRQuery *query3 = [[query queryWhereField:@"f1" isLessThan:@2] + queryWhereField:@"f2" isEqualTo:@3]; + FIRQuery *query4 = [query queryFilteredUsingPredicate: + [NSPredicate predicateWithFormat:@"f1<2 && f2==3"]]; + FIRQuery *query5 = [[[[[query queryWhereField:@"f1" isLessThan:@2] + queryWhereField:@"f2" isEqualTo:@3] + queryWhereField:@"f1" isLessThanOrEqualTo:@"four"] + queryWhereField:@"f1" isGreaterThanOrEqualTo:@"five"] + queryWhereField:@"f1" isGreaterThan:@6]; + FIRQuery *query6 = [query queryFilteredUsingPredicate: + [NSPredicate predicateWithFormat: + @"f1<2 && f2==3 && f1<='four' && f1>='five' && f1>6"]]; + FIRQuery *query7 = [query queryFilteredUsingPredicate: + [NSPredicate predicateWithFormat: + @"2>f1 && 3==f2 && 'four'>=f1 && 'five'<=f1 && 6