-
-
Notifications
You must be signed in to change notification settings - Fork 639
Description
Background
Currently, we represents database columns using a Column enum (e.g., Column::Id, Column::Name).
However, this approach has a limitation for compile-time type safety.
All variants of the Column enumeration share the same type ( Column ), which means that it is not possible to directly attach Rust data types (e.g. i32 , String ) to a single column variant itself.
So, I think we can add a TypedColumn struct:
struct TypedColumn<C, Type>
where
C: ColumnTrait
Type: Into<ValueType>
{
col: C,
ty: PhantomData<Type>
}With TypedColumn, we can then implement methods that are specific to the column's data type. For example:
impl<C, T> TypedColumn<C, T> {
// another new trait for type safty
pub fn eq<T2: ValueOrExpr<T>>(&self, value: T2) -> Expr {
self.col.eq(value.into())
}
}
impl<C> TypedColumn<C, String> {
pub fn ilike<T: ValueOrExpr<String>>(&self, value: T) -> Expr {
self.col.ilike(value.into())
}
}And we can generate TypedColumn constructors in codegen:
impl Entity {
pub fn id() -> TypedColumn<Column, i32> {
TypedColumn {
col: Column::Id,
ty: PhantomData,
}
}
pub fn name() -> TypedColumn<Column, String> {
TypedColumn {
col: Column::Name,
ty: PhantomData,
}
}
}Benefits
- Compile-time type safety
Considerations
As I've rarely encountered type mismatch errors in my own sea-orm usage (perhaps due to careful query construction), I'm unsure how many others would significantly benefit from this feature.
Duplication
Methods implemented on TypedColumn<C, Type> would largely mirror identical methods already presenton ExprTrait. This creates a duplicate API surface for essentially the same underlying functionality.
Maintenance Burden
Conceptually, any new expression method introduced on ExprTrait would need to be implemented in all relevant impl TypedColumn<C, Type> blocks to maintain full type-safety coverage, which would increase the maintenance burden.