palimpsest_sql/error.rs
1// Copyright 2026 Thousand Birds Inc.
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4use thiserror::Error;
5
6/// Errors surfaced by the SQL parsing, lowering, and validation passes.
7#[derive(Debug, Error)]
8pub enum SqlError {
9 /// More than one statement was supplied where exactly one was
10 /// expected (subscriptions accept a single `SELECT`).
11 #[error("expected exactly one SQL statement, got {0}")]
12 StatementCount(usize),
13
14 /// The supplied statement was not a `SELECT`.
15 #[error("only SELECT queries are supported")]
16 UnsupportedStatement,
17
18 /// The supplied query uses a SQL feature outside the v1 surface.
19 #[error("unsupported SQL feature: {0}")]
20 UnsupportedFeature(&'static str),
21
22 /// Referenced table is not in the catalog.
23 #[error("unknown table: {0}")]
24 UnknownTable(String),
25
26 /// Referenced column is not present on the resolved table.
27 #[error("unknown column: {0}")]
28 UnknownColumn(String),
29
30 /// Column name resolves to multiple sources without a qualifier.
31 #[error("ambiguous column reference: {0}")]
32 AmbiguousColumn(String),
33
34 /// Expression failed type-checking against the catalog.
35 #[error("SQL type mismatch: {0}")]
36 TypeMismatch(String),
37
38 /// Parser input exceeded the configured byte budget. Surfaces as a
39 /// 4xx-equivalent on the gRPC wire so a runaway client cannot
40 /// exhaust the parser by submitting megabyte-scale SQL strings.
41 #[error("SQL input is {len} bytes, limit is {limit}")]
42 QueryTooLarge {
43 /// Length of the rejected input.
44 len: usize,
45 /// Configured byte budget.
46 limit: usize,
47 },
48
49 /// Lowered MIR exceeded the configured node-count budget. Same
50 /// rationale as `QueryTooLarge`, but for cases where the SQL itself
51 /// is short yet expands (set ops, joins, CTEs) into a large graph.
52 #[error("MIR has {nodes} nodes, limit is {limit}")]
53 QueryTooComplex {
54 /// Node count of the lowered graph.
55 nodes: usize,
56 /// Configured node budget.
57 limit: usize,
58 },
59
60 /// Wrapped underlying parser failure.
61 #[error(transparent)]
62 Parse(#[from] sqlparser::parser::ParserError),
63}