// Copyright 2023 Greptime Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::any::Any;

use common_datasource::file_format::Format;
use common_error::define_into_tonic_status;
use common_error::ext::{BoxedError, ErrorExt, RetryHint};
use common_error::status_code::StatusCode;
use common_macro::stack_trace_debug;
use common_query::error::Error as QueryResult;
use datafusion::parquet;
use datafusion_common::DataFusionError;
use datatypes::arrow::error::ArrowError;
use object_store::error::retry_hint_from_opendal_error;
use snafu::{Location, Snafu};
use table::metadata::TableType;

#[derive(Snafu)]
#[snafu(visibility(pub))]
#[stack_trace_debug]
pub enum Error {
    #[snafu(display("Table already exists: `{}`", table))]
    TableAlreadyExists {
        table: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to cast result: `{}`", source))]
    Cast {
        #[snafu(source)]
        source: QueryResult,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("View already exists: `{name}`"))]
    ViewAlreadyExists {
        name: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to build admin function args: {msg}"))]
    BuildAdminFunctionArgs { msg: String },

    #[snafu(display("Failed to execute admin function {msg}"))]
    ExecuteAdminFunction {
        msg: String,
        #[snafu(source)]
        error: DataFusionError,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Admin function execution was cancelled"))]
    AdminFunctionCancelled,

    #[snafu(display("Expected {expected} args, but actual {actual}"))]
    FunctionArityMismatch { expected: usize, actual: usize },

    #[snafu(display("Failed to invalidate table cache"))]
    InvalidateTableCache {
        #[snafu(implicit)]
        location: Location,
        source: common_meta::error::Error,
    },

    #[snafu(display("Failed to execute ddl"))]
    ExecuteDdl {
        #[snafu(implicit)]
        location: Location,
        source: common_meta::error::Error,
    },

    #[snafu(display("Unexpected, violated: {}", violated))]
    Unexpected {
        violated: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("external error"))]
    External {
        #[snafu(implicit)]
        location: Location,
        source: BoxedError,
    },

    #[snafu(display("Failed to insert data"))]
    RequestInserts {
        #[snafu(implicit)]
        location: Location,
        source: common_meta::error::Error,
    },

    #[snafu(display("Failed to delete data"))]
    RequestDeletes {
        #[snafu(implicit)]
        location: Location,
        source: common_meta::error::Error,
    },

    #[snafu(display("Failed to send request to region"))]
    RequestRegion {
        #[snafu(implicit)]
        location: Location,
        source: common_meta::error::Error,
    },

    #[snafu(display("Unsupported region request"))]
    UnsupportedRegionRequest {
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to parse SQL"))]
    ParseSql {
        #[snafu(implicit)]
        location: Location,
        source: sql::error::Error,
    },

    #[snafu(display("Failed to convert identifier: {}", ident))]
    ConvertIdentifier {
        ident: String,
        #[snafu(implicit)]
        location: Location,
        #[snafu(source)]
        error: datafusion::error::DataFusionError,
    },

    #[snafu(display("Failed to extract table names"))]
    ExtractTableNames {
        #[snafu(implicit)]
        location: Location,
        source: query::error::Error,
    },

    #[snafu(display("Column datatype error"))]
    ColumnDataType {
        #[snafu(implicit)]
        location: Location,
        source: api::error::Error,
    },

    #[snafu(display("Invalid column proto definition, column: {}", column))]
    InvalidColumnDef {
        column: String,
        #[snafu(implicit)]
        location: Location,
        source: api::error::Error,
    },

    #[snafu(display("Invalid statement to create view"))]
    InvalidViewStmt {
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Expect {expected} columns for view {view_name}, but found {actual}"))]
    ViewColumnsMismatch {
        view_name: String,
        expected: usize,
        actual: usize,
    },

    #[snafu(display("Invalid view \"{view_name}\": {msg}"))]
    InvalidView {
        msg: String,
        view_name: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to convert column default constraint, column: {}", column_name))]
    ConvertColumnDefaultConstraint {
        column_name: String,
        #[snafu(implicit)]
        location: Location,
        source: datatypes::error::Error,
    },

    #[snafu(display("Failed to convert datafusion schema"))]
    ConvertSchema {
        source: datatypes::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to convert expr to struct"))]
    InvalidExpr {
        #[snafu(implicit)]
        location: Location,
        source: common_meta::error::Error,
    },

    #[snafu(display("Invalid partition"))]
    InvalidPartition {
        #[snafu(implicit)]
        location: Location,
        source: partition::error::Error,
    },

    #[snafu(display("Invalid SQL, error: {}", err_msg))]
    InvalidSql {
        err_msg: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Invalid InsertRequest, reason: {}", reason))]
    InvalidInsertRequest {
        reason: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Invalid DeleteRequest, reason: {}", reason))]
    InvalidDeleteRequest {
        reason: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Table not found: {}", table_name))]
    TableNotFound { table_name: String },

    #[snafu(display("Admin function not found: {}", name))]
    AdminFunctionNotFound { name: String },

    #[snafu(display("Flow not found: {}", flow_name))]
    FlowNotFound { flow_name: String },

    #[snafu(display("Failed to join task"))]
    JoinTask {
        #[snafu(source)]
        error: common_runtime::JoinError,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("General catalog error"))]
    Catalog {
        #[snafu(implicit)]
        location: Location,
        source: catalog::error::Error,
    },

    #[snafu(display("Failed to find view info for: {}", view_name))]
    FindViewInfo {
        view_name: String,
        #[snafu(implicit)]
        location: Location,
        source: common_meta::error::Error,
    },

    #[snafu(display("View info not found: {}", view_name))]
    ViewInfoNotFound {
        view_name: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("View not found: {}", view_name))]
    ViewNotFound {
        view_name: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to find table partition rule for table {}", table_name))]
    FindTablePartitionRule {
        table_name: String,
        #[snafu(implicit)]
        location: Location,
        source: partition::error::Error,
    },

    #[snafu(display("Failed to split insert request"))]
    SplitInsert {
        source: partition::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to split delete request"))]
    SplitDelete {
        source: partition::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to find leader for region"))]
    FindRegionLeader {
        source: partition::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to build CreateExpr on insertion"))]
    BuildCreateExprOnInsertion {
        #[snafu(implicit)]
        location: Location,
        source: common_grpc_expr::error::Error,
    },

    #[snafu(display("Failed to find schema, schema info: {}", schema_info))]
    SchemaNotFound {
        schema_info: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Schema {} already exists", name))]
    SchemaExists {
        name: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Schema `{name}` is in use"))]
    SchemaInUse {
        name: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Schema `{name}` is read-only"))]
    SchemaReadOnly {
        name: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Table `{name}` is read-only"))]
    TableReadOnly {
        name: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display(
        "The definition of table `{name}` is managed by GreptimeDB; it cannot be created or altered (DROP recreates it on the next write)"
    ))]
    TableDdlReserved {
        name: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Table occurs error"))]
    Table {
        #[snafu(implicit)]
        location: Location,
        source: table::error::Error,
    },

    #[snafu(display("Cannot find column by name: {}", msg))]
    ColumnNotFound {
        msg: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to execute statement"))]
    ExecuteStatement {
        #[snafu(implicit)]
        location: Location,
        source: query::error::Error,
    },

    #[snafu(display("Failed to plan statement"))]
    PlanStatement {
        #[snafu(implicit)]
        location: Location,
        source: query::error::Error,
    },

    #[snafu(display("Failed to parse query"))]
    ParseQuery {
        #[snafu(implicit)]
        location: Location,
        source: query::error::Error,
    },

    #[snafu(display("Failed to execute logical plan"))]
    ExecLogicalPlan {
        #[snafu(implicit)]
        location: Location,
        source: query::error::Error,
    },

    #[snafu(display("Failed to build DataFusion logical plan"))]
    BuildDfLogicalPlan {
        #[snafu(source)]
        error: datafusion_common::DataFusionError,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to convert AlterExpr to AlterRequest"))]
    AlterExprToRequest {
        #[snafu(implicit)]
        location: Location,
        source: common_grpc_expr::error::Error,
    },

    #[snafu(display("Failed to build table meta for table: {}", table_name))]
    BuildTableMeta {
        table_name: String,
        #[snafu(source)]
        error: table::metadata::TableMetaBuilderError,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Not supported: {}", feat))]
    NotSupported { feat: String },

    #[snafu(display("Failed to find new columns on insertion"))]
    FindNewColumnsOnInsertion {
        #[snafu(implicit)]
        location: Location,
        source: common_grpc_expr::error::Error,
    },

    #[snafu(display("Failed to convert into vectors"))]
    IntoVectors {
        #[snafu(implicit)]
        location: Location,
        source: datatypes::error::Error,
    },

    #[snafu(display("Failed to describe schema for given statement"))]
    DescribeStatement {
        #[snafu(implicit)]
        location: Location,
        source: query::error::Error,
    },

    #[snafu(display("Illegal primary keys definition: {}", msg))]
    IllegalPrimaryKeysDef {
        msg: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Unrecognized table option"))]
    UnrecognizedTableOption {
        #[snafu(implicit)]
        location: Location,
        source: table::error::Error,
    },

    #[snafu(display("Missing time index column"))]
    MissingTimeIndexColumn {
        #[snafu(implicit)]
        location: Location,
        source: table::error::Error,
    },

    #[snafu(display("Failed to build regex"))]
    BuildRegex {
        #[snafu(implicit)]
        location: Location,
        #[snafu(source)]
        error: regex::Error,
    },

    #[snafu(display("Failed to insert value into table: {}", table_name))]
    Insert {
        table_name: String,
        #[snafu(implicit)]
        location: Location,
        source: table::error::Error,
    },

    #[snafu(display("Unsupported format: {:?}", format))]
    UnsupportedFormat {
        #[snafu(implicit)]
        location: Location,
        format: Format,
    },

    #[snafu(display("Failed to parse file format"))]
    ParseFileFormat {
        #[snafu(implicit)]
        location: Location,
        source: common_datasource::error::Error,
    },

    #[snafu(display("Failed to build data source backend"))]
    BuildBackend {
        #[snafu(implicit)]
        location: Location,
        source: common_datasource::error::Error,
    },

    #[snafu(display("Failed to list objects"))]
    ListObjects {
        #[snafu(implicit)]
        location: Location,
        source: common_datasource::error::Error,
    },

    #[snafu(display("Failed to infer schema from path: {}", path))]
    InferSchema {
        path: String,
        #[snafu(implicit)]
        location: Location,
        source: common_datasource::error::Error,
    },

    #[snafu(display("Failed to write stream to path: {}", path))]
    WriteStreamToFile {
        path: String,
        #[snafu(implicit)]
        location: Location,
        source: common_datasource::error::Error,
    },

    #[snafu(display("Failed to read object in path: {}", path))]
    ReadObject {
        path: String,
        #[snafu(implicit)]
        location: Location,
        #[snafu(source)]
        error: object_store::Error,
    },

    #[snafu(display("Failed to read record batch"))]
    ReadDfRecordBatch {
        #[snafu(source)]
        error: datafusion::error::DataFusionError,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to read parquet file metadata"))]
    ReadParquetMetadata {
        #[snafu(source)]
        error: parquet::errors::ParquetError,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to build record batch"))]
    BuildRecordBatch {
        #[snafu(implicit)]
        location: Location,
        source: common_recordbatch::error::Error,
    },

    #[snafu(display("Failed to read orc schema"))]
    ReadOrc {
        source: common_datasource::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to build parquet record batch stream"))]
    BuildParquetRecordBatchStream {
        #[snafu(implicit)]
        location: Location,
        #[snafu(source)]
        error: parquet::errors::ParquetError,
    },

    #[snafu(display("Failed to build file stream"))]
    BuildFileStream {
        #[snafu(implicit)]
        location: Location,
        #[snafu(source)]
        error: common_datasource::error::Error,
    },

    #[snafu(display(
        "Schema datatypes not match at index {}, expected table schema: {}, actual file schema: {}",
        index,
        table_schema,
        file_schema
    ))]
    InvalidSchema {
        index: usize,
        table_schema: String,
        file_schema: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display(
        "CSV header mismatch in path: {}, unknown columns: {:?}, missing columns: {:?}, duplicate columns: {:?}",
        path,
        unknown_columns,
        missing_columns,
        duplicate_columns
    ))]
    CsvHeaderMismatch {
        path: String,
        unknown_columns: Vec<String>,
        missing_columns: Vec<String>,
        duplicate_columns: Vec<String>,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to project schema"))]
    ProjectSchema {
        #[snafu(source)]
        error: ArrowError,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to encode object into json"))]
    EncodeJson {
        #[snafu(source)]
        error: serde_json::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Invalid COPY parameter, key: {}, value: {}", key, value))]
    InvalidCopyParameter {
        key: String,
        value: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Invalid COPY DATABASE location, must end with '/': {}", value))]
    InvalidCopyDatabasePath {
        value: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Table metadata manager error"))]
    TableMetadataManager {
        source: common_meta::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Missing insert body"))]
    MissingInsertBody {
        source: sql::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to parse sql value"))]
    ParseSqlValue {
        source: sql::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to build default value, column: {}", column))]
    ColumnDefaultValue {
        column: String,
        #[snafu(implicit)]
        location: Location,
        source: datatypes::error::Error,
    },

    #[snafu(display(
        "No valid default value can be built automatically, column: {}",
        column,
    ))]
    ColumnNoneDefaultValue {
        column: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to prepare file table"))]
    PrepareFileTable {
        #[snafu(implicit)]
        location: Location,
        source: query::error::Error,
    },

    #[snafu(display("Failed to infer file table schema"))]
    InferFileTableSchema {
        #[snafu(implicit)]
        location: Location,
        source: query::error::Error,
    },

    #[snafu(display("The schema of the file table is incompatible with the table schema"))]
    SchemaIncompatible {
        #[snafu(implicit)]
        location: Location,
        source: query::error::Error,
    },

    #[snafu(display("Invalid table name: {}", table_name))]
    InvalidTableName {
        table_name: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Invalid view name: {name}"))]
    InvalidViewName {
        name: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Invalid flow name: {name}"))]
    InvalidFlowName {
        name: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[cfg(feature = "enterprise")]
    #[snafu(display("Invalid trigger name: {name}"))]
    InvalidTriggerName {
        name: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Empty {} expr", name))]
    EmptyDdlExpr {
        name: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to create logical tables: {}", reason))]
    CreateLogicalTables {
        reason: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Invalid partition rule: {}", reason))]
    InvalidPartitionRule {
        reason: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to serialize partition expression"))]
    SerializePartitionExpr {
        #[snafu(implicit)]
        location: Location,
        source: partition::error::Error,
    },

    #[snafu(display("Failed to deserialize partition expression"))]
    DeserializePartitionExpr {
        #[snafu(source)]
        source: partition::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Invalid configuration value."))]
    InvalidConfigValue {
        source: session::session_config::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Invalid timestamp range, start: `{}`, end: `{}`", start, end))]
    InvalidTimestampRange {
        start: String,
        end: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to convert between logical plan and substrait plan"))]
    SubstraitCodec {
        #[snafu(implicit)]
        location: Location,
        source: substrait::error::Error,
    },

    #[snafu(display(
        "Show create table only for base table. {} is {}",
        table_name,
        table_type
    ))]
    ShowCreateTableBaseOnly {
        table_name: String,
        table_type: TableType,
        #[snafu(implicit)]
        location: Location,
    },
    #[snafu(display("Create physical expr error"))]
    PhysicalExpr {
        #[snafu(source)]
        error: common_recordbatch::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to upgrade catalog manager reference"))]
    UpgradeCatalogManagerRef {
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Invalid json text: {}", json))]
    InvalidJsonFormat {
        #[snafu(implicit)]
        location: Location,
        json: String,
    },

    #[snafu(display("Cursor {name} is not found"))]
    CursorNotFound { name: String },

    #[snafu(display("A cursor named {name} already exists"))]
    CursorExists { name: String },

    #[snafu(display("Column options error"))]
    ColumnOptions {
        #[snafu(source)]
        source: api::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to create partition rules"))]
    CreatePartitionRules {
        #[snafu(source)]
        source: sql::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to decode arrow flight data"))]
    DecodeFlightData {
        source: common_grpc::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to perform arrow compute"))]
    ComputeArrow {
        #[snafu(source)]
        error: ArrowError,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Invalid time index type: {}", ty))]
    InvalidTimeIndexType {
        ty: arrow::datatypes::DataType,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Invalid timezone: {}", timezone))]
    InvalidTimezone {
        timezone: String,
        #[snafu(source)]
        source: common_time::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Invalid process id: {}", id))]
    InvalidProcessId { id: String },

    #[snafu(display("ProcessManager is not present, this can be caused by misconfiguration."))]
    ProcessManagerMissing {
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Sql common error"))]
    SqlCommon {
        source: common_sql::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display("Failed to convert partition expression to protobuf"))]
    PartitionExprToPb {
        source: partition::error::Error,
        #[snafu(implicit)]
        location: Location,
    },

    #[snafu(display(
        "{} not supported when transforming to {} format type",
        format,
        file_format
    ))]
    TimestampFormatNotSupported {
        file_format: String,
        format: String,
        #[snafu(implicit)]
        location: Location,
    },

    #[cfg(feature = "enterprise")]
    #[snafu(display("Too large duration"))]
    TooLargeDuration {
        #[snafu(source)]
        error: prost_types::DurationError,
        #[snafu(implicit)]
        location: Location,
    },

    #[cfg(feature = "enterprise")]
    #[snafu(display("Not trigger querier is specified"))]
    MissingTriggerQuerier {
        #[snafu(implicit)]
        location: Location,
    },

    #[cfg(feature = "enterprise")]
    #[snafu(display("Trigger querier error"))]
    TriggerQuerier {
        source: BoxedError,
        #[snafu(implicit)]
        location: Location,
    },
}

pub type Result<T> = std::result::Result<T, Error>;

impl ErrorExt for Error {
    fn status_code(&self) -> StatusCode {
        match self {
            Error::Cast { source, .. } => source.status_code(),
            Error::InvalidSql { .. }
            | Error::InvalidConfigValue { .. }
            | Error::InvalidInsertRequest { .. }
            | Error::InvalidDeleteRequest { .. }
            | Error::IllegalPrimaryKeysDef { .. }
            | Error::SchemaNotFound { .. }
            | Error::SchemaExists { .. }
            | Error::SchemaInUse { .. }
            | Error::ColumnNotFound { .. }
            | Error::BuildRegex { .. }
            | Error::InvalidSchema { .. }
            | Error::CsvHeaderMismatch { .. }
            | Error::ProjectSchema { .. }
            | Error::UnsupportedFormat { .. }
            | Error::ColumnNoneDefaultValue { .. }
            | Error::PrepareFileTable { .. }
            | Error::InferFileTableSchema { .. }
            | Error::SchemaIncompatible { .. }
            | Error::ConvertSchema { .. }
            | Error::UnsupportedRegionRequest { .. }
            | Error::InvalidTableName { .. }
            | Error::InvalidViewName { .. }
            | Error::InvalidFlowName { .. }
            | Error::InvalidView { .. }
            | Error::InvalidExpr { .. }
            | Error::AdminFunctionNotFound { .. }
            | Error::ViewColumnsMismatch { .. }
            | Error::InvalidViewStmt { .. }
            | Error::ConvertIdentifier { .. }
            | Error::BuildAdminFunctionArgs { .. }
            | Error::FunctionArityMismatch { .. }
            | Error::InvalidPartition { .. }
            | Error::PhysicalExpr { .. }
            | Error::InvalidJsonFormat { .. }
            | Error::PartitionExprToPb { .. }
            | Error::CursorNotFound { .. }
            | Error::CursorExists { .. }
            | Error::CreatePartitionRules { .. } => StatusCode::InvalidArguments,
            Error::TableAlreadyExists { .. } | Error::ViewAlreadyExists { .. } => {
                StatusCode::TableAlreadyExists
            }
            Error::NotSupported { .. }
            | Error::ShowCreateTableBaseOnly { .. }
            | Error::SchemaReadOnly { .. }
            | Error::TableReadOnly { .. }
            | Error::TableDdlReserved { .. } => StatusCode::Unsupported,
            Error::TableMetadataManager { source, .. } => source.status_code(),
            Error::ParseSql { source, .. } => source.status_code(),
            Error::InvalidateTableCache { source, .. } => source.status_code(),
            Error::ParseFileFormat { source, .. } | Error::InferSchema { source, .. } => {
                source.status_code()
            }
            Error::Table { source, .. } | Error::Insert { source, .. } => source.status_code(),
            Error::ConvertColumnDefaultConstraint { source, .. }
            | Error::IntoVectors { source, .. } => source.status_code(),
            Error::RequestInserts { source, .. } | Error::FindViewInfo { source, .. } => {
                source.status_code()
            }
            Error::RequestRegion { source, .. } => source.status_code(),
            Error::RequestDeletes { source, .. } => source.status_code(),
            Error::SubstraitCodec { source, .. } => source.status_code(),
            Error::ColumnDataType { source, .. } | Error::InvalidColumnDef { source, .. } => {
                source.status_code()
            }
            Error::MissingTimeIndexColumn { source, .. } => source.status_code(),
            Error::BuildDfLogicalPlan { .. }
            | Error::BuildTableMeta { .. }
            | Error::MissingInsertBody { .. } => StatusCode::Internal,
            Error::ExecuteAdminFunction { .. }
            | Error::EncodeJson { .. }
            | Error::DeserializePartitionExpr { .. }
            | Error::SerializePartitionExpr { .. } => StatusCode::Unexpected,
            Error::AdminFunctionCancelled => StatusCode::Cancelled,
            Error::ViewNotFound { .. }
            | Error::ViewInfoNotFound { .. }
            | Error::TableNotFound { .. } => StatusCode::TableNotFound,
            Error::FlowNotFound { .. } => StatusCode::FlowNotFound,
            Error::JoinTask { .. } => StatusCode::Internal,
            Error::BuildParquetRecordBatchStream { .. }
            | Error::BuildFileStream { .. }
            | Error::WriteStreamToFile { .. }
            | Error::ReadDfRecordBatch { .. }
            | Error::Unexpected { .. } => StatusCode::Unexpected,
            Error::Catalog { source, .. } => source.status_code(),
            Error::BuildCreateExprOnInsertion { source, .. }
            | Error::FindNewColumnsOnInsertion { source, .. } => source.status_code(),
            Error::ExecuteStatement { source, .. }
            | Error::ExtractTableNames { source, .. }
            | Error::PlanStatement { source, .. }
            | Error::ParseQuery { source, .. }
            | Error::ExecLogicalPlan { source, .. }
            | Error::DescribeStatement { source, .. } => source.status_code(),
            Error::AlterExprToRequest { source, .. } => source.status_code(),
            Error::External { source, .. } => source.status_code(),
            Error::FindTablePartitionRule { source, .. }
            | Error::SplitInsert { source, .. }
            | Error::SplitDelete { source, .. }
            | Error::FindRegionLeader { source, .. } => source.status_code(),
            Error::UnrecognizedTableOption { .. } => StatusCode::InvalidArguments,
            Error::ReadObject { .. }
            | Error::ReadParquetMetadata { .. }
            | Error::ReadOrc { .. } => StatusCode::StorageUnavailable,
            Error::ListObjects { source, .. } | Error::BuildBackend { source, .. } => {
                source.status_code()
            }
            Error::ExecuteDdl { source, .. } => source.status_code(),
            Error::InvalidCopyParameter { .. } | Error::InvalidCopyDatabasePath { .. } => {
                StatusCode::InvalidArguments
            }
            Error::ColumnDefaultValue { source, .. } => source.status_code(),
            Error::EmptyDdlExpr { .. }
            | Error::InvalidPartitionRule { .. }
            | Error::ParseSqlValue { .. }
            | Error::InvalidTimestampRange { .. } => StatusCode::InvalidArguments,
            Error::CreateLogicalTables { .. } => StatusCode::Unexpected,
            Error::BuildRecordBatch { source, .. } => source.status_code(),
            Error::UpgradeCatalogManagerRef { .. } => StatusCode::Internal,
            Error::ColumnOptions { source, .. } => source.status_code(),
            Error::DecodeFlightData { source, .. } => source.status_code(),
            Error::ComputeArrow { .. } => StatusCode::Internal,
            Error::InvalidTimeIndexType { .. } | Error::InvalidTimezone { .. } => {
                StatusCode::InvalidArguments
            }
            Error::InvalidProcessId { .. } => StatusCode::InvalidArguments,
            Error::ProcessManagerMissing { .. } => StatusCode::Unexpected,
            Error::TimestampFormatNotSupported { .. } => StatusCode::InvalidArguments,
            Error::SqlCommon { source, .. } => source.status_code(),
            #[cfg(feature = "enterprise")]
            Error::InvalidTriggerName { .. } => StatusCode::InvalidArguments,
            #[cfg(feature = "enterprise")]
            Error::TooLargeDuration { .. } => StatusCode::InvalidArguments,
            #[cfg(feature = "enterprise")]
            Error::MissingTriggerQuerier { .. } => StatusCode::Internal,
            #[cfg(feature = "enterprise")]
            Error::TriggerQuerier { source, .. } => source.status_code(),
        }
    }

    fn as_any(&self) -> &dyn Any {
        self
    }

    fn retry_hint(&self) -> RetryHint {
        match self {
            Error::ReadObject { error, .. } => retry_hint_from_opendal_error(error),
            Error::ReadParquetMetadata { .. } => RetryHint::Retryable,
            Error::InvalidateTableCache { source, .. }
            | Error::ExecuteDdl { source, .. }
            | Error::RequestInserts { source, .. }
            | Error::RequestDeletes { source, .. }
            | Error::RequestRegion { source, .. }
            | Error::FindViewInfo { source, .. }
            | Error::TableMetadataManager { source, .. } => source.retry_hint(),

            Error::ParseFileFormat { source, .. }
            | Error::InferSchema { source, .. }
            | Error::ListObjects { source, .. }
            | Error::BuildBackend { source, .. }
            | Error::ReadOrc { source, .. } => source.retry_hint(),

            Error::ExtractTableNames { source, .. }
            | Error::ExecuteStatement { source, .. }
            | Error::PlanStatement { source, .. }
            | Error::ParseQuery { source, .. }
            | Error::ExecLogicalPlan { source, .. }
            | Error::DescribeStatement { source, .. } => source.retry_hint(),

            Error::FindTablePartitionRule { source, .. }
            | Error::SplitInsert { source, .. }
            | Error::SplitDelete { source, .. }
            | Error::FindRegionLeader { source, .. } => source.retry_hint(),

            Error::BuildCreateExprOnInsertion { source, .. }
            | Error::FindNewColumnsOnInsertion { source, .. }
            | Error::AlterExprToRequest { source, .. } => source.retry_hint(),

            Error::ConvertColumnDefaultConstraint { source, .. }
            | Error::IntoVectors { source, .. }
            | Error::ColumnDefaultValue { source, .. } => source.retry_hint(),

            Error::ColumnDataType { source, .. }
            | Error::InvalidColumnDef { source, .. }
            | Error::ColumnOptions { source, .. } => source.retry_hint(),

            Error::Table { source, .. }
            | Error::Insert { source, .. }
            | Error::MissingTimeIndexColumn { source, .. } => source.retry_hint(),

            Error::Cast { source, .. } => source.retry_hint(),
            Error::ParseSql { source, .. } => source.retry_hint(),
            Error::Catalog { source, .. } => source.retry_hint(),
            Error::SubstraitCodec { source, .. } => source.retry_hint(),
            Error::External { source, .. } => source.retry_hint(),
            Error::BuildRecordBatch { source, .. } => source.retry_hint(),
            Error::DecodeFlightData { source, .. } => source.retry_hint(),
            Error::SqlCommon { source, .. } => source.retry_hint(),
            Error::ConvertSchema { source, .. } => source.retry_hint(),
            Error::WriteStreamToFile { source, .. } => source.retry_hint(),
            Error::PrepareFileTable { source, .. } | Error::InferFileTableSchema { source, .. } => {
                source.retry_hint()
            }
            #[cfg(feature = "enterprise")]
            Error::TriggerQuerier { source, .. } => source.retry_hint(),
            _ => RetryHint::NonRetryable,
        }
    }
}

define_into_tonic_status!(Error);
