fix(local): corrige contrainte CHECK change_log en fin de serie et contrainte UNIQUE active_exercise_step_progress_states (#190 #191)
Correctifs regroupes: memes hunks de drift_repositories.dart concernes par les deux tickets, decoupage atomique par ticket non applicable proprement. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -1408,28 +1408,76 @@ final class DriftActiveSessionRepository implements ActiveSessionRepository {
|
||||
Future<void> saveScoreStopwatchState(
|
||||
domain.ActiveScoreStopwatchState state,
|
||||
) async {
|
||||
await _upsertWithChangeLog(
|
||||
database: database,
|
||||
tableName: 'active_score_stopwatch_states',
|
||||
entityType: 'ActiveScoreStopwatchState',
|
||||
metadata: state.metadata,
|
||||
write: () => database
|
||||
.into(database.activeScoreStopwatchStates)
|
||||
.insertOnConflictUpdate(_activeScoreStopwatchStateCompanion(state)),
|
||||
);
|
||||
await database.transaction(() async {
|
||||
final existing = await _findActiveScoreStopwatchStateRowByPosition(
|
||||
database,
|
||||
state.activeWorkoutSessionId,
|
||||
state.programIndex,
|
||||
state.exerciseIndex,
|
||||
state.setIndex,
|
||||
);
|
||||
final effectiveState = existing == null
|
||||
? state
|
||||
: state.copyWith(
|
||||
metadata: _metadataWithStoredIdentity(
|
||||
state.metadata,
|
||||
_metadataFromRow(existing),
|
||||
),
|
||||
);
|
||||
final operation = existing == null
|
||||
? 'insert'
|
||||
: _operationForExistingMutation(
|
||||
existingDeletedAt: existing.deletedAt,
|
||||
deletedAt: effectiveState.metadata.deletedAt,
|
||||
);
|
||||
await _upsertActiveScoreStopwatchState(database, effectiveState);
|
||||
await _writeChangeLog(
|
||||
database: database,
|
||||
entityType: 'ActiveScoreStopwatchState',
|
||||
entityId: effectiveState.metadata.id,
|
||||
operation: operation,
|
||||
localRevision: effectiveState.metadata.localRevision,
|
||||
originDeviceId: effectiveState.metadata.originDeviceId,
|
||||
createdAt: effectiveState.metadata.updatedAt,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveManualScoreState(domain.ActiveManualScoreState state) async {
|
||||
await _upsertWithChangeLog(
|
||||
database: database,
|
||||
tableName: 'active_manual_score_states',
|
||||
entityType: 'ActiveManualScoreState',
|
||||
metadata: state.metadata,
|
||||
write: () => database
|
||||
.into(database.activeManualScoreStates)
|
||||
.insertOnConflictUpdate(_activeManualScoreStateCompanion(state)),
|
||||
);
|
||||
await database.transaction(() async {
|
||||
final existing = await _findActiveManualScoreStateRowByPosition(
|
||||
database,
|
||||
state.activeWorkoutSessionId,
|
||||
state.programIndex,
|
||||
state.exerciseIndex,
|
||||
state.setIndex,
|
||||
);
|
||||
final effectiveState = existing == null
|
||||
? state
|
||||
: state.copyWith(
|
||||
metadata: _metadataWithStoredIdentity(
|
||||
state.metadata,
|
||||
_metadataFromRow(existing),
|
||||
),
|
||||
);
|
||||
final operation = existing == null
|
||||
? 'insert'
|
||||
: _operationForExistingMutation(
|
||||
existingDeletedAt: existing.deletedAt,
|
||||
deletedAt: effectiveState.metadata.deletedAt,
|
||||
);
|
||||
await _upsertActiveManualScoreState(database, effectiveState);
|
||||
await _writeChangeLog(
|
||||
database: database,
|
||||
entityType: 'ActiveManualScoreState',
|
||||
entityId: effectiveState.metadata.id,
|
||||
operation: operation,
|
||||
localRevision: effectiveState.metadata.localRevision,
|
||||
originDeviceId: effectiveState.metadata.originDeviceId,
|
||||
createdAt: effectiveState.metadata.updatedAt,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@ -1486,14 +1534,21 @@ final class DriftActiveSessionRepository implements ActiveSessionRepository {
|
||||
return;
|
||||
}
|
||||
final revision = row.localRevision + 1;
|
||||
await (database.delete(
|
||||
await (database.update(
|
||||
database.activeScoreStopwatchStates,
|
||||
)..where((table) => table.id.equals(row.id))).go();
|
||||
)..where((table) => table.id.equals(row.id))).write(
|
||||
db.ActiveScoreStopwatchStatesCompanion(
|
||||
deletedAt: Value(deletedAt.toUtc()),
|
||||
updatedAt: Value(deletedAt.toUtc()),
|
||||
localRevision: Value(revision),
|
||||
syncState: const Value('deleted'),
|
||||
),
|
||||
);
|
||||
await _writeChangeLog(
|
||||
database: database,
|
||||
entityType: 'ActiveScoreStopwatchState',
|
||||
entityId: row.id,
|
||||
operation: 'delete',
|
||||
operation: 'softDelete',
|
||||
localRevision: revision,
|
||||
originDeviceId: row.originDeviceId,
|
||||
createdAt: deletedAt,
|
||||
@ -1522,14 +1577,21 @@ final class DriftActiveSessionRepository implements ActiveSessionRepository {
|
||||
return;
|
||||
}
|
||||
final revision = row.localRevision + 1;
|
||||
await (database.delete(
|
||||
await (database.update(
|
||||
database.activeManualScoreStates,
|
||||
)..where((table) => table.id.equals(row.id))).go();
|
||||
)..where((table) => table.id.equals(row.id))).write(
|
||||
db.ActiveManualScoreStatesCompanion(
|
||||
deletedAt: Value(deletedAt.toUtc()),
|
||||
updatedAt: Value(deletedAt.toUtc()),
|
||||
localRevision: Value(revision),
|
||||
syncState: const Value('deleted'),
|
||||
),
|
||||
);
|
||||
await _writeChangeLog(
|
||||
database: database,
|
||||
entityType: 'ActiveManualScoreState',
|
||||
entityId: row.id,
|
||||
operation: 'delete',
|
||||
operation: 'softDelete',
|
||||
localRevision: revision,
|
||||
originDeviceId: row.originDeviceId,
|
||||
createdAt: deletedAt,
|
||||
@ -4277,6 +4339,184 @@ Future<void> _updateActiveRestPauseFields(
|
||||
);
|
||||
}
|
||||
|
||||
Future<db.ActiveScoreStopwatchState?>
|
||||
_findActiveScoreStopwatchStateRowByPosition(
|
||||
db.AppDatabase database,
|
||||
String sessionId,
|
||||
int programIndex,
|
||||
int exerciseIndex,
|
||||
int setIndex,
|
||||
) {
|
||||
return (database.select(database.activeScoreStopwatchStates)..where(
|
||||
(table) =>
|
||||
table.activeWorkoutSessionId.equals(sessionId) &
|
||||
table.programIndex.equals(programIndex) &
|
||||
table.exerciseIndex.equals(exerciseIndex) &
|
||||
table.setIndex.equals(setIndex),
|
||||
))
|
||||
.getSingleOrNull();
|
||||
}
|
||||
|
||||
Future<db.ActiveManualScoreState?> _findActiveManualScoreStateRowByPosition(
|
||||
db.AppDatabase database,
|
||||
String sessionId,
|
||||
int programIndex,
|
||||
int exerciseIndex,
|
||||
int setIndex,
|
||||
) {
|
||||
return (database.select(database.activeManualScoreStates)..where(
|
||||
(table) =>
|
||||
table.activeWorkoutSessionId.equals(sessionId) &
|
||||
table.programIndex.equals(programIndex) &
|
||||
table.exerciseIndex.equals(exerciseIndex) &
|
||||
table.setIndex.equals(setIndex),
|
||||
))
|
||||
.getSingleOrNull();
|
||||
}
|
||||
|
||||
domain.EntityMetadata _metadataWithStoredIdentity(
|
||||
domain.EntityMetadata metadata,
|
||||
domain.EntityMetadata stored,
|
||||
) {
|
||||
return domain.EntityMetadata(
|
||||
id: stored.id,
|
||||
createdAt: stored.createdAt,
|
||||
updatedAt: metadata.updatedAt,
|
||||
deletedAt: metadata.deletedAt,
|
||||
schemaVersion: metadata.schemaVersion,
|
||||
syncState: metadata.syncState,
|
||||
localRevision: metadata.localRevision,
|
||||
originDeviceId: metadata.originDeviceId,
|
||||
futureOwnerProfileId: metadata.futureOwnerProfileId,
|
||||
lastSyncedAt: metadata.lastSyncedAt,
|
||||
remoteRevision: metadata.remoteRevision,
|
||||
);
|
||||
}
|
||||
|
||||
String _operationForExistingMutation({
|
||||
required DateTime? existingDeletedAt,
|
||||
required DateTime? deletedAt,
|
||||
}) {
|
||||
if (deletedAt != null) {
|
||||
return 'softDelete';
|
||||
}
|
||||
if (existingDeletedAt != null) {
|
||||
return 'restore';
|
||||
}
|
||||
return 'update';
|
||||
}
|
||||
|
||||
Future<void> _upsertActiveScoreStopwatchState(
|
||||
db.AppDatabase database,
|
||||
domain.ActiveScoreStopwatchState state,
|
||||
) async {
|
||||
final metadata = state.metadata;
|
||||
await database.customInsert(
|
||||
'INSERT INTO active_score_stopwatch_states ('
|
||||
'id, created_at, updated_at, deleted_at, schema_version, sync_state, '
|
||||
'local_revision, origin_device_id, future_owner_profile_id, '
|
||||
'last_synced_at, remote_revision, active_workout_session_id, '
|
||||
'program_index, exercise_index, set_index, status, started_at, '
|
||||
'accumulated_ms, stopped_at'
|
||||
') VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) '
|
||||
'ON CONFLICT(active_workout_session_id, program_index, exercise_index, '
|
||||
'set_index) DO UPDATE SET '
|
||||
'id = active_score_stopwatch_states.id, '
|
||||
'created_at = active_score_stopwatch_states.created_at, '
|
||||
'updated_at = excluded.updated_at, '
|
||||
'deleted_at = excluded.deleted_at, '
|
||||
'schema_version = excluded.schema_version, '
|
||||
'sync_state = excluded.sync_state, '
|
||||
'local_revision = excluded.local_revision, '
|
||||
'origin_device_id = excluded.origin_device_id, '
|
||||
'future_owner_profile_id = excluded.future_owner_profile_id, '
|
||||
'last_synced_at = excluded.last_synced_at, '
|
||||
'remote_revision = excluded.remote_revision, '
|
||||
'active_workout_session_id = excluded.active_workout_session_id, '
|
||||
'program_index = excluded.program_index, '
|
||||
'exercise_index = excluded.exercise_index, '
|
||||
'set_index = excluded.set_index, '
|
||||
'status = excluded.status, '
|
||||
'started_at = excluded.started_at, '
|
||||
'accumulated_ms = excluded.accumulated_ms, '
|
||||
'stopped_at = excluded.stopped_at',
|
||||
variables: [
|
||||
Variable<String>(metadata.id),
|
||||
Variable<DateTime>(metadata.createdAt.toUtc()),
|
||||
Variable<DateTime>(metadata.updatedAt.toUtc()),
|
||||
Variable<DateTime>(_utcOrNull(metadata.deletedAt)),
|
||||
Variable<int>(metadata.schemaVersion),
|
||||
Variable<String>(_syncStateToDb(metadata.syncState)),
|
||||
Variable<int>(metadata.localRevision),
|
||||
Variable<String>(metadata.originDeviceId),
|
||||
Variable<String>(metadata.futureOwnerProfileId),
|
||||
Variable<DateTime>(_utcOrNull(metadata.lastSyncedAt)),
|
||||
Variable<String>(metadata.remoteRevision),
|
||||
Variable<String>(state.activeWorkoutSessionId),
|
||||
Variable<int>(state.programIndex),
|
||||
Variable<int>(state.exerciseIndex),
|
||||
Variable<int>(state.setIndex),
|
||||
Variable<String>(_scoreStopwatchStatusToDb(state.status)),
|
||||
Variable<DateTime>(state.startedAt.toUtc()),
|
||||
Variable<int>(state.accumulatedMs),
|
||||
Variable<DateTime>(_utcOrNull(state.stoppedAt)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _upsertActiveManualScoreState(
|
||||
db.AppDatabase database,
|
||||
domain.ActiveManualScoreState state,
|
||||
) async {
|
||||
final metadata = state.metadata;
|
||||
await database.customInsert(
|
||||
'INSERT INTO active_manual_score_states ('
|
||||
'id, created_at, updated_at, deleted_at, schema_version, sync_state, '
|
||||
'local_revision, origin_device_id, future_owner_profile_id, '
|
||||
'last_synced_at, remote_revision, active_workout_session_id, '
|
||||
'program_index, exercise_index, set_index, value, score_updated_at'
|
||||
') VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) '
|
||||
'ON CONFLICT(active_workout_session_id, program_index, exercise_index, '
|
||||
'set_index) DO UPDATE SET '
|
||||
'id = active_manual_score_states.id, '
|
||||
'created_at = active_manual_score_states.created_at, '
|
||||
'updated_at = excluded.updated_at, '
|
||||
'deleted_at = excluded.deleted_at, '
|
||||
'schema_version = excluded.schema_version, '
|
||||
'sync_state = excluded.sync_state, '
|
||||
'local_revision = excluded.local_revision, '
|
||||
'origin_device_id = excluded.origin_device_id, '
|
||||
'future_owner_profile_id = excluded.future_owner_profile_id, '
|
||||
'last_synced_at = excluded.last_synced_at, '
|
||||
'remote_revision = excluded.remote_revision, '
|
||||
'active_workout_session_id = excluded.active_workout_session_id, '
|
||||
'program_index = excluded.program_index, '
|
||||
'exercise_index = excluded.exercise_index, '
|
||||
'set_index = excluded.set_index, '
|
||||
'value = excluded.value, '
|
||||
'score_updated_at = excluded.score_updated_at',
|
||||
variables: [
|
||||
Variable<String>(metadata.id),
|
||||
Variable<DateTime>(metadata.createdAt.toUtc()),
|
||||
Variable<DateTime>(metadata.updatedAt.toUtc()),
|
||||
Variable<DateTime>(_utcOrNull(metadata.deletedAt)),
|
||||
Variable<int>(metadata.schemaVersion),
|
||||
Variable<String>(_syncStateToDb(metadata.syncState)),
|
||||
Variable<int>(metadata.localRevision),
|
||||
Variable<String>(metadata.originDeviceId),
|
||||
Variable<String>(metadata.futureOwnerProfileId),
|
||||
Variable<DateTime>(_utcOrNull(metadata.lastSyncedAt)),
|
||||
Variable<String>(metadata.remoteRevision),
|
||||
Variable<String>(state.activeWorkoutSessionId),
|
||||
Variable<int>(state.programIndex),
|
||||
Variable<int>(state.exerciseIndex),
|
||||
Variable<int>(state.setIndex),
|
||||
Variable<double>(state.value),
|
||||
Variable<DateTime>(state.updatedAt.toUtc()),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _upsertActiveSetTimerState(
|
||||
db.AppDatabase database,
|
||||
domain.ActiveSetTimerState state,
|
||||
@ -4459,58 +4699,6 @@ String? _activeMeasuresPredicate(ActivePerformanceMeasures measures) {
|
||||
};
|
||||
}
|
||||
|
||||
db.ActiveScoreStopwatchStatesCompanion _activeScoreStopwatchStateCompanion(
|
||||
domain.ActiveScoreStopwatchState state,
|
||||
) {
|
||||
final values = _metadataValues(state.metadata);
|
||||
return db.ActiveScoreStopwatchStatesCompanion(
|
||||
id: values[0] as Value<String>,
|
||||
createdAt: values[1] as Value<DateTime>,
|
||||
updatedAt: values[2] as Value<DateTime>,
|
||||
deletedAt: values[3] as Value<DateTime?>,
|
||||
schemaVersion: values[4] as Value<int>,
|
||||
syncState: values[5] as Value<String>,
|
||||
localRevision: values[6] as Value<int>,
|
||||
originDeviceId: values[7] as Value<String>,
|
||||
futureOwnerProfileId: values[8] as Value<String?>,
|
||||
lastSyncedAt: values[9] as Value<DateTime?>,
|
||||
remoteRevision: values[10] as Value<String?>,
|
||||
activeWorkoutSessionId: Value(state.activeWorkoutSessionId),
|
||||
programIndex: Value(state.programIndex),
|
||||
exerciseIndex: Value(state.exerciseIndex),
|
||||
setIndex: Value(state.setIndex),
|
||||
status: Value(_scoreStopwatchStatusToDb(state.status)),
|
||||
startedAt: Value(state.startedAt.toUtc()),
|
||||
accumulatedMs: Value(state.accumulatedMs),
|
||||
stoppedAt: Value(_utcOrNull(state.stoppedAt)),
|
||||
);
|
||||
}
|
||||
|
||||
db.ActiveManualScoreStatesCompanion _activeManualScoreStateCompanion(
|
||||
domain.ActiveManualScoreState state,
|
||||
) {
|
||||
final values = _metadataValues(state.metadata);
|
||||
return db.ActiveManualScoreStatesCompanion(
|
||||
id: values[0] as Value<String>,
|
||||
createdAt: values[1] as Value<DateTime>,
|
||||
updatedAt: values[2] as Value<DateTime>,
|
||||
deletedAt: values[3] as Value<DateTime?>,
|
||||
schemaVersion: values[4] as Value<int>,
|
||||
syncState: values[5] as Value<String>,
|
||||
localRevision: values[6] as Value<int>,
|
||||
originDeviceId: values[7] as Value<String>,
|
||||
futureOwnerProfileId: values[8] as Value<String?>,
|
||||
lastSyncedAt: values[9] as Value<DateTime?>,
|
||||
remoteRevision: values[10] as Value<String?>,
|
||||
activeWorkoutSessionId: Value(state.activeWorkoutSessionId),
|
||||
programIndex: Value(state.programIndex),
|
||||
exerciseIndex: Value(state.exerciseIndex),
|
||||
setIndex: Value(state.setIndex),
|
||||
value: Value(state.value),
|
||||
scoreUpdatedAt: Value(state.updatedAt.toUtc()),
|
||||
);
|
||||
}
|
||||
|
||||
domain.ActiveManualScoreState _activeManualScoreStateFromRow(
|
||||
db.ActiveManualScoreState row,
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user