sqlbrite 1.2.0

  • Readme
  • Changelog
  • Example
  • Installing
  • 83

SQL Brite alt text #

Author: Petrus Nguyễn Thái Học #

Pub Build Status codecov License: MIT

  • Reactive stream wrapper around sqflite for Flutter inspired by sqlbrite
  • Streaming sqflite
  • RxDart reactive stream sqflite for Flutter
  • A lightweight wrapper around sqflite which introduces reactive stream semantics to SQL operations.

Getting Started #

  1. Depend on it: In your flutter project, add the dependency to your pubspec.yaml
dependencies:
  ...
  sqlbrite: ^1.2.0
  1. Install it: You can install packages from the command line with Flutter:
$ flutter packages get
  1. Import it: Now in your Dart code, you can use:
import 'package:sqlbrite/sqlbrite.dart';

Usage #

1. Wrap your database in a BriteDatabase: #

final Database db = await openDb();
final briteDb = BriteDatabase(db);

2. Using #

  • The BriteDatabase.createQuery method is similar to Database.query. Listen to the returned Stream<Query> which will immediately notify with a Query to run.
  • These queries will run once to get the current data, then again whenever the given table is modified though the BriteDatabase.

Create entity model

class Entity {
  factory Entity.fromJson(Map<String, dynamic> map) { ... }
  
  factory Entity.default() { ... }

  Map<String, dynamic> toJson() { ... }
}

Use mapToOne extension method on Stream<Query>

// Emits a single row, doesn't emit if the row doesn't exist, emit error if more than 1 row in result set
final Stream<Entity> singleQuery$ = briteDb.createQuery(
  'table',
  where: 'id = ?',
  whereArgs: [id],
  limit: 1,
).mapToOne((row) => Entity.fromJson(row));

Use mapToOneOrDefault extension method on Stream<Query>

// Emits a single row, or the given default value if the row doesn't exist, or emit error if more than 1 row in result set
final Stream<Entity> singleOrDefaultQuery$ = briteDb.createQuery(
  'table',
  where: 'id = ?',
  whereArgs: [id],
  limit: 1,
).mapToOneOrDefault(
  (row) => Entity.fromJson(row),
  defaultValue: Entity.default()
);

Use mapToList extension method on Stream<Query>

// Emits a list of rows.
final Stream<List<Entity>> listQuery$ = briteDb.createQuery(
  'table',
  where: 'name LIKE ?',
  whereArgs: [queryName],
).mapToList((row) => Entity.fromJson(row));

Same API like Database


// will trigger query stream again
briteDb.insert(
  'table',
  Entity(...).toJson()
);

// will trigger query stream again
briteDb.update(
  'table',
  Entity(...).toJson(),
  where: 'id = ?',
  whereArgs: [id],
);

// will trigger query stream again
briteDb.update(
  'table',
  where: 'id = ?',
  whereArgs: [id],
);

Full power of RxDart operators

  • You can use RxDart operators to control the frequency of notifications to subscribers.
  • The full power of RxDart's operators are available for combining, filtering, and triggering any number of queries and data changes.
briteDb
    .createQuery(
      'table',
      where: 'name LIKE ?',
      whereArgs: [queryName],
    )
    .debounceTime(const Duration(milliseconds: 500))
    .where(filterQuery) // query is lazy, this lets you not even execute it if you don't need to
    .mapToList((row) => Entity.fromJson(row))
    .listen(updateUI);

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's not going to perform database migrations for you.

License #

MIT License
Copyright (c) 2020 Petrus Nguyễn Thái Học

1.2.0 - Feb 04, 2020 #

  • Update dependencies: rxdart, sqflite.

  • Add more documents for public API.

  • Fix some bugs.

  • Upgrade dart minsdk to 2.6.0 with extension method feature.

  • Refactor internal implementations.

1.1.0 - May 04, 2019 #

  • Add document for public API.

  • Fix error when call method mapToOne and mapToList.

  • Minor changes.

1.0.1 - May 03, 2019 #

  • Update rxdart dependency, fix error when call method mapToOne and mapToList.

1.0.0 - May 03, 2019 #

  • Initial release.

example/lib/main.dart

import 'package:example/data/app_db.dart';
import 'package:example/data/item.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:random_string/random_string.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData.dark(),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final _dateFormatter = DateFormat.Hms().add_yMMMd();

  MyHomePage({Key key}) : super(key: key);

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('sqlbrite example'),
      ),
      body: Container(
        constraints: BoxConstraints.expand(),
        child: StreamBuilder<List<Item>>(
          stream: AppDb.getInstance().getAllItems(),
          builder: (context, snapshot) {
            if (!snapshot.hasData) {
              return Center(
                child: CircularProgressIndicator(),
              );
            }

            final items = snapshot.data;

            return ListView.builder(
              itemCount: items.length,
              itemBuilder: (context, index) {
                final item = items[index];

                return ListTile(
                  title: Text(item.content),
                  subtitle:
                      Text('Created: ${_dateFormatter.format(item.createdAt)}'),
                  trailing: IconButton(
                    icon: Icon(Icons.remove_circle),
                    onPressed: () => _remove(item),
                  ),
                );
              },
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: _add,
      ),
    );
  }

  void _add() async {
    final item = Item(
      null,
      randomString(20),
      DateTime.now(),
    );
    final success = await AppDb.getInstance().insert(item);
    print('Add: $success');
  }

  void _remove(Item item) async {
    final success = await AppDb.getInstance().remove(item);
    print('Remove: $success');
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  sqlbrite: ^1.2.0

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:sqlbrite/sqlbrite.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
65
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
83
Learn more about scoring.

We analyzed this package on Mar 31, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6
  • Flutter: 1.12.13+hotfix.8

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.6.0 <3.0.0
collection ^1.14.11 1.14.11 1.14.12
flutter 0.0.0
meta ^1.1.8 1.1.8
rxdart ^0.23.1 0.23.1 0.24.0-dev.1
sqflite ^1.2.0 1.3.0
Transitive dependencies
path 1.6.4
sky_engine 0.0.99
sqflite_common 1.0.0+1
synchronized 2.2.0
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
flutter_test
mockito ^4.1.1
pedantic 1.8.0+1
test_api ^0.2.11