spacetimedb_query_planner/logical/
errors.rs1use 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 pub fn var(name: &str) -> Self {
24 Self::Var(name.to_owned())
25 }
26
27 pub fn table(name: &str) -> Self {
29 Self::Table(name.to_owned())
30 }
31
32 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#[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#[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}