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