Skip to main content

drizzle_seed/
error.rs

1use core::fmt;
2
3/// Why [`SeedConfig`](crate::SeedConfig) could not build the statements
4/// (returned by `try_generate` and `reset_plan`).
5#[derive(Clone, Debug, Eq, PartialEq)]
6#[non_exhaustive]
7pub enum SeedError {
8    /// The non-skipped `tables` have a foreign-key cycle, so there is no
9    /// parent-first order. A self-reference counts only when all of its
10    /// columns are `NOT NULL`.
11    CyclicForeignKeys { tables: Vec<String> },
12    /// A `NOT NULL` foreign key in `child` has no `parent` row to point at:
13    /// the seeded parent got zero rows, or the relation count is zero. (A
14    /// nullable foreign key is set to `NULL` instead.)
15    MissingParentRows { child: String, parent: String },
16    /// `reset_plan` would delete a parent's rows while a skipped table still
17    /// references it.
18    UnsafeResetSelection {
19        /// The table that would be emptied.
20        parent: String,
21        /// The skipped table that references it.
22        skipped_child: String,
23    },
24    /// A single row needs more bind parameters than the limit (`max_params`,
25    /// or the dialect's maximum).
26    ParameterLimitTooLow {
27        /// The table being seeded.
28        table: String,
29        /// Parameters one row needs.
30        required: usize,
31        /// The configured limit.
32        limit: usize,
33    },
34    /// A `*_by_name` setting names a table the schema does not have.
35    UnknownTable {
36        /// The name as given.
37        table: String,
38        /// The schema's tables.
39        known: Vec<String>,
40    },
41    /// A `*_by_name` setting names a table that exists in several
42    /// namespaces; qualify it as `schema.table`.
43    AmbiguousTable {
44        /// The name as given.
45        table: String,
46        /// The matching tables.
47        candidates: Vec<String>,
48    },
49    /// A `*_by_name` setting names a column the table does not have.
50    UnknownColumn {
51        /// The table.
52        table: String,
53        /// The column name as given.
54        column: String,
55        /// The table's columns.
56        known: Vec<String>,
57    },
58    /// `relation_by_name` was given a `child` with no foreign key to
59    /// `parent`.
60    NotRelated {
61        /// The parent table.
62        parent: String,
63        /// The child table.
64        child: String,
65    },
66    /// `Schema::from_snapshot` was given a snapshot for a dialect whose
67    /// feature (`sqlite`, `postgres` or `mysql`) is off.
68    DialectNotEnabled {
69        /// The snapshot's dialect.
70        dialect: String,
71    },
72    /// A value has no SQL literal form, so the statement cannot be written
73    /// with its values inline (`inline_sql`, `try_generate_script`).
74    NoLiteral {
75        /// What is wrong with the value.
76        reason: String,
77    },
78    /// A generated value cannot be stored in the column's SQL type.
79    InvalidValue {
80        /// The table being seeded.
81        table: String,
82        /// The column.
83        column: String,
84        /// What is wrong with the value.
85        reason: String,
86    },
87}
88
89impl fmt::Display for SeedError {
90    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
91        match self {
92            Self::CyclicForeignKeys { tables } => write!(
93                formatter,
94                "cannot seed a foreign-key cycle in one portable pass: {}",
95                tables.join(", ")
96            ),
97            Self::MissingParentRows { child, parent } => write!(
98                formatter,
99                "cannot seed {child}: referenced parent {parent} has no generated rows"
100            ),
101            Self::UnsafeResetSelection {
102                parent,
103                skipped_child,
104            } => write!(
105                formatter,
106                "cannot reset {parent} while referenced table {skipped_child} is skipped"
107            ),
108            Self::ParameterLimitTooLow {
109                table,
110                required,
111                limit,
112            } => write!(
113                formatter,
114                "cannot seed {table}: one row needs {required} bind parameters, above limit {limit}"
115            ),
116            Self::UnknownTable { table, known } => write!(
117                formatter,
118                "no table `{table}` in the schema (tables: {})",
119                known.join(", ")
120            ),
121            Self::AmbiguousTable { table, candidates } => write!(
122                formatter,
123                "table name `{table}` matches {}; qualify it as `schema.table`",
124                candidates.join(", ")
125            ),
126            Self::UnknownColumn {
127                table,
128                column,
129                known,
130            } => write!(
131                formatter,
132                "table {table} has no column `{column}` (columns: {})",
133                known.join(", ")
134            ),
135            Self::NotRelated { parent, child } => write!(
136                formatter,
137                "cannot set a relation count from {parent} to {child}: {child} has no foreign key to {parent}"
138            ),
139            Self::DialectNotEnabled { dialect } => write!(
140                formatter,
141                "a {dialect} snapshot needs drizzle-seed's feature for that dialect"
142            ),
143            Self::NoLiteral { reason } => {
144                write!(formatter, "cannot write a value inline: {reason}")
145            }
146            Self::InvalidValue {
147                table,
148                column,
149                reason,
150            } => write!(formatter, "cannot seed {table}.{column}: {reason}"),
151        }
152    }
153}
154
155impl std::error::Error for SeedError {}