use crate::iam::Error as IamError;
use crate::idx::ft::MatchRef;
use crate::idx::trees::vector::SharedVector;
use crate::key::error::KeyCategory;
use crate::sql::idiom::Idiom;
use crate::sql::index::Distance;
use crate::sql::thing::Thing;
use crate::sql::value::Value;
use crate::syn::error::RenderedError as RenderedParserError;
use crate::vs::Error as VersionstampError;
use base64_lib::DecodeError as Base64Error;
use bincode::Error as BincodeError;
use fst::Error as FstError;
use jsonwebtoken::errors::Error as JWTError;
use revision::Error as RevisionError;
use serde::Serialize;
use std::io::Error as IoError;
use std::string::FromUtf8Error;
use storekey::decode::Error as DecodeError;
use storekey::encode::Error as EncodeError;
use thiserror::Error;
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum Error {
#[doc(hidden)]
#[error("Conditional clause is not truthy")]
Ignore,
#[doc(hidden)]
#[error("Break statement has been reached")]
Break,
#[doc(hidden)]
#[error("Continue statement has been reached")]
Continue,
#[doc(hidden)]
#[error("This document should be retried with a new ID")]
RetryWithId(Thing),
#[error("The database encountered unreachable logic")]
Unreachable,
#[error("{0}")]
Deprecated(String),
#[error("An error occurred: {0}")]
Thrown(String),
#[error("There was a problem with the underlying datastore: {0}")]
Ds(String),
#[error("There was a problem with a datastore transaction: {0}")]
Tx(String),
#[error("There was an error when starting a new datastore transaction")]
TxFailure,
#[error("Couldn't update a finished transaction")]
TxFinished,
#[error("Couldn't write to a read only transaction")]
TxReadonly,
#[error("Value being checked was not correct")]
TxConditionNotMet,
#[error("The key being inserted already exists")]
#[deprecated(note = "Use TxKeyAlreadyExistsCategory")]
TxKeyAlreadyExists,
#[error("Record id or key is too large")]
TxKeyTooLarge,
#[error("Record or value is too large")]
TxValueTooLarge,
#[error("Transaction is too large")]
TxTooLarge,
#[error("Specify a namespace to use")]
NsEmpty,
#[error("Specify a database to use")]
DbEmpty,
#[error("Specify some SQL code to execute")]
QueryEmpty,
#[error("The SQL query was not parsed fully")]
QueryRemaining,
#[error("Parse error: {0}")]
InvalidQuery(RenderedParserError),
#[error("Can not use {value} in a CONTENT clause")]
InvalidContent {
value: Value,
},
#[error("Can not use {value} in a MERGE clause")]
InvalidMerge {
value: Value,
},
#[error("The JSON Patch contains invalid operations. {message}")]
InvalidPatch {
message: String,
},
#[error("Given test operation failed for JSON Patch. Expected `{expected}`, but got `{got}` instead.")]
PatchTest {
expected: String,
got: String,
},
#[error("Remote HTTP request functions are not enabled")]
HttpDisabled,
#[error("Found '{name}' but it is not possible to set a variable with this name")]
InvalidParam {
name: String,
},
#[error("Found '{field}' in SELECT clause on line {line}, but field is not an aggregate function, and is not present in GROUP BY expression")]
InvalidField {
line: usize,
field: String,
},
#[error("Found '{field}' in SPLIT ON clause on line {line}, but field is not present in SELECT expression")]
InvalidSplit {
line: usize,
field: String,
},
#[error("Found '{field}' in ORDER BY clause on line {line}, but field is not present in SELECT expression")]
InvalidOrder {
line: usize,
field: String,
},
#[error("Found '{field}' in GROUP BY clause on line {line}, but field is not present in SELECT expression")]
InvalidGroup {
line: usize,
field: String,
},
#[error("Found {value} but the LIMIT clause must evaluate to a positive integer")]
InvalidLimit {
value: String,
},
#[error("Found {value} but the START clause must evaluate to a positive integer")]
InvalidStart {
value: String,
},
#[error("Problem with embedded script function. {message}")]
InvalidScript {
message: String,
},
#[error("There was a problem running the {name}() function. {message}")]
InvalidFunction {
name: String,
message: String,
},
#[error("Incorrect arguments for function {name}(). {message}")]
InvalidArguments {
name: String,
message: String,
},
#[error("The URL `{0}` is invalid")]
InvalidUrl(String),
#[error("Incorrect vector dimension ({current}). Expected a vector of {expected} dimension.")]
InvalidVectorDimension {
current: usize,
expected: usize,
},
#[error("Unable to compute distance.The calculated result is not a valid number: {dist}. Vectors: {left:?} - {right:?}")]
InvalidVectorDistance {
left: SharedVector,
right: SharedVector,
dist: f64,
},
#[error("The vector element ({current}) is not a number.")]
InvalidVectorType {
current: String,
expected: &'static str,
},
#[error("The value '{current}' is not a vector.")]
InvalidVectorValue {
current: String,
},
#[error("Invalid regular expression: {0:?}")]
InvalidRegex(String),
#[error("The query was not executed because it exceeded the timeout")]
QueryTimedout,
#[error("The query was not executed due to a cancelled transaction")]
QueryCancelled,
#[error("The query was not executed due to a failed transaction")]
QueryNotExecuted,
#[error("The query was not executed due to a failed transaction. {message}")]
QueryNotExecutedDetail {
message: String,
},
#[error("You don't have permission to change to the {ns} namespace")]
NsNotAllowed {
ns: String,
},
#[error("You don't have permission to change to the {db} database")]
DbNotAllowed {
db: String,
},
#[error("The namespace '{value}' does not exist")]
NsNotFound {
value: String,
},
#[error("The namespace token '{value}' does not exist")]
NtNotFound {
value: String,
},
#[error("The namespace login '{value}' does not exist")]
NlNotFound {
value: String,
},
#[error("The database '{value}' does not exist")]
DbNotFound {
value: String,
},
#[error("The database token '{value}' does not exist")]
DtNotFound {
value: String,
},
#[error("The database login '{value}' does not exist")]
DlNotFound {
value: String,
},
#[error("The function 'fn::{value}' does not exist")]
FcNotFound {
value: String,
},
#[error("The scope '{value}' does not exist")]
ScNotFound {
value: String,
},
#[error("The node '{value}' already exists")]
ClAlreadyExists {
value: String,
},
#[error("The node '{value}' does not exist")]
NdNotFound {
value: String,
},
#[error("The scope token '{value}' does not exist")]
StNotFound {
value: String,
},
#[error("The param '${value}' does not exist")]
PaNotFound {
value: String,
},
#[error("The table '{value}' does not exist")]
TbNotFound {
value: String,
},
#[error("The live query '{value}' does not exist")]
LvNotFound {
value: String,
},
#[error("The cluster live query '{value}' does not exist")]
LqNotFound {
value: String,
},
#[error("The analyzer '{value}' does not exist")]
AzNotFound {
value: String,
},
#[error("The index '{value}' does not exist")]
IxNotFound {
value: String,
},
#[error("Unsupported distance: {0}")]
UnsupportedDistance(Distance),
#[error("The root user '{value}' does not exist")]
UserRootNotFound {
value: String,
},
#[error("The user '{value}' does not exist in the namespace '{ns}'")]
UserNsNotFound {
value: String,
ns: String,
},
#[error("The user '{value}' does not exist in the database '{db}'")]
UserDbNotFound {
value: String,
ns: String,
db: String,
},
#[error("Unable to perform the realtime query")]
RealtimeDisabled,
#[error("Reached excessive computation depth due to functions, subqueries, or futures")]
ComputationDepthExceeded,
#[error("Can not execute statement using value '{value}'")]
InvalidStatementTarget {
value: String,
},
#[error("Can not execute CREATE statement using value '{value}'")]
CreateStatement {
value: String,
},
#[error("Can not execute UPDATE statement using value '{value}'")]
UpdateStatement {
value: String,
},
#[error("Can not execute RELATE statement using value '{value}'")]
RelateStatement {
value: String,
},
#[error("Can not execute DELETE statement using value '{value}'")]
DeleteStatement {
value: String,
},
#[error("Can not execute INSERT statement using value '{value}'")]
InsertStatement {
value: String,
},
#[error("Can not execute LIVE statement using value '{value}'")]
LiveStatement {
value: String,
},
#[error("Can not execute KILL statement using id '{value}'")]
KillStatement {
value: String,
},
#[error("Expected a single result output when using the ONLY keyword")]
SingleOnlyOutput,
#[error("You don't have permission to run this query on the `{table}` table")]
TablePermissions {
table: String,
},
#[error("You don't have permission to view the ${name} parameter")]
ParamPermissions {
name: String,
},
#[error("You don't have permission to run the fn::{name} function")]
FunctionPermissions {
name: String,
},
#[error("Unable to write to the `{table}` table while setup as a view")]
TableIsView {
table: String,
},
#[error("Database record `{thing}` already exists")]
RecordExists {
thing: String,
},
#[error("Database index `{index}` already contains {value}, with record `{thing}`")]
IndexExists {
thing: Thing,
index: String,
value: String,
},
#[error("Found {value} for field `{field}`, with record `{thing}`, but expected a {check}")]
FieldCheck {
thing: String,
value: String,
field: Idiom,
check: String,
},
#[error("Found {value} for field `{field}`, with record `{thing}`, but field must conform to: {check}")]
FieldValue {
thing: String,
value: String,
field: Idiom,
check: String,
},
#[error("Found {value} for the id field, but a specific record has been specified")]
IdMismatch {
value: String,
},
#[error("Found {value} for the Record ID but this is not a valid id")]
IdInvalid {
value: String,
},
#[error("Expected a {into} but found {from}")]
CoerceTo {
from: Value,
into: String,
},
#[error("Expected a {into} but cannot convert {from} into a {into}")]
ConvertTo {
from: Value,
into: String,
},
#[error("Expected a {kind} but the array had {size} items")]
LengthInvalid {
kind: String,
size: usize,
},
#[error("Cannot perform addition with '{0}' and '{1}'")]
TryAdd(String, String),
#[error("Cannot perform subtraction with '{0}' and '{1}'")]
TrySub(String, String),
#[error("Cannot perform multiplication with '{0}' and '{1}'")]
TryMul(String, String),
#[error("Cannot perform division with '{0}' and '{1}'")]
TryDiv(String, String),
#[error("Cannot perform remainder with '{0}' and '{1}'")]
TryRem(String, String),
#[error("Cannot raise the value '{0}' with '{1}'")]
TryPow(String, String),
#[error("Cannot negate the value '{0}'")]
TryNeg(String),
#[error("Cannot convert from '{0}' to '{1}'")]
TryFrom(String, &'static str),
#[error("There was an error processing a remote HTTP request: {0}")]
Http(String),
#[error("There was an error processing a value in parallel: {0}")]
Channel(String),
#[error("I/O error: {0}")]
Io(#[from] IoError),
#[error("Key encoding error: {0}")]
Encode(#[from] EncodeError),
#[error("Key decoding error: {0}")]
Decode(#[from] DecodeError),
#[error("Versioned error: {0}")]
Revision(#[from] RevisionError),
#[error("Index is corrupted")]
CorruptedIndex,
#[error("There was no suitable index supporting the expression '{value}'")]
NoIndexFoundForMatch {
value: String,
},
#[error("A value can't be analyzed: {0}")]
AnalyzerError(String),
#[error("A value can't be highlighted: {0}")]
HighlightError(String),
#[error("Bincode error: {0}")]
Bincode(#[from] BincodeError),
#[error("FstError error: {0}")]
FstError(#[from] FstError),
#[error("Utf8 error: {0}")]
Utf8Error(#[from] FromUtf8Error),
#[error("Feature not yet implemented: {feature}")]
FeatureNotYetImplemented {
feature: String,
},
#[error("Duplicated Match reference: {mr}")]
DuplicatedMatchRef {
mr: MatchRef,
},
#[error("Timestamp arithmetic error: {0}")]
TimestampOverflow(String),
#[error("Internal database error: {0}")]
Internal(String),
#[error("Unimplemented functionality: {0}")]
Unimplemented(String),
#[error("Versionstamp in key is corrupted: {0}")]
CorruptedVersionstampInKey(#[from] VersionstampError),
#[error("Invalid level '{0}'")]
InvalidLevel(String),
#[error("IAM error: {0}")]
IamError(#[from] IamError),
#[error("Scripting functions are not allowed")]
ScriptingNotAllowed,
#[error("Function '{0}' is not allowed to be executed")]
FunctionNotAllowed(String),
#[error("Access to network target '{0}' is not allowed")]
NetTargetNotAllowed(String),
#[error("There was an error creating the token")]
TokenMakingFailed,
#[error("No record was returned")]
NoRecordFound,
#[error("The signup query failed")]
SignupQueryFailed,
#[error("The signin query failed")]
SigninQueryFailed,
#[error("This scope does not allow signup")]
ScopeNoSignup,
#[error("This scope does not allow signin")]
ScopeNoSignin,
#[error("The scope does not exist")]
NoScopeFound,
#[error("Username or Password was not provided")]
MissingUserOrPass,
#[error("No signin target to either SC or DB or NS or KV")]
NoSigninTarget,
#[error("The password did not verify")]
InvalidPass,
#[error("There was a problem with authentication")]
InvalidAuth,
#[error("There was a problem with signing up")]
InvalidSignup,
#[error("Auth was expected to be set but was unknown")]
UnknownAuth,
#[error("The key being inserted already exists: {0}")]
TxKeyAlreadyExistsCategory(KeyCategory),
}
impl From<Error> for String {
fn from(e: Error) -> String {
e.to_string()
}
}
impl From<Base64Error> for Error {
fn from(_: Base64Error) -> Error {
Error::InvalidAuth
}
}
impl From<JWTError> for Error {
fn from(_: JWTError) -> Error {
Error::InvalidAuth
}
}
impl From<regex::Error> for Error {
fn from(error: regex::Error) -> Self {
Error::InvalidRegex(error.to_string())
}
}
#[cfg(feature = "kv-mem")]
impl From<echodb::err::Error> for Error {
fn from(e: echodb::err::Error) -> Error {
match e {
echodb::err::Error::KeyAlreadyExists => {
Error::TxKeyAlreadyExistsCategory(crate::key::error::KeyCategory::Unknown)
}
echodb::err::Error::ValNotExpectedValue => Error::TxConditionNotMet,
_ => Error::Tx(e.to_string()),
}
}
}
#[cfg(feature = "kv-indxdb")]
impl From<indxdb::err::Error> for Error {
fn from(e: indxdb::err::Error) -> Error {
match e {
indxdb::err::Error::KeyAlreadyExists => {
Error::TxKeyAlreadyExistsCategory(crate::key::error::KeyCategory::Unknown)
}
indxdb::err::Error::ValNotExpectedValue => Error::TxConditionNotMet,
_ => Error::Tx(e.to_string()),
}
}
}
#[cfg(feature = "kv-tikv")]
impl From<tikv::Error> for Error {
fn from(e: tikv::Error) -> Error {
match e {
tikv::Error::DuplicateKeyInsertion => {
Error::TxKeyAlreadyExistsCategory(crate::key::error::KeyCategory::Unknown)
}
tikv::Error::KeyError(ke) if ke.abort.contains("KeyTooLarge") => Error::TxKeyTooLarge,
tikv::Error::RegionError(re) if re.raft_entry_too_large.is_some() => Error::TxTooLarge,
_ => Error::Tx(e.to_string()),
}
}
}
#[cfg(feature = "kv-speedb")]
impl From<speedb::Error> for Error {
fn from(e: speedb::Error) -> Error {
Error::Tx(e.to_string())
}
}
#[cfg(feature = "kv-rocksdb")]
impl From<rocksdb::Error> for Error {
fn from(e: rocksdb::Error) -> Error {
Error::Tx(e.to_string())
}
}
impl From<channel::RecvError> for Error {
fn from(e: channel::RecvError) -> Error {
Error::Channel(e.to_string())
}
}
impl<T> From<channel::SendError<T>> for Error {
fn from(e: channel::SendError<T>) -> Error {
Error::Channel(e.to_string())
}
}
#[cfg(feature = "http")]
impl From<reqwest::Error> for Error {
fn from(e: reqwest::Error) -> Error {
Error::Http(e.to_string())
}
}
impl Serialize for Error {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.to_string().as_str())
}
}