A lightweight wrapper around SQLiteOpenHelper which introduces reactive stream semantics to SQL operations.

Related tags

O/R Mapping sqlbrite
Overview

SQL Brite

A lightweight wrapper around SupportSQLiteOpenHelper and ContentResolver which introduces reactive stream semantics to queries.

Deprecated

This library is no longer actively developed and is considered complete.

Its database features (and far, far more) are now offered by SQLDelight and its upgrading guide offers some migration help.

For content provider monitoring please use Copper instead.

Usage

Create a SqlBrite instance which is an adapter for the library functionality.

SqlBrite sqlBrite = new SqlBrite.Builder().build();

Pass a SupportSQLiteOpenHelper instance and a Scheduler to create a BriteDatabase.

BriteDatabase db = sqlBrite.wrapDatabaseHelper(openHelper, Schedulers.io());

A Scheduler is required for a few reasons, but the most important is that query notifications can trigger on the thread of your choice. The query can then be run without blocking the main thread or the thread which caused the trigger.

The BriteDatabase.createQuery method is similar to SupportSQLiteDatabase.query except it takes an additional parameter of table(s) on which to listen for changes. Subscribe to the returned Observable<Query> which will immediately notify with a Query to run.

Observable<Query> users = db.createQuery("users", "SELECT * FROM users");
users.subscribe(new Consumer<Query>() {
  @Override public void accept(Query query) {
    Cursor cursor = query.run();
    // TODO parse data...
  }
});

Unlike a traditional query, updates to the specified table(s) will trigger additional notifications for as long as you remain subscribed to the observable. This means that when you insert, update, or delete data, any subscribed queries will update with the new data instantly.

final AtomicInteger queries = new AtomicInteger();
users.subscribe(new Consumer<Query>() {
  @Override public void accept(Query query) {
    queries.getAndIncrement();
  }
});
System.out.println("Queries: " + queries.get()); // Prints 1

db.insert("users", SQLiteDatabase.CONFLICT_ABORT, createUser("jw", "Jake Wharton"));
db.insert("users", SQLiteDatabase.CONFLICT_ABORT, createUser("mattp", "Matt Precious"));
db.insert("users", SQLiteDatabase.CONFLICT_ABORT, createUser("strong", "Alec Strong"));

System.out.println("Queries: " + queries.get()); // Prints 4

In the previous example we re-used the BriteDatabase object "db" for inserts. All insert, update, or delete operations must go through this object in order to correctly notify subscribers.

Unsubscribe from the returned Subscription to stop getting updates.

final AtomicInteger queries = new AtomicInteger();
Subscription s = users.subscribe(new Consumer<Query>() {
  @Override public void accept(Query query) {
    queries.getAndIncrement();
  }
});
System.out.println("Queries: " + queries.get()); // Prints 1

db.insert("users", SQLiteDatabase.CONFLICT_ABORT, createUser("jw", "Jake Wharton"));
db.insert("users", SQLiteDatabase.CONFLICT_ABORT, createUser("mattp", "Matt Precious"));
s.unsubscribe();

db.insert("users", SQLiteDatabase.CONFLICT_ABORT, createUser("strong", "Alec Strong"));

System.out.println("Queries: " + queries.get()); // Prints 3

Use transactions to prevent large changes to the data from spamming your subscribers.

final AtomicInteger queries = new AtomicInteger();
users.subscribe(new Consumer<Query>() {
  @Override public void accept(Query query) {
    queries.getAndIncrement();
  }
});
System.out.println("Queries: " + queries.get()); // Prints 1

Transaction transaction = db.newTransaction();
try {
  db.insert("users", SQLiteDatabase.CONFLICT_ABORT, createUser("jw", "Jake Wharton"));
  db.insert("users", SQLiteDatabase.CONFLICT_ABORT, createUser("mattp", "Matt Precious"));
  db.insert("users", SQLiteDatabase.CONFLICT_ABORT, createUser("strong", "Alec Strong"));
  transaction.markSuccessful();
} finally {
  transaction.end();
}

System.out.println("Queries: " + queries.get()); // Prints 2

Note: You can also use try-with-resources with a Transaction instance.

Since queries are just regular RxJava Observable objects, operators can also be used to control the frequency of notifications to subscribers.

users.debounce(500, MILLISECONDS).subscribe(new Consumer<Query>() {
  @Override public void accept(Query query) {
    // TODO...
  }
});

The SqlBrite object can also wrap a ContentResolver for observing a query on another app's content provider.

BriteContentResolver resolver = sqlBrite.wrapContentProvider(contentResolver, Schedulers.io());
Observable<Query> query = resolver.createQuery(/*...*/);

The full power of RxJava's operators are available for combining, filtering, and triggering any number of queries and data changes.

Philosophy

SQL Brite's only responsibility is to be a mechanism for coordinating and composing the notification of updates to tables such that you can update queries as soon as data changes.

This library is not an ORM. It is not a type-safe query mechanism. It won't serialize the same POJOs you use for Gson. It's not going to perform database migrations for you.

Some of these features are offered by SQL Delight which can be used with SQL Brite.

Download

implementation 'com.squareup.sqlbrite3:sqlbrite:3.2.0'

For the 'kotlin' module that adds extension functions to Observable<Query>:

implementation 'com.squareup.sqlbrite3:sqlbrite-kotlin:3.2.0'

Snapshots of the development version are available in Sonatype's snapshots repository.

License

Copyright 2015 Square, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • WAL mode

    WAL mode

    I see that sqlbrite opens transaction using beginTransactionWithListener() which as you may know starts the transaction in EXCLUSIVE mode. I was wondering why you don't use beginTransactionWithListenerNonExclusive() which makes it possible for read operations to be performed concurrently alongside a write.

    enhancement 
    opened by avsector 18
  • Support object mapping of query result rows

    Support object mapping of query result rows

    Nobody wants to work with a Query and Cursor. Add support for mapping rows to objects. This should support both table-based and custom view-based objects.

    opened by JakeWharton 10
  • Port to RxJava 2.

    Port to RxJava 2.

    • Maven groupId is now com.squareup.sqlbrite2.
    • Package name is now com.squareup.sqlbrite2.
    • Query.mapTo* methods now return ObserverOperator instead of Function for use with lift instead of to.
    • Backpressure is no longer supported and must be applied with operators.

    Closes #136

    opened by JakeWharton 9
  • Observable gets triggered multiple times in Transaction

    Observable gets triggered multiple times in Transaction

    On App-Startup i query the db and update a view on result. At the same time i do get new entries from a webservice - those are written in the db with a transaction (i'm using a contenresolver here, so i already have overridden the applyBatch method to use transactions, as it seems, it's not done per default)

        public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) {
            ...
            db.beginTransaction();
            try {
                for (ContentProviderOperation operation : operations) {
                    result[i++] = operation.apply(this, result, i);
                }
    
                db.setTransactionSuccessful();
            } catch (OperationApplicationException e) {
                Log.d(TAG, "batch failed: " + e.getLocalizedMessage());
            } finally {
                db.endTransaction();
            }
    
            return result;
        }
    

    Problem is, that the observable is triggered for every db action, alltough i perform them inside a transaction.

    How do i achieve only one update of the observable?

    opened by chriswiesner 9
  • StrictMode complaining, but i'm not sure if i have anything to worry about.

    StrictMode complaining, but i'm not sure if i have anything to worry about.

    So i created a class called CursorListAdapter that extends from AbstractList and uses a Cursor as it's backing:

    public class CursorListAdapter<T>
            extends AbstractList<T> {
    
        private Cursor cursor;
        private Func1<Cursor, T> mapper;
    
        public CursorListAdapter(Func1<Cursor, T> mapper) {
            this.mapper = mapper;
        }
    
        public CursorListAdapter(Cursor cursor, Func1<Cursor, T> mapper) {
            this.cursor = cursor;
            this.mapper = mapper;
        }
    
        public void setCursor(Cursor cursor) {
            this.cursor = cursor;
        }
    
        public synchronized void closeCursor() {
            if (cursor!=null && !cursor.isClosed()) {
                this.cursor.close();;
            }
        }
    
        public Cursor getCursor() {
            return this.cursor;
        }
    
        @Override
        public T get(int location) {
            if (cursor==null) {
                throw new IndexOutOfBoundsException("cursor is null");
            } else if (cursor.isClosed()) {
                throw new IndexOutOfBoundsException("cursor is closed");
            }
            if (!cursor.moveToPosition(location)) {
                throw new IndexOutOfBoundsException("moveToPosition failed");
            }
            return mapper.call(cursor);
        }
    
        @Override
        public int size() {
            return cursor!=null && !cursor.isClosed()
                    ? cursor.getCount()
                    : 0;
        }
    }
    

    and then i created an Observable.Operator to lift(...) Observable<SqlBrite.Query>s into an Observable of the given type:

    public class CursorListAdapterOperator<T>
        implements Observable.Operator<List<T>, SqlBrite.Query> {
    
        private final Func1<Cursor, T> mapper;
    
        public CursorListAdapterOperator(Func1<Cursor, T> mapper) {
            this.mapper = mapper;
        }
    
        @Override
        public Subscriber<? super SqlBrite.Query> call(final Subscriber<? super List<T>> subscriber) {
            return new Subscriber<SqlBrite.Query>(subscriber) {
    
                final CursorListAdapter<T> list = new CursorListAdapter<>(mapper);
    
                @Override
                public void onNext(SqlBrite.Query query) {
                    try {
                        list.closeCursor();
                        list.setCursor(query.run());
                        if (!subscriber.isUnsubscribed()) {
                            subscriber.onNext(list);
                        }
                    } catch (Throwable e) {
                        Exceptions.throwIfFatal(e);
                        onError(OnErrorThrowable.addValueAsLastCause(e, query.toString()));
                    }
                }
    
                @Override
                public void onCompleted() {
                    subscriber.onCompleted();
                    list.closeCursor();
                }
    
                @Override
                public void onError(Throwable e) {
                    subscriber.onError(e);
                    list.closeCursor();
                }
            };
        }
    }
    

    I see a StrictMode warning in my console about not calling close on the cursor and I'm wondering if that's something i need to worry about or not. Here's the warning:

        flipagram E/StrictMode: A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.
        java.lang.Throwable: Explicit termination method 'close' not called
           at dalvik.system.CloseGuard.open(CloseGuard.java:180)
           at android.content.ContentResolver$CursorWrapperInner.<init>(ContentResolver.java:2507)
           at android.content.ContentResolver.query(ContentResolver.java:515)
           at android.content.ContentResolver.query(ContentResolver.java:434)
           at com.squareup.sqlbrite.BriteContentResolver$1.run(BriteContentResolver.java:83)
           at XXXX.CursorListAdapterOperator$1.onNext(CursorListAdapterOperator.java:41)
           at XXXX.CursorListAdapterOperator$1.onNext(CursorListAdapterOperator.java:32)
           at com.squareup.sqlbrite.BackpressureBufferLastOperator$BufferLastSubscriber.onNext(BackpressureBufferLastOperator.java:101)
    

    I'm relatively new to RxJava and SqlBrite - but my Operator should be properly closing the Cursor right?

    opened by briandilley 8
  • Support more fine-grained notifications for queries

    Support more fine-grained notifications for queries

    As it stands now, a Observable<Query> emits a new query object for every change in the table, even if the corresponding rows of the query haven't changed.

    It would be great if means of further filtering the notifications were added to avoid these unnecessary updates (and database queries).

    Maybe something like tags for queries and updates/inserts/deletes:

    // Tag the query with a string
    Observable<Query> users = db.createQuery("users", "tag", "SELECT * FROM users WHERE company=?", "Square");
    // This observable would now only be refreshed with database updates that are tagged with "tag"
    
    // Tag an insert with the same tag
    db.insert("users", createUser("jw", "Jake Wharton", "Square"), "tag"); // users gets notified
    
    db.insert("users", createUser("lp", "Larry Page", "Google")); // the tag is optional, users wouldn't get notified
    
    opened by iomu 8
  • mDataManager.getContentQuery(catId).subscribe called multiples times

    mDataManager.getContentQuery(catId).subscribe called multiples times

    I have created a getContentQuery(int catId) method which return Observable<SqlBrite.Query> . Problem is that when I called mDataManager.getContentQuery(catId).subscribe() then call(SqlBrite.Query query) of Action1 inside .subscribe() executes multiple times. I used .doOnNext(new Action1<SqlBrite.Query>() this also called multiples times.

    opened by joginder89 7
  • Content resolver Observable produces duplicates sometimes/usually

    Content resolver Observable produces duplicates sometimes/usually

    Sorry about the cryptic title. The issue is better expressed with some code and an explanation.

    I'm creating an Observable for listening to sms messages, specifically I care about sent messages.

    Observable<SqlBrite.Query> query = resolver.createQuery(Uri.parse("content://sms/"), null, null, null, null, true);
    
    subscription = query
        // Ignore first immediately emitted value
      .skip(1)
        // read the query, output Message object, which has data from the cursor
      .flatMap(…) 
        // filter everything except sent messages
      .filter(…)
        // Only unique messages
      .distinct(…)
        // We only care about certain keyword in the message
      .filter(…)
        // Show a dialog box
      .compose(…)
        // Filter out if user canceled dialog
      .filter(…)
      .subscribeOn(Schedulers.io())
      .observeOn(scheduler)
      .subscribe(…);
    

    Even after filtering on "sent" I'll get about 5 or 6 Messageobjects per actual sent sms message. When I first push a build to my phone, everything works as expected. Some unknown time later (I usually notice the next day) two identical Message objects pass distinct(). Specifically the first two.

    Message has correctly implemented equals() and hashCode().

    This may or may not be an issue with SqlBrite but I've been battling this for a while so I'm exploring all of my options. (I have a similar message out on the RxJava mailing list).

    opened by djensen47 7
  • Question marks in a query don't match number of arguments lint check

    Question marks in a query don't match number of arguments lint check

    https://github.com/square/sqlbrite/issues/58

    This is my first lint check so I am not sure if I've covered all the cases. I was using Timber lint checks as a reference. I'll appreciate any feedback!

    opened by geralt-encore 6
  • Problem with

    Problem with "concat()" operator

    I'm not able to use Observable.concat() with SqlBrite to concatenate few observables. So, after SqlBrite returned some result the other observables is not called. For example, in this case I always get null from localSource and noting else:

    return Observable.concat(localSource, remoteSource).first();
    

    In this case localSource returns null (since there is no data, e.g. first application launch) and after that code execution stops in first filter check:

    return Observable.concat(localSource, remoteSource)
            .filter(new Func1<Item, Boolean>() {
                @Override
                public Boolean call(Item item) {
                    return item!= null;
                }
            });
    

    For fetch data from db using next code:

    @Override
    public Observable<Item> get(String id) {
        //creating sql query
    
        return databaseHelper.createQuery(ItemEntry.TABLE_NAME, sqlQuery, id)
            .mapToOneOrDefault(mapperFunction, null);
    }
    
    opened by amolkov 6
  • Use Android's Sqlite abstraction instead of raw android.database.* classes.

    Use Android's Sqlite abstraction instead of raw android.database.* classes.

    Could there be some investigation and perhaps implementation of a mechanic to allow for switching between Android's default SQLite engine or one issued by Requery?

    @JakeWharton have you given this any thought?

    blocked 
    opened by yesitskev 6
  • Incompatible Lint warning

    Incompatible Lint warning

    When running Lint on a project that uses SqlBrite 3.2.0:

    Warning: Lint found an issue registry (com.squareup.sqlbrite3.BriteIssueRegistry) which did not specify the Lint API version it was compiled with.

    This means that the lint checks are likely not compatible.

    If you are the author of this lint check, make your lint IssueRegistry class contain   override val api: Int = com.android.tools.lint.detector.api.CURRENT_API or from Java,   @Override public int getApi() { return com.android.tools.lint.detector.api.ApiKt.CURRENT_API; }

    If you are just using lint checks from a third party library you have no control over, you can disable these lint checks (if they misbehave) like this:

        android {         lintOptions {             disable "SqlBriteArgCount"         }     } [ObsoleteLintCustomCheck] Applies to variants: debug

    Explanation for issues of type "ObsoleteLintCustomCheck": Lint can be extended with "custom checks": additional checks implemented by developers and libraries to for example enforce specific API usages required by a library or a company coding style guideline.

    The Lint APIs are not yet stable, so these checks may either cause a performance, degradation, or stop working, or provide wrong results.

    This warning flags custom lint checks that are found to be using obsolete APIs and will need to be updated to run in the current lint environment. It may also flag issues found to be using a newer version of the API, meaning that you need to use a newer version of lint (or Android Studio or Gradle plugin etc) to work with these checks.

    Unfortunately, disabling 'SqlBriteArgCount' as shown above results in the following error:

    Error: Unknown issue id "SqlBriteArgCount" [LintError] disable "SqlBriteArgCount"

    opened by nhaarman 0
  • Separate table change observation from querying

    Separate table change observation from querying

    Add a method Observable<List<String>> observeTables(String... tables) or similar to BriteDatabase, that notifies observers with a set of affected tables, but does not create any query.

    Scenario: We sync cats and dogs stored on our backend, and persist them using a transaction.(pseudo-code, cursor/cv mapping omitted)

    try (Transaction transaction = database.newTransaction()) {
        for(Cat cat: cats) {
            database.insert("cat", cat);
        }
        for(Dog dog: dogs) {
            database.insert("dog", dog);
        }
        transaction.markSuccessful();
    }
    

    We fetch all cats and dogs when initializing our view. (In real code in a background thread, obviously)

    List cats = database.query("SELECT * FROM cat");
    List dogs = database.query("SELECT * FROM dog");
    catAndDogView.setCatsAndDogs(cats, dogs);
    

    How do I make this reactive?

    Observable<List> cats = database.createQuery("cat", "SELECT * FROM cat");
    Observable<List> dogs = database.createQuery("dog", "SELECT * FROM dog");
    Observable.combineLatest(cats, dogs, (cats, dogs) -> new Object[]{cats, dogs})
        .subscribe(objects -> catAndDogView.setCatsAndDogs(objects[0], objects[1]));
    

    This is flawed, because I'm now getting two updates per transaction. Replacing combineLatest() with zip() won't do neither, because then I'm missing out on updates that involve only cats, or only dogs. A work-around is having each query triggered by changes on either table, but that comes at the expense of running some redundant queries.

    As an added benefit of my proposal, having the opportunity to react to table changes myself, would allow me to create DAOs with synchronous methods, and reusing these methods when I want to create reactive versions.

    class DAO {
        List<Cat> findBlackCats(BriteDatabase database) {
            return database.query("SELECT * FROM cat WHERE color = black");
        }
    }
    
    Observable<List<Cat>> blackCats = database.observeTables("cat")
        .map(ignore -> dao.findBlackCats(database));
    

    My proposal is based on what SquiDB seems to offer.

    icebox 
    opened by m6s 8
  • StrictMode for detecting queries on the main thread

    StrictMode for detecting queries on the main thread

    StrictMode is lazy and only detects slow queries on the main thread. This is mostly useless since the query execution time is subjective based on the data in the DB and CPU/disk performance of the device.

    There's a few options here:

    • Inform StrictMode via noteSlowCall and allow normal penalties to apply. This sucks because there's no granularity between those posting to this method and puts the subjectiveness of what's slow into the libraries. There would be no way to enable slow call penalties from one library but disable it from another. Granted, this is unlikely.
    • Add our own strict mode analogous which allowed the detection of queries running on the UI thread.
    • Provide a composition point for either observable creation or query object creation. This would allow someone to mix in things like main thread checking, or perhaps default schedulers.

    This isn't urgent, so we have time to think about what's most appropriate.

    icebox 
    opened by JakeWharton 0
  • Lint checks for runtime assertions and common errors.

    Lint checks for runtime assertions and common errors.

    • [ ] Creating a query inside of a transaction
    • [x] Question marks in a query don't match number of arguments (#220)
    • [ ] Missing mark success in try/finally or try-with-resources
    • [ ] Multiple insert/update/delete statements not in a transaction in a single method
    • [ ] Ensure first argument looks like a table / list of tables
    • [ ] Second argument looks like SQL and contains all tables from the first argument
    help wanted icebox 
    opened by JakeWharton 0
  • Any way to reload the database and make all observables to re-query?

    Any way to reload the database and make all observables to re-query?

    Reload SQLiteOpenHelper and re-query

    In my app I have a import/export functionality, by importing, the SQLite database file is replaced by one on the sdcard, so I need to reload the SQLiteOpenHelper and then notify all the Queries.

    Something like the following method would be really handy!

    public void reloadDatabase(SQLiteOpenHelper helper, Set<String> tables){
       // Replace the SQLiteOpenHelper
       synchronized (databaseLock) {
          readableDatabase = null;
          writeableDatabase = null;
          this.helper.close();
          this.helper = helper;
       }
       // Make all Queries to reload
       sendTableTrigger(tables);
    }
    

    Or prehaps BriteDatabase can save a Set of tables, filled as we query them, to be notified on a potential database reload?

    I guess I could make the user restart the app, but I rather not.

    SQLBrite is amazing as it is very simple and allow us to get rid of loaders, and IMO notifying on tables is far better than the Uri system, thanks for creating SQLBrite!

    Re-query only

    Let's say my app is a calendar, I have an upcoming event list, starting by today's events. In every event list I want to mark each yesterday's event as missed.

    Then I need to reload event's Queries every day at 00:00. In this particular case it would make sense to make the sendTableTrigger() public and call it every day.

    I could also use a Observable.combineLatest with a Query and a PublishSubject and call this Subject every day to run the Query again, but since table triggers are managed the same way, it seems simple to switch sendTableTrigger() to public.

    To support this idea; ContentResolver's notifyChange(Uri uri, null) is public.

    icebox 
    opened by varyoo 4
Releases(0.6.2)
  • 0.6.2(Mar 1, 2016)

    • Fix: Document explicitly and correctly handle the fact that Query.run() can return null in some situations. The mapToOne, mapToOneOrDefault, mapToList, and asRows helpers have all been updated to handle this case and each is documented with their respective behavior.
    Source code(tar.gz)
    Source code(zip)
  • 0.6.1(Mar 1, 2016)

    • Fix: Apply backpressure strategy between database/content provider and the supplied Scheduler. This guards against backpressure exceptions when the scheduler is unable to keep up with the rate at which queries are being triggered.
    • Fix: Indent the subsequent lines of a multi-line queries when logging.
    Source code(tar.gz)
    Source code(zip)
  • 0.6.0(Feb 17, 2016)

    • New: Require a Scheduler when wrapping a database or content provider which will be used when sending query triggers. This allows the query to be run in subsequent operators without needing an additional observeOn. It also eliminates the need to use subscribeOn since the supplied Scheduler will be used for all emissions (similar to RxJava's timer, interval, etc.).

      This also corrects a potential violation of the RxJava contract and potential source of bugs in that all triggers now occur on the supplied Scheduler. Previously the initial value would trigger synchronously (on the subscribing thread) while subsequent ones trigger on the thread which performed the transaction. The new behavior puts the initial trigger on the same thread as all subsequent triggers and also does not force transactions to block while sending triggers.

    Source code(tar.gz)
    Source code(zip)
  • 0.5.1(Feb 17, 2016)

    • New: Query logs now contain timing information on how long they took to execute. This only covers the time until a Cursor was made available, not object mapping or delivering to subscribers.
    • Fix: Switch query logging to happen when Query.run is called, not when a query is triggered.
    • Fix: Check for subscribing inside a transaction using a more accurate primitive.
    Source code(tar.gz)
    Source code(zip)
  • 0.5.0(Dec 9, 2015)

    • New: Expose mapToOne, mapToOneOrDefault, and mapToList as static methods on Query. These mirror the behavior of the methods of the same name on QueryObservable but can be used later in a stream by passing the returned Operator instances to lift() (e.g., take(1).lift(Query.mapToOne(..))).
    • Requires RxJava 1.1.0 or newer.
    Source code(tar.gz)
    Source code(zip)
  • 0.4.1(Oct 19, 2015)

    • New: execute method provides the ability to execute arbitrary SQL statements.
    • New: executeAndTrigger method provides the ability to execute arbitrary SQL statements and notifying any queries to update on the specified table.
    • Fix: Query.asRows no longer calls onCompleted when the downstream subscriber has unsubscribed.
    Source code(tar.gz)
    Source code(zip)
  • 0.4.0(Sep 22, 2015)

    • New: mapToOneOrDefault replaces mapToOneOrNull for more flexibility.
    • Fix: Notifications of table updates as the result of a transaction now occur after the transaction has been applied. Previous the notification would happen during the commit at which time it was invalid to create a new transaction in a subscriber.

    Download:

    compile 'com.squareup.sqlbrite:sqlbrite:0.4.0'
    
    Source code(tar.gz)
    Source code(zip)
  • 0.3.1(Sep 2, 2015)

    • New: mapToOne and mapToOneOrNull operators on QueryObservable. These work on queries which return 0 or 1 rows and are a convenience for turning them into a type T given a mapper of type Func1<Cursor, T> (the same which can be used for mapToList).
    • Fix: Remove @WorkerThread annotations for now. Various combinations of lint, RxJava, and retrolambda can cause false-positives.

    Download:

    compile 'com.squareup.sqlbrite:sqlbrite:0.3.1'
    
    Source code(tar.gz)
    Source code(zip)
  • 0.3.0(Aug 31, 2015)

    • Transactions are now exposed as objects instead of methods. Call newTransaction() to start a transaction. On the Transaction instance, call markSuccessful() to indicate success and end() to commit or rollback the transaction. The Transaction instance implements Closeable to allow its use in a try-with-resources construct. See the newTransaction() Javadoc for more information.
    • Query instances can now be turned directly into an Observable<T> by calling asRows with a Func1<Cursor, T> that maps rows to a type T. This allows easy filtering and limiting in memory rather than in the query. See the asRows Javadoc for more information.
    • createQuery now returns a QueryObservable which offers a mapToList operator. This operator also takes a Func1<Cursor, T> for mapping rows to a type T, but instead of individual rows it collects all the rows into a list. For large query results or frequently updated tables this can create a lot of objects. See the mapToList Javadoc for more information.
    • New: Nullability, @CheckResult, and @WorkerThread annotations on all APIs allow a more useful interaction with lint in consuming projects.

    Download:

    compile 'com.squareup.sqlbrite:sqlbrite:0.3.0'
    
    Source code(tar.gz)
    Source code(zip)
A wrapper around Android's SQLiteDatabase with restoring capability

Restorable SQLiteDatabase RestorableSQLiteDatabase is a wrapper to replicate android's SQLiteDatabase class with restoring capability. This wrapper ma

Navid 21 Oct 21, 2022
sql-delight example, a plugin by Square which is pure kotlin and it is useful in kmm

Sql-Delight-Example01 Developed by Mahdi Razzaghi Ghaleh first example of sql-delight What is SqlDelight? Kotlin Multiplatform is one of the most inte

rq_mehdi 0 Jan 24, 2022
A simple ToDo app to demonstrate the use of Realm Database in android to perform some basic CRUD operations like Create, Update and Delete.

Creating a Realm Model Class @RealmClass open class Note() : RealmModel { @PrimaryKey var id: String = "" @Required var title: String

Joel Kanyi 15 Dec 18, 2022
requery - modern SQL based query & persistence for Java / Kotlin / Android

A light but powerful object mapping and SQL generator for Java/Kotlin/Android with RxJava and Java 8 support. Easily map to or create databases, perfo

requery 3.1k Dec 29, 2022
A simple NoSQL client for Android. Meant as a document store using key/value pairs and some rudimentary querying. Useful for avoiding the hassle of SQL code.

SimpleNoSQL A simple NoSQL client for Android. If you ever wanted to just save some data but didn't really want to worry about where it was going to b

Colin Miller 389 Sep 25, 2022
Android library for auto generating SQL schema and Content provider

Android-AnnotatedSQL Android library for auto generating SQL schema and Content Provider by annotations. You will get a full-featured content provider

Gennadiy Dubina 161 Dec 3, 2022
Upsert DSL extension for Exposed, Kotlin SQL framework

Exposed Upsert Upsert DSL extension for Exposed, Kotlin SQL framework. Project bases on various solutions provided by community in the official "Expos

Dzikoysk 23 Oct 6, 2022
Upsert DSL extension for Exposed, Kotlin SQL framework

Exposed Upsert Upsert DSL extension for Exposed, Kotlin SQL framework. Project bases on various solutions provided by community in the official "Expos

Reposilite Playground 23 Oct 6, 2022
Reactive extensions for SimpleNoSQL

RxSimpleNoSQL Reactive extensions for SimpleNoSQL. Manipulate entities using Observables and Completables. Examples Suppose we have the following enti

xmartlabs 37 Aug 29, 2021
A MySQL connector wrapper that supports mapping to Kotlin classes.

Racoon Racoon is a wrapper for the MySQL connector. It makes communicating with the database easier by providing a bunch of functionalities: Mapping q

null 1 Jun 3, 2022
lightweight and minimalist ORM for Java/Android. works with SQLite & MySQL. (not actively maintained)

Description ORMAN is an minimalistic and lightweight ORM framework for Java which can handle your common database usage without writing SQL and strugg

Ahmet Alp Balkan 246 Nov 20, 2022
lightweight and minimalist ORM for Java/Android. works with SQLite & MySQL. (not actively maintained)

Description ORMAN is an minimalistic and lightweight ORM framework for Java which can handle your common database usage without writing SQL and strugg

Ahmet Alp Balkan 246 Nov 20, 2022
LiteGo is a Java-based asynchronous concurrency library. It has a smart executor, which can be freely set the maximum number of concurrent at same time , and the number of threads in waiting queue. It can also set waiting policies and overload strategies.

LiteGo:「迷你」的Android异步并发类库 LiteGo是一款基于Java语言的「异步并发类库」,它的核心是一枚「迷你」并发器,它可以自由地设置同一时段的最大「并发」数量,等待「排队」线程数量,还可以设置「排队策略」和「超载策略」。 LiteGo可以直接投入Runnable、Callable

马天宇 189 Nov 10, 2022
AndroidQuery is an Android ORM for SQLite and ContentProvider which focuses on easy of use and performances thanks to annotation processing and code generation

WARNING: now that Room is out, I no longer maintain that library. If you need a library to easy access to default android ContentProvider, I would may

Frédéric Julian 19 Dec 11, 2021
This is an Online Book App in which user can read and add their books on favourites fragment and also give rating on it.

BookHub-AndroidApp BookHub Basic Android App Based on the concept of Fragment, Navigation Drawer, Database (Room), Internet Access, etc. See the app o

Yash Kumar Shrivas 3 Mar 10, 2022
Kotlin-Exposed-SQL - Example of using Exposed with Kotlin for the consumption of relational SQL Databases

Kotlin Exposed SQL Sencillo ejemplo sobre el uso y abuso de Exposed ORM de Jetbr

José Luis González Sánchez 3 Jun 14, 2022
A lightweight Kotlin friendly wrapper around Couchbase lite for Android.

CouchBaseKtx ?? Work In-Progress ?? A lightweight Kotlin friendly wrapper around Couchbase-lite for Android Read up a little bit of documentation abou

Jaya Surya Thotapalli 5 Feb 15, 2022
A Lightweight PDF Viewer Android library which only occupies around 125kb while most of the Pdf viewer occupies up to 16MB space.

Pdf Viewer For Android A Simple PDF Viewer library which only occupies around 125kb while most of the Pdf viewer occupies upto 16MB space. How to inte

Rajat 362 Dec 29, 2022
Wrapper around the android Camera class that simplifies its usage

EasyCamera Wrapper around the android Camera class that simplifies its usage (read more about the process) Usage: // the surface where the preview wil

Bozhidar Bozhanov 642 Nov 27, 2022
A wrapper around Android's SQLiteDatabase with restoring capability

Restorable SQLiteDatabase RestorableSQLiteDatabase is a wrapper to replicate android's SQLiteDatabase class with restoring capability. This wrapper ma

Navid 21 Oct 21, 2022