I think there is no one answer for this. In some cases pure SQL is better, in other cases, you need higher level constructs to be efficient, consistent and less error prone.
We have lots of experience with ORMs based on dynamic languages (i.e. Objective-C and Ruby) and if not careful, you can indeed go sideways pretty quickly.
Recently, we've been using https://ash-hq.org. It tries to solve the same problems as an ORM, but using a pure functional language (Elixir). You are using structs instead of objects, so it can feel very close to using raw dictionaries/hashes. It also makes it super easy to drop down to raw sql, while maintaining that struct interface at the top.
While it does take some getting used to (especially coming from a dynamic, OO language), I'm liking this alternative a lot!