パッケージ、リポジトリ、アプリカテゴリを検索

パッケージ詳細v5.1.1

sqlcool

簡単でリアクティブなSqlite。変更のストリーム、選択ブロック、カスタムデータベースモデル

30日間ダウンロード
148
いいね数
43
Pub ポイント
40

パッケージをインストール

flutter pub add sqlcool

パッケージ概要

公開情報に基づく選定ガイドです。参考としてご利用ください。

Sqlcool は、データベースの変更に対するリアクティブストリーム、組み込みの select bloc パターン、カスタムデータベースモデルのサポートを提供することで、SQLite データベースとの連携を簡素化する Flutter/Dart パッケージです。最小限のボイラープレートでリアルタイムでのデータ同期と効率的なクエリを可能にします。Flutter アプリにおけるローカル永続データストレージのための軽量で直感的なソリューションを求める開発者向けに設計されており、リアクティブプログラミングパラダイムとシームレスに統合されます。複雑なデータベース操作に対しても柔軟性を維持しながら、使いやすさを重視しています。

用途

  • オフライン優先アプリにおけるリアルタイムデータ同期
  • データベースの変更に基づくリアクティブなUIの更新
  • 構造化データベースモデルを使用したローカル状態の管理
  • 動的データ読み込みを使用したフォームの作成
  • SQLite を用いたキャッシュレイヤーの実装
  • カスタムモデルを使用したCRUD操作の簡素化

主な機能

  • データベース変更通知のリアクティブストリーム
  • 状態管理のための組み込み選択ブロックパターン
  • カスタムデータベースモデル定義のサポート
  • クエリおよびミューテーションのためのシンプルな API
  • 自動的な型安全なモデルマッピング
  • 軽量で依存関係が最小限

適している対象

  • オフライン対応のFlutterアプリを開発する開発者
  • リアクティブな状態管理を使用するチーム
  • リアルタイムデータベースの更新を必要とするプロジェクト
  • 構造化されたローカルデータの永続化を必要とするアプリ
  • FlutterでSQLiteを学ぶ初心者
  • 頻繁なローカルデータ操作を持つアプリ

注意事項

  • SQLiteのみに制限(他のデータベースは不可)
  • 組み込みのマイグレーション処理なし(手動または外部ツールが必要)
  • 複雑なスキーマの変更には追加の設定が必要になる場合があります
  • 大規模なサーバーサイドデータベース操作には適していません
  • モバイルおよびデスクトップの使用ケースに最適
  • リアクティブプログラミングの概念を理解する必要がある

元の README

関連するソースリポジトリの README 原文のスナップショットです。最新の内容はリポジトリをご覧ください。

Sqlcool

pub package Build Status Coverage Status

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
  • Adaptative: plug custom models into the database

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)
   ..integer("price")
   ..text("descripton", nullable: true)
   ..foreignKey("category", onDelete: OnDelete.cascade)
   ..index("name");
List<DbTable> schema = [category, product];
Initialize the database
String dbpath = "db.sqlite"; // relative to the documents directory
try {
  await db.init(path: dbpath, schema: schema);
} catch(e) {
  rethrow;
}
Insert
final Map<String, String> row = {name: "My item"};
try {
  int id = await db.insert(table: "category", row: row)
} catch(e) {
  rethrow;
}
Select
try {
  List<Map<String, dynamic>> rows = await db.select(
    table: "product",
    limit: 20,
    columns: "id,name",
    where: "name LIKE '%something%'",
    orderBy: "name ASC",
  );
} catch (e) {
  rethrow;
}
Update
try {
  int numRowsUpdated = await db.update(table: "category", 
   row: row, where: "id=1");
} catch(e) {
  rethrow;
}
Delete
try {
  await db.delete(table: "category", where: "id=3");
} catch(e) {
  rethrow;
}
Join queries
try {
  final data = await db.join(
   table: "product",
   columns: "product.name,price,category.name as category_name",
   joinTable: "category",
   joinOn: "product.category=category.id");
} catch(e) {
  rethrow;
}
Join on multiple tables
try {
  final data = db.mJoin(table: "product", joinsTables: <String>[
   "category",
   "manufacturer"
 ], joinsOn: <String>[
   "product.category=category.id",
   "product.manufacturer=manufacturer.id"
 ]);
} catch(e) {
  rethrow;
}

Reactivity

Changefeed

A stream of database change events is available. Inspired by Rethinkdb

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
changefeed.cancel();
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;

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

  @override
  void dispose() {
    bloc.dispose();
    super.dispose();
  }

  @override
  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 (snapshot.data.length == 0) {
                return Center(child: const Text("No data"));
              }
              // the select query has results
              return ListView.builder(
                  itemCount: snapshot.data.length,
                  itemBuilder: (BuildContext context, int index) {
                    var item = snapshot.data[index];
                    return ListTile(
                      title: GestureDetector(
                        child: Text(item["name"]),
                        onTap: () => someFunction()),
                    );
                  });
            } else {
              // the select query is still running
              return CircularProgressIndicator();
            }
          }),
    );
  }
}

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

Database models

New in 4.0.0: define models that have database methods. The main advantage of this is to use only typed model data and avoid the type conversions from maps for every query. It directly plugs custom models into the database. Example:

In schema.dart:

final carTable = DbTable("car")
  ..varchar("name")
  ..integer("max_speed")
  ..real("price")
  ..integer("year")
  ..boolean("is_4wd", defaultValue: false)
  ..foreignKey("manufacturer", onDelete: OnDelete.cascade);

final manufacturerTable = DbTable("manufacturer")..varchar("name");

In car_model.dart:

import 'package:sqlcool/sqlcool.dart';
// the database schema
import 'schema.dart';
// another model
import 'manufacturer_model.dart';

class Car with DbModel {
  Car(
      {this.id,
      this.name,
      this.maxSpeed,
      this.price,
      this.year,
      this.is4wd,
      this.manufacturer});

  /// define some class properties

  final String name;
  final int maxSpeed;
  final double price;
  final DateTime year;
  final bool is4wd;
  // this is a foreign key to another model
  Manufacturer manufacturer;

  /// [DbModel] required overrides

  @override
  int id;

  /// the [Db] used
  /// pass it your main db
  @override
  Db get db => db;

  /// the table schema representation
  /// check example/pages/dbmodels/schema.dart
  @override
  DbTable get table => carTable;

  /// serialize a row to the database
  @override
  Map<String, dynamic> toDb() {
    // we want the foreign key to be recorded
    assert(manufacturer?.id != null);
    final row = <String, dynamic>{
      "name": name,
      "max_speed": maxSpeed,
      "price": price,
      "year": year.millisecondsSinceEpoch,
      "is_4wd": is4wd,
      "manufacturer": manufacturer.id
    };
    return row;
  }

  /// deserialize a row from database
  @override
  Car fromDb(Map<String, dynamic> map) {
    final car = Car(
      id: map["id"] as int,
      name: map["name"].toString(),
      maxSpeed: map["max_speed"] as int,
      price: map["price"] as double,
      year: DateTime.fromMillisecondsSinceEpoch(map["year"] as int),
      is4wd: (map["is_4wd"].toString() == "true"),
    );
    // the key will be present only with join queries
    // in a simple select this data is not present
    if (map.containsKey("manufacturer")) {
      car.manufacturer =
          Manufacturer().fromDb(map["manufacturer"] as Map<String, dynamic>);
    }
    return car;
  }

  /// Create a static join method for convenience

  static Future<List<Car>> selectRelated({String where, int limit}) async {
    final cars = List<Car>.from(
        await Car().sqlJoin(where: where, limit: limit, verbose: true));
    return cars;
  }
}

Then use the models:

/// car is an instance of [Car]
await car.sqlInsert();
await car.sqlUpdate();
await car.sqlUpsert();
await car.sqlDelete();
final cars = Car.selectRelated(where: "speed>200");
// foreign keys are retrieved as model instances
print(cars[0].manufacturer.name);

Using this

  • Sqlview: admin view and infinite list view
  • Kvsql: a type safe key/value store
  • Geopoint sql: sql operations for geospatial data

カテゴリー

依存関係

依存関係一覧 5 件

ソースリポジトリ

このパッケージを使用しているプロジェクト

データはまだありません。