143 lines
4.4 KiB
Dart
143 lines
4.4 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:dartx/dartx_io.dart';
|
|
import 'package:guru_utils/file/file_utils.dart';
|
|
import 'package:guru_utils/id/id_utils.dart';
|
|
import 'package:guru_utils/log/log.dart';
|
|
import 'package:path/path.dart';
|
|
import 'package:sqflite/sqflite.dart';
|
|
export 'batch/batch_data.dart';
|
|
export 'batch/batch_aware.dart';
|
|
export 'package:sqflite/sqflite.dart';
|
|
|
|
/// Created by Haoyi on 2022/8/24
|
|
///
|
|
part 'migration.dart';
|
|
|
|
typedef TableCreator = Future Function(Transaction delegate);
|
|
|
|
abstract class AppDatabase {
|
|
late Database _database;
|
|
|
|
List<TableCreator> get tableCreators;
|
|
|
|
List<Migration> get migrations;
|
|
|
|
int get version;
|
|
|
|
String get dbName;
|
|
|
|
Future<String> getTestingPath() async {
|
|
return "./mocks_dir/db";
|
|
}
|
|
|
|
Future _createTables(Database db) {
|
|
return db.transaction((Transaction delegate) async {
|
|
final List<TableCreator> creators = tableCreators;
|
|
for (var creator in creators) {
|
|
await creator(delegate);
|
|
}
|
|
});
|
|
}
|
|
|
|
Future _migrate(Database database, int from, int to) async {
|
|
Log.d("MIGRATE [$from] => [$to]");
|
|
final _migrations = migrations;
|
|
return database.transaction((txn) async {
|
|
for (int index = from - 1; (index < to - 1) && (index < _migrations.length); ++index) {
|
|
var result = MigrateResult.failed;
|
|
try {
|
|
Log.d("====> BEGIN MIGRATE [${index + 1}] => [${index + 2}]");
|
|
result = await _migrations[index].migrate(txn);
|
|
} catch (error) {
|
|
Log.d(" migrate [${index + 1}] => [${index + 2}] error:[$error]");
|
|
rethrow;
|
|
}
|
|
Log.d("====> END MIGRATE [${index + 1}] => [${index + 2}] result: $result");
|
|
}
|
|
});
|
|
}
|
|
Future initDatabase() async {
|
|
final isTesting = Platform.environment.containsKey('FLUTTER_TEST');
|
|
final dbDir = isTesting ? await getTestingPath() : await getDatabasesPath();
|
|
final dbPath = join(dbDir, "$dbName.db");
|
|
Log.d("dbPath:$dbPath");
|
|
_database = await openDatabase(
|
|
dbPath,
|
|
version: version,
|
|
onCreate: (Database db, int version) async {
|
|
// When creating the db, create the table
|
|
try {
|
|
await _createTables(db);
|
|
} catch (error, stacktrace) {
|
|
Log.w("createTables error! $error", stackTrace: stacktrace);
|
|
}
|
|
},
|
|
onUpgrade: (Database db, int oldVersion, int newVersion) async {
|
|
await _migrate(db, oldVersion, newVersion);
|
|
},
|
|
);
|
|
}
|
|
|
|
Database getDb() {
|
|
return _database;
|
|
}
|
|
|
|
Future<T> runInTransaction<T>(Future<T> Function(Transaction txn) action) {
|
|
return getDb().transaction(action);
|
|
}
|
|
|
|
Future backup(String token) async {
|
|
final uuid = IdUtils.keyUuid(token);
|
|
final isTesting = Platform.environment.containsKey('FLUTTER_TEST');
|
|
final dbDir = isTesting ? await getTestingPath() : await getDatabasesPath();
|
|
final dbFile = File(join(dbDir, "$dbName.db"));
|
|
final backupDbFile = File(join(dbDir, "$dbName.$uuid.db"));
|
|
Log.d("backup dbPath:${dbFile.name} to ${backupDbFile.name}");
|
|
if (await FileUtils.instance.checkFileExists(backupDbFile)) {
|
|
await backupDbFile.delete();
|
|
}
|
|
await dbFile.copy(backupDbFile.path);
|
|
}
|
|
|
|
Future<bool> restore(String token) async {
|
|
final uuid = IdUtils.keyUuid(token);
|
|
final isTesting = Platform.environment.containsKey('FLUTTER_TEST');
|
|
final dbDir = isTesting ? await getTestingPath() : await getDatabasesPath();
|
|
final dbFile = File(join(dbDir, "$dbName.db"));
|
|
final restoreDbFile = File(join(dbDir, "$dbName.$uuid.db"));
|
|
Log.d("restore dbPath:${restoreDbFile.name} to ${dbFile.name}");
|
|
if (await FileUtils.instance.checkFileExists(dbFile)) {
|
|
_database.close();
|
|
await dbFile.delete();
|
|
}
|
|
|
|
if (await FileUtils.instance.checkFileExists(restoreDbFile) == false) {
|
|
Log.w("backupDbFile not exists");
|
|
return false;
|
|
}
|
|
await restoreDbFile.copy(dbFile.path);
|
|
return true;
|
|
}
|
|
|
|
Future<bool> switchSession(String oldToken, String newToken) async {
|
|
if (oldToken == newToken) {
|
|
Log.w("same uid, no need to switch");
|
|
return false;
|
|
}
|
|
await getDb().close();
|
|
if (oldToken.isNotEmpty) {
|
|
await backup(oldToken);
|
|
}
|
|
await restore(newToken);
|
|
await initDatabase();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
extension DatabaseExt on AppDatabase {
|
|
String joinTextValue(List<String> value, [String separator = ""]) {
|
|
return value.map((str) => "'$str'").toList().join(separator);
|
|
}
|
|
}
|