Skip to content

Proposal: type safe column expr methods #2764

@Huliiiiii

Description

@Huliiiiii

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions