1use std::error::Error;
4use std::io::ErrorKind;
5use std::net::{AddrParseError, IpAddr, SocketAddr};
6use std::num::ParseIntError;
7use std::sync::Arc;
8use thiserror::Error;
9
10use crate::frame::response;
11
12pub use crate::client::pager::{NextPageError, NextRowError};
14
15use crate::statement::prepared::TokenCalculationError;
16pub use crate::response::query_result::{
18 FirstRowError, IntoRowsResultError, MaybeFirstRowError, ResultNotRowsError, RowsError,
19 SingleRowError,
20};
21
22pub use crate::authentication::AuthError;
24
25pub use crate::network::tls::TlsError;
27
28pub use scylla_cql::deserialize::{DeserializationError, TypeCheckError};
30pub use scylla_cql::frame::frame_errors::{
31 CqlAuthChallengeParseError, CqlAuthSuccessParseError, CqlAuthenticateParseError,
32 CqlErrorParseError, CqlEventParseError, CqlRequestSerializationError, CqlResponseParseError,
33 CqlResultParseError, CqlSupportedParseError, FrameBodyExtensionsParseError,
34 FrameHeaderParseError,
35};
36pub use scylla_cql::frame::request::CqlRequestKind;
37pub use scylla_cql::frame::response::error::{DbError, OperationType, WriteType};
38pub use scylla_cql::frame::response::CqlResponseKind;
39pub use scylla_cql::serialize::SerializationError;
40
41#[derive(Error, Debug, Clone)]
43#[non_exhaustive]
44pub enum ExecutionError {
45 #[error(transparent)]
47 BadQuery(#[from] BadQuery),
48
49 #[error(
51 "Load balancing policy returned an empty plan.\
52 First thing to investigate should be the logic of custom LBP implementation.\
53 If you think that your LBP implementation is correct, or you make use of `DefaultPolicy`,\
54 then this is most probably a driver bug!"
55 )]
56 EmptyPlan,
57
58 #[error("Failed to prepare the statement: {0}")]
61 PrepareError(#[from] PrepareError),
62
63 #[error("No connections in the pool: {0}")]
65 ConnectionPoolError(#[from] ConnectionPoolError),
66
67 #[error(transparent)]
69 LastAttemptError(#[from] RequestAttemptError),
70
71 #[error(
73 "Request execution exceeded a client timeout of {}ms",
74 std::time::Duration::as_millis(.0)
75 )]
76 RequestTimeout(std::time::Duration),
77
78 #[error("'USE KEYSPACE <>' request failed: {0}")]
80 UseKeyspaceError(#[from] UseKeyspaceError),
81
82 #[error("Failed to await schema agreement: {0}")]
84 SchemaAgreementError(#[from] SchemaAgreementError),
85
86 #[error("Cluster metadata fetch error occurred during automatic schema agreement: {0}")]
88 MetadataError(#[from] MetadataError),
89}
90
91impl From<SerializationError> for ExecutionError {
92 fn from(serialized_err: SerializationError) -> ExecutionError {
93 ExecutionError::BadQuery(BadQuery::SerializationError(serialized_err))
94 }
95}
96
97#[derive(Error, Debug, Clone)]
99#[non_exhaustive]
100pub enum PrepareError {
101 #[error("Failed to find a node with working connection pool: {0}")]
103 ConnectionPoolError(#[from] ConnectionPoolError),
104
105 #[error("Preparation failed on every connection from the selected pool. First attempt error: {first_attempt}")]
107 AllAttemptsFailed { first_attempt: RequestAttemptError },
108
109 #[error(
111 "Prepared statement id mismatch between multiple connections - all result ids should be equal."
112 )]
113 PreparedStatementIdsMismatch,
114}
115
116#[derive(Error, Debug, Clone)]
118#[non_exhaustive]
119pub enum PagerExecutionError {
120 #[error("Failed to prepare the statement to be used by the pager: {0}")]
122 PrepareError(#[from] PrepareError),
123
124 #[error("Failed to serialize statement parameters: {0}")]
126 SerializationError(#[from] SerializationError),
127
128 #[error("Failed to fetch the first page of the result: {0}")]
130 NextPageError(#[from] NextPageError),
131}
132
133#[derive(Error, Debug, Clone)]
135#[non_exhaustive]
136pub enum NewSessionError {
137 #[error("Couldn't resolve any hostname: {0:?}")]
139 FailedToResolveAnyHostname(Vec<String>),
140
141 #[error("Empty known nodes list")]
144 EmptyKnownNodesList,
145
146 #[error("Failed to perform initial cluster metadata fetch: {0}")]
148 MetadataError(#[from] MetadataError),
149
150 #[error("'USE KEYSPACE <>' request failed: {0}")]
152 UseKeyspaceError(#[from] UseKeyspaceError),
153}
154
155#[derive(Error, Debug, Clone)]
157#[non_exhaustive]
158pub enum UseKeyspaceError {
159 #[error("Passed invalid keyspace name to use: {0}")]
161 BadKeyspaceName(#[from] BadKeyspaceName),
162
163 #[error(transparent)]
165 RequestError(#[from] RequestAttemptError),
166
167 #[error("Keyspace name mismtach; expected: {expected_keyspace_name_lowercase}, received: {result_keyspace_name_lowercase}")]
169 KeyspaceNameMismatch {
170 expected_keyspace_name_lowercase: String,
171 result_keyspace_name_lowercase: String,
172 },
173
174 #[error(
176 "Request execution exceeded a client timeout of {}ms",
177 std::time::Duration::as_millis(.0)
178 )]
179 RequestTimeout(std::time::Duration),
180}
181
182#[derive(Error, Debug, Clone)]
184#[non_exhaustive]
185pub enum SchemaAgreementError {
186 #[error("Failed to find a node with working connection pool: {0}")]
188 ConnectionPoolError(#[from] ConnectionPoolError),
189
190 #[error("Failed to execute schema version query: {0}")]
196 RequestError(#[from] RequestAttemptError),
197
198 #[error("Failed to convert schema version query result into rows result: {0}")]
200 TracesEventsIntoRowsResultError(IntoRowsResultError),
201
202 #[error(transparent)]
204 SingleRowError(SingleRowError),
205
206 #[error("Schema agreement exceeded {}ms", std::time::Duration::as_millis(.0))]
208 Timeout(std::time::Duration),
209}
210
211#[derive(Error, Debug, Clone)]
213#[non_exhaustive]
214pub enum TracingError {
215 #[error(
217 "Failed to execute queries to \"system_traces.sessions\" or \"system_traces.events\" system tables: {0}"
218 )]
219 ExecutionError(#[from] ExecutionError),
220
221 #[error("Failed to convert result of system_traces.session query to rows result")]
223 TracesSessionIntoRowsResultError(IntoRowsResultError),
224
225 #[error("system_traces.session has invalid column type: {0}")]
227 TracesSessionInvalidColumnType(TypeCheckError),
228
229 #[error("Response to system_traces.session failed to deserialize: {0}")]
231 TracesSessionDeserializationFailed(DeserializationError),
232
233 #[error("Failed to convert result of system_traces.events query to rows result")]
235 TracesEventsIntoRowsResultError(IntoRowsResultError),
236
237 #[error("system_traces.events has invalid column type: {0}")]
239 TracesEventsInvalidColumnType(TypeCheckError),
240
241 #[error("Response to system_traces.events failed to deserialize: {0}")]
243 TracesEventsDeserializationFailed(DeserializationError),
244
245 #[error(
247 "All tracing queries returned an empty result, \
248 maybe the trace information didn't propagate yet. \
249 Consider configuring Session with \
250 a longer fetch interval (tracing_info_fetch_interval)"
251 )]
252 EmptyResults,
253}
254
255#[derive(Error, Debug, Clone)]
269#[non_exhaustive]
270pub enum MetadataError {
271 #[error("Control connection pool error: {0}")]
273 ConnectionPoolError(#[from] ConnectionPoolError),
274
275 #[error("transparent")]
277 FetchError(#[from] MetadataFetchError),
278
279 #[error("Bad peers metadata: {0}")]
281 Peers(#[from] PeersMetadataError),
282
283 #[error("Bad keyspaces metadata: {0}")]
285 Keyspaces(#[from] KeyspacesMetadataError),
286
287 #[error("Bad UDTs metadata: {0}")]
289 Udts(#[from] UdtMetadataError),
290
291 #[error("Bad tables metadata: {0}")]
293 Tables(#[from] TablesMetadataError),
294}
295
296#[derive(Error, Debug, Clone)]
298#[error("Metadata fetch failed for table \"{table}\": {error}")]
299#[non_exhaustive]
300pub struct MetadataFetchError {
301 pub error: MetadataFetchErrorKind,
303 pub table: &'static str,
305}
306
307#[derive(Error, Debug, Clone)]
309#[non_exhaustive]
310pub enum MetadataFetchErrorKind {
311 #[error("The table has invalid column type: {0}")]
313 InvalidColumnType(#[from] TypeCheckError),
314
315 #[error("Failed to prepare the statement: {0}")]
317 PrepareError(#[from] RequestAttemptError),
318
319 #[error("Failed to serialize statement parameters: {0}")]
321 SerializationError(#[from] SerializationError),
322
323 #[error("Failed to obtain next row from response to the query: {0}")]
325 NextRowError(#[from] NextRowError),
326}
327
328#[derive(Error, Debug, Clone)]
330#[non_exhaustive]
331pub enum PeersMetadataError {
332 #[error("Peers list is empty")]
334 EmptyPeers,
335
336 #[error("All peers have empty token lists")]
338 EmptyTokenLists,
339}
340
341#[derive(Error, Debug, Clone)]
343#[non_exhaustive]
344pub enum KeyspacesMetadataError {
345 #[error("Bad keyspace <{keyspace}> replication strategy: {error}")]
347 Strategy {
348 keyspace: String,
349 error: KeyspaceStrategyError,
350 },
351}
352
353#[derive(Error, Debug, Clone)]
355#[non_exhaustive]
356pub enum KeyspaceStrategyError {
357 #[error("keyspace strategy definition is missing a 'class' field")]
359 MissingClassForStrategyDefinition,
360
361 #[error("Missing replication factor field for SimpleStrategy")]
363 MissingReplicationFactorForSimpleStrategy,
364
365 #[error("Failed to parse a replication factor as unsigned integer: {0}")]
367 ReplicationFactorParseError(ParseIntError),
368
369 #[error("Unexpected NetworkTopologyStrategy option: '{key}': '{value}'")]
372 UnexpectedNetworkTopologyStrategyOption { key: String, value: String },
373}
374
375#[derive(Error, Debug, Clone)]
377#[non_exhaustive]
378pub enum UdtMetadataError {
379 #[error(
381 "Failed to parse a CQL type returned from system_schema.types query. \
382 Type '{typ}', at position {position}: {reason}"
383 )]
384 InvalidCqlType {
385 typ: String,
386 position: usize,
387 reason: String,
388 },
389
390 #[error("Detected circular dependency between user defined types - toposort is impossible!")]
392 CircularTypeDependency,
393}
394
395#[derive(Error, Debug, Clone)]
397#[non_exhaustive]
398pub enum TablesMetadataError {
399 #[error(
401 "Failed to parse a CQL type returned from system_schema.columns query. \
402 Type '{typ}', at position {position}: {reason}"
403 )]
404 InvalidCqlType {
405 typ: String,
406 position: usize,
407 reason: String,
408 },
409
410 #[error("Unknown column kind '{column_kind}' for {keyspace_name}.{table_name}.{column_name}")]
412 UnknownColumnKind {
413 keyspace_name: String,
414 table_name: String,
415 column_name: String,
416 column_kind: String,
417 },
418}
419
420#[derive(Error, Debug, Clone)]
422#[error("Invalid statement passed to Session")]
423#[non_exhaustive]
424pub enum BadQuery {
425 #[error("Unable extract a partition key based on prepared statement's metadata")]
427 PartitionKeyExtraction,
428
429 #[error("Serializing values failed: {0} ")]
431 SerializationError(#[from] SerializationError),
432
433 #[error("Serialized values are too long to compute partition key! Length: {0}, Max allowed length: {1}")]
435 ValuesTooLongForKey(usize, usize),
436
437 #[error("Number of statements in Batch Statement supplied is {0} which has exceeded the max value of 65,535")]
439 TooManyQueriesInBatchStatement(usize),
440}
441
442#[derive(Debug, Error, Clone)]
444#[non_exhaustive]
445pub enum BadKeyspaceName {
446 #[error("Keyspace name is empty")]
448 Empty,
449
450 #[error("Keyspace name too long, must be up to 48 characters, found {1} characters. Bad keyspace name: '{0}'")]
452 TooLong(String, usize),
453
454 #[error("Illegal character found: '{1}', only alphanumeric and underscores allowed. Bad keyspace name: '{0}'")]
456 IllegalCharacter(String, char),
457}
458
459#[derive(Error, Debug, Clone)]
462#[non_exhaustive]
463pub enum ConnectionPoolError {
464 #[error("The pool is broken; Last connection failed with: {last_connection_error}")]
466 Broken {
467 last_connection_error: ConnectionError,
468 },
469
470 #[error("Pool is still being initialized")]
472 Initializing,
473
474 #[error("The node has been disabled by a host filter")]
476 NodeDisabledByHostFilter,
477}
478
479#[derive(Error, Debug, Clone)]
483#[non_exhaustive]
484pub enum ConnectionError {
485 #[error("Connect timeout elapsed")]
487 ConnectTimeout,
488
489 #[error(transparent)]
491 IoError(Arc<std::io::Error>),
492
493 #[error("Could not find free source port for shard {0}")]
495 NoSourcePortForShard(u32),
496
497 #[error("Address translation failed: {0}")]
499 TranslationError(#[from] TranslationError),
500
501 #[error(transparent)]
503 BrokenConnection(#[from] BrokenConnectionError),
504
505 #[error(transparent)]
507 ConnectionSetupRequestError(#[from] ConnectionSetupRequestError),
508}
509
510impl From<std::io::Error> for ConnectionError {
511 fn from(value: std::io::Error) -> Self {
512 ConnectionError::IoError(Arc::new(value))
513 }
514}
515
516impl ConnectionError {
517 pub fn is_address_unavailable_for_use(&self) -> bool {
522 if let ConnectionError::IoError(io_error) = self {
523 match io_error.kind() {
524 ErrorKind::AddrInUse | ErrorKind::PermissionDenied => return true,
525 _ => {}
526 }
527 }
528
529 false
530 }
531}
532
533#[non_exhaustive]
535#[derive(Debug, Clone, Error)]
536pub enum TranslationError {
537 #[error("No rule for address {0}")]
539 NoRuleForAddress(SocketAddr),
540
541 #[error("Failed to parse translated address: {translated_addr_str}, reason: {reason}")]
543 InvalidAddressInRule {
544 translated_addr_str: &'static str,
545 reason: AddrParseError,
546 },
547
548 #[error("An I/O error occurred during address translation: {0}")]
550 IoError(Arc<std::io::Error>),
551}
552
553#[derive(Error, Debug, Clone)]
556#[error("Failed to perform a connection setup request. Request: {request_kind}, reason: {error}")]
557#[non_exhaustive]
558pub struct ConnectionSetupRequestError {
559 pub request_kind: CqlRequestKind,
560 pub error: ConnectionSetupRequestErrorKind,
561}
562
563#[derive(Error, Debug, Clone)]
564#[non_exhaustive]
565pub enum ConnectionSetupRequestErrorKind {
566 #[error("Failed to serialize CQL request: {0}")]
568 CqlRequestSerialization(#[from] CqlRequestSerializationError),
569
570 #[error(transparent)]
572 BodyExtensionsParseError(#[from] FrameBodyExtensionsParseError),
573
574 #[error("Unable to allocate stream id")]
576 UnableToAllocStreamId,
577
578 #[error(transparent)]
580 BrokenConnection(#[from] BrokenConnectionError),
581
582 #[error("Database returned an error: {0}, Error message: {1}")]
584 DbError(DbError, String),
585
586 #[error("Received unexpected response from the server: {0}")]
588 UnexpectedResponse(CqlResponseKind),
589
590 #[error("Failed to deserialize SUPPORTED response: {0}")]
592 CqlSupportedParseError(#[from] CqlSupportedParseError),
593
594 #[error("Failed to deserialize AUTHENTICATE response: {0}")]
596 CqlAuthenticateParseError(#[from] CqlAuthenticateParseError),
597
598 #[error("Failed to deserialize AUTH_SUCCESS response: {0}")]
600 CqlAuthSuccessParseError(#[from] CqlAuthSuccessParseError),
601
602 #[error("Failed to deserialize AUTH_CHALLENGE response: {0}")]
604 CqlAuthChallengeParseError(#[from] CqlAuthChallengeParseError),
605
606 #[error("Failed to deserialize ERROR response: {0}")]
608 CqlErrorParseError(#[from] CqlErrorParseError),
609
610 #[error("Failed to start client's auth session: {0}")]
612 StartAuthSessionError(AuthError),
613
614 #[error("Failed to evaluate auth challenge on client side: {0}")]
616 AuthChallengeEvaluationError(AuthError),
617
618 #[error("Failed to finish auth challenge on client side: {0}")]
620 AuthFinishError(AuthError),
621
622 #[error("Authentication is required. You can use SessionBuilder::user(\"user\", \"pass\") to provide credentials or SessionBuilder::authenticator_provider to provide custom authenticator")]
626 MissingAuthentication,
627}
628
629impl ConnectionSetupRequestError {
630 pub(crate) fn new(
631 request_kind: CqlRequestKind,
632 error: ConnectionSetupRequestErrorKind,
633 ) -> Self {
634 ConnectionSetupRequestError {
635 request_kind,
636 error,
637 }
638 }
639
640 pub fn get_error(&self) -> &ConnectionSetupRequestErrorKind {
641 &self.error
642 }
643}
644
645#[derive(Error, Debug, Clone)]
652#[error("Connection broken, reason: {0}")]
653pub struct BrokenConnectionError(Arc<dyn Error + Sync + Send>);
654
655impl BrokenConnectionError {
656 pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
658 self.0.downcast_ref()
659 }
660}
661
662#[derive(Error, Debug)]
667#[non_exhaustive]
668pub enum BrokenConnectionErrorKind {
669 #[error("Timed out while waiting for response to keepalive request on connection to node {0}")]
671 KeepaliveTimeout(IpAddr),
672
673 #[error("Failed to execute keepalive request: {0}")]
675 KeepaliveRequestError(Arc<dyn Error + Sync + Send>),
676
677 #[error("Failed to deserialize frame: {0}")]
679 FrameHeaderParseError(FrameHeaderParseError),
680
681 #[error("Failed to handle server event: {0}")]
683 CqlEventHandlingError(#[from] CqlEventHandlingError),
684
685 #[error("Received a server frame with unexpected stream id: {0}")]
687 UnexpectedStreamId(i16),
688
689 #[error("Failed to write data: {0}")]
691 WriteError(std::io::Error),
692
693 #[error("Too many orphaned stream ids: {0}")]
695 TooManyOrphanedStreamIds(u16),
696
697 #[error(
700 "Failed to send/receive data needed to perform a request via tokio channel.
701 It implies that other half of the channel has been dropped.
702 The connection was already broken for some other reason."
703 )]
704 ChannelError,
705}
706
707impl From<BrokenConnectionErrorKind> for BrokenConnectionError {
708 fn from(value: BrokenConnectionErrorKind) -> Self {
709 BrokenConnectionError(Arc::new(value))
710 }
711}
712
713#[derive(Error, Debug)]
720#[non_exhaustive]
721pub enum CqlEventHandlingError {
722 #[error("Failed to deserialize EVENT response: {0}")]
724 CqlEventParseError(#[from] CqlEventParseError),
725
726 #[error("Received unexpected server response on stream -1: {0}. Expected EVENT response")]
728 UnexpectedResponse(CqlResponseKind),
729
730 #[error("Failed to deserialize a header of frame received on stream -1: {0}")]
732 BodyExtensionParseError(#[from] FrameBodyExtensionsParseError),
733
734 #[error("Failed to send event info via channel. The channel is probably closed, which is caused by connection being broken")]
737 SendError,
738}
739
740#[derive(Error, Debug, Clone)]
750#[non_exhaustive]
751pub enum RequestError {
752 #[error(
754 "Load balancing policy returned an empty plan.\
755 First thing to investigate should be the logic of custom LBP implementation.\
756 If you think that your LBP implementation is correct, or you make use of `DefaultPolicy`,\
757 then this is most probably a driver bug!"
758 )]
759 EmptyPlan,
760
761 #[error("No connections in the pool: {0}")]
763 ConnectionPoolError(#[from] ConnectionPoolError),
764
765 #[error(
767 "Request execution exceeded a client timeout of {}ms",
768 std::time::Duration::as_millis(.0)
769 )]
770 RequestTimeout(std::time::Duration),
771
772 #[error(transparent)]
774 LastAttemptError(#[from] RequestAttemptError),
775}
776
777impl RequestError {
778 pub fn into_execution_error(self) -> ExecutionError {
779 match self {
780 RequestError::EmptyPlan => ExecutionError::EmptyPlan,
781 RequestError::ConnectionPoolError(e) => e.into(),
782 RequestError::RequestTimeout(dur) => ExecutionError::RequestTimeout(dur),
783 RequestError::LastAttemptError(e) => ExecutionError::LastAttemptError(e),
784 }
785 }
786}
787
788#[derive(Error, Debug, Clone)]
797#[non_exhaustive]
798pub enum RequestAttemptError {
799 #[error("Failed to serialize query parameters: {0}")]
803 SerializationError(#[from] SerializationError),
804
805 #[error("Failed to serialize CQL request: {0}")]
807 CqlRequestSerialization(#[from] CqlRequestSerializationError),
808
809 #[error("Unable to allocate stream id")]
811 UnableToAllocStreamId,
812
813 #[error(transparent)]
815 BrokenConnectionError(#[from] BrokenConnectionError),
816
817 #[error(transparent)]
819 BodyExtensionsParseError(#[from] FrameBodyExtensionsParseError),
820
821 #[error(transparent)]
823 CqlResultParseError(#[from] CqlResultParseError),
824
825 #[error("Failed to deserialize ERROR response: {0}")]
827 CqlErrorParseError(#[from] CqlErrorParseError),
828
829 #[error("Database returned an error: {0}, Error message: {1}")]
831 DbError(DbError, String),
832
833 #[error(
835 "Received unexpected response from the server: {0}. Expected RESULT or ERROR response."
836 )]
837 UnexpectedResponse(CqlResponseKind),
838
839 #[error(
841 "Prepared statement id changed after repreparation; md5 sum (computed from the query string) should stay the same;\
842 Statement: \"{statement}\"; expected id: {expected_id:?}; reprepared id: {reprepared_id:?}"
843 )]
844 RepreparedIdChanged {
845 statement: String,
846 expected_id: Vec<u8>,
847 reprepared_id: Vec<u8>,
848 },
849
850 #[error("Reprepared statement's id does not exist in the batch.")]
853 RepreparedIdMissingInBatch,
854
855 #[error("Unpaged query returned a non-empty paging state! This is a driver-side or server-side bug.")]
857 NonfinishedPagingState,
858}
859
860impl From<response::error::Error> for RequestAttemptError {
861 fn from(value: response::error::Error) -> Self {
862 RequestAttemptError::DbError(value.error, value.reason)
863 }
864}
865
866impl From<InternalRequestError> for RequestAttemptError {
867 fn from(value: InternalRequestError) -> Self {
868 match value {
869 InternalRequestError::CqlRequestSerialization(e) => e.into(),
870 InternalRequestError::BodyExtensionsParseError(e) => e.into(),
871 InternalRequestError::CqlResponseParseError(e) => match e {
872 CqlResponseParseError::CqlErrorParseError(e) => e.into(),
875 CqlResponseParseError::CqlResultParseError(e) => e.into(),
876 _ => RequestAttemptError::UnexpectedResponse(e.to_response_kind()),
877 },
878 InternalRequestError::BrokenConnection(e) => e.into(),
879 InternalRequestError::UnableToAllocStreamId => {
880 RequestAttemptError::UnableToAllocStreamId
881 }
882 }
883 }
884}
885
886#[derive(Error, Debug)]
897#[non_exhaustive]
898pub(crate) enum InternalRequestError {
899 #[error("Failed to serialize CQL request: {0}")]
901 CqlRequestSerialization(#[from] CqlRequestSerializationError),
902
903 #[error(transparent)]
905 BodyExtensionsParseError(#[from] FrameBodyExtensionsParseError),
906
907 #[error(transparent)]
909 CqlResponseParseError(#[from] CqlResponseParseError),
910
911 #[error(transparent)]
913 BrokenConnection(#[from] BrokenConnectionError),
914
915 #[error("Unable to allocate a stream id")]
917 UnableToAllocStreamId,
918}
919
920impl From<ResponseParseError> for InternalRequestError {
921 fn from(value: ResponseParseError) -> Self {
922 match value {
923 ResponseParseError::BodyExtensionsParseError(e) => e.into(),
924 ResponseParseError::CqlResponseParseError(e) => e.into(),
925 }
926 }
927}
928
929#[derive(Error, Debug)]
932pub(crate) enum ResponseParseError {
933 #[error(transparent)]
934 BodyExtensionsParseError(#[from] FrameBodyExtensionsParseError),
935 #[error(transparent)]
936 CqlResponseParseError(#[from] CqlResponseParseError),
937}
938
939#[derive(Clone, Debug, Error)]
941#[non_exhaustive]
942pub enum ClusterStateTokenError {
943 #[error(transparent)]
945 TokenCalculation(#[from] TokenCalculationError),
946
947 #[error(transparent)]
949 Serialization(#[from] SerializationError),
950
951 #[error("Can't find metadata for requested table ({keyspace}.{table}).")]
953 UnknownTable { keyspace: String, table: String },
954}
955
956#[cfg(test)]
957mod tests {
958 use scylla_cql::Consistency;
959
960 use super::{DbError, ExecutionError, RequestAttemptError, WriteType};
961
962 #[test]
963 fn write_type_from_str() {
964 let test_cases: [(&str, WriteType); 9] = [
965 ("SIMPLE", WriteType::Simple),
966 ("BATCH", WriteType::Batch),
967 ("UNLOGGED_BATCH", WriteType::UnloggedBatch),
968 ("COUNTER", WriteType::Counter),
969 ("BATCH_LOG", WriteType::BatchLog),
970 ("CAS", WriteType::Cas),
971 ("VIEW", WriteType::View),
972 ("CDC", WriteType::Cdc),
973 ("SOMEOTHER", WriteType::Other("SOMEOTHER".to_string())),
974 ];
975
976 for (write_type_str, expected_write_type) in &test_cases {
977 let write_type = WriteType::from(*write_type_str);
978 assert_eq!(write_type, *expected_write_type);
979 }
980 }
981
982 #[test]
988 fn dberror_full_info() {
989 let db_error = DbError::Unavailable {
991 consistency: Consistency::Three,
992 required: 3,
993 alive: 2,
994 };
995
996 let db_error_displayed: String = format!("{}", db_error);
997
998 let mut expected_dberr_msg =
999 "Not enough nodes are alive to satisfy required consistency level ".to_string();
1000 expected_dberr_msg += "(consistency: Three, required: 3, alive: 2)";
1001
1002 assert_eq!(db_error_displayed, expected_dberr_msg);
1003
1004 let execution_error = ExecutionError::LastAttemptError(RequestAttemptError::DbError(
1006 db_error,
1007 "a message about unavailable error".to_string(),
1008 ));
1009 let execution_error_displayed: String = format!("{}", execution_error);
1010
1011 let mut expected_execution_err_msg = "Database returned an error: ".to_string();
1012 expected_execution_err_msg += &expected_dberr_msg;
1013 expected_execution_err_msg += ", Error message: a message about unavailable error";
1014
1015 assert_eq!(execution_error_displayed, expected_execution_err_msg);
1016 }
1017}