1use thiserror::Error;
2
3pub type Result<T> = std::result::Result<T, SqlError>;
4
5#[derive(Debug, Error)]
6pub enum SqlError {
7 #[error("parse error: {0}")]
8 Parse(String),
9
10 #[error("plan error: {0}")]
11 Plan(String),
12
13 #[error("table '{0}' not found")]
14 TableNotFound(String),
15
16 #[error("table '{0}' already exists")]
17 TableAlreadyExists(String),
18
19 #[error("column '{0}' not found")]
20 ColumnNotFound(String),
21
22 #[error("duplicate primary key")]
23 DuplicateKey,
24
25 #[error("NOT NULL constraint failed: {0}")]
26 NotNullViolation(String),
27
28 #[error("type mismatch: expected {expected}, got {got}")]
29 TypeMismatch { expected: String, got: String },
30
31 #[error("primary key required")]
32 PrimaryKeyRequired,
33
34 #[error("duplicate column: {0}")]
35 DuplicateColumn(String),
36
37 #[error("row too large: encoded size {size} exceeds limit {max}")]
38 RowTooLarge { size: usize, max: usize },
39
40 #[error("key too large: encoded size {size} exceeds limit {max}")]
41 KeyTooLarge { size: usize, max: usize },
42
43 #[error("unsupported: {0}")]
44 Unsupported(String),
45
46 #[error("invalid value: {0}")]
47 InvalidValue(String),
48
49 #[error("division by zero")]
50 DivisionByZero,
51
52 #[error("integer overflow")]
53 IntegerOverflow,
54
55 #[error("column '{0}' is ambiguous")]
56 AmbiguousColumn(String),
57
58 #[error("index '{0}' not found")]
59 IndexNotFound(String),
60
61 #[error("index '{0}' already exists")]
62 IndexAlreadyExists(String),
63
64 #[error("unique constraint violated on index '{0}'")]
65 UniqueViolation(String),
66
67 #[error("CHECK constraint failed: {0}")]
68 CheckViolation(String),
69
70 #[error("FOREIGN KEY constraint violated: {0}")]
71 ForeignKeyViolation(String),
72
73 #[error("transaction already active")]
74 TransactionAlreadyActive,
75
76 #[error("no active transaction")]
77 NoActiveTransaction,
78
79 #[error("savepoint '{0}' does not exist")]
80 SavepointNotFound(String),
81
82 #[error("subquery must return exactly one column")]
83 SubqueryMultipleColumns,
84
85 #[error("scalar subquery returned more than one row")]
86 SubqueryMultipleRows,
87
88 #[error("query returned no rows")]
89 QueryReturnedNoRows,
90
91 #[error("parameter count mismatch: expected {expected}, got {got}")]
92 ParameterCountMismatch { expected: usize, got: usize },
93
94 #[error("compound column count mismatch: left has {left}, right has {right}")]
95 CompoundColumnCountMismatch { left: usize, right: usize },
96
97 #[error("CTE '{name}' column alias count mismatch: expected {expected}, got {got}")]
98 CteColumnAliasMismatch {
99 name: String,
100 expected: usize,
101 got: usize,
102 },
103
104 #[error("duplicate CTE name: '{0}'")]
105 DuplicateCteName(String),
106
107 #[error("recursive CTE '{0}' requires UNION or UNION ALL")]
108 RecursiveCteNoUnion(String),
109
110 #[error("recursive CTE '{0}' exceeded maximum iterations ({1})")]
111 RecursiveCteMaxIterations(String, usize),
112
113 #[error("window function '{0}' requires ORDER BY")]
114 WindowFunctionRequiresOrderBy(String),
115
116 #[error("view '{0}' not found")]
117 ViewNotFound(String),
118
119 #[error("view '{0}' already exists")]
120 ViewAlreadyExists(String),
121
122 #[error("cannot modify view '{0}'")]
123 CannotModifyView(String),
124
125 #[error("circular or too deeply nested view reference: '{0}'")]
126 CircularViewReference(String),
127
128 #[error("storage error: {0}")]
129 Storage(#[from] citadel_core::Error),
130
131 #[error("invalid DATE literal: {0}")]
132 InvalidDateLiteral(String),
133
134 #[error("invalid TIME literal: {0}")]
135 InvalidTimeLiteral(String),
136
137 #[error("invalid TIMESTAMP literal: {0}")]
138 InvalidTimestampLiteral(String),
139
140 #[error("invalid INTERVAL literal: {0}")]
141 InvalidIntervalLiteral(String),
142
143 #[error("invalid EXTRACT field: {0}")]
144 InvalidExtractField(String),
145
146 #[error("invalid DATE_TRUNC unit: {0}")]
147 InvalidDateTruncUnit(String),
148
149 #[error("time zone not supported: {0}")]
150 TimeZoneUnsupported(String),
151
152 #[error("invalid timezone: {0}")]
153 InvalidTimezone(String),
154}