Repository: SeaQL/sea-orm (rust)

Issue:
sea-orm-codegen: Enum `use` statements getting generated multiple times
<!--

Welcome! Thank you for reporting bugs!

First of all, please star our repo. Your support is vital to the continued maintenance of SeaORM.

Want to ask a question? You can reach us via:

- Discord: https://discord.com/invite/uCPdDXzbdv
- GitHub Discussions: https://github.com/SeaQL/sea-orm/discussions/new

Please make sure that you are not asking for a missing feature; a bug is incorrect behavior -
either in the feature specification or implementation.

Please also make sure your description is clear and precise - maintainers don't have access to your
code and can't see what you have seen. Please avoid vague descriptions like "they are different"
or "the program crashes" - in either case, provide exact information.

If you are certain there is a bug, please provide a reproducible example, which helps the investigator
to pin-point the bug and the implementor to verify that a solution is satisfactory. Bug reports without 
reproducible example may be closed immediately or dangle forever.

Finally, please search for existing issues and discussions before submission. Feel free to revive old
threads if you have new information to add, but please don't ask for ETA or "+1".

-->

## Description

When using PostgreSQL, a table that has two columns using the same enum causes the generated entity to have duplicate `use` statements, which cause a compilation error.

## Steps to Reproduce

1. Create a migration like this:
<details>

```Rust
use sea_orm_migration::prelude::*;
use sea_orm_migration::prelude::extension::postgres::Type;
use sea_orm_migration::sea_orm::DbBackend;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
    async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        assert_eq!(manager.get_database_backend(), DbBackend::Postgres);
        manager.create_type(Type::create().as_enum(MyEnum::Table).values([MyEnum::A, MyEnum::B]).to_owned()).await?;

        manager
            .create_table(
                Table::create()
                    .table(MyTable::Table)
                    .if_not_exists()
                    .col(
                        ColumnDef::new(MyTable::Id)
                            .integer()
                            .not_null()
                            .auto_increment()
                            .primary_key(),
                    )
                    .col(ColumnDef::new(MyTable::Col1).enumeration(MyEnum::Table, [MyEnum::A, MyEnum::B]).not_null())
                    .col(ColumnDef::new(MyTable::Col2).enumeration(MyEnum::Table, [MyEnum::A, MyEnum::B]).not_null())
                    .to_owned(),
            )
            .await
    }

    async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        manager
            .drop_table(Table::drop().table(MyTable::Table).to_owned())
            .await
    }
}

/// Learn more at https://docs.rs/sea-query#iden
#[derive(Iden)]
enum MyTable {
    Table,
    Id,
    Col1,
    Col2,
}

#[derive(Iden)]
enum MyEnum {
    Table,
    A,
    B,
}
```
</details>

2. Migrate: `sea migrate`
3. Generate entities: `sea generate entity -o src/entities`
4. Have a look at the generated file (in this case: `src/entities/my_table.rs`)

### Expected Behavior

The generated file has only one import and compiles without errors.
Generated file should look like this:

```Rust
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.0

use super::sea_orm_active_enums::MyEnum;
use sea_orm::entity::prelude::*;

/* ... */
```

### Actual Behavior

Generated file has duplicate use statements and looks like this:

```Rust
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.0

use super::sea_orm_active_enums::MyEnum;
use super::sea_orm_active_enums::MyEnum;
use sea_orm::entity::prelude::*;

/* ... */
```

### Reproduces How Often

Always

### Workarounds

1. Manually remove the duplicate `use` statement each time

2. I've implemented a simple fix in https://github.com/SeaQL/sea-orm/commit/7cf319556d17c57cb95a91b96b573468a310bc44

Note: I tried to fix this and manage to solve it for my project where the bug originally showed up. 
However, I would have liked to add some kind of tests for that but I didn't really understand how. - https://github.com/SeaQL/sea-orm/blob/master/CONTRIBUTING.md did state how to run all the tests (which were successful for my commit) but not how the test system works and where to add my own tests.
I currently don't have the time to try to understand how tests work, so unfortunately, I don't think it would be much help if I opened a PR myself (or would it?).

So if someone wants to pick this up - feel free to use my changes, the main thing that's missing is some test.

## Reproducible Example

Currently, it does not seem like I will have time to add a PR for that unfortunately.

## Versions
> sea-orm-cli: master (1431d80)
> Postgres (14.5 - should not matter)
> Windows 10 (should not matter)

Pull request description:
Fix duplicated active enum `use` statements on generated entities
<!--

Thank you for contributing to this project!

If you need any help please feel free to contact us on Discord: https://discord.com/invite/uCPdDXzbdv
Or, mention our core members by typing `@GitHub_Handle` on any issue / PR

Add some test cases! It help reviewers to understand the behaviour and prevent it to be broken in the future.

-->

## PR Info
Merges original fix by @lukasschlueter and adds tests for `gen_import_active_enum`

<!-- mention the related issue -->
- Closes #1699 

 
## Bug Fixes

- Fixes generated entities containing multiple identically typed `ColumnType::Enum` columns from having duplicated import statements.

Patch:
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 6e3a523b..7be8cd0f 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -232,7 +232,7 @@ jobs:
     steps:
       - uses: actions/checkout@v3
       - id: set-matrix
-        run: echo "path_matrix=$(find examples -mindepth 1 -maxdepth 1 -type d -printf '%P\0' | jq -Rc '[  split("\u0000") | .[] | "examples/\(.)" ]')" >> $GITHUB_OUTPUT
+        run: echo "path_matrix=$(find examples -mindepth 1 -maxdepth 1 -type d -not -path 'examples/rocket_okapi_example' -printf '%P\0' | jq -Rc '[  split("\u0000") | .[] | "examples/\(.)" ]')" >> $GITHUB_OUTPUT
     outputs:
       path_matrix: ${{ steps.set-matrix.outputs.path_matrix }}
 
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 46d9bec3..d554f115 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](http://keepachangelog.com/)
 and this project adheres to [Semantic Versioning](http://semver.org/).
 
+## 0.12.6 - pending
+
+### New Features
+
+* Added `#[sea_orm(skip)]` for `FromQueryResult` derive macro
+
+## 0.12.5 - skipped
+
 ## 0.12.4 - 2023-10-19
 
 ### New Features
diff --git a/examples/rocket_example/api/Cargo.toml b/examples/rocket_example/api/Cargo.toml
index 26269bcf..cbcc3047 100644
--- a/examples/rocket_example/api/Cargo.toml
+++ b/examples/rocket_example/api/Cargo.toml
@@ -11,12 +11,8 @@ async-trait = { version = "0.1" }
 rocket-example-service = { path = "../service" }
 futures = { version = "0.3" }
 futures-util = { version = "0.3" }
-rocket = { version = "0.5.0-rc.1", features = [
-  "json",
-] }
-rocket_dyn_templates = { version = "0.1.0-rc.1", features = [
-  "tera",
-] }
+rocket = { version = "0.5.0-rc.4", features = ["json"] }
+rocket_dyn_templates = { version = "0.1.0-rc.1", features = ["tera"] }
 serde_json = { version = "1" }
 entity = { path = "../entity" }
 migration = { path = "../migration" }
@@ -24,4 +20,4 @@ tokio = "1.29.0"
 
 [dependencies.sea-orm-rocket]
 path = "../../../sea-orm-rocket/lib" # remove this line in your own project and uncomment the following line
-# version = "0.5.2"
+# version = "0.5.3"
diff --git a/examples/rocket_example/entity/Cargo.toml b/examples/rocket_example/entity/Cargo.toml
index 28bd59ae..f5f93181 100644
--- a/examples/rocket_example/entity/Cargo.toml
+++ b/examples/rocket_example/entity/Cargo.toml
@@ -9,9 +9,7 @@ name = "entity"
 path = "src/lib.rs"
 
 [dependencies]
-rocket = { version = "0.5.0-rc.1", features = [
-  "json",
-] }
+rocket = { version = "0.5.0-rc.4", features = ["json"] }
 
 [dependencies.sea-orm]
 path = "../../../" # remove this line in your own project
diff --git a/examples/rocket_example/migration/Cargo.toml b/examples/rocket_example/migration/Cargo.toml
index e2774d56..3bd0ff4f 100644
--- a/examples/rocket_example/migration/Cargo.toml
+++ b/examples/rocket_example/migration/Cargo.toml
@@ -9,7 +9,7 @@ name = "migration"
 path = "src/lib.rs"
 
 [dependencies]
-rocket = { version = "0.5.0-rc.1" }
+rocket = { version = "0.5.0-rc.4" }
 async-std = { version = "1", features = ["attributes", "tokio1"] }
 
 [dependencies.sea-orm-migration]
diff --git a/examples/rocket_okapi_example/api/Cargo.toml b/examples/rocket_okapi_example/api/Cargo.toml
index 1698ca43..91fe0e6a 100644
--- a/examples/rocket_okapi_example/api/Cargo.toml
+++ b/examples/rocket_okapi_example/api/Cargo.toml
@@ -11,12 +11,8 @@ async-trait = { version = "0.1" }
 rocket-okapi-example-service = { path = "../service" }
 futures = { version = "0.3" }
 futures-util = { version = "0.3" }
-rocket = { version = "0.5.0-rc.1", features = [
-  "json",
-] }
-rocket_dyn_templates = { version = "0.1.0-rc.1", features = [
-  "tera",
-] }
+rocket = { version = "0.5.0-rc.4", features = ["json"] }
+rocket_dyn_templates = { version = "0.1.0-rc.1", features = ["tera"] }
 serde_json = { version = "1" }
 entity = { path = "../entity" }
 migration = { path = "../migration" }
@@ -26,14 +22,16 @@ dto = { path = "../dto" }
 
 [dependencies.sea-orm-rocket]
 path = "../../../sea-orm-rocket/lib" # remove this line in your own project and use the version line
-features = ["rocket_okapi"] # enables rocket_okapi so to have open api features enabled
+features = [
+  "rocket_okapi",
+] # enables rocket_okapi so to have open api features enabled
 # version = "0.5.1"
 
 [dependencies.rocket_okapi]
 version = "0.8.0-rc.2"
-features = ["swagger", "rapidoc","rocket_db_pools"]
+features = ["swagger", "rapidoc", "rocket_db_pools"]
 
 [dependencies.rocket_cors]
 git = "https://github.com/lawliet89/rocket_cors.git"
 rev = "54fae070"
-default-features = false
\ No newline at end of file
+default-features = false
diff --git a/examples/rocket_okapi_example/dto/Cargo.toml b/examples/rocket_okapi_example/dto/Cargo.toml
index a0f208db..233a3dc8 100644
--- a/examples/rocket_okapi_example/dto/Cargo.toml
+++ b/examples/rocket_okapi_example/dto/Cargo.toml
@@ -9,12 +9,10 @@ name = "dto"
 path = "src/lib.rs"
 
 [dependencies]
-rocket = { version = "0.5.0-rc.1", features = [
-    "json",
-] }
+rocket = { version = "0.5.0-rc.4", features = ["json"] }
 
 [dependencies.entity]
 path = "../entity"
 
 [dependencies.rocket_okapi]
-version = "0.8.0-rc.2"
\ No newline at end of file
+version = "0.8.0-rc.2"
diff --git a/examples/rocket_okapi_example/entity/Cargo.toml b/examples/rocket_okapi_example/entity/Cargo.toml
index 10cbf52a..5cc820a0 100644
--- a/examples/rocket_okapi_example/entity/Cargo.toml
+++ b/examples/rocket_okapi_example/entity/Cargo.toml
@@ -9,9 +9,7 @@ name = "entity"
 path = "src/lib.rs"
 
 [dependencies]
-rocket = { version = "0.5.0-rc.1", features = [
-  "json",
-] }
+rocket = { version = "0.5.0-rc.4", features = ["json"] }
 
 [dependencies.sea-orm]
 path = "../../../" # remove this line in your own project
diff --git a/examples/rocket_okapi_example/migration/Cargo.toml b/examples/rocket_okapi_example/migration/Cargo.toml
index e2774d56..3bd0ff4f 100644
--- a/examples/rocket_okapi_example/migration/Cargo.toml
+++ b/examples/rocket_okapi_example/migration/Cargo.toml
@@ -9,7 +9,7 @@ name = "migration"
 path = "src/lib.rs"
 
 [dependencies]
-rocket = { version = "0.5.0-rc.1" }
+rocket = { version = "0.5.0-rc.4" }
 async-std = { version = "1", features = ["attributes", "tokio1"] }
 
 [dependencies.sea-orm-migration]
diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs
index dc60654f..6600f462 100644
--- a/sea-orm-codegen/src/entity/writer.rs
+++ b/sea-orm-codegen/src/entity/writer.rs
@@ -460,15 +460,23 @@ impl EntityWriter {
         entity
             .columns
             .iter()
-            .fold(TokenStream::new(), |mut ts, col| {
-                if let sea_query::ColumnType::Enum { name, .. } = col.get_inner_col_type() {
-                    let enum_name = format_ident!("{}", name.to_string().to_upper_camel_case());
-                    ts.extend([quote! {
-                        use super::sea_orm_active_enums::#enum_name;
-                    }]);
-                }
-                ts
-            })
+            .fold(
+                (TokenStream::new(), Vec::new()),
+                |(mut ts, mut enums), col| {
+                    if let sea_query::ColumnType::Enum { name, .. } = col.get_inner_col_type() {
+                        if !enums.contains(&name) {
+                            enums.push(name);
+                            let enum_name =
+                                format_ident!("{}", name.to_string().to_upper_camel_case());
+                            ts.extend([quote! {
+                                use super::sea_orm_active_enums::#enum_name;
+                            }]);
+                        }
+                    }
+                    (ts, enums)
+                },
+            )
+            .0
     }
 
     pub fn gen_model_struct(
@@ -814,7 +822,8 @@ mod tests {
     };
     use pretty_assertions::assert_eq;
     use proc_macro2::TokenStream;
-    use sea_query::{ColumnType, ForeignKeyAction, RcOrArc};
+    use quote::quote;
+    use sea_query::{Alias, ColumnType, ForeignKeyAction, RcOrArc, SeaRc};
     use std::io::{self, BufRead, BufReader, Read};
 
     fn setup() -> Vec<Entity> {
@@ -2275,4 +2284,129 @@ mod tests {
 
         Ok(())
     }
+
+    #[test]
+    fn test_gen_import_active_enum() -> io::Result<()> {
+        let entities = vec![
+            Entity {
+                table_name: "tea_pairing".to_owned(),
+                columns: vec![
+                    Column {
+                        name: "id".to_owned(),
+                        col_type: ColumnType::Integer,
+                        auto_increment: true,
+                        not_null: true,
+                        unique: false,
+                    },
+                    Column {
+                        name: "first_tea".to_owned(),
+                        col_type: ColumnType::Enum {
+                            name: SeaRc::new(Alias::new("tea_enum")),
+                            variants: vec![
+                                SeaRc::new(Alias::new("everyday_tea")),
+                                SeaRc::new(Alias::new("breakfast_tea")),
+                            ],
+                        },
+                        auto_increment: false,
+                        not_null: true,
+                        unique: false,
+                    },
+                    Column {
+                        name: "second_tea".to_owned(),
+                        col_type: ColumnType::Enum {
+                            name: SeaRc::new(Alias::new("tea_enum")),
+                            variants: vec![
+                                SeaRc::new(Alias::new("everyday_tea")),
+                                SeaRc::new(Alias::new("breakfast_tea")),
+                            ],
+                        },
+                        auto_increment: false,
+                        not_null: true,
+                        unique: false,
+                    },
+                ],
+                relations: vec![],
+                conjunct_relations: vec![],
+                primary_keys: vec![PrimaryKey {
+                    name: "id".to_owned(),
+                }],
+            },
+            Entity {
+                table_name: "tea_pairing_with_size".to_owned(),
+                columns: vec![
+                    Column {
+                        name: "id".to_owned(),
+                        col_type: ColumnType::Integer,
+                        auto_increment: true,
+                        not_null: true,
+                        unique: false,
+                    },
+                    Column {
+                        name: "first_tea".to_owned(),
+                        col_type: ColumnType::Enum {
+                            name: SeaRc::new(Alias::new("tea_enum")),
+                            variants: vec![
+                                SeaRc::new(Alias::new("everyday_tea")),
+                                SeaRc::new(Alias::new("breakfast_tea")),
+                            ],
+                        },
+                        auto_increment: false,
+                        not_null: true,
+                        unique: false,
+                    },
+                    Column {
+                        name: "second_tea".to_owned(),
+                        col_type: ColumnType::Enum {
+                            name: SeaRc::new(Alias::new("tea_enum")),
+                            variants: vec![
+                                SeaRc::new(Alias::new("everyday_tea")),
+                                SeaRc::new(Alias::new("breakfast_tea")),
+                            ],
+                        },
+                        auto_increment: false,
+                        not_null: true,
+                        unique: false,
+                    },
+                    Column {
+                        name: "size".to_owned(),
+                        col_type: ColumnType::Enum {
+                            name: SeaRc::new(Alias::new("tea_size")),
+                            variants: vec![
+                                SeaRc::new(Alias::new("small")),
+                                SeaRc::new(Alias::new("medium")),
+                                SeaRc::new(Alias::new("huge")),
+                            ],
+                        },
+                        auto_increment: false,
+                        not_null: true,
+                        unique: false,
+                    },
+                ],
+                relations: vec![],
+                conjunct_relations: vec![],
+                primary_keys: vec![PrimaryKey {
+                    name: "id".to_owned(),
+                }],
+            },
+        ];
+
+        assert_eq!(
+            quote!(
+                use super::sea_orm_active_enums::TeaEnum;
+            )
+            .to_string(),
+            EntityWriter::gen_import_active_enum(&entities[0]).to_string()
+        );
+
+        assert_eq!(
+            quote!(
+                use super::sea_orm_active_enums::TeaEnum;
+                use super::sea_orm_active_enums::TeaSize;
+            )
+            .to_string(),
+            EntityWriter::gen_import_active_enum(&entities[1]).to_string()
+        );
+
+        Ok(())
+    }
 }
diff --git a/sea-orm-macros/Cargo.toml b/sea-orm-macros/Cargo.toml
index 9c0397a9..db529910 100644
--- a/sea-orm-macros/Cargo.toml
+++ b/sea-orm-macros/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sea-orm-macros"
-version = "0.12.4"
+version = "0.12.5"
 authors = [ "Billy Chan <ccw.billy.123@gmail.com>" ]
 edition = "2021"
 description = "Derive macros for SeaORM"
diff --git a/sea-orm-macros/src/derives/from_query_result.rs b/sea-orm-macros/src/derives/from_query_result.rs
index 999db62f..a072827b 100644
--- a/sea-orm-macros/src/derives/from_query_result.rs
+++ b/sea-orm-macros/src/derives/from_query_result.rs
@@ -1,6 +1,29 @@
+use self::util::GetMeta;
 use proc_macro2::{Ident, TokenStream};
-use quote::{format_ident, quote, quote_spanned};
-use syn::{ext::IdentExt, Data, DataStruct, Field, Fields, Generics};
+use quote::{format_ident, quote, quote_spanned, ToTokens};
+use syn::{
+    ext::IdentExt, punctuated::Punctuated, token::Comma, Data, DataStruct, Fields, Generics, Meta,
+};
+
+pub struct FromQueryResultItem {
+    pub skip: bool,
+    pub ident: Ident,
+}
+impl ToTokens for FromQueryResultItem {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        let Self { ident, skip } = self;
+        if *skip {
+            tokens.extend(quote! {
+                #ident: std::default::Default::default(),
+            });
+        } else {
+            let name = ident.unraw().to_string();
+            tokens.extend(quote! {
+                #ident: row.try_get(pre, #name)?,
+            });
+        }
+    }
+}
 
 /// Method to derive a [QueryResult](sea_orm::QueryResult)
 pub fn expand_derive_from_query_result(
@@ -19,20 +42,23 @@ pub fn expand_derive_from_query_result(
             })
         }
     };
+    let mut field = Vec::with_capacity(fields.len());
 
-    let field: Vec<Ident> = fields
-        .into_iter()
-        .map(|Field { ident, .. }| format_ident!("{}", ident.unwrap().to_string()))
-        .collect();
-
-    let name: Vec<TokenStream> = field
-        .iter()
-        .map(|f| {
-            let s = f.unraw().to_string();
-            quote! { #s }
-        })
-        .collect();
-
+    for parsed_field in fields.into_iter() {
+        let mut skip = false;
+        for attr in parsed_field.attrs.iter() {
+            if !attr.path().is_ident("sea_orm") {
+                continue;
+            }
+            if let Ok(list) = attr.parse_args_with(Punctuated::<Meta, Comma>::parse_terminated) {
+                for meta in list.iter() {
+                    skip = meta.exists("skip");
+                }
+            }
+        }
+        let ident = format_ident!("{}", parsed_field.ident.unwrap().to_string());
+        field.push(FromQueryResultItem { skip, ident });
+    }
     let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
 
     Ok(quote!(
@@ -40,9 +66,25 @@ pub fn expand_derive_from_query_result(
         impl #impl_generics sea_orm::FromQueryResult for #ident #ty_generics #where_clause {
             fn from_query_result(row: &sea_orm::QueryResult, pre: &str) -> std::result::Result<Self, sea_orm::DbErr> {
                 Ok(Self {
-                    #(#field: row.try_get(pre, #name)?),*
+                    #(#field)*
                 })
             }
         }
     ))
 }
+mod util {
+    use syn::Meta;
+
+    pub(super) trait GetMeta {
+        fn exists(&self, k: &str) -> bool;
+    }
+
+    impl GetMeta for Meta {
+        fn exists(&self, k: &str) -> bool {
+            let Meta::Path(path) = self else {
+                return false;
+            };
+            path.is_ident(k)
+        }
+    }
+}
diff --git a/sea-orm-macros/src/lib.rs b/sea-orm-macros/src/lib.rs
index 85a9fee6..52f2e734 100644
--- a/sea-orm-macros/src/lib.rs
+++ b/sea-orm-macros/src/lib.rs
@@ -579,6 +579,9 @@ pub fn derive_active_enum(input: TokenStream) -> TokenStream {
 
 /// Convert a query result into the corresponding Model.
 ///
+/// ### Attributes
+/// - `skip`: Will not try to pull this field from the query result. And set it to the default value of the type.
+///
 /// ### Usage
 ///
 /// ```
@@ -588,10 +591,12 @@ pub fn derive_active_enum(input: TokenStream) -> TokenStream {
 /// struct SelectResult {
 ///     name: String,
 ///     num_of_fruits: i32,
+///     #[sea_orm(skip)]
+///     skip_me: i32,
 /// }
 /// ```
 #[cfg(feature = "derive")]
-#[proc_macro_derive(FromQueryResult)]
+#[proc_macro_derive(FromQueryResult, attributes(sea_orm))]
 pub fn derive_from_query_result(input: TokenStream) -> TokenStream {
     let DeriveInput {
         ident,
diff --git a/sea-orm-rocket/codegen/Cargo.toml b/sea-orm-rocket/codegen/Cargo.toml
index 03e34ab0..52600884 100644
--- a/sea-orm-rocket/codegen/Cargo.toml
+++ b/sea-orm-rocket/codegen/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sea-orm-rocket-codegen"
-version = "0.5.0"
+version = "0.5.1"
 authors = ["Sergio Benitez <sb@sergio.bz>", "Jeb Rosen <jeb@jebrosen.com>"]
 description = "Procedural macros for sea_orm_rocket."
 repository = "https://github.com/SergioBenitez/Rocket/contrib/db_pools"
@@ -17,6 +17,6 @@ devise = "0.3"
 quote = "1"
 
 [dev-dependencies]
-rocket = { version = "0.5.0-rc.1", default-features = false }
+rocket = { version = "0.5.0-rc.4", default-features = false }
 trybuild = "1.0"
 version_check = "0.9"
diff --git a/sea-orm-rocket/codegen/src/database.rs b/sea-orm-rocket/codegen/src/database.rs
index 360c8474..c1aba5f3 100644
--- a/sea-orm-rocket/codegen/src/database.rs
+++ b/sea-orm-rocket/codegen/src/database.rs
@@ -64,7 +64,7 @@ pub fn derive_database(input: TokenStream) -> TokenStream {
                     ) -> rocket::request::Outcome<Self, Self::Error> {
                         match #db_ty::fetch(req.rocket()) {
                             Some(db) => rocket::outcome::Outcome::Success(db),
-                            None => rocket::outcome::Outcome::Failure((
+                            None => rocket::outcome::Outcome::Error((
                                 rocket::http::Status::InternalServerError, ()))
                         }
                     }
diff --git a/sea-orm-rocket/lib/Cargo.toml b/sea-orm-rocket/lib/Cargo.toml
index 57ad8b6a..c9dcaffd 100644
--- a/sea-orm-rocket/lib/Cargo.toml
+++ b/sea-orm-rocket/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sea-orm-rocket"
-version = "0.5.2"
+version = "0.5.3"
 authors = ["Sergio Benitez <sb@sergio.bz>", "Jeb Rosen <jeb@jebrosen.com>"]
 description = "SeaORM Rocket support crate"
 repository = "https://github.com/SeaQL/sea-orm"
@@ -13,19 +13,22 @@ edition = "2021"
 all-features = true
 
 [dependencies.rocket]
-version = "0.5.0-rc.1"
+version = "0.5.0-rc.4"
 default-features = false
 
 [dependencies.sea-orm-rocket-codegen]
 path = "../codegen"
-version = "0.5.0"
+version = "0.5.1"
 
-[dependencies.rocket_okapi]
-version = "0.8.0-rc.2"
-default-features = false
-optional = true
+# [dependencies.rocket_okapi]
+# version = "0.8.0-rc.4"
+# default-features = false
+# optional = true
 
 [dev-dependencies.rocket]
-version = "0.5.0-rc.1"
+version = "0.5.0-rc.4"
 default-features = false
-features = ["json"]
\ No newline at end of file
+features = ["json"]
+
+[features]
+rocket_okapi = []
\ No newline at end of file
diff --git a/sea-orm-rocket/lib/src/database.rs b/sea-orm-rocket/lib/src/database.rs
index 54f6da34..fe275e18 100644
--- a/sea-orm-rocket/lib/src/database.rs
+++ b/sea-orm-rocket/lib/src/database.rs
@@ -131,10 +131,10 @@ pub trait Database:
         }
 
         let dbtype = std::any::type_name::<Self>();
-        let fairing = Paint::default(format!("{dbtype}::init()")).bold();
+        let fairing = Paint::new(format!("{dbtype}::init()")).bold();
         error!(
             "Attempted to fetch unattached database `{}`.",
-            Paint::default(dbtype).bold()
+            Paint::new(dbtype).bold()
         );
         info_!(
             "`{}` fairing must be attached prior to using this database.",
@@ -261,7 +261,7 @@ impl<'r, D: Database> FromRequest<'r> for Connection<'r, D> {
     async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
         match D::fetch(req.rocket()) {
             Some(pool) => Outcome::Success(Connection(pool.borrow())),
-            None => Outcome::Failure((Status::InternalServerError, None)),
+            None => Outcome::Error((Status::InternalServerError, None)),
         }
     }
 }


Test patch:
diff --git a/tests/derive_tests.rs b/tests/derive_tests.rs
index 20e49d06..bd99a3b4 100644
--- a/tests/derive_tests.rs
+++ b/tests/derive_tests.rs
@@ -56,3 +56,10 @@ where
 {
     _foo: T::Item,
 }
+
+#[derive(FromQueryResult)]
+struct FromQueryAttributeTests {
+    #[sea_orm(skip)]
+    _foo: i32,
+    _bar: String,
+}