-
Notifications
You must be signed in to change notification settings - Fork 216
/
lib.rs
97 lines (75 loc) · 4.04 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#![deny(rust_2018_idioms, unsafe_code, missing_docs)]
//! This crate defines the API exposed by the connectors to the migration engine core. The entry point for this API is the [MigrationConnector](trait.MigrationConnector.html) trait.
mod checksum;
mod database_migration_step_applier;
mod destructive_change_checker;
mod diff;
mod error;
mod migration_persistence;
pub mod migrations_directory;
pub use database_migration_step_applier::DatabaseMigrationStepApplier;
pub use destructive_change_checker::{
DestructiveChangeChecker, DestructiveChangeDiagnostics, MigrationWarning, UnexecutableMigration,
};
pub use diff::DiffTarget;
pub use error::{ConnectorError, ConnectorResult};
pub use migration_persistence::{MigrationPersistence, MigrationRecord, PersistenceNotInitializedError, Timestamp};
use migrations_directory::MigrationDirectory;
/// A boxed migration, opaque to the migration engine core. The connectors are
/// sole responsible for producing and understanding migrations — the core just
/// orchestrates.
pub struct Migration(Box<dyn std::any::Any + Send + Sync>);
impl Migration {
/// Type-erase a migration.
pub fn new<T: 'static + Send + Sync>(migration: T) -> Self {
Migration(Box::new(migration))
}
/// Should never be used in the core, only in connectors that know what they put there.
pub fn downcast_ref<T: 'static>(&self) -> &T {
self.0.downcast_ref().unwrap()
}
}
/// The top-level trait for connectors. This is the abstraction the migration engine core relies on to
/// interface with different database backends.
#[async_trait::async_trait]
pub trait MigrationConnector: Send + Sync + 'static {
/// If possible on the target connector, acquire an advisory lock, so multiple instances of migrate do not run concurrently.
async fn acquire_lock(&self) -> ConnectorResult<()>;
/// A string that should identify what database backend is being used. Note that this is not necessarily
/// the connector name. The SQL connector for example can return "postgresql", "mysql" or "sqlite".
fn connector_type(&self) -> &'static str;
/// Create a migration by comparing two database schemas. See
/// [DiffTarget](/enum.DiffTarget.html) for possible inputs.
async fn diff(&self, from: DiffTarget<'_>, to: DiffTarget<'_>) -> ConnectorResult<Migration>;
/// The version of the underlying database.
async fn version(&self) -> ConnectorResult<String>;
/// Drop all database state.
async fn reset(&self) -> ConnectorResult<()>;
/// Optionally check that the features implied by the provided datamodel are all compatible with
/// the specific database version being used.
fn check_database_version_compatibility(
&self,
_datamodel: &datamodel::dml::Datamodel,
) -> Option<user_facing_errors::common::DatabaseVersionIncompatibility> {
None
}
/// The file extension for generated migration files.
fn migration_file_extension(&self) -> &'static str;
/// Return whether the migration is empty.
fn migration_is_empty(&self, migration: &Migration) -> bool {
self.migration_len(migration) == 0
}
/// Return the number of steps in the migration.
/// Invariant: migration_is_empty() == true iff migration_len() == 0.
fn migration_len(&self, migration: &Migration) -> usize;
/// See [MigrationPersistence](trait.MigrationPersistence.html).
fn migration_persistence(&self) -> &dyn MigrationPersistence;
/// Render a human-readable drift summary for the migration.
fn migration_summary(&self, migration: &Migration) -> String;
/// See [DatabaseMigrationStepApplier](trait.DatabaseMigrationStepApplier.html).
fn database_migration_step_applier(&self) -> &dyn DatabaseMigrationStepApplier;
/// See [DestructiveChangeChecker](trait.DestructiveChangeChecker.html).
fn destructive_change_checker(&self) -> &dyn DestructiveChangeChecker;
/// If possible, check that the passed in migrations apply cleanly.
async fn validate_migrations(&self, _migrations: &[MigrationDirectory]) -> ConnectorResult<()>;
}