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

Maybe I'm holding it wrong, but my experience with sqlx is a bit more lukewarm. It's really great that compilation success means that you didn't fuck up any queries, but... there's just SO much boilerplate. I find that due to Rust's extremely strict type system, I have to create dedicated record structs for all of my domain models representing how a model is stored in the database. So once everything's up and running it almost always implies there's essentially no bugs, but man is getting there a drag.

Also, testing is quite annoying too. If you're using sqlite, you can use in-memory mode and that's quite nice. But for other databases you basically have only two options: 1. setup and teardown an actual testing db 2. wrap your sqlx interfacing code in something vaguely resembling the repository pattern and create an in-memory implementation for testing. I'd call both of these options less than ideal.



The question is what's the cost of a bug? Lost hours for customer support to collect user reports (which take some time and usually multiple reports before being believed), time spend by CSRs to individually, time by the dev or ops team to fix the affected accounts en-masse, more time by the CSRs to manually fix up affected accounts and give them individual credits where credits are due (which may be manual and thus error-prone process), and finally time spent by the dev team to identify and fix the bug for future users, which is time spent not adding new features or paying down other tech-debt. That's not to say using scripting languages isn't necessarily worth it for increased speed of development, but the time spent above may be impossible to quantify in aggregate. If you're in a low stakes environment, where a bug costs you single digit basis points/bips, not a problem. If you're somewhere like crypto where a bug that an attacker discovered ends up costing the exchange, your employer, 9-figures, or worse, the medical or aerospace industry where bug(s) literally costs people's lives, then avoiding bugs is of paramount importance.

The other option is avoid such a high stakes environment, but someones got to be in those fields.


> But for other databases you basically have only two options: 1. setup and teardown an actual testing db 2. wrap your sqlx interfacing code in something vaguely resembling the repository pattern and create an in-memory implementation for testing. I'd call both of these options less than ideal.

Why not just BEGIN a transaction and then ROLLBACK it after every test case? That's what every other significant backend codebase (using SQL) that I've worked on does. Maybe that's what you meant by #1? Not sure why you'd want to avoid it then—it will help significantly in testing out any piece of code you have that's even slightly outside of the CRUD norms. What does Diesel do, reimplement a completely separate "testing" version for all of its SQL queries?


Just using a transaction that will be rolled back after each test case is exactly what diesel suggests. There is a separate function for this on diesels connection trait[1]

[1]: https://docs.diesel.rs/2.0.x/diesel/connection/trait.Connect...


The database schema is owned by the database, the types in your program are owned by your program, these two things change over time independent of each other, mapping from schema to type is an inherently fallible operation, success can only be determined at runtime, type checking SQL queries against .sql definitions at compile time can be a sort of optimization but doesn't provide any kind of runtime guarantee, and you gotta handle syscall errors gracefully anyway if you want your program to be anything close to reliable, so it's all a bit moot I guess




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

Search: