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("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}