1use std::any::Any;
16
17use common_error::ext::{BoxedError, ErrorExt};
18use common_error::status_code::StatusCode;
19use common_macro::stack_trace_debug;
20use common_query::error::datafusion_status_code;
21use datafusion::error::DataFusionError;
22use datatypes::arrow::error::ArrowError;
23use snafu::{Location, Snafu};
24
25pub type Result<T> = std::result::Result<T, Error>;
26
27#[derive(Snafu)]
29#[snafu(visibility(pub))]
30#[stack_trace_debug]
31pub enum Error {
32 #[snafu(display("DataFusion error"))]
33 Datafusion {
34 #[snafu(source)]
35 error: DataFusionError,
36 #[snafu(implicit)]
37 location: Location,
38 },
39
40 #[snafu(display("Failed to convert Arrow schema"))]
41 SchemaConversion {
42 source: datatypes::error::Error,
43 #[snafu(implicit)]
44 location: Location,
45 },
46
47 #[snafu(display("Table projection error"))]
48 TableProjection {
49 #[snafu(source)]
50 error: ArrowError,
51 #[snafu(implicit)]
52 location: Location,
53 },
54
55 #[snafu(display("Failed to create record batch for Tables"))]
56 TablesRecordBatch {
57 #[snafu(implicit)]
58 location: Location,
59 source: BoxedError,
60 },
61
62 #[snafu(display("Column {column_name} already exists in table {table_name}"))]
63 ColumnExists {
64 column_name: String,
65 table_name: String,
66 #[snafu(implicit)]
67 location: Location,
68 },
69
70 #[snafu(display("Failed to build schema, msg: {}", msg))]
71 SchemaBuild {
72 #[snafu(implicit)]
73 location: Location,
74 source: datatypes::error::Error,
75 msg: String,
76 },
77
78 #[snafu(display("Column {} not exists in table {}", column_name, table_name))]
79 ColumnNotExists {
80 column_name: String,
81 table_name: String,
82 #[snafu(implicit)]
83 location: Location,
84 },
85
86 #[snafu(display(
87 "Not allowed to remove index column {} from table {}",
88 column_name,
89 table_name
90 ))]
91 RemoveColumnInIndex {
92 column_name: String,
93 table_name: String,
94 #[snafu(implicit)]
95 location: Location,
96 },
97
98 #[snafu(display(
99 "Not allowed to remove partition column {} from table {}",
100 column_name,
101 table_name
102 ))]
103 RemovePartitionColumn {
104 column_name: String,
105 table_name: String,
106 #[snafu(implicit)]
107 location: Location,
108 },
109
110 #[snafu(display(
111 "Failed to build column descriptor for table: {}, column: {}",
112 table_name,
113 column_name,
114 ))]
115 BuildColumnDescriptor {
116 #[snafu(source)]
117 error: store_api::storage::ColumnDescriptorBuilderError,
118 table_name: String,
119 column_name: String,
120 #[snafu(implicit)]
121 location: Location,
122 },
123
124 #[snafu(display("Failed to operate table"))]
125 TableOperation { source: BoxedError },
126
127 #[snafu(display("Unsupported operation: {}", operation))]
128 Unsupported { operation: String },
129
130 #[snafu(display("Failed to parse table option, key: {}, value: {}", key, value))]
131 ParseTableOption {
132 key: String,
133 value: String,
134 #[snafu(implicit)]
135 location: Location,
136 },
137
138 #[snafu(display("Invalid alter table({}) request: {}", table, err))]
139 InvalidAlterRequest {
140 table: String,
141 #[snafu(implicit)]
142 location: Location,
143 err: String,
144 },
145
146 #[snafu(display("Missing time index column in table: {}", table_name))]
147 MissingTimeIndexColumn {
148 table_name: String,
149 #[snafu(implicit)]
150 location: Location,
151 },
152
153 #[snafu(display("Table options value is not valid, key: `{}`, value: `{}`", key, value))]
154 InvalidTableOptionValue { key: String, value: String },
155
156 #[snafu(display("Invalid column option, column name: {}, error: {}", column_name, msg))]
157 InvalidColumnOption {
158 column_name: String,
159 msg: String,
160 #[snafu(implicit)]
161 location: Location,
162 },
163
164 #[snafu(display("Failed to set fulltext options for column {}", column_name))]
165 SetFulltextOptions {
166 column_name: String,
167 source: datatypes::Error,
168 #[snafu(implicit)]
169 location: Location,
170 },
171
172 #[snafu(display("Failed to set skipping index options for column {}", column_name))]
173 SetSkippingOptions {
174 column_name: String,
175 source: datatypes::Error,
176 #[snafu(implicit)]
177 location: Location,
178 },
179
180 #[snafu(display("Failed to unset skipping index options for column {}", column_name))]
181 UnsetSkippingOptions {
182 column_name: String,
183 source: datatypes::Error,
184 #[snafu(implicit)]
185 location: Location,
186 },
187
188 #[snafu(display("Invalid table name: '{s}'"))]
189 InvalidTableName { s: String },
190
191 #[snafu(display("Failed to cast default value, reason: {}", reason))]
192 CastDefaultValue {
193 reason: String,
194 source: datatypes::Error,
195 #[snafu(implicit)]
196 location: Location,
197 },
198}
199
200impl ErrorExt for Error {
201 fn status_code(&self) -> StatusCode {
202 match self {
203 Error::Datafusion { error, .. } => datafusion_status_code::<Self>(error, None),
204 Error::SchemaConversion { .. } | Error::TableProjection { .. } => {
205 StatusCode::EngineExecuteQuery
206 }
207 Error::RemoveColumnInIndex { .. }
208 | Error::RemovePartitionColumn { .. }
209 | Error::BuildColumnDescriptor { .. }
210 | Error::InvalidAlterRequest { .. } => StatusCode::InvalidArguments,
211 Error::CastDefaultValue { source, .. } => source.status_code(),
212 Error::TablesRecordBatch { .. } => StatusCode::Unexpected,
213 Error::ColumnExists { .. } => StatusCode::TableColumnExists,
214 Error::SchemaBuild { source, .. } | Error::SetFulltextOptions { source, .. } => {
215 source.status_code()
216 }
217 Error::TableOperation { source } => source.status_code(),
218 Error::InvalidColumnOption { .. } => StatusCode::InvalidArguments,
219 Error::ColumnNotExists { .. } => StatusCode::TableColumnNotFound,
220 Error::Unsupported { .. } => StatusCode::Unsupported,
221 Error::ParseTableOption { .. } => StatusCode::InvalidArguments,
222 Error::MissingTimeIndexColumn { .. } => StatusCode::IllegalState,
223 Error::InvalidTableOptionValue { .. }
224 | Error::SetSkippingOptions { .. }
225 | Error::UnsetSkippingOptions { .. }
226 | Error::InvalidTableName { .. } => StatusCode::InvalidArguments,
227 }
228 }
229
230 fn as_any(&self) -> &dyn Any {
231 self
232 }
233}
234
235impl From<Error> for DataFusionError {
236 fn from(e: Error) -> DataFusionError {
237 DataFusionError::External(Box::new(e))
238 }
239}