Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

That's what I feel like, too. Every ORM that I've worked with is a separate DSL that I need to learn. Also, abstracting away the database is something I don't get - why abstract away something that I explicitly chose because it does something different than the other alternatives?

I've yet to encouter a project where I'd need to switch to a different database. Even if that happens, there is likely some raw SQL that someone wrote because the ORM didn't do something as expected. Or some part of the code uses DB-specific ORM features that don't map to different databases. The only thing I can imagine where this would be useful is when you don't have control about what DB is being used, for example, when building a product that should be compatible with Postgres and MariaDB (and each is getting used). However, in the age of containerization, this isn't a big problem any more.

In some ORMs, I need to create types that the result of a query containing JOINs is mapped to. Others don't support them _at all_. In TypeORM, there is a query builder which forces you to put in _some_ SQL for things like "WHERE a in (b, c)". Most ORMs I've used have a cumbersome handling of relations, for example when I need to specify which relation should be fetched eagerly.

I created a proof of concept of a different approach: Just embrace SQL and provide static typing based on the query. The return type of a query is whatever that thing is that the query returns in the context of the database schema. It's possible to do in TypeScript, by parsing the SQL query at development time:

https://github.com/nikeee/sequelts

One benefit is that it does not need any runtime code, as it's just a type layer over SQL. You don't have to rely on some type-metadata that TypeScript emits. That's why it also works with JavaScript only. You don't have to fit every result into some type - it just returns an interface that can be used wherever you want. That's especially useful because TS's type system is structural.

One major downside is that it's rather complicate to implement a parser and evaluation of the result type in TypeScript's type annotations. A different story is debugging type-level code; it's basically try-and-error. Providing error messages in case a query is wrong is also something that needs work. That's why it's only a PoC.



>Every ORM that I've worked with is a separate DSL that I need to learn

That is the point of Flyweight. The API is very small, and for everything else you use SQL. The ORM parses the SQL to figure out the types, and when you want it to, it maps the SQL into more complex data structures.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: