proof_of_sql/sql/parse/
error.rs

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