This just isn’t a problem in other languages I’ve used, which granted aren’t as safe.
I love Rust. But saying it’s only hard if you are doing hard things is an oversimplification.
This just isn’t a problem in other languages I’ve used, which granted aren’t as safe.
I love Rust. But saying it’s only hard if you are doing hard things is an oversimplification.
Querying a database while ensuring type safety is harder, but you still don't need an OEM for that. See sqlx.
You can derive FromRow for your structs to cut down the boilerplate, but if you need to join two tables that happen to have a column with the same name it stops working, unless you remember to _always_ alias one of the columns to the same name, every time you query that table from anywhere (even when the duplicate column names would not be present). If a table gets added later that happens to share a column name with another table? Hope you don't ever have to join those two together.
Doing something CRUD-y like "change ordering based on a parameter" is not supported, and you have to fall back to sprintf("%s ORDER BY %s %s") style concatenation.
Gets even worse if you have to parameterize WHERE clauses.
The structs sqlx creates through the macros are unnameable types, they are created on the fly at the invocation site. This means you can't return them without transforming them into a type you own (you declared), either through the FromRow derive, or writing glue code that associates this unnameable type's fields to your own struct's fields, leading to the boilerplate I was referring to. This is very specific to sqlx, don't try to dilute this into "other libraries are similar".
If you choose to forgo the macros, and use the regular .query() methods, then the results you get are tied to the lifetime of the sqlx connection object, which makes them unergonomic, which is again very specific to sqlx.
I know that the compiler complains a lot. But I code with the help of realtime feedback from tools like the language server (rust-analyzer) and bacon. It feels like 'debug as you code'. And I really love the hand holding it does.
Tasks that are simple in most other languages, like a tree that can store many data types, are going to take a lot more code and a lot more thinking to get it to work in rust.
Generics and traits have some rough edges. If I rub up against them, they're really annoying. Otherwise, if I can avoid those then I agree with you that rust is smooth, and the trade off is worth it.
Most languages used with DBs are just as safe. This idea about Rust being more safe than languages with GC needs a rather big [Citation Needed] sign for the fans.