1use crate::error::Span;
4use crate::types::SqlType;
5use std::fmt;
6
7#[derive(Debug, Clone)]
9pub enum AnalyzerErrorKind {
10 TableNotFound { name: String },
12 ColumnNotFound { name: String, table: Option<String> },
14 AmbiguousColumn { name: String, tables: Vec<String> },
16 FunctionNotFound { name: String },
18 WrongArgumentCount {
20 function: String,
21 expected_min: usize,
22 expected_max: Option<usize>,
23 actual: usize,
24 },
25 TypeMismatch {
27 expected: SqlType,
28 actual: SqlType,
29 context: String,
30 },
31 TypesNotComparable { left: SqlType, right: SqlType },
33 InvalidAggregateUse { function: String, reason: String },
35 InvalidWindowUse { function: String, reason: String },
37 DuplicateAlias { name: String },
39 DuplicateGroupByColumn { name: String },
41 NonAggregatedColumn { column: String },
43 OrderByNotInSelect { column: String },
45 HavingWithoutGroupBy,
47 InvalidSubquery { reason: String },
49 DivisionByZero,
51 InvalidCast { from: SqlType, to: SqlType },
53 InvalidDateTimeLiteral {
55 value: String,
56 expected_type: String,
57 },
58 DuplicateCte { name: String },
60 InvalidRecursiveCte { reason: String },
62 StarNotAllowed { context: String },
64 SetOperationColumnMismatch { left: usize, right: usize },
66 Other { message: String },
68}
69
70#[derive(Debug, Clone)]
72pub struct AnalyzerError {
73 pub kind: AnalyzerErrorKind,
75 pub span: Option<Span>,
77}
78
79impl AnalyzerError {
80 pub fn new(kind: AnalyzerErrorKind) -> Self {
82 Self { kind, span: None }
83 }
84
85 pub fn with_span(kind: AnalyzerErrorKind, span: Span) -> Self {
87 Self {
88 kind,
89 span: Some(span),
90 }
91 }
92
93 pub fn table_not_found(name: impl Into<String>) -> Self {
95 Self::new(AnalyzerErrorKind::TableNotFound { name: name.into() })
96 }
97
98 pub fn column_not_found(name: impl Into<String>, table: Option<String>) -> Self {
100 Self::new(AnalyzerErrorKind::ColumnNotFound {
101 name: name.into(),
102 table,
103 })
104 }
105
106 pub fn ambiguous_column(name: impl Into<String>, tables: Vec<String>) -> Self {
108 Self::new(AnalyzerErrorKind::AmbiguousColumn {
109 name: name.into(),
110 tables,
111 })
112 }
113
114 pub fn function_not_found(name: impl Into<String>) -> Self {
116 Self::new(AnalyzerErrorKind::FunctionNotFound { name: name.into() })
117 }
118
119 pub fn wrong_argument_count(
121 function: impl Into<String>,
122 expected_min: usize,
123 expected_max: Option<usize>,
124 actual: usize,
125 ) -> Self {
126 Self::new(AnalyzerErrorKind::WrongArgumentCount {
127 function: function.into(),
128 expected_min,
129 expected_max,
130 actual,
131 })
132 }
133
134 pub fn type_mismatch(expected: SqlType, actual: SqlType, context: impl Into<String>) -> Self {
136 Self::new(AnalyzerErrorKind::TypeMismatch {
137 expected,
138 actual,
139 context: context.into(),
140 })
141 }
142
143 pub fn types_not_comparable(left: SqlType, right: SqlType) -> Self {
145 Self::new(AnalyzerErrorKind::TypesNotComparable { left, right })
146 }
147
148 pub fn non_aggregated_column(column: impl Into<String>) -> Self {
150 Self::new(AnalyzerErrorKind::NonAggregatedColumn {
151 column: column.into(),
152 })
153 }
154
155 pub fn invalid_aggregate_use(function: impl Into<String>, reason: impl Into<String>) -> Self {
157 Self::new(AnalyzerErrorKind::InvalidAggregateUse {
158 function: function.into(),
159 reason: reason.into(),
160 })
161 }
162
163 pub fn set_operation_column_mismatch(left: usize, right: usize) -> Self {
165 Self::new(AnalyzerErrorKind::SetOperationColumnMismatch { left, right })
166 }
167}
168
169impl fmt::Display for AnalyzerError {
170 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171 match &self.kind {
172 AnalyzerErrorKind::TableNotFound { name } => {
173 write!(f, "table '{}' not found", name)
174 }
175 AnalyzerErrorKind::ColumnNotFound { name, table } => {
176 if let Some(t) = table {
177 write!(f, "column '{}' not found in table '{}'", name, t)
178 } else {
179 write!(f, "column '{}' not found", name)
180 }
181 }
182 AnalyzerErrorKind::AmbiguousColumn { name, tables } => {
183 write!(
184 f,
185 "ambiguous column '{}' found in tables: {}",
186 name,
187 tables.join(", ")
188 )
189 }
190 AnalyzerErrorKind::FunctionNotFound { name } => {
191 write!(f, "function '{}' not found", name)
192 }
193 AnalyzerErrorKind::WrongArgumentCount {
194 function,
195 expected_min,
196 expected_max,
197 actual,
198 } => {
199 if let Some(max) = expected_max {
200 if expected_min == max {
201 write!(
202 f,
203 "function '{}' expects {} arguments, got {}",
204 function, expected_min, actual
205 )
206 } else {
207 write!(
208 f,
209 "function '{}' expects {}-{} arguments, got {}",
210 function, expected_min, max, actual
211 )
212 }
213 } else {
214 write!(
215 f,
216 "function '{}' expects at least {} arguments, got {}",
217 function, expected_min, actual
218 )
219 }
220 }
221 AnalyzerErrorKind::TypeMismatch {
222 expected,
223 actual,
224 context,
225 } => {
226 write!(
227 f,
228 "type mismatch in {}: expected {}, got {}",
229 context, expected, actual
230 )
231 }
232 AnalyzerErrorKind::TypesNotComparable { left, right } => {
233 write!(f, "cannot compare {} with {}", left, right)
234 }
235 AnalyzerErrorKind::InvalidAggregateUse { function, reason } => {
236 write!(
237 f,
238 "invalid use of aggregate function '{}': {}",
239 function, reason
240 )
241 }
242 AnalyzerErrorKind::InvalidWindowUse { function, reason } => {
243 write!(
244 f,
245 "invalid use of window function '{}': {}",
246 function, reason
247 )
248 }
249 AnalyzerErrorKind::DuplicateAlias { name } => {
250 write!(f, "duplicate alias '{}'", name)
251 }
252 AnalyzerErrorKind::DuplicateGroupByColumn { name } => {
253 write!(f, "duplicate column '{}' in GROUP BY", name)
254 }
255 AnalyzerErrorKind::NonAggregatedColumn { column } => {
256 write!(
257 f,
258 "column '{}' must appear in GROUP BY clause or be used in an aggregate function",
259 column
260 )
261 }
262 AnalyzerErrorKind::OrderByNotInSelect { column } => {
263 write!(
264 f,
265 "ORDER BY column '{}' must appear in SELECT list when DISTINCT is used",
266 column
267 )
268 }
269 AnalyzerErrorKind::HavingWithoutGroupBy => {
270 write!(f, "HAVING clause requires GROUP BY clause")
271 }
272 AnalyzerErrorKind::InvalidSubquery { reason } => {
273 write!(f, "invalid subquery: {}", reason)
274 }
275 AnalyzerErrorKind::DivisionByZero => {
276 write!(f, "division by zero")
277 }
278 AnalyzerErrorKind::InvalidCast { from, to } => {
279 write!(f, "cannot cast {} to {}", from, to)
280 }
281 AnalyzerErrorKind::InvalidDateTimeLiteral {
282 value,
283 expected_type,
284 } => {
285 write!(f, "invalid {} literal: '{}'", expected_type, value)
286 }
287 AnalyzerErrorKind::DuplicateCte { name } => {
288 write!(f, "duplicate CTE name '{}'", name)
289 }
290 AnalyzerErrorKind::InvalidRecursiveCte { reason } => {
291 write!(f, "invalid recursive CTE: {}", reason)
292 }
293 AnalyzerErrorKind::StarNotAllowed { context } => {
294 write!(f, "* not allowed in {}", context)
295 }
296 AnalyzerErrorKind::SetOperationColumnMismatch { left, right } => {
297 write!(
298 f,
299 "set operations require the same number of columns ({} vs {})",
300 left, right
301 )
302 }
303 AnalyzerErrorKind::Other { message } => {
304 write!(f, "{}", message)
305 }
306 }
307 }
308}
309
310impl std::error::Error for AnalyzerError {}