feat(exécution): dernière performance et meilleur score par exercice (ticket #81)
Ajoute la migration Drift v17 (colonne sourceExerciseIdSnapshot sur workout_history_set_results et workout_history_step_results, index associés), le port ExercisePerformanceReferenceRepository et son implémentation Drift, et le use case ExercisePerformanceReferenceUseCase (dernière performance + meilleur score par métrique active pour un exercice donné). Validé GO par Main : dart analyze propre (1 lint mineur de style), 178 tests (4 échecs préexistants sans rapport avec ce lot). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -48,7 +48,7 @@ final class AppDatabase extends _$AppDatabase {
|
||||
}
|
||||
|
||||
@override
|
||||
int get schemaVersion => 16;
|
||||
int get schemaVersion => 17;
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration {
|
||||
@ -113,6 +113,9 @@ final class AppDatabase extends _$AppDatabase {
|
||||
if (from < 16) {
|
||||
await _migrateToSchema16(migrator);
|
||||
}
|
||||
if (from < 17) {
|
||||
await _migrateToSchema17();
|
||||
}
|
||||
await _createIndexes();
|
||||
},
|
||||
beforeOpen: (details) async {
|
||||
@ -229,10 +232,24 @@ final class AppDatabase extends _$AppDatabase {
|
||||
'CREATE INDEX IF NOT EXISTS idx_workout_history_set_results_history_id '
|
||||
'ON workout_history_set_results (workout_history_id)',
|
||||
);
|
||||
await customStatement(
|
||||
'CREATE INDEX IF NOT EXISTS '
|
||||
'idx_workout_history_set_results_source_exercise '
|
||||
'ON workout_history_set_results (source_exercise_id_snapshot, '
|
||||
'set_index) WHERE deleted_at IS NULL AND '
|
||||
'source_exercise_id_snapshot IS NOT NULL',
|
||||
);
|
||||
await customStatement(
|
||||
'CREATE INDEX IF NOT EXISTS idx_workout_history_step_results_history_id '
|
||||
'ON workout_history_step_results (workout_history_id)',
|
||||
);
|
||||
await customStatement(
|
||||
'CREATE INDEX IF NOT EXISTS '
|
||||
'idx_workout_history_step_results_source_exercise '
|
||||
'ON workout_history_step_results (source_exercise_id_snapshot, '
|
||||
'set_index, step_index) WHERE deleted_at IS NULL AND '
|
||||
'source_exercise_id_snapshot IS NOT NULL',
|
||||
);
|
||||
await customStatement(
|
||||
'CREATE INDEX IF NOT EXISTS idx_change_log_entity '
|
||||
'ON change_log (entity_type, entity_id)',
|
||||
@ -697,6 +714,79 @@ CREATE TABLE IF NOT EXISTS active_set_timer_states (
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _migrateToSchema17() async {
|
||||
await _addColumnIfMissing(
|
||||
tableName: 'workout_history_set_results',
|
||||
columnName: 'source_exercise_id_snapshot',
|
||||
definition: 'source_exercise_id_snapshot TEXT',
|
||||
);
|
||||
await _addColumnIfMissing(
|
||||
tableName: 'workout_history_step_results',
|
||||
columnName: 'source_exercise_id_snapshot',
|
||||
definition: 'source_exercise_id_snapshot TEXT',
|
||||
);
|
||||
await _backfillWorkoutHistorySetSourceExerciseIds();
|
||||
await _backfillWorkoutHistoryStepSourceExerciseIds();
|
||||
}
|
||||
|
||||
Future<void> _backfillWorkoutHistorySetSourceExerciseIds() async {
|
||||
await customStatement(r'''
|
||||
UPDATE workout_history_set_results AS result
|
||||
SET source_exercise_id_snapshot = (
|
||||
SELECT json_extract(exercise.value, '$.sourceExerciseId')
|
||||
FROM workout_history AS history,
|
||||
json_each(
|
||||
COALESCE(
|
||||
json_extract(
|
||||
history.history_snapshot_json,
|
||||
'$.resolvedTemplateSnapshotJson'
|
||||
),
|
||||
history.history_snapshot_json
|
||||
),
|
||||
'$.programs'
|
||||
) AS program,
|
||||
json_each(
|
||||
json_extract(program.value, '$.programSnapshotJson'),
|
||||
'$.exercises'
|
||||
) AS exercise
|
||||
WHERE history.id = result.workout_history_id
|
||||
AND json_extract(program.value, '$.id') = result.program_snapshot_id
|
||||
AND json_extract(exercise.value, '$.id') = result.exercise_snapshot_id
|
||||
LIMIT 1
|
||||
)
|
||||
WHERE result.source_exercise_id_snapshot IS NULL
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> _backfillWorkoutHistoryStepSourceExerciseIds() async {
|
||||
await customStatement(r'''
|
||||
UPDATE workout_history_step_results AS result
|
||||
SET source_exercise_id_snapshot = (
|
||||
SELECT json_extract(exercise.value, '$.sourceExerciseId')
|
||||
FROM workout_history AS history,
|
||||
json_each(
|
||||
COALESCE(
|
||||
json_extract(
|
||||
history.history_snapshot_json,
|
||||
'$.resolvedTemplateSnapshotJson'
|
||||
),
|
||||
history.history_snapshot_json
|
||||
),
|
||||
'$.programs'
|
||||
) AS program,
|
||||
json_each(
|
||||
json_extract(program.value, '$.programSnapshotJson'),
|
||||
'$.exercises'
|
||||
) AS exercise
|
||||
WHERE history.id = result.workout_history_id
|
||||
AND json_extract(program.value, '$.id') = result.program_snapshot_id
|
||||
AND json_extract(exercise.value, '$.id') = result.exercise_snapshot_id
|
||||
LIMIT 1
|
||||
)
|
||||
WHERE result.source_exercise_id_snapshot IS NULL
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> _addColumnIfMissing({
|
||||
required String tableName,
|
||||
required String columnName,
|
||||
|
||||
Reference in New Issue
Block a user