Skip to main content

icydb_core/db/schema/
errors.rs

1//! Module: db::schema::errors
2//! Responsibility: schema validation error taxonomy for runtime schema contracts.
3//! Does not own: predicate AST or planning policy logic.
4//! Boundary: error surface for schema construction and predicate-schema validation.
5
6use crate::{
7    db::predicate::{CoercionId, UnsupportedQueryFeature},
8    model::index::{IndexExpression, IndexModel},
9};
10use std::fmt;
11
12/// Predicate/schema validation failures, including invalid model contracts.
13#[derive(Debug, thiserror::Error)]
14pub enum ValidateError {
15    #[error("unknown field '{field}'")]
16    UnknownField { field: String },
17
18    #[error("field '{field}' is not queryable")]
19    NonQueryableFieldType { field: String },
20
21    #[error("duplicate field '{field}'")]
22    DuplicateField { field: String },
23
24    #[error("{0}")]
25    UnsupportedQueryFeature(#[from] UnsupportedQueryFeature),
26
27    #[error("primary key '{field}' not present in entity fields")]
28    InvalidPrimaryKey { field: String },
29
30    #[error("primary key '{field}' has a non-keyable type")]
31    InvalidPrimaryKeyType { field: String },
32
33    #[error("index '{index}' references unknown field '{field}'")]
34    IndexFieldUnknown {
35        index: Box<IndexModel>,
36        field: String,
37    },
38
39    #[error("index '{index}' references non-queryable field '{field}'")]
40    IndexFieldNotQueryable {
41        index: Box<IndexModel>,
42        field: String,
43    },
44
45    #[error(
46        "index '{index}' references map field '{field}'; map fields are not queryable in icydb 0.7"
47    )]
48    IndexFieldMapNotQueryable {
49        index: Box<IndexModel>,
50        field: String,
51    },
52
53    #[error("index '{index}' repeats field '{field}'")]
54    IndexFieldDuplicate {
55        index: Box<IndexModel>,
56        field: String,
57    },
58
59    #[error("index '{index}' expression key item '{expression}' requires {expected}")]
60    IndexExpressionFieldTypeInvalid {
61        index: &'static str,
62        expression: IndexExpression,
63        expected: &'static str,
64    },
65
66    #[error("duplicate index name '{name}'")]
67    DuplicateIndexName { name: String },
68
69    #[error("index '{index}' predicate '{predicate}' has invalid SQL syntax")]
70    InvalidIndexPredicateSyntax {
71        index: Box<IndexModel>,
72        predicate: &'static str,
73    },
74
75    #[error("index '{index}' predicate '{predicate}' is invalid for schema")]
76    InvalidIndexPredicateSchema {
77        index: Box<IndexModel>,
78        predicate: &'static str,
79    },
80
81    #[error("operator {op} is not valid for field '{field}'")]
82    InvalidOperator { field: String, op: String },
83
84    #[error("coercion {coercion:?} is not valid for field '{field}'")]
85    InvalidCoercion { field: String, coercion: CoercionId },
86
87    #[error("invalid literal for field '{field}': {message}")]
88    InvalidLiteral { field: String, message: String },
89}
90
91impl ValidateError {
92    pub(crate) fn invalid_operator(field: &str, op: impl fmt::Display) -> Self {
93        Self::InvalidOperator {
94            field: field.to_string(),
95            op: op.to_string(),
96        }
97    }
98
99    pub(crate) fn invalid_literal(field: &str, msg: &str) -> Self {
100        Self::InvalidLiteral {
101            field: field.to_string(),
102            message: msg.to_string(),
103        }
104    }
105}