更新数据库

This commit is contained in:
Happi (哈比)
2026-03-06 16:54:51 +08:00
parent bf9e099747
commit 113ecb633a
17 changed files with 604 additions and 117 deletions

View File

View File

@@ -45,7 +45,7 @@ class DatabaseDataSource {
}
final file = File('${dbDir.path}/$uid.sqlite');
_db = _databaseFactory(NativeDatabase(file));
_db = _databaseFactory(NativeDatabase.createInBackground(file));
return _db!;
}

View File

@@ -4,11 +4,14 @@ import '../wiring/storage_sdk_wiring.dart';
/// 本地数据库的统一公开接口。
///
/// 通过 [StorageSdkApi] 工厂方法获取实例,传入 App 侧的数据库工厂即可:
/// 通过 [StorageSdkApi] 工厂方法获取实例,传入 App 侧的数据库工厂和表注册表即可:
///
/// ```dart
/// final api = StorageSdkApi(
/// databaseFactory: (executor) => AppDatabase(executor),
/// tableRegistry: (db) => {
/// User: (db as AppDatabase).users,
/// },
/// );
/// ```
///
@@ -19,98 +22,124 @@ import '../wiring/storage_sdk_wiring.dart';
///
/// 内部接口,仅供 App 层生命周期管理使用
abstract class StorageSdkLifecycle {
/// 打开指定用户的数据库(按 uid 隔离文件)。
Future<void> openDatabase(int uid);
/// 关闭当前数据库连接。
Future<void> closeDatabase();
/// 是否已开库。
bool get isDatabaseOpen;
}
///
///
/// ## CRUD
/// 所有 CRUD 方法均为泛型,接受 Drift 的 [TableInfo],与具体业务表解耦。
/// App 层传入自己定义的 Table 即可复用全部操作
/// 所有 CRUD 方法均通过泛型数据类型查找对应表,与具体业务表解耦。
/// App 层通过 [tableRegistry] 注入表映射,无需在调用时传入 [TableInfo]
abstract class StorageSdkApi {
/// 创建 SDK 实例。
///
/// [databaseFactory] 由 App 层提供:接受 [QueryExecutor]
/// 返回自定义的 [GeneratedDatabase] 子类(含表定义和迁移策略)。
///
/// [tableRegistry] 由 App 层提供:将数据类映射到对应的表信息,
/// storage_sdk 不感知具体表结构。
///
/// 示例:
/// ```dart
/// final api = StorageSdkApi(
/// databaseFactory: (executor) => AppDatabase(executor),
/// tableRegistry: (db) => {
/// User: (db as AppDatabase).users,
/// },
/// );
/// ```
factory StorageSdkApi({
required GeneratedDatabase Function(QueryExecutor) databaseFactory,
required Map<Type, TableInfo> Function(GeneratedDatabase) tableRegistry,
}) =>
StorageSdkWiring.build(databaseFactory: databaseFactory);
StorageSdkWiring.build(
databaseFactory: databaseFactory,
tableRegistry: tableRegistry,
);
// ── 插入 ─────────────────────────────────────────────────────────────────
/// 插入或替换(主键冲突时覆盖)。
Future<void> insertOrReplace<T extends Table, D>(
TableInfo<T, D> table,
Insertable<D> companion,
);
///
/// 示例:
/// ```dart
/// await sdk.insertOrReplace<UsersCompanion>(
/// UsersCompanion.insert(nickname: Value('Edmund')),
/// );
/// ```
Future<void> insertOrReplace<D>(Insertable<D> companion);
/// 插入或忽略(主键冲突时跳过)。
Future<void> insert<T extends Table, D>(
TableInfo<T, D> table,
Insertable<D> companion,
);
Future<void> insert<D>(Insertable<D> companion);
/// 批量插入或替换。
Future<void> batchInsertOrReplace<T extends Table, D>(
TableInfo<T, D> table,
List<Insertable<D>> companions,
);
Future<void> batchInsertOrReplace<D>(List<Insertable<D>> companions);
// ── 更新 ─────────────────────────────────────────────────────────────────
/// 按条件更新。
Future<void> updateWhere<T extends Table, D>(
TableInfo<T, D> table,
Insertable<D> companion,
Expression<bool> Function(T) filter,
);
///
/// 示例:
/// ```dart
/// await sdk.updateWhere<User, $UsersTable>(
/// UsersCompanion(nickname: Value('NewName')),
/// (t) => t.uid.equals(123),
/// );
/// ```
Future<void> updateWhere<D, T extends Table>(
Insertable<D> companion,
Expression<bool> Function(T) filter,
);
// ── 删除 ─────────────────────────────────────────────────────────────────
/// 按条件删除。
Future<void> deleteWhere<T extends Table, D>(
TableInfo<T, D> table,
Expression<bool> Function(T) filter,
);
Future<void> deleteWhere<D, T extends Table>(
Expression<bool> Function(T) filter,
);
/// 清空整张表。
Future<void> deleteAll<T extends Table, D>(TableInfo<T, D> table);
Future<void> deleteAll<D>();
// ── 查询 ─────────────────────────────────────────────────────────────────
/// 查询全部记录。
Future<List<D>> selectAll<T extends Table, D>(TableInfo<T, D> table);
///
/// 示例:
/// ```dart
/// final users = await sdk.selectAll<User>();
/// ```
Future<List<D>> selectAll<D>();
/// 按条件查询。
Future<List<D>> selectWhere<T extends Table, D>(
TableInfo<T, D> table,
Expression<bool> Function(T) filter,
);
Future<List<D>> selectWhere<D, T extends Table>(
Expression<bool> Function(T) filter,
);
/// 查询第一条匹配记录。
Future<D?> selectFirst<T extends Table, D>(
TableInfo<T, D> table,
Expression<bool> Function(T) filter,
);
Future<D?> selectFirst<D, T extends Table>(
Expression<bool> Function(T) filter,
);
// ── 监听 ─────────────────────────────────────────────────────────────────
/// 监听全部记录(实时流)。
Stream<List<D>> watchAll<T extends Table, D>(TableInfo<T, D> table);
Stream<List<D>> watchAll<D>();
/// 按条件监听(实时流)。
Stream<List<D>> watchWhere<T extends Table, D>(
TableInfo<T, D> table,
Expression<bool> Function(T) filter,
);
Stream<List<D>> watchWhere<D, T extends Table>(
Expression<bool> Function(T) filter,
);
/// 监听第一条匹配记录(实时流)。
Stream<D?> watchFirst<T extends Table, D>(
TableInfo<T, D> table,
Expression<bool> Function(T) filter,
);
Stream<D?> watchFirst<D, T extends Table>(
Expression<bool> Function(T) filter,
);
// ── 原始 SQL ─────────────────────────────────────────────────────────────
@@ -123,8 +152,7 @@ abstract class StorageSdkApi {
// ── 统计 ─────────────────────────────────────────────────────────────────
/// 统计记录数。
Future<int> count<T extends Table, D>(
TableInfo<T, D> table, {
Future<int> count<D, T extends Table>({
Expression<bool> Function(T)? filter,
});
}
}

View File

@@ -6,14 +6,29 @@ import 'storage_sdk_core.dart';
/// [StorageSdkApi] 的实现,委托给 [StorageSdkCore]。
class StorageSdkApiImpl implements StorageSdkApi, StorageSdkLifecycle {
final StorageSdkCore _core;
final Map<Type, TableInfo> Function(GeneratedDatabase) _tableRegistry;
StorageSdkApiImpl({required StorageSdkCore core}) : _core = core;
StorageSdkApiImpl({
required StorageSdkCore core,
required Map<Type, TableInfo> Function(GeneratedDatabase) tableRegistry,
}) : _core = core,
_tableRegistry = tableRegistry;
// ── 表查找 ───────────────────────────────────────────────────────────────
/// 根据泛型数据类型从注册表中查找对应的 [TableInfo]。
TableInfo<T, D> _tableFor<T extends Table, D>() {
final db = _core.dataSource.current;
if (db == null) throw StateError('数据库未开启,请先调用 openDatabase()');
final table = _tableRegistry(db)[D];
if (table == null) throw StateError('未注册类型 $D 对应的表,请检查 tableRegistry');
return table as TableInfo<T, D>;
}
// ── 生命周期 ─────────────────────────────────────────────────────────────
@override
Future<void> openDatabase(int uid) =>
_core.dataSource.openDatabase(uid);
Future<void> openDatabase(int uid) => _core.dataSource.openDatabase(uid);
@override
Future<void> closeDatabase() => _core.dataSource.closeDatabase();
@@ -24,88 +39,73 @@ class StorageSdkApiImpl implements StorageSdkApi, StorageSdkLifecycle {
// ── 插入 ─────────────────────────────────────────────────────────────────
@override
Future<void> insertOrReplace<T extends Table, D>(
TableInfo<T, D> table,
Insertable<D> companion,
) =>
_core.repo.insertOrReplace(table, companion);
Future<void> insertOrReplace<D>(Insertable<D> companion) =>
_core.repo.insertOrReplace(_tableFor<Table, D>(), companion);
@override
Future<void> insert<T extends Table, D>(
TableInfo<T, D> table,
Insertable<D> companion,
) =>
_core.repo.insert(table, companion);
Future<void> insert<D>(Insertable<D> companion) =>
_core.repo.insert(_tableFor<Table, D>(), companion);
@override
Future<void> batchInsertOrReplace<T extends Table, D>(
TableInfo<T, D> table,
List<Insertable<D>> companions,
) =>
_core.repo.batchInsertOrReplace(table, companions);
Future<void> batchInsertOrReplace<D>(List<Insertable<D>> companions) =>
_core.repo.batchInsertOrReplace(_tableFor<Table, D>(), companions);
// ── 更新 ─────────────────────────────────────────────────────────────────
@override
Future<void> updateWhere<T extends Table, D>(
TableInfo<T, D> table,
Insertable<D> companion,
Expression<bool> Function(T) filter,
) =>
_core.repo.updateWhere(table, companion, filter);
Future<void> updateWhere<D, T extends Table>(
Insertable<D> companion,
Expression<bool> Function(T) filter,
) =>
_core.repo.updateWhere(_tableFor<T, D>(), companion, filter);
// ── 删除 ─────────────────────────────────────────────────────────────────
@override
Future<void> deleteWhere<T extends Table, D>(
TableInfo<T, D> table,
Expression<bool> Function(T) filter,
) =>
_core.repo.deleteWhere(table, filter);
Future<void> deleteWhere<D, T extends Table>(
Expression<bool> Function(T) filter,
) =>
_core.repo.deleteWhere(_tableFor<T, D>(), filter);
@override
Future<void> deleteAll<T extends Table, D>(TableInfo<T, D> table) =>
_core.repo.deleteAll(table);
Future<void> deleteAll<D>() =>
_core.repo.deleteAll(_tableFor<Table, D>());
// ── 查询 ─────────────────────────────────────────────────────────────────
@override
Future<List<D>> selectAll<T extends Table, D>(TableInfo<T, D> table) =>
_core.repo.selectAll(table);
Future<List<D>> selectAll<D>() =>
_core.repo.selectAll(_tableFor<Table, D>());
@override
Future<List<D>> selectWhere<T extends Table, D>(
TableInfo<T, D> table,
Expression<bool> Function(T) filter,
) =>
_core.repo.selectWhere(table, filter);
Future<List<D>> selectWhere<D, T extends Table>(
Expression<bool> Function(T) filter,
) =>
_core.repo.selectWhere(_tableFor<T, D>(), filter);
@override
Future<D?> selectFirst<T extends Table, D>(
TableInfo<T, D> table,
Expression<bool> Function(T) filter,
) =>
_core.repo.selectFirst(table, filter);
Future<D?> selectFirst<D, T extends Table>(
Expression<bool> Function(T) filter,
) =>
_core.repo.selectFirst(_tableFor<T, D>(), filter);
// ── 监听 ─────────────────────────────────────────────────────────────────
@override
Stream<List<D>> watchAll<T extends Table, D>(TableInfo<T, D> table) =>
_core.repo.watchAll(table);
Stream<List<D>> watchAll<D>() =>
_core.repo.watchAll(_tableFor<Table, D>());
@override
Stream<List<D>> watchWhere<T extends Table, D>(
TableInfo<T, D> table,
Expression<bool> Function(T) filter,
) =>
_core.repo.watchWhere(table, filter);
Stream<List<D>> watchWhere<D, T extends Table>(
Expression<bool> Function(T) filter,
) =>
_core.repo.watchWhere(_tableFor<T, D>(), filter);
@override
Stream<D?> watchFirst<T extends Table, D>(
TableInfo<T, D> table,
Expression<bool> Function(T) filter,
) =>
_core.repo.watchFirst(table, filter);
Stream<D?> watchFirst<D, T extends Table>(
Expression<bool> Function(T) filter,
) =>
_core.repo.watchFirst(_tableFor<T, D>(), filter);
// ── 原始 SQL ─────────────────────────────────────────────────────────────
@@ -120,9 +120,8 @@ class StorageSdkApiImpl implements StorageSdkApi, StorageSdkLifecycle {
// ── 统计 ─────────────────────────────────────────────────────────────────
@override
Future<int> count<T extends Table, D>(
TableInfo<T, D> table, {
Future<int> count<D, T extends Table>({
Expression<bool> Function(T)? filter,
}) =>
_core.repo.count(table, filter: filter);
}
_core.repo.count(_tableFor<T, D>(), filter: filter);
}

View File

@@ -8,12 +8,15 @@ import 'storage_sdk_api_impl.dart';
/// SDK 依赖装配入口。
///
/// 调用方传入数据库工厂SDK 负责连接生命周期和 CRUD 机制。
/// 调用方传入数据库工厂和表注册表SDK 负责连接生命周期和 CRUD 机制。
///
/// 示例im_app 的 DI 层):
/// ```dart
/// StorageSdkWiring.build(
/// databaseFactory: (executor) => AppDatabase(executor),
/// tableRegistry: (db) => {
/// User: (db as AppDatabase).users,
/// },
/// );
/// ```
class StorageSdkWiring {
@@ -21,10 +24,11 @@ class StorageSdkWiring {
static StorageSdkApi build({
required GeneratedDatabase Function(QueryExecutor) databaseFactory,
required Map<Type, TableInfo> Function(GeneratedDatabase) tableRegistry,
}) {
final dataSource = DatabaseDataSource(databaseFactory: databaseFactory);
final repo = DatabaseRepositoryImpl(dataSource);
final core = StorageSdkCore(dataSource: dataSource, repo: repo);
return StorageSdkApiImpl(core: core);
return StorageSdkApiImpl(core: core, tableRegistry: tableRegistry);
}
}
}