3 ms·
Your point a) is moot, this is not what this is about. When writing manual SQL nothing stops you from doing `SELECT * FROM persons WHERE age > 'eighteen'` (the
by hendi_ 6y ago
Your point a) is moot, this is not what this is about. When writing manual SQL nothing stops you from doing `SELECT * FROM persons WHERE age > 'eighteen'` (the `age` field is a number, obviously). Coming from Django I was often bitten by `Person.objects.filter(age__gt=trashhold) # boom!` (note the misspelled variable "threshold") or, if you prefer manual writin SQL: `Person.objects.raw("SELECT * FROM persons WHERE age > {}", trashhold) # boom! as well`. (Admittedly this is unrelated to type safety, just a disadvantage of Python being interpreted, but still something that Haskell/IHP protects me of.)
Regarding b), yes there are good reasons for prepared statements. I won't go into your argument "for scalability" (premature optimization cough) but cached query plans aren't perfect either: data and data typologies change, and so does the optimal query plan. See https://blog.soykaf.com/post/postgresql-elixir-troubles/ https://blog.soykaf.com/post/postgresql-elixir-troubles/ for a blog post about Elixir/Phoenix/Ecto users being bitten by that.
> I wonder if the person who wrote this understands SQL to sufficient depth. Not saying either way, just asking.
I did not write the IHP code, just the above comment. But I've read many of CJ Date's books and have a good grasp on the relational model, and of SQL too. I simply don't see things as black/white, there are certain queries where I do prefer prepared statements and functions, or PL/pgSQL even, then there are ones where I use an external .sql file to keep things tidy. But most of the time (especially in the user facing part of a web app) I like my ORMs or SQL DSLs.
- necovek 6y agoUnless you've got `trashhold` actually defined, tools like flake8 would protect you from that mistake with Python. Using type hints would also protect you from using variables with incompatible types with a better designed API (Django's ORM API is anything but). As for SQL performance, I've usually only worked with up to hundreds of millions of rows per table, and the most important thing at that scale was to attempt to keep indexes in memory cache (that improves or degrades the performance by a couple of orders of magnitude). I haven't had a need for query plans to be cached, though I did use subselects to force particular query plans when needed (which has the similar problem of query plans not being the most efficient ones when data evolves sufficiently).