use std::path::{Path, PathBuf};
use diesel_migrations::MigrationError;
use crate::infer_schema_internals::TableName;
#[derive(thiserror::Error, Debug)]
#[allow(clippy::enum_variant_names)]
pub enum Error {
#[error("Initializing `.env` file failed: {0}")]
DotenvError(#[from] dotenvy::Error),
#[error("Could not connect to database via `{url}`: {error}")]
ConnectionError {
error: diesel::ConnectionError,
url: String,
},
#[error("Invalid argument for table filtering regex: {0}")]
TableFilterRegexInvalid(#[from] regex::Error),
#[error("Unable to find diesel.toml or Cargo.toml in {0:?} or any parent directories.")]
ProjectRootNotFound(PathBuf),
#[error("The --database-url argument must be passed, or the DATABASE_URL environment variable must be set.")]
DatabaseUrlMissing,
#[error("Encountered an IO error: {0} for `{n}`", n=print_optional_path(.1))]
IoError(#[source] std::io::Error, Option<PathBuf>),
#[error("Failed to execute a database query: {0}")]
QueryError(#[from] diesel::result::Error),
#[error("Failed to run migrations: {0}")]
MigrationError(Box<dyn std::error::Error + Send + Sync + 'static>),
#[error("Failed to parse schema: {0}")]
SynError(#[from] syn::Error),
#[error("sqlite cannot infer schema for databases other than the main database")]
#[cfg(feature = "sqlite")]
InvalidSqliteSchema,
#[error("No table with the name `{0}` exists")]
NoTableFound(TableName),
#[error("Unsupported type: `{0}`")]
#[cfg(any(feature = "sqlite", feature = "mysql"))]
UnsupportedType(String),
#[error(
"Diesel only supports tables with primary keys. \
Table `{0}` has no primary key"
)]
NoPrimaryKeyFound(TableName),
#[error("{0}")]
UnsupportedFeature(String),
#[error(
"Command would result in changes to `{0}`. \
Rerun the command locally, and commit the changes."
)]
SchemaWouldChange(String),
#[error("Failed to parse config file: {0}")]
InvalidConfig(#[from] toml::de::Error),
#[error("Failed to format a string: {0}")]
FmtError(#[from] std::fmt::Error),
#[error("Failed to parse patch file: {0}")]
DiffyParseError(#[from] diffy::ParsePatchError),
#[error("Failed to apply patch: {0}")]
DiffyApplyError(#[from] diffy::ApplyError),
#[error("Column length literal can't be parsed as u64: {0}")]
ColumnLiteralParseError(syn::Error),
#[error("Failed to parse database url: {0}")]
UrlParsingError(#[from] url::ParseError),
#[error("Failed to parse CLI parameter: {0}")]
ClapMatchesError(#[from] clap::parser::MatchesError),
#[error("No `[print_schema.{0}]` entries in your diesel.toml")]
NoSchemaKeyFound(String),
#[error("Failed To Run rustfmt")]
RustFmtFail(String),
#[error("Failed to acquire migration folder lock: {1} for `{n}`", n=print_path(.0))]
FailedToAcquireMigrationFolderLock(PathBuf, String),
#[error("Tried to generate too many migrations with the same version `{1}` - Migrations folder is `{n}`", n=print_path(.0))]
TooManyMigrations(PathBuf, String),
#[error("Specified migration version `{1}` already exists inside `{n}`", n=print_path(.0))]
DuplicateMigrationVersion(PathBuf, String),
}
fn print_path(path: &Path) -> String {
format!("{}", path.display())
}
fn print_optional_path(path: &Option<PathBuf>) -> String {
path.as_ref().map(|p| print_path(p)).unwrap_or_default()
}
impl Error {
pub fn from_migration_error<T: Into<PathBuf>>(error: MigrationError, path: Option<T>) -> Self {
match error {
MigrationError::IoError(error) => Self::IoError(error, path.map(Into::into)),
_ => Self::MigrationError(Box::new(error)),
}
}
}