questdb/error.rs
1/*******************************************************************************
2 * ___ _ ____ ____
3 * / _ \ _ _ ___ ___| |_| _ \| __ )
4 * | | | | | | |/ _ \/ __| __| | | | _ \
5 * | |_| | |_| | __/\__ \ |_| |_| | |_) |
6 * \__\_\\__,_|\___||___/\__|____/|____/
7 *
8 * Copyright (c) 2014-2019 Appsicle
9 * Copyright (c) 2019-2025 QuestDB
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 *
23 ******************************************************************************/
24use std::convert::Infallible;
25use std::fmt::{Display, Formatter};
26
27macro_rules! fmt {
28 ($code:ident, $($arg:tt)*) => {
29 crate::error::Error::new(
30 crate::error::ErrorCode::$code,
31 format!($($arg)*))
32 }
33}
34
35/// Category of error.
36///
37/// Accessible via Error's [`code`](Error::code) method.
38#[derive(Debug, Copy, Clone, PartialEq)]
39pub enum ErrorCode {
40 /// The host, port, or interface was incorrect.
41 CouldNotResolveAddr,
42
43 /// Called methods in the wrong order. E.g. `symbol` after `column`.
44 InvalidApiCall,
45
46 /// A network error connecting or flushing data out.
47 SocketError,
48
49 /// The string or symbol field is not encoded in valid UTF-8.
50 ///
51 /// *This error is reserved for the
52 /// [C and C++ API](https://github.com/questdb/c-questdb-client/).*
53 InvalidUtf8,
54
55 /// The table name or column name contains bad characters.
56 InvalidName,
57
58 /// The supplied timestamp is invalid.
59 InvalidTimestamp,
60
61 /// Error during the authentication process.
62 AuthError,
63
64 /// Error during TLS handshake.
65 TlsError,
66
67 /// The server does not support ILP-over-HTTP.
68 HttpNotSupported,
69
70 /// Error sent back from the server during flush.
71 ServerFlushError,
72
73 /// Bad configuration.
74 ConfigError,
75
76 /// There was an error serializing an array.
77 ArrayError,
78
79 /// Validate protocol version error.
80 ProtocolVersionError,
81
82 /// The supplied decimal is invalid.
83 InvalidDecimal,
84}
85
86/// An error that occurred when using QuestDB client library.
87#[derive(Debug, PartialEq)]
88pub struct Error {
89 code: ErrorCode,
90 msg: String,
91}
92
93impl Error {
94 /// Create an error with the given code and message.
95 pub fn new<S: Into<String>>(code: ErrorCode, msg: S) -> Error {
96 Error {
97 code,
98 msg: msg.into(),
99 }
100 }
101
102 #[cfg(feature = "sync-sender-http")]
103 pub(crate) fn from_ureq_error(err: ureq::Error, url: &str) -> Error {
104 match err {
105 ureq::Error::StatusCode(code) => {
106 if code == 404 {
107 fmt!(
108 HttpNotSupported,
109 "Could not flush buffer: HTTP endpoint does not support ILP."
110 )
111 } else if [401, 403].contains(&code) {
112 fmt!(
113 AuthError,
114 "Could not flush buffer: HTTP endpoint authentication error [code: {}]",
115 code
116 )
117 } else {
118 fmt!(SocketError, "Could not flush buffer: {}: {}", url, err)
119 }
120 }
121 e => {
122 fmt!(SocketError, "Could not flush buffer: {}: {}", url, e)
123 }
124 }
125 }
126
127 /// Get the error code (category) of this error.
128 pub fn code(&self) -> ErrorCode {
129 self.code
130 }
131
132 /// Get the string message of this error.
133 pub fn msg(&self) -> &str {
134 &self.msg
135 }
136}
137
138impl Display for Error {
139 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
140 f.write_str(&self.msg)
141 }
142}
143
144impl std::error::Error for Error {}
145
146impl From<Infallible> for Error {
147 fn from(_: Infallible) -> Self {
148 unreachable!()
149 }
150}
151
152/// A specialized `Result` type for the crate's [`Error`] type.
153pub type Result<T> = std::result::Result<T, Error>;
154
155pub(crate) use fmt;