They give you the ability to manipulate the query in interesting ways at any point before you execute it. They let you join different queries together, built by different parts of the system, in a safe way. They let you work with the native language you're working in instead of having to construct clauses in a foreign language, using strings. They let you post optimise your loading strategies.
You might want "exactly like that", but it's not going to be as flexible as a chainable wrapper system.
Hell, I could probably give you pretty close to that in python with a little work, but it's not something I'd want to use myself.
I get it. I like working in SQL too. I know it really really well, and I cringe when I see developers writing totally sub-optimal code because they don't understand the relational data model.
But there are other ways to do things, and what you're describing doesn't give you much more than raw SQL, so why not just use raw SQL? You've added some syntactic sugar that, in my language (Python), would be a bit of a horror show (strings access local variables implicitly, no thanks). What else do you gain?
This is more verbose, granted:
q = session.query(Products)
if title:
q = q.filter(Products.title.like(title))
if price_range:
q = q.filter(Products.price.lte(price_range))
if offset:
q = q.offset(offset)
if limit:
q = q.limit(limit)
products = q.all()
But then you get more stuff for free, like drilling down into the other tables: p = products[0]
p.supplier.contracts[0]
But that's rubbish, because you'll be loading in a really inefficient way. That's ok though, tell the system how you're going to want to load the additional data. q = q.options(
joinedload('supplier').
subqueryload('contracts')
)
See what I got with my "ball and chain"? Turns out it was actually the anchor for the whole boat. Sure, you have to learn a new syntax, sure, it's not sql, but that doesn't make it bad or wrong.Use whatever makes sense for your use-case. Don't limit yourself because you'd have to learn something new. Honestly, before using SQLAlchemy I mostly felt the same as you do. Many ORMs get in the way, but that's not really a problem intrinsic to ORMs.