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 {}