Skip to main content

table/
error.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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/// Default error implementation of table.
28#[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(
139        "Conflicting table options: {}={} and {}={}",
140        first_key,
141        first_value,
142        second_key,
143        second_value
144    ))]
145    ConflictingTableOptions {
146        first_key: String,
147        first_value: String,
148        second_key: String,
149        second_value: String,
150        #[snafu(implicit)]
151        location: Location,
152    },
153
154    #[snafu(display("Invalid alter table({}) request: {}", table, err))]
155    InvalidAlterRequest {
156        table: String,
157        #[snafu(implicit)]
158        location: Location,
159        err: String,
160    },
161
162    #[snafu(display("Missing time index column in table: {}", table_name))]
163    MissingTimeIndexColumn {
164        table_name: String,
165        #[snafu(implicit)]
166        location: Location,
167    },
168
169    #[snafu(display("Invalid column option, column name: {}, error: {}", column_name, msg))]
170    InvalidColumnOption {
171        column_name: String,
172        msg: String,
173        #[snafu(implicit)]
174        location: Location,
175    },
176
177    #[snafu(display("Failed to set fulltext options for column {}", column_name))]
178    SetFulltextOptions {
179        column_name: String,
180        source: datatypes::Error,
181        #[snafu(implicit)]
182        location: Location,
183    },
184
185    #[snafu(display("Failed to set skipping index options for column {}", column_name))]
186    SetSkippingOptions {
187        column_name: String,
188        source: datatypes::Error,
189        #[snafu(implicit)]
190        location: Location,
191    },
192
193    #[snafu(display("Failed to unset skipping index options for column {}", column_name))]
194    UnsetSkippingOptions {
195        column_name: String,
196        source: datatypes::Error,
197        #[snafu(implicit)]
198        location: Location,
199    },
200
201    #[snafu(display("Invalid table name: '{s}'"))]
202    InvalidTableName { s: String },
203
204    #[snafu(display("Failed to cast default value, reason: {}", reason))]
205    CastDefaultValue {
206        reason: String,
207        source: datatypes::Error,
208        #[snafu(implicit)]
209        location: Location,
210    },
211
212    #[snafu(display("Sql common error"))]
213    SqlCommon {
214        source: common_sql::error::Error,
215        #[snafu(implicit)]
216        location: Location,
217    },
218}
219
220impl ErrorExt for Error {
221    fn status_code(&self) -> StatusCode {
222        match self {
223            Error::Datafusion { error, .. } => datafusion_status_code::<Self>(error, None),
224            Error::SchemaConversion { .. } | Error::TableProjection { .. } => {
225                StatusCode::EngineExecuteQuery
226            }
227            Error::RemoveColumnInIndex { .. }
228            | Error::RemovePartitionColumn { .. }
229            | Error::BuildColumnDescriptor { .. }
230            | Error::InvalidAlterRequest { .. } => StatusCode::InvalidArguments,
231            Error::CastDefaultValue { source, .. } => source.status_code(),
232            Error::TablesRecordBatch { .. } => StatusCode::Unexpected,
233            Error::ColumnExists { .. } => StatusCode::TableColumnExists,
234            Error::SqlCommon { source, .. } => source.status_code(),
235            Error::SchemaBuild { source, .. } | Error::SetFulltextOptions { source, .. } => {
236                source.status_code()
237            }
238            Error::TableOperation { source } => source.status_code(),
239            Error::InvalidColumnOption { .. } => StatusCode::InvalidArguments,
240            Error::ColumnNotExists { .. } => StatusCode::TableColumnNotFound,
241            Error::Unsupported { .. } => StatusCode::Unsupported,
242            Error::ParseTableOption { .. } | Error::ConflictingTableOptions { .. } => {
243                StatusCode::InvalidArguments
244            }
245            Error::MissingTimeIndexColumn { .. } => StatusCode::IllegalState,
246            Error::SetSkippingOptions { .. }
247            | Error::UnsetSkippingOptions { .. }
248            | Error::InvalidTableName { .. } => StatusCode::InvalidArguments,
249        }
250    }
251
252    fn as_any(&self) -> &dyn Any {
253        self
254    }
255}
256
257impl From<Error> for DataFusionError {
258    fn from(e: Error) -> DataFusionError {
259        DataFusionError::External(Box::new(e))
260    }
261}