Files
smooth-app/packages/smooth_app/lib/database/local_database.dart
monsieurtanuki 1662685825 feat: #2280 - DaoProduct's just migrated to sqflite (#2289)
New files:
* `abstract_sql_dao.dart`: DAO abstraction for SQL.
* `bulk_deletable.dart`: Interface for bulk database deletes.
* `bulk_insertable.dart`: Interface for bulk database inserts.
* `bulk_manager.dart`: Manager for bulk database inserts and deletes.
* `dao_hive_product.dart`: moved code from the previous `hive` version of `DaoProduct`, renamed here `DaoHiveProduct`

Impacted files:
* `dao_product.dart`: `sqflite` version of `DaoProduct`, that is from now on the only one to be used
* `local_database.dart`: added `sqflite` and its one table so far, also named `DaoProduct` in order to minimize the changes everywhere else (the old `DaoProduct` being renamed `DaoHiveProduct`); migrated the product data from `hive` to `sqflite`
* `Podfile.lock`: wtf
* `pubspec.lock`: wtf
* `data_importer/pubspec.yaml`: updated the `sqflite` dependency to the same as in `smooth_app`
* `smooth_app/pubspec.yaml`: added a dependency to `sqflite`
2022-06-16 07:09:09 +02:00

123 lines
4.1 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:openfoodfacts/model/Product.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:smooth_app/database/abstract_dao.dart';
import 'package:smooth_app/database/dao_hive_product.dart';
import 'package:smooth_app/database/dao_int.dart';
import 'package:smooth_app/database/dao_product.dart';
import 'package:smooth_app/database/dao_product_list.dart';
import 'package:smooth_app/database/dao_string.dart';
import 'package:smooth_app/database/dao_string_list.dart';
import 'package:smooth_app/database/dao_string_list_map.dart';
import 'package:sqflite/sqflite.dart';
class LocalDatabase extends ChangeNotifier {
LocalDatabase._(final Database database) : _database = database;
final Database _database;
Database get database => _database;
/// Notify listeners
/// Comments added only in order to avoid a "warning"
/// For the record, we need to override the method
/// because the parent's is protected
@override
void notifyListeners() => super.notifyListeners();
static Future<LocalDatabase> getLocalDatabase() async {
// sql from there
final String databasesRootPath;
if (defaultTargetPlatform == TargetPlatform.iOS) {
// as suggested in https://pub.dev/documentation/sqflite/latest/sqflite/getDatabasesPath.html
final Directory directory = await getLibraryDirectory();
databasesRootPath = directory.path;
} else {
databasesRootPath = await getDatabasesPath();
}
final String databasePath = join(databasesRootPath, 'smoothie.db');
final Database database = await openDatabase(
databasePath,
version: 1,
singleInstance: true,
onUpgrade: _onUpgrade,
);
final LocalDatabase localDatabase = LocalDatabase._(database);
// only hive from there
await Hive.initFlutter();
final List<AbstractDao> daos = <AbstractDao>[
DaoHiveProduct(localDatabase),
DaoProductList(localDatabase),
DaoStringList(localDatabase),
DaoString(localDatabase),
DaoInt(localDatabase),
DaoStringListMap(localDatabase),
];
for (final AbstractDao dao in daos) {
dao.registerAdapter();
}
for (final AbstractDao dao in daos) {
await dao.init();
}
// Migration here
await _migrate(localDatabase);
return localDatabase;
}
static Future<void> _migrate(final LocalDatabase localDatabase) async {
final DaoHiveProduct daoHiveProduct = DaoHiveProduct(localDatabase);
final List<String> barcodesFrom = await daoHiveProduct.getAllKeys();
if (barcodesFrom.isEmpty) {
// nothing to migrate, or already migrated and cleaned.
return;
}
final DaoProduct daoProduct = DaoProduct(localDatabase);
final List<String> barcodesAlreadyThere = await daoProduct.getAllKeys();
final List<String> barcodesToBeCopied = List<String>.from(barcodesFrom);
barcodesToBeCopied.removeWhere(
(final String barcode) => barcodesAlreadyThere.contains(barcode));
if (barcodesToBeCopied.isNotEmpty) {
final Map<String, Product> copiedProducts =
await daoHiveProduct.getAll(barcodesToBeCopied);
await daoProduct.putAll(copiedProducts.values);
final List<String> barcodesFinallyThere = await daoProduct.getAllKeys();
if (barcodesFinallyThere.length !=
barcodesAlreadyThere.length + barcodesToBeCopied.length) {
// unexpected
return;
}
}
// cleaning the old product table
await daoHiveProduct.deleteAll(barcodesFrom);
final List<String> barcodesNoMore = await daoProduct.getAllKeys();
if (barcodesNoMore.isNotEmpty) {
// unexpected
}
}
static int nowInMillis() => DateTime.now().millisecondsSinceEpoch;
/// we don't use onCreate and onUpgrade, we use only onUpgrade instead.
/// checked: from scratch, onUpgrade is called with oldVersion = 0.
static FutureOr<void> _onUpgrade(
final Database db,
final int oldVersion,
final int newVersion,
) async {
await DaoProduct.onUpgrade(db, oldVersion, newVersion);
}
}