proof_of_sql/sql/parse/
error.rs

1use crate::{
2    base::{
3        database::{ColumnOperationError, ColumnType, TableRef},
4        math::decimal::{DecimalError, IntermediateDecimalError},
5    },
6    sql::AnalyzeError,
7};
8use alloc::{
9    boxed::Box,
10    format,
11    string::{String, ToString},
12};
13use core::result::Result;
14use proof_of_sql_parser::posql_time::PoSQLTimestampError;
15use snafu::Snafu;
16use sqlparser::ast::{Ident, ObjectName};
17
18/// Errors from converting an intermediate AST into a provable AST.
19#[derive(Snafu, Debug, PartialEq, Eq)]
20pub enum ConversionError {
21    #[snafu(display("Column '{identifier}' was not found in table '{table_ref}'"))]
22    /// The column is missing in the table
23    MissingColumn {
24        /// The missing column identifier
25        identifier: Box<Ident>,
26        /// The table ref
27        table_ref: TableRef,
28    },
29
30    #[snafu(display("Missing schema or table identifier in ObjectName"))]
31    /// Missing schema or table identifier
32    MissingSchemaOrTable {
33        /// The `ObjectName`
34        object_name: ObjectName,
35    },
36
37    #[snafu(display("Column '{identifier}' was not found"))]
38    /// The column is missing (without table information)
39    MissingColumnWithoutTable {
40        /// The missing column identifier
41        identifier: Box<Ident>,
42    },
43
44    #[snafu(display("Expected '{expected}' but found '{actual}'"))]
45    /// Invalid data type received
46    InvalidDataType {
47        /// Expected data type
48        expected: ColumnType,
49        /// Actual data type found
50        actual: ColumnType,
51    },
52
53    #[snafu(display("Left side has '{left_type}' type but right side has '{right_type}' type"))]
54    /// Data types do not match
55    DataTypeMismatch {
56        /// The left side datatype
57        left_type: String,
58        /// The right side datatype
59        right_type: String,
60    },
61
62    #[snafu(display("Columns have different lengths: {len_a} != {len_b}"))]
63    /// Two columns do not have the same length
64    DifferentColumnLength {
65        /// The length of the first column
66        len_a: usize,
67        /// The length of the second column
68        len_b: usize,
69    },
70
71    #[snafu(display("Multiple result columns with the same alias '{alias}' have been found."))]
72    /// Duplicate alias in result columns
73    DuplicateResultAlias {
74        /// The duplicate alias
75        alias: String,
76    },
77
78    #[snafu(display(
79        "A WHERE clause must have boolean type. It is currently of type '{datatype}'."
80    ))]
81    /// WHERE clause is not boolean
82    NonbooleanWhereClause {
83        /// The actual datatype of the WHERE clause
84        datatype: ColumnType,
85    },
86
87    #[snafu(display(
88        "Invalid order by: alias '{alias}' does not appear in the result expressions."
89    ))]
90    /// ORDER BY clause references a non-existent alias
91    InvalidOrderBy {
92        /// The non-existent alias in the ORDER BY clause
93        alias: String,
94    },
95
96    #[snafu(display(
97        "Invalid group by: column '{column}' must appear in the group by expression."
98    ))]
99    /// GROUP BY clause references a non-existent column
100    InvalidGroupByColumnRef {
101        /// The non-existent column in the GROUP BY clause
102        column: String,
103    },
104
105    #[snafu(display("Invalid expression: {expression}"))]
106    /// General error for invalid expressions
107    InvalidExpression {
108        /// The invalid expression error
109        expression: String,
110    },
111
112    #[snafu(display("Encountered parsing error: {error}"))]
113    /// General parsing error
114    ParseError {
115        /// The underlying error
116        error: String,
117    },
118
119    #[snafu(transparent)]
120    /// Errors related to decimal operations
121    DecimalConversionError {
122        /// The underlying source error
123        source: DecimalError,
124    },
125
126    /// Errors related to timestamp parsing
127    #[snafu(context(false), display("Timestamp conversion error: {source}"))]
128    TimestampConversionError {
129        /// The underlying source error
130        source: PoSQLTimestampError,
131    },
132
133    /// Errors related to column operations
134    #[snafu(transparent)]
135    ColumnOperationError {
136        /// The underlying source error
137        source: ColumnOperationError,
138    },
139
140    /// Errors related to postprocessing
141    #[snafu(transparent)]
142    PostprocessingError {
143        /// The underlying source error
144        source: crate::sql::postprocessing::PostprocessingError,
145    },
146
147    #[snafu(display("Query not provable because: {error}"))]
148    /// Query requires unprovable feature
149    Unprovable {
150        /// The underlying error
151        error: String,
152    },
153
154    #[snafu(display("Unsupported operator: {message}"))]
155    /// Unsupported operation
156    UnsupportedOperation {
157        /// The operator that is unsupported
158        message: String,
159    },
160    /// Errors in converting `Ident` to `Identifier`
161    #[snafu(display("Failed to convert `Ident` to `Identifier`: {error}"))]
162    IdentifierConversionError {
163        /// The underlying error message
164        error: String,
165    },
166    /// Errors in the native analyze process
167    #[snafu(transparent)]
168    AnalyzeError {
169        /// The underlying source error
170        source: AnalyzeError,
171    },
172}
173
174impl From<String> for ConversionError {
175    fn from(value: String) -> Self {
176        ConversionError::ParseError { error: value }
177    }
178}
179
180impl From<ConversionError> for String {
181    fn from(error: ConversionError) -> Self {
182        error.to_string()
183    }
184}
185
186impl From<IntermediateDecimalError> for ConversionError {
187    fn from(err: IntermediateDecimalError) -> ConversionError {
188        ConversionError::DecimalConversionError {
189            source: DecimalError::IntermediateDecimalConversionError { source: err },
190        }
191    }
192}
193
194impl ConversionError {
195    /// Returns a `ConversionError::InvalidExpression` for non-numeric types used in numeric aggregation functions.
196    pub fn non_numeric_expr_in_agg<S: Into<String>>(dtype: S, func: S) -> Self {
197        ConversionError::InvalidExpression {
198            expression: format!(
199                "cannot use expression of type '{}' with numeric aggregation function '{}'",
200                dtype.into().to_lowercase(),
201                func.into().to_lowercase()
202            ),
203        }
204    }
205}
206
207pub type ConversionResult<T> = Result<T, ConversionError>;