Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions SeaORM/docs/04-generate-entity/05-newtype.md
Original file line number Diff line number Diff line change
Expand Up @@ -384,3 +384,60 @@ impl std::str::FromStr for Tag3 {
}
}
```

## Binary-like newtypes

It's also possible to use binary newtypes in your models. Even though there is no `DeriveValueType` for those, you can implement the traits directly. Here's an example implementation for a `Bin` newtype that implements `TryFrom<Vec<u8>>` and `Into<Vec<u8>>`:

```rust
impl From<Bin> for sea_orm::sea_query::Value {
fn from(t: Bin) -> Self {
Value::Bytes(Some(t.into()))
}
}

impl sea_orm::TryGetable for Bin {
fn try_get_by<I: sea_orm::ColIdx>(
res: &sea_orm::QueryResult,
index: I,
) -> Result<Self, sea_orm::error::TryGetError> {
let val = <Vec<u8> as sea_orm::TryGetable>::try_get_by(res, index)?;
Copy link
Copy Markdown
Member

@Huliiiiii Huliiiiii May 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be reduced further to a minimal example: When implementing TryGetable manually, <T as TryGetable>::try_get_by should be used instead of QueryResult::try_get_by. They have the same name, but they are very different methods.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry i'm not sure i follow. Isn't that precisely what's in the example here? (i followed your previous suggestions but i don't understand the difference with this one)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the other examples already provide sufficient context. The focus here is on ensuring users don't accidentally use QueryResult::try_get_by, and previous examples have clearly illustrated this with syntax like <T as sea_orm::TryGetable>.

Therefore, I think this section could be made more concise by removing unnecessary example code. In short, it should focus more on explaining the core principles rather than adding more examples.

Bin::try_from(val).map_err(|e| {
sea_orm::error::TryGetError::DbErr(sea_orm::DbErr::TryIntoErr {
from: "Bytes",
into: "TorrentFile",
source: std::sync::Arc::new(e),
})
})
}
}

impl sea_orm::sea_query::ValueType for Bin {
fn try_from(v: sea_orm::Value) -> Result<Self, sea_orm::sea_query::ValueTypeErr> {
match v {
sea_orm::Value::Bytes(Some(s)) => {
Bin::try_from(s).map_err(|_e| sea_orm::sea_query::ValueTypeErr)
}
_ => Err(sea_orm::sea_query::ValueTypeErr),
}
}

fn type_name() -> String {
"Bin".to_string()
}

fn array_type() -> sea_orm::sea_query::ArrayType {
sea_orm::sea_query::ArrayType::Bytes
}

fn column_type() -> sea_orm::sea_query::ColumnType {
sea_orm::sea_query::ColumnType::VarBinary(StringLen::None)
}
}

impl sea_orm::sea_query::Nullable for Bin {
fn null() -> sea_orm::sea_query::Value {
sea_orm::sea_query::Value::Bytes(None)
}
}
```