Skip to content

Commit 65bfd41

Browse files
cbaker6TomWFox
andauthored
Add modifiers to containsString, hasPrefix, hasSuffix (#85)
* fix changelog link and set codecov patch back to auto * Add modifiers to containsString, hasPrefix, hasSuffix * nits * Update CHANGELOG.md * Update CHANGELOG.md Co-authored-by: Tom Fox <[email protected]> Co-authored-by: Tom Fox <[email protected]>
1 parent 8bab749 commit 65bfd41

File tree

4 files changed

+114
-27
lines changed

4 files changed

+114
-27
lines changed

.codecov.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ coverage:
55
status:
66
patch:
77
default:
8-
target: 49
8+
target: auto
99
changes: false
1010
project:
1111
default:

CHANGELOG.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22

33
### main
44
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.1.6...main)
5-
* _Contributing to this repo? Add info about your change here to be included in next release_
5+
* _Contributing to this repo? Add info about your change here to be included in the next release_
6+
7+
__New features__
8+
- Add modifiers to containsString, hasPrefix, hasSuffix ([#85](https://github.com/parse-community/Parse-Swift/pull/85)), thanks to [Corey Baker](https://github.com/cbaker6).
69

710
### 1.1.6
811
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.1.5...1.1.6)
912

1013
__Fixes__
11-
- Send correct SDK version number to Parse Server ([#82](https://github.com/parse-community/Parse-Swift/pull/82)), thanks to [Corey Baker](https://github.com/cbaker6).
14+
- Send correct SDK version number to Parse Server ([#84](https://github.com/parse-community/Parse-Swift/pull/84)), thanks to [Corey Baker](https://github.com/cbaker6).
1215

1316
### 1.1.5
1417
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.1.4...1.1.5)

Sources/ParseSwift/Types/Query.swift

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -410,28 +410,22 @@ public func matchesText(key: String, text: String) -> QueryConstraint {
410410
- warning: This may be slow for large datasets.
411411
- parameter key: The key that the string to match is stored in.
412412
- parameter regex: The regular expression pattern to match.
413-
- returns: The same instance of `Query` as the receiver.
414-
*/
415-
public func matchesRegex(key: String, regex: String) -> QueryConstraint {
416-
.init(key: key, value: regex, comparator: .regex)
417-
}
418-
419-
/**
420-
Add a regular expression constraint for finding string values that match the provided regular expression.
421-
- warning: This may be slow for large datasets.
422-
- parameter key: The key that the string to match is stored in.
423-
- parameter regex: The regular expression pattern to match.
424-
- parameter modifiers: Any of the following supported PCRE modifiers:
413+
- parameter modifiers: Any of the following supported PCRE modifiers (defaults to nil):
425414
- `i` - Case insensitive search
426415
- `m` - Search across multiple lines of input
427416
- returns: The same instance of `Query` as the receiver.
428417
*/
429-
public func matchesRegex(key: String, regex: String, modifiers: String) -> QueryConstraint {
430-
let dictionary = [
431-
QueryConstraint.Comparator.regex.rawValue: regex,
432-
QueryConstraint.Comparator.regexOptions.rawValue: modifiers
433-
]
434-
return .init(key: key, value: dictionary)
418+
public func matchesRegex(key: String, regex: String, modifiers: String? = nil) -> QueryConstraint {
419+
420+
if let modifiers = modifiers {
421+
let dictionary = [
422+
QueryConstraint.Comparator.regex.rawValue: regex,
423+
QueryConstraint.Comparator.regexOptions.rawValue: modifiers
424+
]
425+
return .init(key: key, value: dictionary)
426+
} else {
427+
return .init(key: key, value: regex, comparator: .regex)
428+
}
435429
}
436430

437431
private func regexStringForString(_ inputString: String) -> String {
@@ -444,35 +438,44 @@ private func regexStringForString(_ inputString: String) -> String {
444438
- warning: This will be slow for large datasets.
445439
- parameter key: The key that the string to match is stored in.
446440
- parameter substring: The substring that the value must contain.
441+
- parameter modifiers: Any of the following supported PCRE modifiers (defaults to nil):
442+
- `i` - Case insensitive search
443+
- `m` - Search across multiple lines of input
447444
- returns: The same instance of `Query` as the receiver.
448445
*/
449-
public func containsString(key: String, substring: String) -> QueryConstraint {
446+
public func containsString(key: String, substring: String, modifiers: String? = nil) -> QueryConstraint {
450447
let regex = regexStringForString(substring)
451-
return matchesRegex(key: key, regex: regex)
448+
return matchesRegex(key: key, regex: regex, modifiers: modifiers)
452449
}
453450

454451
/**
455452
Add a constraint for finding string values that start with a provided prefix.
456453
This will use smart indexing, so it will be fast for large datasets.
457454
- parameter key: The key that the string to match is stored in.
458455
- parameter prefix: The substring that the value must start with.
456+
- parameter modifiers: Any of the following supported PCRE modifiers (defaults to nil):
457+
- `i` - Case insensitive search
458+
- `m` - Search across multiple lines of input
459459
- returns: The same instance of `Query` as the receiver.
460460
*/
461-
public func hasPrefix(key: String, prefix: String) -> QueryConstraint {
461+
public func hasPrefix(key: String, prefix: String, modifiers: String? = nil) -> QueryConstraint {
462462
let regex = "^\(regexStringForString(prefix))"
463-
return matchesRegex(key: key, regex: regex)
463+
return matchesRegex(key: key, regex: regex, modifiers: modifiers)
464464
}
465465

466466
/**
467467
Add a constraint for finding string values that end with a provided suffix.
468468
- warning: This will be slow for large datasets.
469469
- parameter key: The key that the string to match is stored in.
470470
- parameter suffix: The substring that the value must end with.
471+
- parameter modifiers: Any of the following supported PCRE modifiers (defaults to nil):
472+
- `i` - Case insensitive search
473+
- `m` - Search across multiple lines of input
471474
- returns: The same instance of `Query` as the receiver.
472475
*/
473-
public func hasSuffix(key: String, suffix: String) -> QueryConstraint {
476+
public func hasSuffix(key: String, suffix: String, modifiers: String? = nil) -> QueryConstraint {
474477
let regex = "\(regexStringForString(suffix))$"
475-
return matchesRegex(key: key, regex: regex)
478+
return matchesRegex(key: key, regex: regex, modifiers: modifiers)
476479
}
477480

478481
/**

Tests/ParseSwiftTests/ParseQueryTests.swift

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,33 @@ class ParseQueryTests: XCTestCase { // swiftlint:disable:this type_body_length
895895
}
896896
}
897897

898+
func testWhereKeyContainsStringModifier() {
899+
let expected: [String: AnyCodable] = [
900+
"yolo": ["$regex": "\\Qyarr\\E",
901+
"$options": "i"]
902+
]
903+
let constraint = containsString(key: "yolo", substring: "yarr", modifiers: "i")
904+
let query = GameScore.query(constraint)
905+
let queryWhere = query.`where`
906+
907+
do {
908+
let encoded = try ParseCoding.jsonEncoder().encode(queryWhere)
909+
let decodedDictionary = try JSONDecoder().decode([String: AnyCodable].self, from: encoded)
910+
XCTAssertEqual(expected.keys, decodedDictionary.keys)
911+
912+
guard let expectedValues = expected.values.first?.value as? [String: String],
913+
let decodedValues = decodedDictionary.values.first?.value as? [String: String] else {
914+
XCTFail("Should have casted")
915+
return
916+
}
917+
XCTAssertEqual(expectedValues, decodedValues)
918+
919+
} catch {
920+
XCTFail(error.localizedDescription)
921+
return
922+
}
923+
}
924+
898925
func testWhereKeyHasPrefix() {
899926
let expected: [String: AnyCodable] = [
900927
"yolo": ["$regex": "^\\Qyarr\\E"]
@@ -921,6 +948,33 @@ class ParseQueryTests: XCTestCase { // swiftlint:disable:this type_body_length
921948
}
922949
}
923950

951+
func testWhereKeyHasPrefixModifier() {
952+
let expected: [String: AnyCodable] = [
953+
"yolo": ["$regex": "^\\Qyarr\\E",
954+
"$options": "i"]
955+
]
956+
let constraint = hasPrefix(key: "yolo", prefix: "yarr", modifiers: "i")
957+
let query = GameScore.query(constraint)
958+
let queryWhere = query.`where`
959+
960+
do {
961+
let encoded = try ParseCoding.jsonEncoder().encode(queryWhere)
962+
let decodedDictionary = try JSONDecoder().decode([String: AnyCodable].self, from: encoded)
963+
XCTAssertEqual(expected.keys, decodedDictionary.keys)
964+
965+
guard let expectedValues = expected.values.first?.value as? [String: String],
966+
let decodedValues = decodedDictionary.values.first?.value as? [String: String] else {
967+
XCTFail("Should have casted")
968+
return
969+
}
970+
XCTAssertEqual(expectedValues, decodedValues)
971+
972+
} catch {
973+
XCTFail(error.localizedDescription)
974+
return
975+
}
976+
}
977+
924978
func testWhereKeyHasSuffix() {
925979
let expected: [String: AnyCodable] = [
926980
"yolo": ["$regex": "\\Qyarr\\E$"]
@@ -947,6 +1001,33 @@ class ParseQueryTests: XCTestCase { // swiftlint:disable:this type_body_length
9471001
}
9481002
}
9491003

1004+
func testWhereKeyHasSuffixModifier() {
1005+
let expected: [String: AnyCodable] = [
1006+
"yolo": ["$regex": "\\Qyarr\\E$",
1007+
"$options": "i"]
1008+
]
1009+
let constraint = hasSuffix(key: "yolo", suffix: "yarr", modifiers: "i")
1010+
let query = GameScore.query(constraint)
1011+
let queryWhere = query.`where`
1012+
1013+
do {
1014+
let encoded = try ParseCoding.jsonEncoder().encode(queryWhere)
1015+
let decodedDictionary = try JSONDecoder().decode([String: AnyCodable].self, from: encoded)
1016+
XCTAssertEqual(expected.keys, decodedDictionary.keys)
1017+
1018+
guard let expectedValues = expected.values.first?.value as? [String: String],
1019+
let decodedValues = decodedDictionary.values.first?.value as? [String: String] else {
1020+
XCTFail("Should have casted")
1021+
return
1022+
}
1023+
XCTAssertEqual(expectedValues, decodedValues)
1024+
1025+
} catch {
1026+
XCTFail(error.localizedDescription)
1027+
return
1028+
}
1029+
}
1030+
9501031
func testOrQuery() {
9511032
let expected: [String: AnyCodable] = [
9521033
"$or": [

0 commit comments

Comments
 (0)