spacetimedb/db/datastore/
error.rs1use super::system_tables::SystemTable;
2use enum_as_inner::EnumAsInner;
3use spacetimedb_lib::buffer::DecodeError;
4use spacetimedb_lib::{
5 db::{
6 error::LibError,
7 raw_def::{v9::RawSql, RawIndexDefV8},
8 },
9 AlgebraicType, AlgebraicValue, ProductValue,
10};
11use spacetimedb_primitives::{ColId, ColList, IndexId, SequenceId, TableId};
12use spacetimedb_sats::{product_value::InvalidFieldError, satn::Satn};
13use spacetimedb_snapshot::SnapshotError;
14use spacetimedb_table::{
15 bflatn_to, read_column,
16 table::{self, ReadViaBsatnError, UniqueConstraintViolation},
17};
18use thiserror::Error;
19
20#[derive(Error, Debug, EnumAsInner)]
21pub enum DatastoreError {
22 #[error("LibError: {0}")]
23 Lib(#[from] LibError),
24 #[error("TableError: {0}")]
25 Table(#[from] TableError),
26 #[error("IndexError: {0}")]
27 Index(#[from] IndexError),
28 #[error("SequenceError: {0}")]
29 Sequence(#[from] SequenceError),
30 #[error(transparent)]
31 Snapshot(#[from] Box<SnapshotError>),
33 #[error("Error reading a value from a table through BSATN: {0}")]
35 ReadViaBsatnError(#[from] ReadViaBsatnError),
36 #[error(transparent)]
37 Other(#[from] anyhow::Error),
38}
39
40#[derive(Error, Debug, EnumAsInner)]
41pub enum TableError {
42 #[error("Table with name `{0}` start with 'st_' and that is reserved for internal system tables.")]
43 System(Box<str>),
44 #[error("Table with name `{0}` already exists.")]
45 Exist(String),
46 #[error("Table with name `{0}` not found.")]
47 NotFound(String),
48 #[error("Table with ID `{1}` not found in `{0}`.")]
49 IdNotFound(SystemTable, u32),
50 #[error("Sql `{1}` not found in `{0}`.")]
51 RawSqlNotFound(SystemTable, RawSql),
52 #[error("Table with ID `{0}` not found in `TxState`.")]
53 IdNotFoundState(TableId),
54 #[error("Column `{0}.{1}` is missing a name")]
55 ColumnWithoutName(String, ColId),
56 #[error("schema_for_table: Table has invalid schema: {0} Err: {1}")]
57 InvalidSchema(TableId, LibError),
58 #[error("Row has invalid row type for table: {0} Err: {1}", table_id, row.to_satn())]
59 RowInvalidType { table_id: TableId, row: ProductValue },
60 #[error("failed to decode row in table")]
61 RowDecodeError(DecodeError),
62 #[error("Column with name `{0}` already exists")]
63 DuplicateColumnName(String),
64 #[error("Column `{0}` not found")]
65 ColumnNotFound(ColId),
66 #[error(
67 "DecodeError for field `{0}.{1}`, expect `{2}` but found `{3}`",
68 table,
69 field,
70 expect,
71 found
72 )]
73 DecodeField {
74 table: String,
75 field: Box<str>,
76 expect: String,
77 found: String,
78 },
79 #[error(transparent)]
80 Bflatn(#[from] bflatn_to::Error),
81 #[error(transparent)]
82 Duplicate(#[from] table::DuplicateError),
83 #[error(transparent)]
84 ReadColTypeError(#[from] read_column::TypeError),
85}
86
87#[derive(Error, Debug, PartialEq, Eq)]
88pub enum IndexError {
89 #[error("Index not found: {0:?}")]
90 NotFound(IndexId),
91 #[error("Column not found: {0:?}")]
92 ColumnNotFound(RawIndexDefV8),
93 #[error(transparent)]
94 UniqueConstraintViolation(#[from] UniqueConstraintViolation),
95 #[error("Attempt to define a index with more than 1 auto_inc column: Table: {0:?}, Columns: {1:?}")]
96 OneAutoInc(TableId, Vec<String>),
97 #[error("Could not decode arguments to index scan")]
98 Decode(DecodeError),
99 #[error("Index was not unique: {0:?}")]
100 NotUnique(IndexId),
101 #[error("Key {1:?} was not found in index {0:?}")]
102 KeyNotFound(IndexId, AlgebraicValue),
103}
104
105#[derive(Error, Debug, PartialEq, Eq)]
106pub enum SequenceError {
107 #[error("Sequence with name `{0}` already exists.")]
108 Exist(String),
109 #[error("Sequence `{0}`: The increment is 0, and this means the sequence can't advance.")]
110 IncrementIsZero(String),
111 #[error("Sequence `{0}`: The min_value {1} must < max_value {2}.")]
112 MinMax(String, i128, i128),
113 #[error("Sequence `{0}`: The start value {1} must be >= min_value {2}.")]
114 MinStart(String, i128, i128),
115 #[error("Sequence `{0}`: The start value {1} must be <= min_value {2}.")]
116 MaxStart(String, i128, i128),
117 #[error("Sequence `{0}` failed to decode value from Sled (not a u128).")]
118 SequenceValue(String),
119 #[error("Sequence ID `{0}` not found.")]
120 NotFound(SequenceId),
121 #[error("Sequence applied to a non-integer field. Column `{col}` is of type {{found.to_sats()}}.")]
122 NotInteger { col: String, found: AlgebraicType },
123 #[error("Sequence ID `{0}` still had no values left after allocation.")]
124 UnableToAllocate(SequenceId),
125 #[error("Autoinc constraint on table {0:?} spans more than one column: {1:?}")]
126 MultiColumnAutoInc(TableId, ColList),
127}
128
129impl From<InvalidFieldError> for DatastoreError {
130 fn from(value: InvalidFieldError) -> Self {
131 LibError::from(value).into()
132 }
133}
134
135impl From<spacetimedb_table::read_column::TypeError> for DatastoreError {
136 fn from(err: spacetimedb_table::read_column::TypeError) -> Self {
137 TableError::from(err).into()
138 }
139}
140
141impl From<table::InsertError> for DatastoreError {
142 fn from(err: table::InsertError) -> Self {
143 match err {
144 table::InsertError::Duplicate(e) => TableError::from(e).into(),
145 table::InsertError::Bflatn(e) => TableError::from(e).into(),
146 table::InsertError::IndexError(e) => IndexError::from(e).into(),
147 }
148 }
149}
150
151impl From<bflatn_to::Error> for DatastoreError {
152 fn from(err: bflatn_to::Error) -> Self {
153 Self::Table(err.into())
154 }
155}
156
157impl From<SnapshotError> for DatastoreError {
158 fn from(e: SnapshotError) -> Self {
159 DatastoreError::Snapshot(Box::new(e))
160 }
161}