Skip to content

Commit e3f1bab

Browse files
authored
feat(datastore): support sorting by related models (#1141)
1 parent 00272bf commit e3f1bab

File tree

9 files changed

+93
-23
lines changed

9 files changed

+93
-23
lines changed

aws-datastore/src/androidTest/java/com/amplifyframework/datastore/storage/sqlite/SQLiteStorageAdapterQueryTest.java

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ public void querySavedDataWithPredicatesOnForeignKey() throws DataStoreException
301301

302302
final List<Blog> blogsOwnedByJaneDoe = adapter.query(
303303
Blog.class,
304-
Where.matches(field("BlogOwner.name").eq("Jane Doe"))
304+
Where.matches(BlogOwner.NAME.eq("Jane Doe"))
305305
);
306306
assertTrue(blogsOwnedByJaneDoe.contains(blog));
307307
}
@@ -417,6 +417,71 @@ public void queryWithOrderBy() throws DataStoreException {
417417
assertEquals(sorted, result);
418418
}
419419

420+
/**
421+
* Test query with order by. Validate that a list of Blog can be sorted by the names of BlogOwners.
422+
* @throws DataStoreException On failure to arrange items into store, or from the query action itself
423+
*/
424+
@Test
425+
public void queryWithOrderByRelatedModel() throws DataStoreException {
426+
// Expect: Create BlogOwners and their respective blogs
427+
List<String> names = Arrays.asList("Joe", "Bob", "Dan", "Jane");
428+
List<Blog> blogs = new ArrayList<>();
429+
430+
for (String name : names) {
431+
BlogOwner owner = BlogOwner.builder()
432+
.name(name)
433+
.build();
434+
adapter.save(owner);
435+
Blog blog = Blog.builder()
436+
.name("")
437+
.owner(owner)
438+
.build();
439+
adapter.save(blog);
440+
blogs.add(blog);
441+
}
442+
443+
// Act: Query Blogs sorted by owner's name
444+
List<Blog> result = adapter.query(Blog.class, Where.sorted(BlogOwner.NAME.ascending()));
445+
446+
// Verify: Query result is sorted by owner's name
447+
List<Blog> sorted = new ArrayList<>(blogs);
448+
Collections.sort(sorted, Comparator.comparing(blog -> blog.getOwner().getName()));
449+
assertEquals(sorted, result);
450+
}
451+
452+
/**
453+
* Test that new QueryField with explicit model name produces the same result as old QueryField.
454+
* @throws DataStoreException On failure to arrange items into store, or from the query action itself
455+
*/
456+
@Test
457+
public void queryFieldsAreBackwardsCompatible() throws DataStoreException {
458+
BlogOwner blogOwner = BlogOwner.builder().name("Test Dummy").build();
459+
adapter.save(blogOwner);
460+
Blog blog = Blog.builder().name("Blogging for Dummies").owner(blogOwner).build();
461+
adapter.save(blog);
462+
463+
final int numModels = 10;
464+
for (int counter = 0; counter < numModels; counter++) {
465+
final Post post = Post.builder()
466+
.title("title " + counter)
467+
.status(PostStatus.INACTIVE)
468+
.rating(counter)
469+
.blog(blog)
470+
.build();
471+
adapter.save(post);
472+
}
473+
474+
// Assert that using QueryField without model name yields same results if there is no column ambiguity
475+
assertEquals(
476+
adapter.query(Post.class, Where.matches(field("Post", "title").contains("4"))),
477+
adapter.query(Post.class, Where.matches(field("title").contains("4")))
478+
);
479+
assertEquals(
480+
adapter.query(Post.class, Where.matches(field("Post", "rating").gt(3))),
481+
adapter.query(Post.class, Where.matches(field("rating").gt(3)))
482+
);
483+
}
484+
420485
private void createBlogOwnerRecords(final int count) throws DataStoreException {
421486
for (int i = 0; i < count * 2; i++) {
422487
final BlogOwner blogOwner = BlogOwner.builder()

aws-datastore/src/main/java/com/amplifyframework/datastore/storage/sqlite/SQLiteCommandFactory.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,13 @@ public SqlCommand queryFor(@NonNull ModelSchema modelSchema,
220220
Iterator<QuerySortBy> sortByIterator = sortByList.iterator();
221221
while (sortByIterator.hasNext()) {
222222
final QuerySortBy sortBy = sortByIterator.next();
223-
SQLiteColumn column = table.getColumn(sortBy.getField());
224-
rawQuery.append(Wrap.inBackticks(column.getAliasedName()))
223+
String modelName = Wrap.inBackticks(sortBy.getModelName());
224+
String fieldName = Wrap.inBackticks(sortBy.getField());
225+
if (modelName == null) {
226+
modelName = Wrap.inBackticks(tableName);
227+
}
228+
final String columnName = modelName + "." + fieldName;
229+
rawQuery.append(columnName)
225230
.append(SqlKeyword.DELIMITER)
226231
.append(SqlKeyword.fromQuerySortOrder(sortBy.getSortOrder()));
227232

aws-datastore/src/test/java/com/amplifyframework/datastore/storage/sqlite/SqlCommandTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ public void queryWithSortBy() throws DataStoreException {
238238
);
239239
assertNotNull(sqlCommand);
240240
assertEquals(
241-
PERSON_BASE_QUERY + " ORDER BY `Person_lastName` ASC, `Person_firstName` DESC;",
241+
PERSON_BASE_QUERY + " ORDER BY `Person`.`lastName` ASC, `Person`.`firstName` DESC;",
242242
sqlCommand.sqlStatement()
243243
);
244244
assertEquals(0, sqlCommand.getBindings().size());

testmodels/src/main/java/com/amplifyframework/testmodels/commentsblog/Author.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
@SuppressWarnings("all")
2121
@ModelConfig(pluralName = "Authors")
2222
public final class Author implements Model {
23-
public static final QueryField ID = field("id");
24-
public static final QueryField NAME = field("name");
23+
public static final QueryField ID = field("Author", "id");
24+
public static final QueryField NAME = field("Author", "name");
2525
private final @ModelField(targetType="ID", isRequired = true) String id;
2626
private final @ModelField(targetType="String", isRequired = true) String name;
2727
private final @ModelField(targetType="PostAuthorJoin") @HasMany(associatedWith = "author", type = PostAuthorJoin.class) List<PostAuthorJoin> posts = null;

testmodels/src/main/java/com/amplifyframework/testmodels/commentsblog/Blog.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
@SuppressWarnings("all")
2222
@ModelConfig(pluralName = "Blogs")
2323
public final class Blog implements Model {
24-
public static final QueryField ID = field("id");
25-
public static final QueryField NAME = field("name");
26-
public static final QueryField OWNER = field("blogOwnerId");
24+
public static final QueryField ID = field("Blog", "id");
25+
public static final QueryField NAME = field("Blog", "name");
26+
public static final QueryField OWNER = field("Blog", "blogOwnerId");
2727
private final @ModelField(targetType="ID", isRequired = true) String id;
2828
private final @ModelField(targetType="String", isRequired = true) String name;
2929
private final @ModelField(targetType="Post") @HasMany(associatedWith = "blog", type = Post.class) List<Post> posts = null;

testmodels/src/main/java/com/amplifyframework/testmodels/commentsblog/BlogOwner.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
@SuppressWarnings("all")
1818
@ModelConfig(pluralName = "BlogOwners")
1919
public final class BlogOwner implements Model {
20-
public static final QueryField NAME = field("name");
21-
public static final QueryField ID = field("id");
22-
public static final QueryField WEA = field("wea");
20+
public static final QueryField NAME = field("BlogOwner", "name");
21+
public static final QueryField ID = field("BlogOwner", "id");
22+
public static final QueryField WEA = field("BlogOwner", "wea");
2323
private final @ModelField(targetType="String", isRequired = true) String name;
2424
private final @ModelField(targetType="ID", isRequired = true) String id;
2525
private final @ModelField(targetType="Blog") @HasOne(associatedWith = "owner", type = Blog.class) Blog blog = null;

testmodels/src/main/java/com/amplifyframework/testmodels/commentsblog/Comment.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
@SuppressWarnings("all")
2121
@ModelConfig(pluralName = "Comments")
2222
public final class Comment implements Model {
23-
public static final QueryField ID = field("id");
24-
public static final QueryField CONTENT = field("content");
25-
public static final QueryField POST = field("commentPostId");
23+
public static final QueryField ID = field("Comment", "id");
24+
public static final QueryField CONTENT = field("Comment", "content");
25+
public static final QueryField POST = field("Comment", "commentPostId");
2626
private final @ModelField(targetType="ID", isRequired = true) String id;
2727
private final @ModelField(targetType="String") String content;
2828
private final @ModelField(targetType="Post") @BelongsTo(targetName = "commentPostId", type = Post.class) Post post;

testmodels/src/main/java/com/amplifyframework/testmodels/commentsblog/Post.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
@SuppressWarnings("all")
2222
@ModelConfig(pluralName = "Posts")
2323
public final class Post implements Model {
24-
public static final QueryField ID = field("id");
25-
public static final QueryField TITLE = field("title");
26-
public static final QueryField BLOG = field("postBlogId");
27-
public static final QueryField STATUS = field("status");
28-
public static final QueryField RATING = field("rating");
24+
public static final QueryField ID = field("Post", "id");
25+
public static final QueryField TITLE = field("Post", "title");
26+
public static final QueryField BLOG = field("Post", "postBlogId");
27+
public static final QueryField STATUS = field("Post", "status");
28+
public static final QueryField RATING = field("Post", "rating");
2929
private final @ModelField(targetType="ID", isRequired = true) String id;
3030
private final @ModelField(targetType="String", isRequired = true) String title;
3131
private final @ModelField(targetType="Blog") @BelongsTo(targetName = "postBlogId", type = Blog.class) Blog blog;

testmodels/src/main/java/com/amplifyframework/testmodels/commentsblog/PostAuthorJoin.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
@Index(name = "byAuthor", fields = {"authorId"})
2323
@Index(name = "byPost", fields = {"postId"})
2424
public final class PostAuthorJoin implements Model {
25-
public static final QueryField ID = field("id");
26-
public static final QueryField AUTHOR = field("authorId");
27-
public static final QueryField POST = field("postId");
25+
public static final QueryField ID = field("PostAuthorJoin", "id");
26+
public static final QueryField AUTHOR = field("PostAuthorJoin", "authorId");
27+
public static final QueryField POST = field("PostAuthorJoin", "postId");
2828
private final @ModelField(targetType="ID", isRequired = true) String id;
2929
private final @ModelField(targetType="Author") @BelongsTo(targetName = "authorId", type = Author.class) Author author;
3030
private final @ModelField(targetType="Post") @BelongsTo(targetName = "postId", type = Post.class) Post post;

0 commit comments

Comments
 (0)