Skip to main content

nodedb_sql/
error.rs

1//! Error types for the nodedb-sql crate.
2
3/// Errors produced during SQL parsing, resolution, or planning.
4#[derive(Debug, thiserror::Error)]
5pub enum SqlError {
6    #[error("parse error: {detail}")]
7    Parse { detail: String },
8
9    #[error("unknown table: {name}")]
10    UnknownTable { name: String },
11
12    #[error("unknown column '{column}' in table '{table}'")]
13    UnknownColumn { table: String, column: String },
14
15    #[error("ambiguous column '{column}' — qualify with table name")]
16    AmbiguousColumn { column: String },
17
18    #[error("type mismatch: {detail}")]
19    TypeMismatch { detail: String },
20
21    #[error("unsupported: {detail}")]
22    Unsupported { detail: String },
23
24    #[error("invalid function call: {detail}")]
25    InvalidFunction { detail: String },
26
27    #[error("missing required field '{field}' for {context}")]
28    MissingField { field: String, context: String },
29
30    /// A descriptor the planner depends on is being drained by
31    /// an in-flight DDL. Callers (pgwire handlers) should retry
32    /// the whole statement after a short backoff. Propagated
33    /// from `SqlCatalogError::RetryableSchemaChanged`.
34    #[error("retryable schema change on {descriptor}")]
35    RetryableSchemaChanged { descriptor: String },
36
37    /// Collection is soft-deleted (within retention window).
38    /// Propagated from `SqlCatalogError::CollectionDeactivated`;
39    /// the pgwire layer renders this as sqlstate 42P01 with an
40    /// `UNDROP COLLECTION <name>` hint in the message.
41    #[error(
42        "collection '{name}' was dropped; \
43         restore with `{undrop_hint}` before retention elapses \
44         at {retention_expires_at_ns} ns"
45    )]
46    CollectionDeactivated {
47        name: String,
48        retention_expires_at_ns: u64,
49        undrop_hint: String,
50    },
51}
52
53impl From<crate::catalog::SqlCatalogError> for SqlError {
54    fn from(e: crate::catalog::SqlCatalogError) -> Self {
55        match e {
56            crate::catalog::SqlCatalogError::RetryableSchemaChanged { descriptor } => {
57                Self::RetryableSchemaChanged { descriptor }
58            }
59            crate::catalog::SqlCatalogError::CollectionDeactivated {
60                name,
61                retention_expires_at_ns,
62            } => {
63                let undrop_hint = format!("UNDROP COLLECTION {name}");
64                Self::CollectionDeactivated {
65                    name,
66                    retention_expires_at_ns,
67                    undrop_hint,
68                }
69            }
70        }
71    }
72}
73
74impl From<sqlparser::parser::ParserError> for SqlError {
75    fn from(e: sqlparser::parser::ParserError) -> Self {
76        Self::Parse {
77            detail: e.to_string(),
78        }
79    }
80}
81
82pub type Result<T> = std::result::Result<T, SqlError>;