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("Invalid column option, column name: {}, error: {}", column_name, msg))]
154 InvalidColumnOption {
155 column_name: String,
156 msg: String,
157 #[snafu(implicit)]
158 location: Location,
159 },
160
161 #[snafu(display("Failed to set fulltext options for column {}", column_name))]
162 SetFulltextOptions {
163 column_name: String,
164 source: datatypes::Error,
165 #[snafu(implicit)]
166 location: Location,
167 },
168
169 #[snafu(display("Failed to set skipping index options for column {}", column_name))]
170 SetSkippingOptions {
171 column_name: String,
172 source: datatypes::Error,
173 #[snafu(implicit)]
174 location: Location,
175 },
176
177 #[snafu(display("Failed to unset skipping index options for column {}", column_name))]
178 UnsetSkippingOptions {
179 column_name: String,
180 source: datatypes::Error,
181 #[snafu(implicit)]
182 location: Location,
183 },
184
185 #[snafu(display("Invalid table name: '{s}'"))]
186 InvalidTableName { s: String },
187
188 #[snafu(display("Failed to cast default value, reason: {}", reason))]
189 CastDefaultValue {
190 reason: String,
191 source: datatypes::Error,
192 #[snafu(implicit)]
193 location: Location,
194 },
195
196 #[snafu(display("Sql common error"))]
197 SqlCommon {
198 source: common_sql::error::Error,
199 #[snafu(implicit)]
200 location: Location,
201 },
202}
203
204impl ErrorExt for Error {
205 fn status_code(&self) -> StatusCode {
206 match self {
207 Error::Datafusion { error, .. } => datafusion_status_code::<Self>(error, None),
208 Error::SchemaConversion { .. } | Error::TableProjection { .. } => {
209 StatusCode::EngineExecuteQuery
210 }
211 Error::RemoveColumnInIndex { .. }
212 | Error::RemovePartitionColumn { .. }
213 | Error::BuildColumnDescriptor { .. }
214 | Error::InvalidAlterRequest { .. } => StatusCode::InvalidArguments,
215 Error::CastDefaultValue { source, .. } => source.status_code(),
216 Error::TablesRecordBatch { .. } => StatusCode::Unexpected,
217 Error::ColumnExists { .. } => StatusCode::TableColumnExists,
218 Error::SqlCommon { source, .. } => source.status_code(),
219 Error::SchemaBuild { source, .. } | Error::SetFulltextOptions { source, .. } => {
220 source.status_code()
221 }
222 Error::TableOperation { source } => source.status_code(),
223 Error::InvalidColumnOption { .. } => StatusCode::InvalidArguments,
224 Error::ColumnNotExists { .. } => StatusCode::TableColumnNotFound,
225 Error::Unsupported { .. } => StatusCode::Unsupported,
226 Error::ParseTableOption { .. } => StatusCode::InvalidArguments,
227 Error::MissingTimeIndexColumn { .. } => StatusCode::IllegalState,
228 Error::SetSkippingOptions { .. }
229 | Error::UnsetSkippingOptions { .. }
230 | Error::InvalidTableName { .. } => StatusCode::InvalidArguments,
231 }
232 }
233
234 fn as_any(&self) -> &dyn Any {
235 self
236 }
237}
238
239impl From<Error> for DataFusionError {
240 fn from(e: Error) -> DataFusionError {
241 DataFusionError::External(Box::new(e))
242 }
243}