Skip to content
This repository has been archived by the owner on Aug 17, 2020. It is now read-only.

Commit

Permalink
Merge commit 'e82dd77a766dd1b8fc5e029714ef03c02e79db05'
Browse files Browse the repository at this point in the history
  • Loading branch information
michael t committed Sep 20, 2016
2 parents 45d0750 + e82dd77 commit 1824981
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 5 deletions.
1 change: 1 addition & 0 deletions sqlbrite/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ android {

lintOptions {
textOutput 'stdout'
textReport true
}

buildTypes {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
import java.util.concurrent.CountDownLatch;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import rx.Observable;
import rx.Subscription;
Expand All @@ -53,6 +55,7 @@
import static com.squareup.sqlbrite.TestDb.employee;
import static com.squareup.sqlbrite.TestDb.manager;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.fail;

@RunWith(AndroidJUnit4.class)
Expand All @@ -65,8 +68,11 @@ public final class BriteDatabaseTest {
private SQLiteDatabase real;
private BriteDatabase db;

@Before public void setUp() {
helper = new TestDb(InstrumentationRegistry.getContext());
@Rule
public TemporaryFolder dbFolder = new TemporaryFolder();

@Before public void setUp() throws IOException {
helper = new TestDb(InstrumentationRegistry.getContext(), dbFolder.newFile().getPath());
real = helper.getWritableDatabase();

SqlBrite.Logger logger = new SqlBrite.Logger() {
Expand Down Expand Up @@ -745,6 +751,40 @@ public final class BriteDatabaseTest {
o.assertNoMoreEvents();
}

@Test public void nonExclusiveTransactionWorks() throws InterruptedException {
final CountDownLatch transactionStarted = new CountDownLatch(1);
final CountDownLatch transactionProceed = new CountDownLatch(1);
final CountDownLatch transactionCompleted = new CountDownLatch(1);

new Thread() {
@Override public void run() {
Transaction transaction = db.newNonExclusiveTransaction();
transactionStarted.countDown();
try {
db.insert(TABLE_EMPLOYEE, employee("hans", "Hans Hanson"));
transactionProceed.await(10, SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException("Exception in transaction thread", e);
}
transaction.markSuccessful();
transaction.close();
transactionCompleted.countDown();
}
}.start();

assertThat(transactionStarted.await(10, SECONDS)).isTrue();

//Simple query
Employee employees = db.createQuery(TABLE_EMPLOYEE, SELECT_EMPLOYEES + " LIMIT 1")
.lift(Query.mapToOne(Employee.MAPPER))
.toBlocking()
.first();
assertThat(employees).isEqualTo(new Employee("alice", "Alice Allison"));

transactionProceed.countDown();
assertThat(transactionCompleted.await(10, SECONDS)).isTrue();
}

@Test public void backpressureSupportedWhenConsumerSlow() {
o.doRequest(2);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public final class QueryTest {

@Before public void setUp() {
SqlBrite sqlBrite = SqlBrite.create();
TestDb helper = new TestDb(InstrumentationRegistry.getContext());
TestDb helper = new TestDb(InstrumentationRegistry.getContext(), null /* memory */);
db = sqlBrite.wrapDatabaseHelper(helper, Schedulers.immediate());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ interface ManagerTable {
long bobId;
long eveId;

TestDb(Context context) {
super(context, null /* memory */, null /* cursor factory */, 1 /* version */);
TestDb(Context context, String path) {
super(context, path, null /* cursor factory */, 1 /* version */);
}

@Override public void onCreate(@NonNull SQLiteDatabase db) {
Expand Down
52 changes: 52 additions & 0 deletions sqlbrite/src/main/java/com/squareup/sqlbrite/BriteDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package com.squareup.sqlbrite;

import android.annotation.TargetApi;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
Expand All @@ -24,6 +25,7 @@
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import com.squareup.sqlbrite.SqlBrite.Query;
import java.io.Closeable;
import java.lang.annotation.Retention;
Expand All @@ -45,6 +47,7 @@
import static android.database.sqlite.SQLiteDatabase.CONFLICT_NONE;
import static android.database.sqlite.SQLiteDatabase.CONFLICT_REPLACE;
import static android.database.sqlite.SQLiteDatabase.CONFLICT_ROLLBACK;
import static android.os.Build.VERSION_CODES.HONEYCOMB;
import static java.lang.System.nanoTime;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
Expand Down Expand Up @@ -216,6 +219,55 @@ public Transaction newTransaction() {
return this.transaction;
}

/**
* Begins a transaction in IMMEDIATE mode for this thread.
* <p>
* Transactions may nest. If the transaction is not in progress, then a database connection is
* obtained and a new transaction is started. Otherwise, a nested transaction is started.
* <p>
* Each call to {@code newNonExclusiveTransaction} must be matched exactly by a call to
* {@link Transaction#end()}. To mark a transaction as successful, call
* {@link Transaction#markSuccessful()} before calling {@link Transaction#end()}. If the
* transaction is not successful, or if any of its nested transactions were not successful, then
* the entire transaction will be rolled back when the outermost transaction is ended.
* <p>
* Transactions queue up all query notifications until they have been applied.
* <p>
* Here is the standard idiom for transactions:
*
* <pre>{@code
* try (Transaction transaction = db.newNonExclusiveTransaction()) {
* ...
* transaction.markSuccessful();
* }
* }</pre>
*
* Manually call {@link Transaction#end()} when try-with-resources is not available:
* <pre>{@code
* Transaction transaction = db.newNonExclusiveTransaction();
* try {
* ...
* transaction.markSuccessful();
* } finally {
* transaction.end();
* }
* }</pre>
*
*
* @see SQLiteDatabase#beginTransactionNonExclusive()
*/
@TargetApi(HONEYCOMB)
@RequiresApi(HONEYCOMB)
@CheckResult @NonNull
public Transaction newNonExclusiveTransaction() {
SqliteTransaction transaction = new SqliteTransaction(transactions.get());
transactions.set(transaction);
if (logging) log("TXN BEGIN %s", transaction);
getWriteableDatabase().beginTransactionWithListenerNonExclusive(transaction);

return this.transaction;
}

/**
* Close the underlying {@link SQLiteOpenHelper} and remove cached readable and writeable
* databases. This does not prevent existing observables from retaining existing references as
Expand Down

0 comments on commit 1824981

Please sign in to comment.