Skip to content

feat: adds equalTo QueryConstraint along which uses $eq #310

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jan 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/2.5.1...3.0.0)

__New features__
- Adds equalTo QueryConstraint along with ability to change the SDK default behavior of using $eq QueryConstraint parameter or not ([#310](https://github.com/parse-community/Parse-Swift/pull/310)), thanks to [Corey Baker](https://github.com/cbaker6).
- Adds isNull and isNotNull QueryConstraint along with the ability set/forceSet null using ParseOperation ([#308](https://github.com/parse-community/Parse-Swift/pull/308)), thanks to [Corey Baker](https://github.com/cbaker6).
- Adds auth support for GitHub, Google, and LinkedIn ([#307](https://github.com/parse-community/Parse-Swift/pull/307)), thanks to [Corey Baker](https://github.com/cbaker6).
- (Breaking Change) Adds options to matchesText QueryConstraint along with the ability to see matching score. The compiler should recommend the new score property to all ParseObjects ([#306](https://github.com/parse-community/Parse-Swift/pull/306)), thanks to [Corey Baker](https://github.com/cbaker6).
- Adds withCount query ([#306](https://github.com/parse-community/Parse-Swift/pull/306)), thanks to [Corey Baker](https://github.com/cbaker6).
- Adds auth support for GitHub, Google, and LinkedIn ([#307](https://github.com/parse-community/Parse-Swift/pull/307)), thanks to [Corey Baker](https://github.com/cbaker6).
- Adds isNull QueryConstraint along with the ability set/forceSet null using ParseOperation ([#308](https://github.com/parse-community/Parse-Swift/pull/308)), thanks to [Corey Baker](https://github.com/cbaker6).

__Improvements__
- (Breaking Change) Change boolean configuration parameters to match Swift conventions. The compilor should help with name changes ([#311](https://github.com/parse-community/Parse-Swift/pull/311)), thanks to [Corey Baker](https://github.com/cbaker6).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ do {
print(error)
}

//: Query all scores whose is null or undefined.
let query1 = GameScore.query(notNull(key: "name"))
//: Query all scores whose name is null or undefined.
let query1 = GameScore.query(isNotNull(key: "name"))
let results1 = try query1.find()
print("Total found: \(results1.count)")
results1.forEach { score in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ query4.find { results in
}
}

//: Get the same results as the previous query whose location is not null or undefined.
var anotherQuery4 = GameScore.query("points" > 9, notNull(key: "location"))
//: If you want to query for points > 9 and whose location is not null or undefined.
var anotherQuery4 = GameScore.query("points" > 9, isNotNull(key: "location"))
anotherQuery4.find { results in
switch results {
case .success(let scores):
Expand Down
16 changes: 9 additions & 7 deletions ParseSwift.playground/Sources/Common.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ import ParseSwift

public func initializeParse() {
ParseSwift.initialize(applicationId: "applicationId",
clientKey: "clientKey",
masterKey: "masterKey",
serverURL: URL(string: "http://localhost:1337/1")!,
isUsingTransactions: false)
clientKey: "clientKey",
masterKey: "masterKey",
serverURL: URL(string: "http://localhost:1337/1")!,
isUsingTransactions: false,
isUsingEqualQueryConstraint: false)
}

public func initializeParseCustomObjectId() {
ParseSwift.initialize(applicationId: "applicationId",
clientKey: "clientKey",
serverURL: URL(string: "http://localhost:1337/1")!,
isAllowingCustomObjectIds: true)
clientKey: "clientKey",
serverURL: URL(string: "http://localhost:1337/1")!,
isAllowingCustomObjectIds: true,
isUsingEqualQueryConstraint: false)
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ let package = Package(
Then run `swift build`.

You can also install using SPM in your Xcode project by going to
"Project->NameOfYourProject->Swift Packages" and placing "https://github.com/parse-community/Parse-Swift.git" in the
"Project->NameOfYourProject->Swift Packages" and placing `https://github.com/parse-community/Parse-Swift.git` in the
search field.

### [CocoaPods](https://cocoapods.org)
Expand Down
13 changes: 13 additions & 0 deletions Sources/ParseSwift/Parse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ public struct ParseConfiguration {
/// - warning: This is experimental.
public internal(set) var isUsingTransactions = false

/// Use the **$eq** query constraint when querying.
/// - warning: This is known not to work for LiveQuery on Parse Servers <= 5.0.0.
public internal(set) var isUsingEqualQueryConstraint = false

/// The default caching policy for all http requests that determines when to
/// return a response from the cache. Defaults to `useProtocolCachePolicy`.
/// See Apple's [documentation](https://developer.apple.com/documentation/foundation/url_loading_system/accessing_cached_data)
Expand Down Expand Up @@ -76,6 +80,7 @@ public struct ParseConfiguration {
- parameter isAllowingCustomObjectIds: Allows objectIds to be created on the client.
side for each object. Must be enabled on the server to work.
- parameter isUsingTransactions: Use transactions when saving/updating multiple objects.
- parameter isUsingEqualQueryConstraint: Use the **$eq** query constraint when querying.
- parameter keyValueStore: A key/value store that conforms to the `ParseKeyValueStore`
protocol. Defaults to `nil` in which one will be created an memory, but never persisted. For Linux, this
this is the only store available since there is no Keychain. Linux users should replace this store with an
Expand Down Expand Up @@ -106,8 +111,10 @@ public struct ParseConfiguration {
masterKey: String? = nil,
serverURL: URL,
liveQueryServerURL: URL? = nil,
allowCustomObjectId: Bool = false,
isAllowingCustomObjectIds: Bool = false,
isUsingTransactions: Bool = false,
isUsingEqualQueryConstraint: Bool = false,
keyValueStore: ParseKeyValueStore? = nil,
requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy,
cacheMemoryCapacity: Int = 512_000,
Expand All @@ -126,6 +133,7 @@ public struct ParseConfiguration {
self.liveQuerysServerURL = liveQueryServerURL
self.isAllowingCustomObjectIds = isAllowingCustomObjectIds
self.isUsingTransactions = isUsingTransactions
self.isUsingEqualQueryConstraint = isUsingEqualQueryConstraint
self.mountPath = "/" + serverURL.pathComponents
.filter { $0 != "/" }
.joined(separator: "/")
Expand Down Expand Up @@ -237,6 +245,7 @@ public struct ParseSwift {
- parameter isAllowingCustomObjectIds: Allows objectIds to be created on the client.
side for each object. Must be enabled on the server to work.
- parameter isUsingTransactions: Use transactions when saving/updating multiple objects.
- parameter isUsingEqualQueryConstraint: Use the **$eq** query constraint when querying.
- parameter keyValueStore: A key/value store that conforms to the `ParseKeyValueStore`
protocol. Defaults to `nil` in which one will be created an memory, but never persisted. For Linux, this
this is the only store available since there is no Keychain. Linux users should replace this store with an
Expand Down Expand Up @@ -268,6 +277,7 @@ public struct ParseSwift {
liveQueryServerURL: URL? = nil,
isAllowingCustomObjectIds: Bool = false,
isUsingTransactions: Bool = false,
isUsingEqualQueryConstraint: Bool = false,
keyValueStore: ParseKeyValueStore? = nil,
requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy,
cacheMemoryCapacity: Int = 512_000,
Expand All @@ -287,6 +297,7 @@ public struct ParseSwift {
liveQueryServerURL: liveQueryServerURL,
isAllowingCustomObjectIds: isAllowingCustomObjectIds,
isUsingTransactions: isUsingTransactions,
isUsingEqualQueryConstraint: isUsingEqualQueryConstraint,
keyValueStore: keyValueStore,
requestCachePolicy: requestCachePolicy,
cacheMemoryCapacity: cacheMemoryCapacity,
Expand All @@ -305,6 +316,7 @@ public struct ParseSwift {
liveQueryServerURL: URL? = nil,
isAllowingCustomObjectIds: Bool = false,
isUsingTransactions: Bool = false,
isUsingEqualQueryConstraint: Bool = false,
keyValueStore: ParseKeyValueStore? = nil,
requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy,
cacheMemoryCapacity: Int = 512_000,
Expand All @@ -324,6 +336,7 @@ public struct ParseSwift {
liveQueryServerURL: liveQueryServerURL,
isAllowingCustomObjectIds: isAllowingCustomObjectIds,
isUsingTransactions: isUsingTransactions,
isUsingEqualQueryConstraint: isUsingEqualQueryConstraint,
keyValueStore: keyValueStore,
requestCachePolicy: requestCachePolicy,
cacheMemoryCapacity: cacheMemoryCapacity,
Expand Down
62 changes: 59 additions & 3 deletions Sources/ParseSwift/Types/QueryConstraint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public struct QueryConstraint: Encodable, Hashable {
case lessThanOrEqualTo = "$lte"
case greaterThan = "$gt"
case greaterThanOrEqualTo = "$gte"
case equalTo = "$eq"
case notEqualTo = "$ne"
case containedIn = "$in"
case notContainedIn = "$nin"
Expand Down Expand Up @@ -136,9 +137,36 @@ public func <= <T>(key: String, value: T) -> QueryConstraint where T: Encodable
- parameter key: The key that the value is stored in.
- parameter value: The value to compare.
- returns: The same instance of `QueryConstraint` as the receiver.
- warning: See `equalTo` for more information.
Behavior changes based on `ParseSwift.configuration.isUsingEqualQueryConstraint`
where isUsingEqualQueryConstraint == true is known not to work for LiveQuery on
Parse Servers <= 5.0.0.
*/
public func == <T>(key: String, value: T) -> QueryConstraint where T: Encodable {
QueryConstraint(key: key, value: value)
equalTo(key: key, value: value)
}

/**
Add a constraint that requires that a key is equal to a value.
- parameter key: The key that the value is stored in.
- parameter value: The value to compare.
- parameter isUsingEQ: Set to **true** to use **$eq** comparater,
allowing for multiple `QueryConstraint`'s to be used on a single **key**.
Setting to *false* may override any `QueryConstraint`'s on the same **key**.
Defaults to `ParseSwift.configuration.isUsingEqualQueryConstraint`.
- returns: The same instance of `QueryConstraint` as the receiver.
- warning: `isUsingEQ == true` is known not to work for LiveQueries
on Parse Servers <= 5.0.0.
*/
public func equalTo <T>(key: String,
value: T,
//swiftlint:disable:next line_length
isUsingEQ: Bool = ParseSwift.configuration.isUsingEqualQueryConstraint) -> QueryConstraint where T: Encodable {
if !isUsingEQ {
return QueryConstraint(key: key, value: value)
} else {
return QueryConstraint(key: key, value: value, comparator: .equalTo)
}
}

/**
Expand All @@ -147,9 +175,37 @@ public func == <T>(key: String, value: T) -> QueryConstraint where T: Encodable
- parameter value: The `ParseObject` to compare.
- returns: The same instance of `QueryConstraint` as the receiver.
- throws: An error of type `ParseError`.
- warning: See `equalTo` for more information.
Behavior changes based on `ParseSwift.configuration.isUsingEqualQueryConstraint`
where isUsingEqualQueryConstraint == true is known not to work for LiveQuery on
Parse Servers <= 5.0.0.
*/
public func == <T>(key: String, value: T) throws -> QueryConstraint where T: ParseObject {
try QueryConstraint(key: key, value: value.toPointer())
try equalTo(key: key, value: value)
}

/**
Add a constraint that requires that a key is equal to a `ParseObject`.
- parameter key: The key that the value is stored in.
- parameter value: The `ParseObject` to compare.
- parameter isUsingEQ: Set to **true** to use **$eq** comparater,
allowing for multiple `QueryConstraint`'s to be used on a single **key**.
Setting to *false* may override any `QueryConstraint`'s on the same **key**.
Defaults to `ParseSwift.configuration.isUsingEqualQueryConstraint`.
- returns: The same instance of `QueryConstraint` as the receiver.
- throws: An error of type `ParseError`.
- warning: `isUsingEQ == true` is known not to work for LiveQueries
on Parse Servers <= 5.0.0.
*/
public func equalTo <T>(key: String,
value: T,
//swiftlint:disable:next line_length
isUsingEQ: Bool = ParseSwift.configuration.isUsingEqualQueryConstraint) throws -> QueryConstraint where T: ParseObject {
if !isUsingEQ {
return try QueryConstraint(key: key, value: value.toPointer())
} else {
return try QueryConstraint(key: key, value: value.toPointer(), comparator: .equalTo)
}
}

/**
Expand Down Expand Up @@ -703,7 +759,7 @@ public func isNull (key: String) -> QueryConstraint {
- parameter key: The key that the value is stored in.
- returns: The same instance of `QueryConstraint` as the receiver.
*/
public func notNull (key: String) -> QueryConstraint {
public func isNotNull (key: String) -> QueryConstraint {
QueryConstraint(key: key, comparator: .notEqualTo, isNull: true)
}

Expand Down
20 changes: 19 additions & 1 deletion Tests/ParseSwiftTests/ParseQueryTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class ParseQueryTests: XCTestCase { // swiftlint:disable:this type_body_length
clientKey: "clientKey",
masterKey: "masterKey",
serverURL: url,
isUsingEqualQueryConstraint: false,
isTesting: true)
}

Expand Down Expand Up @@ -1186,6 +1187,14 @@ class ParseQueryTests: XCTestCase { // swiftlint:disable:this type_body_length
XCTAssertEqual(query.description, expected)
}

func testWhereKeyEqualToBoolEQ() throws {
let query = GameScore.query(equalTo(key: "isCounts", value: true, isUsingEQ: true))
// swiftlint:disable:next line_length
let expected = "GameScore ({\"limit\":100,\"skip\":0,\"_method\":\"GET\",\"where\":{\"isCounts\":{\"$eq\":true}}})"
XCTAssertEqual(query.debugDescription, expected)
XCTAssertEqual(query.description, expected)
}

func testWhereKeyEqualToParseObject() throws {
var compareObject = GameScore(points: 11)
compareObject.objectId = "hello"
Expand All @@ -1195,6 +1204,15 @@ class ParseQueryTests: XCTestCase { // swiftlint:disable:this type_body_length
XCTAssertEqual(query.debugDescription, expected)
}

func testWhereKeyEqualToParseObjectEQ() throws {
var compareObject = GameScore(points: 11)
compareObject.objectId = "hello"
let query = try GameScore.query(equalTo(key: "yolo", value: compareObject, isUsingEQ: true))
// swiftlint:disable:next line_length
let expected = "GameScore ({\"limit\":100,\"skip\":0,\"_method\":\"GET\",\"where\":{\"yolo\":{\"$eq\":{\"__type\":\"Pointer\",\"className\":\"GameScore\",\"objectId\":\"hello\"}}}})"
XCTAssertEqual(query.debugDescription, expected)
}

func testWhereKeyEqualToParseObjectDuplicateConstraint() throws {
var compareObject = GameScore(points: 11)
compareObject.objectId = "hello"
Expand Down Expand Up @@ -1235,7 +1253,7 @@ class ParseQueryTests: XCTestCase { // swiftlint:disable:this type_body_length
func testWhereKeyNotNull() throws {
var compareObject = GameScore(points: 11)
compareObject.objectId = "hello"
let query = GameScore.query(notNull(key: "yolo"))
let query = GameScore.query(isNotNull(key: "yolo"))
let expected = "GameScore ({\"limit\":100,\"skip\":0,\"_method\":\"GET\",\"where\":{\"yolo\":{\"$ne\":null}}})"
XCTAssertEqual(query.debugDescription, expected)
}
Expand Down