Skip to main content

spacetimedb_query_planner/logical/
errors.rs

1use spacetimedb_sql_parser::{ast::BinOp, parser::errors::SqlParseError};
2use thiserror::Error;
3
4use super::{
5    stmt::InvalidVar,
6    ty::{InvalidTypeId, TypeWithCtx},
7};
8
9#[derive(Error, Debug)]
10pub enum Unresolved {
11    #[error("`{0}` is not in scope")]
12    Var(String),
13    #[error("`{0}` is not a valid table")]
14    Table(String),
15    #[error("`{0}` does not have a field `{1}`")]
16    Field(String, String),
17    #[error("Cannot resolve type for literal expression")]
18    Literal,
19}
20
21impl Unresolved {
22    /// Cannot resolve name
23    pub fn var(name: &str) -> Self {
24        Self::Var(name.to_owned())
25    }
26
27    /// Cannot resolve table name
28    pub fn table(name: &str) -> Self {
29        Self::Table(name.to_owned())
30    }
31
32    /// Cannot resolve field name within table
33    pub fn field(table: &str, field: &str) -> Self {
34        Self::Field(table.to_owned(), field.to_owned())
35    }
36}
37
38#[derive(Error, Debug)]
39pub enum InvalidWildcard {
40    #[error("SELECT * is not supported for joins")]
41    Join,
42    #[error("SELECT * is not valid for scalar types")]
43    Scalar,
44}
45
46#[derive(Error, Debug)]
47pub enum Unsupported {
48    #[error("Column projections are not supported in subscriptions; Subscriptions must return a table type")]
49    ReturnType,
50    #[error("Unsupported expression in projection")]
51    ProjectExpr,
52    #[error("ORDER BY is not supported")]
53    OrderBy,
54    #[error("LIMIT is not supported")]
55    Limit,
56}
57
58// TODO: It might be better to return the missing/extra fields
59#[derive(Error, Debug)]
60#[error("Inserting a row with {values} values into `{table}` which has {fields} fields")]
61pub struct InsertValuesError {
62    pub table: String,
63    pub values: usize,
64    pub fields: usize,
65}
66
67// TODO: It might be better to return the missing/extra fields
68#[derive(Error, Debug)]
69#[error("The number of fields ({nfields}) in the INSERT does not match the number of columns ({ncols}) of the table `{table}`")]
70pub struct InsertFieldsError {
71    pub table: String,
72    pub ncols: usize,
73    pub nfields: usize,
74}
75
76#[derive(Debug, Error)]
77#[error("Invalid binary operator `{op}` for type `{ty}`")]
78pub struct InvalidOp {
79    op: BinOp,
80    ty: String,
81}
82
83impl InvalidOp {
84    pub fn new(op: BinOp, ty: &TypeWithCtx) -> Self {
85        Self { op, ty: ty.to_string() }
86    }
87}
88
89#[derive(Debug, Error)]
90#[error("Expected a relation, but found a scalar type `{ty}` instead")]
91pub struct ExpectedRelation {
92    ty: String,
93}
94
95impl ExpectedRelation {
96    pub fn new(ty: &TypeWithCtx) -> Self {
97        Self { ty: ty.to_string() }
98    }
99}
100
101#[derive(Error, Debug)]
102#[error("The literal expression `{literal}` cannot be parsed as type `{ty}`")]
103pub struct InvalidLiteral {
104    literal: String,
105    ty: String,
106}
107
108impl InvalidLiteral {
109    pub fn new(literal: String, expected: &TypeWithCtx) -> Self {
110        Self {
111            literal,
112            ty: expected.to_string(),
113        }
114    }
115}
116
117#[derive(Debug, Error)]
118#[error("Unexpected type: (expected) {expected} != {inferred} (inferred)")]
119pub struct UnexpectedType {
120    expected: String,
121    inferred: String,
122}
123
124impl UnexpectedType {
125    pub fn new(expected: &TypeWithCtx, inferred: &TypeWithCtx) -> Self {
126        Self {
127            expected: expected.to_string(),
128            inferred: inferred.to_string(),
129        }
130    }
131}
132
133#[derive(Debug, Error)]
134#[error("Duplicate name `{0}`")]
135pub struct DuplicateName(pub String);
136
137#[derive(Error, Debug)]
138pub enum TypingError {
139    #[error(transparent)]
140    Unsupported(#[from] Unsupported),
141    #[error(transparent)]
142    Unresolved(#[from] Unresolved),
143    #[error(transparent)]
144    InvalidTyId(#[from] InvalidTypeId),
145    #[error(transparent)]
146    InvalidVar(#[from] InvalidVar),
147    #[error(transparent)]
148    InsertValues(#[from] InsertValuesError),
149    #[error(transparent)]
150    InsertFields(#[from] InsertFieldsError),
151    #[error(transparent)]
152    ParseError(#[from] SqlParseError),
153
154    #[error(transparent)]
155    InvalidOp(#[from] InvalidOp),
156    #[error(transparent)]
157    Literal(#[from] InvalidLiteral),
158    #[error(transparent)]
159    Relation(#[from] ExpectedRelation),
160    #[error(transparent)]
161    Unexpected(#[from] UnexpectedType),
162    #[error(transparent)]
163    Wildcard(#[from] InvalidWildcard),
164    #[error(transparent)]
165    DuplicateName(#[from] DuplicateName),
166}