Skip to content

Commit c26b1d2

Browse files
authored
fix: Handle .all predicate for create/update (#1640)
1 parent a204ddb commit c26b1d2

File tree

5 files changed

+124
-3
lines changed

5 files changed

+124
-3
lines changed

AmplifyPlugins/DataStore/AWSDataStoreCategoryPlugin/Storage/SQLite/QueryPredicate+SQLite.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,13 @@ extension QueryOperator {
5050
}
5151
}
5252
}
53+
54+
extension QueryPredicate {
55+
var isAll: Bool {
56+
if let allPredicate = self as? QueryPredicateConstant, allPredicate == .all {
57+
return true
58+
} else {
59+
return false
60+
}
61+
}
62+
}

AmplifyPlugins/DataStore/AWSDataStoreCategoryPlugin/Storage/SQLite/StorageEngineAdapter+SQLite.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ final class SQLiteStorageEngineAdapter: StorageEngineAdapter {
128128
let modelExists = try exists(modelSchema, withId: model.id)
129129

130130
if !modelExists {
131-
if condition != nil {
131+
if let condition = condition, !condition.isAll {
132132
let dataStoreError = DataStoreError.invalidCondition(
133133
"Cannot apply a condition on model which does not exist.",
134134
"Save the model instance without a condition first.")
@@ -141,7 +141,7 @@ final class SQLiteStorageEngineAdapter: StorageEngineAdapter {
141141
}
142142

143143
if modelExists {
144-
if condition != nil {
144+
if let condition = condition, !condition.isAll {
145145
let modelExistsWithCondition = try exists(modelSchema, withId: model.id, predicate: condition)
146146
if !modelExistsWithCondition {
147147
let dataStoreError = DataStoreError.invalidCondition(

AmplifyPlugins/DataStore/AWSDataStoreCategoryPlugin/Storage/StorageEngine.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ final class StorageEngine: StorageEngineBehavior {
193193

194194
let mutationType = modelExists ? MutationEvent.MutationType.update : .create
195195

196-
if mutationType == .create && condition != nil {
196+
// If it is `create`, and there is a condition, and that condition is not `.all`, fail the request
197+
if mutationType == .create, let condition = condition, !condition.isAll {
197198
let dataStoreError = DataStoreError.invalidCondition(
198199
"Cannot apply a condition on model which does not exist.",
199200
"Save the model instance without a condition first.")

AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/Core/SQLiteStorageEngineAdapterTests.swift

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,45 @@ class SQLiteStorageEngineAdapterTests: BaseDataStoreTests {
5757
wait(for: [expectation], timeout: 5)
5858
}
5959

60+
/// - Given: a list a `Post` instance
61+
/// - When:
62+
/// - the `save(post, condition = .all)` is called
63+
/// - Then:
64+
/// - call `query(Post)` to check if the model was correctly inserted
65+
func testInsertPostWithAll() {
66+
let expectation = self.expectation(
67+
description: "it should save and select a Post from the database")
68+
69+
// insert a post
70+
let post = Post(title: "title", content: "content", createdAt: .now())
71+
storageAdapter.save(post, condition: QueryPredicateConstant.all) { saveResult in
72+
switch saveResult {
73+
case .success:
74+
self.storageAdapter.query(Post.self) { queryResult in
75+
switch queryResult {
76+
case .success(let posts):
77+
XCTAssert(posts.count == 1)
78+
if let savedPost = posts.first {
79+
XCTAssert(post.id == savedPost.id)
80+
XCTAssert(post.title == savedPost.title)
81+
XCTAssert(post.content == savedPost.content)
82+
XCTAssertEqual(post.createdAt.iso8601String, savedPost.createdAt.iso8601String)
83+
}
84+
expectation.fulfill()
85+
case .failure(let error):
86+
XCTFail(String(describing: error))
87+
expectation.fulfill()
88+
}
89+
}
90+
case .failure(let error):
91+
XCTFail(String(describing: error))
92+
expectation.fulfill()
93+
}
94+
}
95+
96+
wait(for: [expectation], timeout: 5)
97+
}
98+
6099
/// - Given: a list a `Post` instance
61100
/// - When:
62101
/// - the `save(post)` is called
@@ -198,6 +237,55 @@ class SQLiteStorageEngineAdapterTests: BaseDataStoreTests {
198237
wait(for: [expectation], timeout: 5)
199238
}
200239

240+
/// - Given: A Post instance
241+
/// - When:
242+
/// - The `save(post)` is called
243+
/// - Then:
244+
/// - call `update(post, condition = .all)` with `post.title` updated and condition `.all`
245+
/// - a successful update for `update(post, condition)`
246+
/// - call `query(Post)` to check if the model was correctly updated
247+
func testInsertPostAndThenUpdateItWithConditionAll() {
248+
let expectation = self.expectation(
249+
description: "it should insert and update a Post")
250+
251+
func checkSavedPost(id: String) {
252+
storageAdapter.query(Post.self) {
253+
switch $0 {
254+
case .success(let posts):
255+
XCTAssertEqual(posts.count, 1)
256+
if let post = posts.first {
257+
XCTAssertEqual(post.id, id)
258+
XCTAssertEqual(post.title, "title updated")
259+
}
260+
expectation.fulfill()
261+
case .failure(let error):
262+
XCTFail(String(describing: error))
263+
expectation.fulfill()
264+
}
265+
}
266+
}
267+
268+
var post = Post(title: "title", content: "content", createdAt: .now())
269+
storageAdapter.save(post) { insertResult in
270+
switch insertResult {
271+
case .success:
272+
post.title = "title updated"
273+
self.storageAdapter.save(post, condition: QueryPredicateConstant.all) { updateResult in
274+
switch updateResult {
275+
case .success:
276+
checkSavedPost(id: post.id)
277+
case .failure(let error):
278+
XCTFail(error.errorDescription)
279+
}
280+
}
281+
case .failure(let error):
282+
XCTFail(String(describing: error))
283+
}
284+
}
285+
286+
wait(for: [expectation], timeout: 5)
287+
}
288+
201289
/// - Given: A Post instance
202290
/// - When:
203291
/// - The `save(post, condition)` is called, condition is passed in.

AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/Storage/StorageEngineTestsHasOne.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,28 @@ class StorageEngineTestsHasOne: StorageEngineTestsBase {
4848
}
4949
}
5050

51+
func testSaveModelWithPredicateAll() {
52+
let team = Team(name: "Team")
53+
let saveFinished = expectation(description: "Save finished")
54+
var result: DataStoreResult<Team>?
55+
storageEngine.save(team, condition: QueryPredicateConstant.all) { sResult in
56+
result = sResult
57+
saveFinished.fulfill()
58+
}
59+
wait(for: [saveFinished], timeout: defaultTimeout)
60+
61+
guard let saveResult = result else {
62+
XCTFail("Save operation timed out")
63+
return
64+
}
65+
66+
guard case .success =
67+
querySingleModelSynchronous(modelType: Team.self, predicate: Team.keys.id == team.id) else {
68+
XCTFail("Failed to query Team")
69+
return
70+
}
71+
}
72+
5173
func testBelongsToRelationshipWithoutOwner() {
5274
let teamA = Team(name: "A-Team")
5375
let projectA = Project(name: "ProjectA", team: teamA)

0 commit comments

Comments
 (0)