From f92770aceda3d011b5cef9ee5125acfa48afb442 Mon Sep 17 00:00:00 2001 From: Hamlet Jiang Su Date: Fri, 1 Nov 2024 06:28:59 -0700 Subject: [PATCH] chore: bring back sqflite dependency, improve database initialization --- ios/Podfile.lock | 26 ++++++++++- lib/core/database/connection/native.dart | 23 +++------- lib/core/database/connection/unsupported.dart | 5 -- lib/core/database/connection/web.dart | 46 +++++++------------ lib/core/database/database.dart | 21 ++++++++- lib/main.dart | 21 +++++---- linux/flutter/generated_plugin_registrant.cc | 4 ++ linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + macos/Podfile.lock | 26 ++++++++++- pubspec.lock | 30 ++++++++++-- pubspec.yaml | 11 +++-- test/database/migration_test.dart | 4 +- .../flutter/generated_plugin_registrant.cc | 3 ++ windows/flutter/generated_plugins.cmake | 1 + 15 files changed, 153 insertions(+), 71 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index a0dcadd91..5b7a98edb 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -51,6 +51,24 @@ PODS: - sqflite_darwin (0.0.4): - Flutter - FlutterMacOS + - sqlite3 (3.47.0): + - sqlite3/common (= 3.47.0) + - sqlite3/common (3.47.0) + - sqlite3/dbstatvtab (3.47.0): + - sqlite3/common + - sqlite3/fts5 (3.47.0): + - sqlite3/common + - sqlite3/perf-threadsafe (3.47.0): + - sqlite3/common + - sqlite3/rtree (3.47.0): + - sqlite3/common + - sqlite3_flutter_libs (0.0.1): + - Flutter + - sqlite3 (~> 3.47.0) + - sqlite3/dbstatvtab + - sqlite3/fts5 + - sqlite3/perf-threadsafe + - sqlite3/rtree - uni_links (0.0.1): - Flutter - url_launcher_ios (0.0.1): @@ -84,6 +102,7 @@ DEPENDENCIES: - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) + - sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/ios`) - uni_links (from `.symlinks/plugins/uni_links/ios`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`) @@ -92,6 +111,7 @@ DEPENDENCIES: SPEC REPOS: trunk: - OrderedSet + - sqlite3 EXTERNAL SOURCES: background_fetch: @@ -136,6 +156,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/shared_preferences_foundation/darwin" sqflite_darwin: :path: ".symlinks/plugins/sqflite_darwin/darwin" + sqlite3_flutter_libs: + :path: ".symlinks/plugins/sqlite3_flutter_libs/ios" uni_links: :path: ".symlinks/plugins/uni_links/ios" url_launcher_ios: @@ -168,6 +190,8 @@ SPEC CHECKSUMS: share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 sqflite_darwin: a553b1fd6fe66f53bbb0fe5b4f5bab93f08d7a13 + sqlite3: 0aa20658a9b238a3b1ff7175eb7bdd863b0ab4fd + sqlite3_flutter_libs: b55ef23cfafea5318ae5081e0bf3fbbce8417c94 uni_links: d97da20c7701486ba192624d99bffaaffcfc298a url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3 @@ -175,4 +199,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 8d23d5c4d896af3a5f2a08e0206462ca9882e556 -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.0 diff --git a/lib/core/database/connection/native.dart b/lib/core/database/connection/native.dart index f1efd31c1..5006c318b 100644 --- a/lib/core/database/connection/native.dart +++ b/lib/core/database/connection/native.dart @@ -1,33 +1,24 @@ import 'dart:io'; +import 'package:flutter/foundation.dart'; + import 'package:drift/drift.dart'; import 'package:drift_dev/api/migrations.dart'; -import 'package:flutter/foundation.dart'; +import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:path/path.dart' as p; -import 'package:drift/native.dart'; -import '../database.dart'; Future get databaseFile async { - // We use `path_provider` to find a suitable path to store our data in. - final appDir = await getApplicationDocumentsDirectory(); - final dbPath = p.join(appDir.path, 'todo-app.sqlite'); - return File(dbPath); -} + final dbFolder = await getApplicationDocumentsDirectory(); + final file = File(join(dbFolder.path, 'thunder.sqlite')); -AppDatabase constructDb() { - final db = LazyDatabase(() async { - final dbFolder = await getApplicationDocumentsDirectory(); - final file = File(p.join(dbFolder.path, 'db.sqlite')); - return NativeDatabase(file); - }); - return AppDatabase(db); + return file; } Future validateDatabaseSchema(GeneratedDatabase database) async { // This method validates that the actual schema of the opened database matches // the tables, views, triggers and indices for which drift_dev has generated // code. + // // Validating the database's schema after opening it is generally a good idea, // since it allows us to get an early warning if we change a table definition // without writing a schema migration for it. diff --git a/lib/core/database/connection/unsupported.dart b/lib/core/database/connection/unsupported.dart index f291a1fdb..2161a3549 100644 --- a/lib/core/database/connection/unsupported.dart +++ b/lib/core/database/connection/unsupported.dart @@ -1,14 +1,9 @@ import 'package:drift/drift.dart'; -import '../database.dart'; Never _unsupported() { throw UnsupportedError('No suitable database implementation was found on this platform.'); } -// Depending on the platform the app is compiled to, the following stubs will -// be replaced with the methods in native.dart or web.dart -AppDatabase constructDb() => throw UnimplementedError(); - Future validateDatabaseSchema(GeneratedDatabase database) async { _unsupported(); } diff --git a/lib/core/database/connection/web.dart b/lib/core/database/connection/web.dart index 8e46139e7..7e81c5f94 100644 --- a/lib/core/database/connection/web.dart +++ b/lib/core/database/connection/web.dart @@ -1,34 +1,22 @@ +import 'package:flutter/foundation.dart'; + import 'package:drift/drift.dart'; -import 'package:drift/wasm.dart'; -import '../database.dart'; Future validateDatabaseSchema(GeneratedDatabase database) async { - // Unfortunately, validating database schemas only works for native platforms - // right now. - // As we also have migration tests (see the `Testing migrations` section in - // the readme of this example), this is not a huge issue. -} - -DatabaseConnection connectOnWeb() { - return DatabaseConnection.delayed(Future(() async { - final result = await WasmDatabase.open( - databaseName: 'thunder', // prefer to only use valid identifiers here - sqlite3Uri: Uri.parse('sqlite3.wasm'), - driftWorkerUri: Uri.parse('drift_worker.dart.js'), - ); - - if (result.missingFeatures.isNotEmpty) { - // Depending how central local persistence is to your app, you may want - // to show a warning to the user if only unrealiable implemetentations - // are available. - print('Using ${result.chosenImplementation} due to missing browser ' - 'features: ${result.missingFeatures}'); - } - - return result.resolvedExecutor; - })); -} + // This method validates that the actual schema of the opened database matches + // the tables, views, triggers and indices for which drift_dev has generated + // code. + // + // Validating the database's schema after opening it is generally a good idea, + // since it allows us to get an early warning if we change a table definition + // without writing a schema migration for it. + // + // For details, see: https://drift.simonbinder.eu/docs/advanced-features/migrations/#verifying-a-database-schema-at-runtime + if (kDebugMode) { + // TODO: Add validation when updating to drift 2.22 + // final sqlite = await WasmSqlite3.loadFromUrl(Uri.parse('/sqlite3.wasm')); + // sqlite.registerVirtualFileSystem(InMemoryFileSystem(), makeDefault: true); -AppDatabase constructDb() { - return AppDatabase(connectOnWeb()); + // await VerifySelf(database).validateDatabaseSchema(sqlite3: sqlite); + } } diff --git a/lib/core/database/database.dart b/lib/core/database/database.dart index 52a644ffc..aa377d0d8 100644 --- a/lib/core/database/database.dart +++ b/lib/core/database/database.dart @@ -1,10 +1,13 @@ import 'dart:io'; -import 'package:drift/drift.dart'; import 'package:flutter/foundation.dart'; + +import 'package:drift/drift.dart'; +import 'package:drift_flutter/drift_flutter.dart'; import 'package:flutter_file_dialog/flutter_file_dialog.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; + import 'package:thunder/core/database/schema_versions.dart'; import 'package:thunder/core/database/tables.dart'; import 'package:thunder/core/database/type_converters.dart'; @@ -16,7 +19,21 @@ part 'database.g.dart'; @DriftDatabase(tables: [Accounts, Favorites, LocalSubscriptions, UserLabels, Drafts]) class AppDatabase extends _$AppDatabase { - AppDatabase(super.e); + AppDatabase() + : super( + driftDatabase( + name: 'thunder', + web: DriftWebOptions( + sqlite3Wasm: Uri.parse('sqlite3.wasm'), + driftWorker: Uri.parse('drift_worker.js'), + onResult: (result) { + if (result.missingFeatures.isNotEmpty) { + debugPrint('Using ${result.chosenImplementation} due to unsupported browser features: ${result.missingFeatures}'); + } + }, + ), + ), + ); @override int get schemaVersion => 5; diff --git a/lib/main.dart b/lib/main.dart index 6ee0ca115..cb60d0cd5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -54,18 +54,21 @@ bool _isDatabaseInitialized = false; Future initializeDatabase() async { if (_isDatabaseInitialized) return; - debugPrint('Initializing drift db.'); + if (kIsWeb) { + database = AppDatabase(); + return; + } - database = constructDb(); + // There is a specific ordering here. + // We're checking to see if the drift database exists. If it doesn't exist, we perform migration from the old SQLite database. + // The ordering matters here as database = AppDatabase() will create the database if it doesn't exist. + File dbFile = File(join((await getApplicationDocumentsDirectory()).path, 'thunder.sqlite')); - // Bypass migrateToSQList for web. - if (!kIsWeb) { - File dbFile = File(join((await getApplicationDocumentsDirectory()).path, 'thunder.sqlite')); + database = AppDatabase(); - if (!await dbFile.exists()) { - debugPrint('Migrating from SQLite db.'); - await migrateToSQLite(database); - } + if (!await dbFile.exists()) { + debugPrint('Migrating from SQLite db.'); + await migrateToSQLite(database); } _isDatabaseInitialized = true; diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 36af2d701..f3a9a7889 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include void fl_register_plugins(FlPluginRegistry* registry) { @@ -17,6 +18,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); file_selector_plugin_register_with_registrar(file_selector_linux_registrar); + g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin"); + sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index f308ccc60..54fe97516 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color file_selector_linux + sqlite3_flutter_libs url_launcher_linux ) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 464487c2f..a2b182b07 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -16,6 +16,7 @@ import path_provider_foundation import share_plus import shared_preferences_foundation import sqflite_darwin +import sqlite3_flutter_libs import url_launcher_macos import video_player_avfoundation import webview_flutter_wkwebview @@ -32,6 +33,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) + Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin")) FLTWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "FLTWebViewFlutterPlugin")) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 0c1301f44..e2498014b 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -29,6 +29,24 @@ PODS: - sqflite_darwin (0.0.4): - Flutter - FlutterMacOS + - sqlite3 (3.47.0): + - sqlite3/common (= 3.47.0) + - sqlite3/common (3.47.0) + - sqlite3/dbstatvtab (3.47.0): + - sqlite3/common + - sqlite3/fts5 (3.47.0): + - sqlite3/common + - sqlite3/perf-threadsafe (3.47.0): + - sqlite3/common + - sqlite3/rtree (3.47.0): + - sqlite3/common + - sqlite3_flutter_libs (0.0.1): + - FlutterMacOS + - sqlite3 (~> 3.47.0) + - sqlite3/dbstatvtab + - sqlite3/fts5 + - sqlite3/perf-threadsafe + - sqlite3/rtree - url_launcher_macos (0.0.1): - FlutterMacOS - video_player_avfoundation (0.0.1): @@ -51,6 +69,7 @@ DEPENDENCIES: - share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`) - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`) + - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - video_player_avfoundation (from `Flutter/ephemeral/.symlinks/plugins/video_player_avfoundation/darwin`) - webview_flutter_wkwebview (from `Flutter/ephemeral/.symlinks/plugins/webview_flutter_wkwebview/darwin`) @@ -58,6 +77,7 @@ DEPENDENCIES: SPEC REPOS: trunk: - OrderedSet + - sqlite3 EXTERNAL SOURCES: connectivity_plus: @@ -84,6 +104,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin sqflite_darwin: :path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin + sqlite3_flutter_libs: + :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos url_launcher_macos: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos video_player_avfoundation: @@ -105,10 +127,12 @@ SPEC CHECKSUMS: share_plus: fd717ef89a2801d3491e737630112b80c310640e shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 sqflite_darwin: a553b1fd6fe66f53bbb0fe5b4f5bab93f08d7a13 + sqlite3: 0aa20658a9b238a3b1ff7175eb7bdd863b0ab4fd + sqlite3_flutter_libs: f0b7a85544d8bac7b8bac12eac7d05bcfdd786d0 url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404 video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3 webview_flutter_wkwebview: 0982481e3d9c78fd5c6f62a002fcd24fc791f1e4 PODFILE CHECKSUM: c2e95c8c0fe03c5c57e438583cae4cc732296009 -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.0 diff --git a/pubspec.lock b/pubspec.lock index efd47dc27..7551d0b8a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -394,10 +394,18 @@ packages: dependency: "direct dev" description: name: drift_dev - sha256: "27bab15e7869b69259663590381180117873b9b273a1ea9ebb21bb73133d1233" + sha256: "623649abe932fc17bd32e578e7e05f7ac5e7dd0b33e6c8669a0634105d1389bf" url: "https://pub.dev" source: hosted - version: "2.21.0" + version: "2.21.2" + drift_flutter: + dependency: "direct main" + description: + name: drift_flutter + sha256: fec503e9d408f36bb345f9f6d24bc9d62b7b5f970db49760253d9e8d3acd48d5 + url: "https://pub.dev" + source: hosted + version: "0.2.1" dynamic_color: dependency: "direct main" description: @@ -1648,7 +1656,7 @@ packages: source: hosted version: "7.0.0" sqflite: - dependency: transitive + dependency: "direct dev" description: name: sqflite sha256: "79a297dc3cc137e758c6a4baf83342b039e5a6d2436fcdf3f96a00adaaf2ad62" @@ -1671,6 +1679,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.5.4+5" + sqflite_common_ffi: + dependency: "direct dev" + description: + name: sqflite_common_ffi + sha256: d316908f1537725427ff2827a5c5f3b2c1bc311caed985fe3c9b10939c9e11ca + url: "https://pub.dev" + source: hosted + version: "2.3.4" sqflite_darwin: dependency: transitive description: @@ -1695,6 +1711,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.7" + sqlite3_flutter_libs: + dependency: transitive + description: + name: sqlite3_flutter_libs + sha256: "7ae52b23366e5295005022e62fa093f64bfe190810223ea0ebf733a4cd140bce" + url: "https://pub.dev" + source: hosted + version: "0.5.26" sqlparser: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 563e13767..d11df7906 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,7 +39,8 @@ dependencies: dart_ping: "^9.0.0" dart_ping_ios: "^4.0.0" device_info_plus: "^10.0.1" - drift: "^2.16.0" + drift: "^2.21.0" + drift_flutter: "^0.2.1" dynamic_color: "^1.6.5" equatable: "^2.0.5" expandable: "^5.0.1" @@ -84,7 +85,7 @@ dependencies: unifiedpush: "^5.0.1" url_launcher: "^6.1.11" # There is an intentional space between the packge name and colon below. Do not remove! - version : ^3.0.2 + version : "^3.0.2" video_player: "^2.9.2" visibility_detector: "^0.4.0+2" webview_flutter: "^4.2.2" @@ -96,10 +97,12 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: "^2.4.6" - drift_dev: "^2.16.0" + build_runner: "^2.4.13" + drift_dev: "^2.21.2" flutter_launcher_icons: "^0.14.1" flutter_lints: "^4.0.0" + sqflite: "^2.4.0" + sqflite_common_ffi: "^2.3.4" flutter: uses-material-design: true diff --git a/test/database/migration_test.dart b/test/database/migration_test.dart index 331594a10..06f511e87 100644 --- a/test/database/migration_test.dart +++ b/test/database/migration_test.dart @@ -1,9 +1,11 @@ import 'dart:io'; -import 'package:drift/drift.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:drift/drift.dart'; +import 'package:sqflite_common_ffi/sqflite_ffi.dart'; + import 'package:thunder/core/database/database.dart'; import 'package:thunder/core/database/migrations.dart'; diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index db25c6c91..89c67bc9f 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { @@ -30,6 +31,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); SharePlusWindowsPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); + Sqlite3FlutterLibsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 0c5c9e02b..85dbf62ed 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -10,6 +10,7 @@ list(APPEND FLUTTER_PLUGIN_LIST gal permission_handler_windows share_plus + sqlite3_flutter_libs url_launcher_windows )