use of com.pushtorefresh.storio.sqlite.StorIOSQLite in project storio by pushtorefresh.
the class PreparedDeleteCollectionOfObjects method executeAsBlocking.
/**
* Executes Delete Operation immediately in current thread.
* <p>
* Notice: This is blocking I/O operation that should not be executed on the Main Thread,
* it can cause ANR (Activity Not Responding dialog), block the UI and drop animations frames.
* So please, call this method on some background thread. See {@link WorkerThread}.
*
* @return non-null results of Delete Operation.
*/
@SuppressWarnings("unchecked")
@WorkerThread
@NonNull
@Override
public DeleteResults<T> executeAsBlocking() {
try {
final StorIOSQLite.LowLevel lowLevel = storIOSQLite.lowLevel();
// Nullable
final List<SimpleImmutableEntry<T, DeleteResolver<T>>> objectsAndDeleteResolvers;
if (explicitDeleteResolver != null) {
objectsAndDeleteResolvers = null;
} else {
objectsAndDeleteResolvers = new ArrayList<SimpleImmutableEntry<T, DeleteResolver<T>>>(objects.size());
for (final T object : objects) {
final SQLiteTypeMapping<T> typeMapping = (SQLiteTypeMapping<T>) lowLevel.typeMapping(object.getClass());
if (typeMapping == null) {
throw new IllegalStateException("One of the objects from the collection does not have type mapping: " + "object = " + object + ", object.class = " + object.getClass() + "," + "db was not affected by this operation, please add type mapping for this type");
}
objectsAndDeleteResolvers.add(new SimpleImmutableEntry<T, DeleteResolver<T>>(object, typeMapping.deleteResolver()));
}
}
if (useTransaction) {
lowLevel.beginTransaction();
}
final Map<T, DeleteResult> results = new HashMap<T, DeleteResult>(objects.size());
boolean transactionSuccessful = false;
try {
if (explicitDeleteResolver != null) {
for (final T object : objects) {
final DeleteResult deleteResult = explicitDeleteResolver.performDelete(storIOSQLite, object);
results.put(object, deleteResult);
if (!useTransaction && deleteResult.numberOfRowsDeleted() > 0) {
lowLevel.notifyAboutChanges(Changes.newInstance(deleteResult.affectedTables()));
}
}
} else {
for (final SimpleImmutableEntry<T, DeleteResolver<T>> objectAndDeleteResolver : objectsAndDeleteResolvers) {
final T object = objectAndDeleteResolver.getKey();
final DeleteResolver<T> deleteResolver = objectAndDeleteResolver.getValue();
final DeleteResult deleteResult = deleteResolver.performDelete(storIOSQLite, object);
results.put(object, deleteResult);
if (!useTransaction && deleteResult.numberOfRowsDeleted() > 0) {
lowLevel.notifyAboutChanges(Changes.newInstance(deleteResult.affectedTables()));
}
}
}
if (useTransaction) {
lowLevel.setTransactionSuccessful();
transactionSuccessful = true;
}
} finally {
if (useTransaction) {
lowLevel.endTransaction();
// if delete was in transaction and it was successful -> notify about changes
if (transactionSuccessful) {
// in most cases it will be one table
final Set<String> affectedTables = new HashSet<String>(1);
for (final T object : results.keySet()) {
final DeleteResult deleteResult = results.get(object);
if (deleteResult.numberOfRowsDeleted() > 0) {
affectedTables.addAll(results.get(object).affectedTables());
}
}
// It'll reduce number of possible deadlock situations
if (!affectedTables.isEmpty()) {
lowLevel.notifyAboutChanges(Changes.newInstance(affectedTables));
}
}
}
}
return DeleteResults.newInstance(results);
} catch (Exception exception) {
throw new StorIOException("Error has occurred during Delete operation. objects = " + objects, exception);
}
}
use of com.pushtorefresh.storio.sqlite.StorIOSQLite in project storio by pushtorefresh.
the class PreparedGetNumberOfResultsTest method shouldWrapExceptionIntoStorIOExceptionForObservable.
@Test
public void shouldWrapExceptionIntoStorIOExceptionForObservable() {
final StorIOSQLite storIOSQLite = mock(StorIOSQLite.class);
when(storIOSQLite.observeChangesInTables(eq(singleton("test_table")))).thenReturn(Observable.<Changes>empty());
//noinspection unchecked
final GetResolver<Integer> getResolver = mock(GetResolver.class);
when(getResolver.performGet(eq(storIOSQLite), any(Query.class))).thenThrow(new IllegalStateException("test exception"));
final TestSubscriber<Integer> testSubscriber = new TestSubscriber<Integer>();
new PreparedGetNumberOfResults.Builder(storIOSQLite).withQuery(Query.builder().table("test_table").build()).withGetResolver(getResolver).prepare().asRxObservable().subscribe(testSubscriber);
testSubscriber.awaitTerminalEvent(60, SECONDS);
testSubscriber.assertError(StorIOException.class);
assertThat(testSubscriber.getOnErrorEvents()).hasSize(1);
StorIOException storIOException = (StorIOException) testSubscriber.getOnErrorEvents().get(0);
IllegalStateException cause = (IllegalStateException) storIOException.getCause();
assertThat(cause).hasMessage("test exception");
testSubscriber.unsubscribe();
}
use of com.pushtorefresh.storio.sqlite.StorIOSQLite in project storio by pushtorefresh.
the class PreparedGetNumberOfResultsTest method shouldWrapExceptionIntoStorIOExceptionForBlocking.
@Test
public void shouldWrapExceptionIntoStorIOExceptionForBlocking() {
final StorIOSQLite storIOSQLite = mock(StorIOSQLite.class);
//noinspection unchecked
final GetResolver<Integer> getResolver = mock(GetResolver.class);
when(getResolver.performGet(eq(storIOSQLite), any(Query.class))).thenThrow(new IllegalStateException("test exception"));
try {
new PreparedGetNumberOfResults.Builder(storIOSQLite).withQuery(Query.builder().table("test_table").build()).withGetResolver(getResolver).prepare().executeAsBlocking();
failBecauseExceptionWasNotThrown(StorIOException.class);
} catch (StorIOException expected) {
IllegalStateException cause = (IllegalStateException) expected.getCause();
assertThat(cause).hasMessage("test exception");
}
}
use of com.pushtorefresh.storio.sqlite.StorIOSQLite in project storio by pushtorefresh.
the class DefaultPutResolverTest method update.
/**
* Verifies behavior of {@link DefaultPutResolver} for "update"
*/
@Test
public void update() {
final StorIOSQLite storIOSQLite = mock(StorIOSQLite.class);
final StorIOSQLite.Internal internal = mock(StorIOSQLite.Internal.class);
// item with some id, should be updated
final TestItem testItem = new TestItem(null);
when(storIOSQLite.lowLevel()).thenReturn(internal);
final Query expectedQuery = Query.builder().table(TestItem.TABLE).where(TestItem.COLUMN_ID + " = ?").whereArgs(testItem.getId()).build();
final Cursor cursor = mock(Cursor.class);
when(internal.query(eq(expectedQuery))).thenReturn(cursor);
when(cursor.getCount()).thenReturn(// Some rows already in db -> update should be performed
1);
final Integer expectedNumberOfRowsUpdated = 1;
when(internal.update(any(UpdateQuery.class), any(ContentValues.class))).thenReturn(expectedNumberOfRowsUpdated);
final UpdateQuery expectedUpdateQuery = UpdateQuery.builder().table(TestItem.TABLE).where(TestItem.COLUMN_ID + " = ?").whereArgs(testItem.getId()).build();
final PutResolver<TestItem> putResolver = new DefaultPutResolver<TestItem>() {
@NonNull
@Override
protected InsertQuery mapToInsertQuery(@NonNull TestItem object) {
fail("Should not be called");
return null;
}
@NonNull
@Override
protected UpdateQuery mapToUpdateQuery(@NonNull TestItem object) {
return UpdateQuery.builder().table(TestItem.TABLE).where(TestItem.COLUMN_ID + " = ?").whereArgs(object.getId()).build();
}
@NonNull
@Override
protected ContentValues mapToContentValues(@NonNull TestItem object) {
return TestItem.MAP_TO_CONTENT_VALUES.call(object);
}
};
final ContentValues expectedContentValues = TestItem.MAP_TO_CONTENT_VALUES.call(testItem);
// Performing Put that should "update"
final PutResult putResult = putResolver.performPut(storIOSQLite, testItem);
verify(internal, times(1)).beginTransaction();
verify(internal, times(1)).setTransactionSuccessful();
verify(internal, times(1)).endTransaction();
// checks that it asks db for results
verify(internal, times(1)).query(eq(expectedQuery));
// checks that cursor was closed
verify(cursor, times(1)).close();
// only one query should occur
verify(internal, times(1)).query(any(Query.class));
// checks that required update was performed
verify(internal, times(1)).update(eq(expectedUpdateQuery), eq(expectedContentValues));
// only one update should occur
verify(internal, times(1)).update(any(UpdateQuery.class), any(ContentValues.class));
// no inserts should occur
verify(internal, times(0)).insert(any(InsertQuery.class), any(ContentValues.class));
// put result checks
assertThat(putResult.wasInserted()).isFalse();
assertThat(putResult.wasUpdated()).isTrue();
assertThat(putResult.numberOfRowsUpdated()).isEqualTo(expectedNumberOfRowsUpdated);
assertThat(putResult.insertedId()).isNull();
}
use of com.pushtorefresh.storio.sqlite.StorIOSQLite in project storio by pushtorefresh.
the class PreparedPutContentValuesIterableTest method verifyBehaviorInCaseOfExceptionWithoutTransactionCompletable.
@Test
public void verifyBehaviorInCaseOfExceptionWithoutTransactionCompletable() {
final StorIOSQLite storIOSQLite = mock(StorIOSQLite.class);
final StorIOSQLite.Internal internal = mock(StorIOSQLite.Internal.class);
//noinspection unchecked
final PutResolver<ContentValues> putResolver = mock(PutResolver.class);
final List<ContentValues> contentValues = singletonList(mock(ContentValues.class));
when(putResolver.performPut(same(storIOSQLite), any(ContentValues.class))).thenThrow(new IllegalStateException("test exception"));
final TestSubscriber<PutResults<ContentValues>> testSubscriber = new TestSubscriber<PutResults<ContentValues>>();
new PreparedPutContentValuesIterable.Builder(storIOSQLite, contentValues).withPutResolver(putResolver).useTransaction(false).prepare().asRxCompletable().subscribe(testSubscriber);
testSubscriber.awaitTerminalEvent();
testSubscriber.assertNoValues();
testSubscriber.assertError(StorIOException.class);
//noinspection ThrowableResultOfMethodCallIgnored
StorIOException expected = (StorIOException) testSubscriber.getOnErrorEvents().get(0);
IllegalStateException cause = (IllegalStateException) expected.getCause();
assertThat(cause).hasMessage("test exception");
// Main check of this test
verify(internal, never()).endTransaction();
verify(storIOSQLite).lowLevel();
verify(storIOSQLite).defaultScheduler();
verify(putResolver).performPut(same(storIOSQLite), any(ContentValues.class));
verifyNoMoreInteractions(storIOSQLite, internal, putResolver);
}
Aggregations