use crate::identifier::Identifier;
use crate::relation::{FieldName, Header};
use crate::table_name::TableName;
use derive_more::Display;
use spacetimedb_lib::db::raw_def::IndexType;
use spacetimedb_primitives::{ColId, ColList};
use spacetimedb_sats::product_value::InvalidFieldError;
use spacetimedb_sats::raw_identifier::RawIdentifier;
use spacetimedb_sats::satn::Satn as _;
use spacetimedb_sats::{buffer, AlgebraicType, AlgebraicValue};
use std::fmt;
use std::string::FromUtf8Error;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum TypeError {
#[error("The type of `{{value.to_satns()}}` cannot be inferred")]
CannotInferType { value: AlgebraicValue },
}
#[derive(Error, Debug, Clone)]
pub enum DecodeError {
#[error("Decode UTF8: {0}")]
Utf8(#[from] FromUtf8Error),
#[error("AlgebraicType::decode: Unknown: {0}")]
AlgebraicTypeUnknown(u8),
#[error("AlgebraicType::decode: Byte array has invalid length: {0:?}")]
AlgebraicType(usize),
#[error("SumType::decode: Byte array has invalid length: {0:?}")]
SumType(usize),
#[error("ProductType::decode: Byte array has invalid length: {0:?}")]
ProductType(usize),
#[error("ProductTypeElement::decode: Byte array has invalid length: {0:?}")]
ProductTypeElement(usize),
#[error("AlgebraicValue::decode: byte array length not long enough to decode {0:?}")]
AlgebraicValue(AlgebraicType),
#[error("AlgebraicValue::decode: byte array length not long enough to get length of {0:?}")]
AlgebraicValueGetLength(AlgebraicType),
#[error(
"AlgebraicValue::decode: buffer has no room to decode any more elements from this {kind:?}. (len: {len} <= read:{read})"
)]
AlgebraicValueRoom {
kind: AlgebraicType,
len: usize,
read: usize,
},
#[error("AlgebraicValue::decode: Cannot decode {kind:?}, buffer not long enough. (len: {len}, read:{read})")]
TypeBufferSmall {
kind: AlgebraicType,
len: usize,
read: usize,
},
#[error(
"AlgebraicValue::decode: byte array length not long enough to decode {kind:?}. (expect: {expect}, read:{read})"
)]
TypeTooSmall {
kind: AlgebraicType,
expect: usize,
read: usize,
},
#[error("EnumValue::decode: Byte array length is invalid.")]
EnumValue,
}
#[derive(Error, Debug, Clone)]
pub enum LibError {
#[error("DecodeError: {0}")]
Decode(#[from] DecodeError),
#[error("BufferError: {0}")]
Buffer(#[from] buffer::DecodeError),
#[error(transparent)]
TupleFieldInvalid(#[from] InvalidFieldError),
}
#[derive(thiserror::Error, Debug)]
pub enum AuthError {
#[error("Table `{named}` is private")]
TablePrivate { named: String },
#[error("Index `{named}` is private")]
IndexPrivate { named: String },
#[error("Sequence `{named}` is private")]
SequencePrivate { named: String },
#[error("Insufficient privileges to perform the requested operation")]
InsuffientPrivileges,
#[error("Constraint `{named}` is private")]
ConstraintPrivate { named: String },
}
#[derive(thiserror::Error, Debug)]
pub enum RelationError {
#[error("Field `{1}` not found. Must be one of {0}")]
FieldNotFound(Header, FieldName),
#[error("Field `{0}` fail to infer the type: {1}")]
TypeInference(FieldName, TypeError),
#[error("Field with value `{}` was not a `bool`", val.to_satn())]
NotBoolValue { val: AlgebraicValue },
#[error("Field `{field}` was expected to be `bool` but is `{}`", ty.to_satn())]
NotBoolType { field: FieldName, ty: AlgebraicType },
#[error("Field declaration only support `table.field` or `field`. It gets instead `{0}`")]
FieldPathInvalid(String),
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Display)]
pub enum DefType {
Column,
Index,
Sequence,
Constraint,
}
#[derive(thiserror::Error, Debug, PartialEq)]
pub enum SchemaError {
#[error("Multiple primary columns defined for table: {table} columns: {pks:?}")]
MultiplePrimaryKeys { table: Box<str>, pks: Vec<String> },
#[error("{ty} {name} columns `{columns:?}` not found in table `{table}`")]
ColumnsNotFound {
name: RawIdentifier,
table: TableName,
columns: Vec<ColId>,
ty: DefType,
},
#[error("table `{table}` {ty} should have name. {ty} id: {id}")]
EmptyName { table: TableName, ty: DefType, id: u32 },
#[error("table `{table}` have `Constraints::unset()` for columns: {columns:?}")]
ConstraintUnset {
table: TableName,
name: RawIdentifier,
columns: ColList,
},
#[error("Attempt to define a column with more than 1 auto_inc sequence: Table: `{table}`, Field: `{field}`")]
OneAutoInc { table: TableName, field: Identifier },
#[error("Only Btree Indexes are supported: Table: `{table}`, Index: `{index}` is a `{index_type}`")]
OnlyBtree {
table: TableName,
index: RawIdentifier,
index_type: IndexType,
},
}
#[derive(thiserror::Error, Debug, PartialEq)]
pub struct SchemaErrors(pub Vec<SchemaError>);
impl fmt::Display for SchemaErrors {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.0.iter()).finish()
}
}