Skip to content
Easy and reactive Sqlite for Flutter
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
android Remove useless statements Mar 15, 2019
coverage Start adding tests Mar 31, 2019
docs Improve the docs for schema definition Jun 1, 2019
example Version 3.0.0: remove SynchronizedMap Jun 14, 2019
lib Apply more strict linting rules Jun 14, 2019
test Apply more strict linting rules Jun 14, 2019
.gitignore Update gitignore Mar 31, 2019
.travis.yml Add .travis.yml Mar 31, 2019 Version 3.0.0: remove SynchronizedMap Jun 14, 2019
LICENSE Initial commit Dec 28, 2018 Version 3.0.0: remove SynchronizedMap Jun 14, 2019
analysis_options.yaml Update linting options Jun 14, 2019
pubspec.yaml Version 3.0.0: remove SynchronizedMap Jun 14, 2019


pub package Build Status Api doc

A database helper library for Sqflite. Forget about implementation details and focus on the business logic.

  • Simple: easy api for crud operations
  • Reactive: stream of changes, select bloc

Check the documentation or the api doc for usage instructions

Simple crud

Define the database schema

import 'package:sqlcool/sqlcool.dart';

Db db = Db();
// define the database schema
DbTable category = DbTable("category")..varchar("name", unique: true);
DbTable product = DbTable("product")
   ..varchar("name", unique: true)
   ..text("descripton", nullable: true)
   ..foreignKey("category", onDelete: OnDelete.cascade)
List<DbTable> schema = [category, product];

Initialize the database

String dbpath = "db.sqlite"; // relative to the documents directory
await db.init(path: dbpath, schema: schema).catchError((e) {
  throw("Error initializing the database: ${e.message}");


Map<String, String> row = {name: "My item",};
await db.insert(table: "category", row: row).catchError((e) {
  throw("Error inserting data: ${e.message}");


List<Map<String, dynamic>> rows = await
   table: "product", limit: 20, columns: "id,name",
   where: "name LIKE '%something%'",
   orderBy: "name ASC").catchError((e) {
    throw("Error selecting data: ${e.message}");


int updated = await db.update(table: "category", 
   row: row, where: "id=1").catchError((e) {
      throw("Error updating data: ${e.message}");


db.delete(table: "category", where: "id=3").catchError((e) {
   throw("Error deleting data: ${e.message}");



A stream of database change events is available

import 'dart:async';
import 'package:sqlcool/sqlcool.dart';

StreamSubscription changefeed;

changefeed = db.changefeed.listen((change) {
   print("Change in the database:");
   print("Query: ${change.query}");
   if (change.type == DatabaseChange.update) {
     print("${change.value} items updated");
// Dispose the changefeed when finished using it

Reactive select bloc

The bloc will rebuild itself on any database change because of the reactive parameter set to true:

import 'package:flutter/material.dart';
import 'package:sqlcool/sqlcool.dart';

class _PageSelectBlocState extends State<PageSelectBloc> {
  SelectBloc bloc;

  void initState() {
    this.bloc = SelectBloc(
        table: "items", orderBy: "name", reactive: true);

  void dispose() {

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("My app")),
      body: StreamBuilder<List<Map>>(
          stream: bloc.items,
          builder: (BuildContext context, AsyncSnapshot snapshot) {
            if (snapshot.hasData) {
              // the select query has not found anything
              if ( == 0) {
                return Center(child: const Text("No data"));
              // the select query has results
              return ListView.builder(
                  itemBuilder: (BuildContext context, int index) {
                    var item =[index];
                    return ListTile(
                      title: GestureDetector(
                        child: Text(item["name"]),
                        onTap: () => someFunction()),
            } else {
              // the select query is still running
              return CircularProgressIndicator();

class PageSelectBloc extends StatefulWidget {
  _PageSelectBlocState createState() => _PageSelectBlocState();


  • Upsert
  • Batch operations
You can’t perform that action at this time.