rollbackToSchema method

Future<PostgresqlRollbackResult> rollbackToSchema({
  1. required SessionExecutor executor,
  2. required SchemaDocument target,
  3. required String targetMigrationName,
  4. String? rollbackName,
  5. bool allowWarnings = false,
})

Rolls migration history back to targetMigrationName.

Implementation

Future<PostgresqlRollbackResult> rollbackToSchema({
  required pg.SessionExecutor executor,
  required SchemaDocument target,
  required String targetMigrationName,
  String? rollbackName,
  bool allowWarnings = false,
}) async {
  await ensureHistoryTable(executor);
  final history = await loadHistory(executor);
  final activeNames = _activeMigrationNames(history);
  if (!activeNames.contains(targetMigrationName)) {
    return PostgresqlRollbackResult(
      targetMigrationName: targetMigrationName,
      rolledBack: false,
      statementCount: 0,
      warnings: const <String>[],
    );
  }

  final source = filterSchemaForUserModels(
    await planner.schemaIntrospector.introspect(executor),
    historyTableName: historyTableName,
  );
  final plan = _mergeRiskWarnings(
    planner.plan(from: source, to: target),
    detectPotentialDataLossWarnings(from: source, to: target),
  );
  if (plan.warnings.isNotEmpty && !allowWarnings) {
    throw StateError(
      'Rollback plan contains warnings: ${plan.warnings.join(' | ')}',
    );
  }
  final effectiveRollbackName =
      rollbackName ??
      '${targetMigrationName}_rollback_${DateTime.now().toUtc().millisecondsSinceEpoch}';
  final beforeSchema = schemaToSource(source);
  final afterSchema = schemaToSource(target);
  final migrationSql = buildMigrationSqlScript(plan);
  final checksum = computeMigrationChecksum(
    provider: providerName,
    beforeSchema: beforeSchema,
    afterSchema: afterSchema,
    migrationSql: migrationSql,
    warnings: plan.warnings,
    requiresRebuild: true,
  );
  var statementCount = 0;

  await executor.runTx((session) async {
    statementCount = await _rebuildDatabase(
      session: session,
      source: source,
      target: target,
    );
    await _recordHistory(
      session,
      migrationName: effectiveRollbackName,
      statementCount: statementCount,
      kind: PostgresqlMigrationRecordKind.rollback,
      targetName: targetMigrationName,
      provider: providerName,
      checksum: checksum,
      beforeSchema: beforeSchema,
      afterSchema: afterSchema,
      warnings: plan.warnings,
      rebuildRequired: true,
    );
  });

  return PostgresqlRollbackResult(
    targetMigrationName: targetMigrationName,
    rolledBack: true,
    statementCount: statementCount,
    warnings: List<String>.unmodifiable(plan.warnings),
  );
}