패키지, 저장소 및 앱 카테고리 검색

패키지 상세v5.1.1

sqlcool

간편하고 반응형 Sqlite. 변경 스트림, 선택 블록, 사용자 정의 데이터베이스 모델

30일 다운로드
148
좋아요
43
Pub 점수
40

패키지 설치

flutter pub add sqlcool

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

Sqlcool은 데이터베이스 변경에 대한 반응형 스트림, 내장된 선택 블록 패턴, 사용자 정의 데이터베이스 모델 지원을 제공함으로써 SQLite 데이터베이스 작업을 간소화하는 Flutter/Dart 패키지입니다. 최소한의 반복 코드로 실시간 데이터 동기화와 효율적인 쿼리가 가능합니다. Flutter 앱에서 로컬 지속성 데이터 저장을 위한 가볍고 직관적인 솔루션을 찾는 개발자를 위해 설계되었으며, 반응형 프로그래밍 패러다임과 원활하게 통합됩니다. 복잡한 데이터베이스 작업에 대한 유연성을 유지하면서도 사용의 용이성을 강조합니다.

사용 사례

  • 오프라인 우선 앱에서의 실시간 데이터 동기화
  • 데이터베이스 변경에 기반한 반응형 UI 업데이트
  • 구조화된 데이터베이스 모델을 사용한 로컬 상태 관리
  • 동적 데이터 로딩을 사용한 폼 만들기
  • SQLite를 사용한 캐시 레이어 구현
  • 사용자 정의 모델을 사용한 CRUD 작업 간소화

주요 기능

  • 데이터베이스 변경 알림을 위한 반응형 스트림
  • 상태 관리를 위한 내장 선택 블록 패턴
  • 사용자 정의 데이터베이스 모델 정의 지원
  • 쿼리 및 변환을 위한 간단한 API
  • 자동 타입 안전 모델 매핑
  • 경량이며 최소한의 종속성

적합한 대상

  • 오프라인 기능을 갖춘 플러터 앱을 개발하는 개발자
  • 반응형 상태 관리 사용 팀
  • 실시간 데이터베이스 업데이트가 필요한 프로젝트
  • 구조화된 로컬 데이터 지속성을 필요로 하는 앱
  • 플러터에서 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 개

소스 저장소

이 패키지를 사용하는 프로젝트

아직 데이터가 없습니다.