Skip to content
This repository was archived by the owner on Aug 17, 2020. It is now read-only.
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
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ public final class BriteDatabaseTest {
db.createQuery(TABLE_EMPLOYEE, SELECT_EMPLOYEES) //
.mapToList(new Func1<Cursor, Employee>() {
private int count;

@Override public Employee call(Cursor cursor) {
return count++ == 2 ? null : Employee.MAPPER.call(cursor);
}
Expand Down Expand Up @@ -207,30 +208,38 @@ public final class BriteDatabaseTest {
}
}

@Test public void queryMapToOneOrNull() {
@Test public void queryMapToOneOrDefault() {
Employee employees = db.createQuery(TABLE_EMPLOYEE, SELECT_EMPLOYEES + " LIMIT 1")
.mapToOneOrNull(Employee.MAPPER)
.mapToOneOrDefault(Employee.MAPPER, null)
.toBlocking()
.first();
assertThat(employees).isEqualTo(new Employee("alice", "Alice Allison"));
}

@Test public void queryMapToOneOrNullEmpty() {
@Test public void queryMapToOneOrDefaultEmpty() {
Employee employees = db.createQuery(TABLE_EMPLOYEE, SELECT_EMPLOYEES + " WHERE 1=2")
.mapToOneOrNull(Employee.MAPPER)
.mapToOneOrDefault(Employee.MAPPER, new Employee("bob", "Bob Bobberson"))
.toBlocking()
.first();
assertThat(employees).isEqualTo(new Employee("bob", "Bob Bobberson"));
}

@Test public void queryMapToOneOrDefaultEmptyUsingNull() {
Employee employees = db.createQuery(TABLE_EMPLOYEE, SELECT_EMPLOYEES + " WHERE 1=2")
.mapToOneOrDefault(Employee.MAPPER, null)
.toBlocking()
.first();
assertThat(employees).isNull();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you duplicate this test and use a non-null default? Maybe rename this one to "EmptyUsingNull" or something.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

@Test public void queryMapToOneOrNullMapperReturnNullThrows() {
@Test public void queryMapToOneOrDefaultMapperReturnNullThrows() {
BlockingObservable<Employee> employees =
db.createQuery(TABLE_EMPLOYEE, SELECT_EMPLOYEES) //
.mapToOneOrNull(new Func1<Cursor, Employee>() {
.mapToOneOrDefault(new Func1<Cursor, Employee>() {
@Override public Employee call(Cursor cursor) {
return null;
}
}) //
}, null) //
.toBlocking();
try {
employees.first();
Expand All @@ -241,10 +250,10 @@ public final class BriteDatabaseTest {
}
}

@Test public void queryMapToOneOrNullMultipleRowsThrows() {
@Test public void queryMapToOneOrDefaultMultipleRowsThrows() {
BlockingObservable<Employee> employees =
db.createQuery(TABLE_EMPLOYEE, SELECT_EMPLOYEES + " LIMIT 2") //
.mapToOneOrNull(Employee.MAPPER) //
.mapToOneOrDefault(Employee.MAPPER, null) //
.toBlocking();
try {
employees.first();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public final class QueryObservable extends Observable<Query> {
*/
@CheckResult @NonNull
public final <T> Observable<T> mapToOne(@NonNull final Func1<Cursor, T> mapper) {
return lift(new QueryToOneOperator<>(mapper, false));
return lift(new QueryToOneOperator<>(mapper, false, null));
}

/**
Expand All @@ -45,18 +45,20 @@ public final <T> Observable<T> mapToOne(@NonNull final Func1<Cursor, T> mapper)
* <p>
* It is an error for a query to pass through this operator with more than 1 row in its result
* set. Use {@code LIMIT 1} on the underlying SQL query to prevent this. Result sets with 0 rows
* emit {@code null}.
* emit {@code defaultValue}.
* <p>
* This method is equivalent to:
* <pre>{@code
* flatMap(q -> q.asRows(mapper).take(1).defaultIfEmpty(null))
* flatMap(q -> q.asRows(mapper).take(1).defaultIfEmpty(defaultValue))
* }</pre>
*
* @param mapper Maps the current {@link Cursor} row to {@code T}. May not return null.
* @param defaultValue Value returned if result set is empty
*/
@CheckResult @NonNull
public final <T> Observable<T> mapToOneOrNull(@NonNull final Func1<Cursor, T> mapper) {
return lift(new QueryToOneOperator<>(mapper, true));
public final <T> Observable<T> mapToOneOrDefault(@NonNull final Func1<Cursor, T> mapper,
T defaultValue) {
return lift(new QueryToOneOperator<>(mapper, true, defaultValue));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@

final class QueryToOneOperator<T> implements Observable.Operator<T, SqlBrite.Query> {
private final Func1<Cursor, T> mapper;
private final boolean emitNull;
private boolean emitDefault;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You still need this boolean but it should probably be called emitDefault. null is a valid default value and right now there's no way to emit it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can still emit null by passing it to the mapToOneOrDefault method (null passed as a second argument). Eventually, there could be two methods mapToOneOrDefault and mapToOneOrNull as it was previously.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But then you break mapToOne which does not emit anything on empty.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. Fixed.

private T defaultValue;

QueryToOneOperator(Func1<Cursor, T> mapper, boolean emitNull) {
QueryToOneOperator(Func1<Cursor, T> mapper, boolean emitDefault, T defaultValue) {
this.mapper = mapper;
this.emitNull = emitNull;
this.emitDefault = emitDefault;
this.defaultValue = defaultValue;
}

@Override public Subscriber<? super SqlBrite.Query> call(final Subscriber<? super T> subscriber) {
Expand All @@ -35,8 +37,12 @@ final class QueryToOneOperator<T> implements Observable.Operator<T, SqlBrite.Que
} finally {
cursor.close();
}
if (!subscriber.isUnsubscribed() && (item != null || emitNull)) {
subscriber.onNext(item);
if (!subscriber.isUnsubscribed()) {
if (item != null) {
subscriber.onNext(item);
} else if (emitDefault) {
subscriber.onNext(defaultValue);
}
}
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
Expand Down