← Back to context

Comment by mr_Fatalyst

9 hours ago

The Rust core is not just about speed. It bundles native database drivers (sqlx), connection pooling, streaming serialization. It's more about the full IO stack than just making Python faster. On F("views"), fair point. It's a conscious trade-off for now. The .pyi stubs cover filter(), create(), and other query methods, but F() is still stringly-typed. Room for improvement there.

> It's more about the full IO stack than just making Python faster.

Does it mean that your db adapter isn't necessarily DBAPI (PEP-249) compliant? That is, it could be that DBAPI exception hierarchy isn't respected, so that middlewares that expect to work across the stack and catch all DB-related issues, may not work if the underlying DB access stack is using your drivers?

> but F() is still stringly-typed. Room for improvement there.

Yeah, I'm pretty sure F() isn't needed. You can look at how sqlalchemy implements combinator-style API around field attributes:

    import sqlalchemy as sa
    from sqlalchemy.orm import DeclarativeBase


    class Base(sa.orm.DeclarativeBase):
        pass

    class Stats(Base):
        __tablename__ = "stats"

        id = sa.Column(sa.Integer, primary_key=True)
        views = sa.Column(sa.Integer, nullable=False)

    print(Stats.views + 1)

The expression `Stats.views + 1` is self-contained, and can be re-used across queries. `Stats.views` is a smart object (https://docs.sqlalchemy.org/en/21/orm/internals.html#sqlalch...) with overloaded operators that make it re-usable in different contexts, such as result getters and query builders.

  • Right, it's not DBAPI compliant. The whole IO stack goes through Rust/sqlx, so PEP-249 doesn't apply. Oxyde has its own exception hierarchy (OxydeError, IntegrityError, NotFoundError, etc.). In practice most people catch ORM-level exceptions rather than DBAPI ones, but fair to call out.

    On F(), good point. The descriptor approach is something I've been thinking about. Definitely on the radar.