migrateToSchema method
Applies the schema diff to target and writes a history record.
Implementation
SqliteMigrationResult migrateToSchema({
required sqlite.Database database,
required SchemaDocument target,
required String migrationName,
bool allowWarnings = false,
}) {
ensureHistoryTable(database);
final appliedNames = _activeMigrationNames(loadHistory(database));
if (appliedNames.contains(migrationName)) {
return SqliteMigrationResult(
plan: const SqliteMigrationPlan(
statements: <String>[],
warnings: <String>[],
),
applied: false,
);
}
final filteredFrom = _currentSourceSchema(database);
final plan = _mergeRiskWarnings(
planner.plan(from: filteredFrom, to: target),
detectPotentialDataLossWarnings(from: filteredFrom, to: target),
);
final beforeSchema = schemaToSource(filteredFrom);
final afterSchema = schemaToSource(target);
final migrationSql = buildMigrationSqlScript(plan);
final checksum = computeMigrationChecksum(
provider: providerName,
beforeSchema: beforeSchema,
afterSchema: afterSchema,
migrationSql: migrationSql,
warnings: plan.warnings,
requiresRebuild: plan.requiresRebuild,
);
if (plan.warnings.isNotEmpty && !allowWarnings) {
throw StateError(
'Migration plan contains warnings: ${plan.warnings.join(' | ')}',
);
}
if (!plan.requiresRebuild && plan.statements.isEmpty) {
_recordHistory(
database: database,
migrationName: migrationName,
statementCount: 0,
kind: SqliteMigrationRecordKind.apply,
provider: providerName,
checksum: checksum,
beforeSchema: beforeSchema,
afterSchema: afterSchema,
warnings: plan.warnings,
rebuildRequired: plan.requiresRebuild,
);
return SqliteMigrationResult(plan: plan, applied: false);
}
if (plan.requiresRebuild) {
final statementCount = _rebuildDatabase(
database: database,
source: filteredFrom,
target: target,
);
_recordHistory(
database: database,
migrationName: migrationName,
statementCount: statementCount,
kind: SqliteMigrationRecordKind.apply,
provider: providerName,
checksum: checksum,
beforeSchema: beforeSchema,
afterSchema: afterSchema,
warnings: plan.warnings,
rebuildRequired: true,
);
return SqliteMigrationResult(plan: plan, applied: true);
}
database.execute('BEGIN');
try {
for (final statement in plan.statements) {
database.execute(statement);
}
_recordHistory(
database: database,
migrationName: migrationName,
statementCount: plan.statements.length,
kind: SqliteMigrationRecordKind.apply,
provider: providerName,
checksum: checksum,
beforeSchema: beforeSchema,
afterSchema: afterSchema,
warnings: plan.warnings,
rebuildRequired: false,
);
database.execute('COMMIT');
return SqliteMigrationResult(plan: plan, applied: true);
} catch (_) {
database.execute('ROLLBACK');
rethrow;
}
}