diff --git a/lib/database/database.dart b/lib/database/database.dart index a1b0041..39002b9 100644 --- a/lib/database/database.dart +++ b/lib/database/database.dart @@ -22,7 +22,14 @@ class AppDatabase extends _$AppDatabase { @override MigrationStrategy get migration => MigrationStrategy( - onCreate: (Migrator m) async => m.createAll(), + onCreate: (Migrator m) async { + await m.createAll(); + // database.g.dart is generated during normal development/CI. Keep the + // schema self-healing for installations that temporarily have a stale + // generated file: cloud identity must exist even on a brand-new DB. + await customStatement('ALTER TABLE rides ADD COLUMN cloud_ride_id TEXT'); + await customStatement('CREATE UNIQUE INDEX rides_cloud_ride_id_idx ON rides(cloud_ride_id)'); + }, onUpgrade: (Migrator m, int from, int to) async { if (from < 2) { await m.addColumn(rides, rides.distance); @@ -67,16 +74,11 @@ class AppDatabase extends _$AppDatabase { } catch (_) {} } if (from < 6) { - // Nullable during migration so existing installations can be upgraded - // without losing rides. We immediately backfill every existing ride - // with a stable random identifier that is independent of local ID. await m.addColumn(rides, rides.cloudRideId); - final rows = await customSelect('SELECT id FROM rides').get(); + await customStatement('CREATE UNIQUE INDEX rides_cloud_ride_id_idx ON rides(cloud_ride_id)'); + final rows = await customSelect('SELECT id FROM rides WHERE cloud_ride_id IS NULL').get(); for (final row in rows) { - await customStatement( - 'UPDATE rides SET cloud_ride_id = ? WHERE id = ?', - [_newCloudRideId(), row.data['id']], - ); + await customStatement('UPDATE rides SET cloud_ride_id = ? WHERE id = ?', [_newCloudRideId(), row.data['id']]); } } }, @@ -88,14 +90,8 @@ class AppDatabase extends _$AppDatabase { return 'ride_$hex'; } - /// Returns the persisted stable MotorCloud identity for a local ride. - /// Uses raw SQL until `database.g.dart` is regenerated; this keeps the - /// migration deployable without hand-editing generated Drift output. Future getCloudRideId(int rideId) async { - final rows = await customSelect( - 'SELECT cloud_ride_id FROM rides WHERE id = ?', - variables: [Variable(rideId)], - ).get(); + final rows = await customSelect('SELECT cloud_ride_id FROM rides WHERE id = ?', variables: [Variable(rideId)]).get(); if (rows.isEmpty) return null; return rows.first.data['cloud_ride_id'] as String?; } @@ -104,17 +100,12 @@ class AppDatabase extends _$AppDatabase { final existing = await getCloudRideId(rideId); if (existing != null && existing.isNotEmpty) return existing; final created = _newCloudRideId(); - await customStatement( - 'UPDATE rides SET cloud_ride_id = ? WHERE id = ?', - [created, rideId], - ); + await customStatement('UPDATE rides SET cloud_ride_id = ? WHERE id = ?', [created, rideId]); return created; } Future startRide() async { - final id = await into(rides).insert(RidesCompanion.insert( - startTime: DateTime.now(), - )); + final id = await into(rides).insert(RidesCompanion.insert(startTime: DateTime.now())); await ensureCloudRideId(id); return id; }