I am happy to announce sqlc-hs — a Haskell code generator plugin for sqlc, allowing you to generate Haskell types and functions directly from your SQL queries.
I’d be thrilled to hear your feedback, suggestions, or ideas for improvement. Contributions of any kind — from bug reports to pull requests — are more than welcome. Your input will help shape sqlc-hs into a more robust and useful tool for the Haskell community.
This is the first I’ve heard of sqlc; after looking at it a bit, I’m having a hard time figuring why I may want to use it over esqueleto or another haskell eDSL-style encoding. Excepting, of course, the case that for some reason I do want to write the literal sql queries, and then can get some typesafety with sqlc.
Is there some additional elevator-pitch I’m missing? Thanks! Project looks cool.
Thanks @joelmccracken. I am currently working on multiple sufficiently large projects, one with beam and one with sqlc. Both approaches work fine in practice but I tend to enjoy writing SQL more than writing beam queries. Especially since I have the full power of PostgreSQL at my hands where with beam I am stuck with what it offers mostly – it’s complicated DSL nature making it hard to extend. Sqlc “typechecks” your queries and ensures that referenced columns are present making it a great companion when developing the queries.
So I guess all in all it’s a matter of preference but it’s nice being able to have full control over the queries where needed.
esqueleto is barely better than raw SQL for anything complicated. so much toil. even with a bunch of the new stuff (records, automatic :& search, etc. all interestingly born from real world use where esqueleto was a pain).
so if sqlc can let me write raw SQL but get some type safety, that’s a step up.
idk about composability for either though. esqueleto is built on silly abstractions so abstracting over stuff is often confusing or just hard.
it’s basically carried by having a “smooth” funnel from persistent when you immediately hit its ceiling.
Having been burned by a number of “simple” SQL DSLs and ORMs, I am more than ever convinced that sometimes you just have to learn two languages and that’s okay. Give me a string interpolator that will marshal interpolated terms to the appropriate parameters to a prepared statement and I’ll happily write the raw SQL. The amount of effort I’ve had to put in to reverse engineer the queries from a DSL is just hard to justify compared to learning the transferable skill of writing SQL.
There are pros and cons to database libraries like beam and opaleye. The main advantage, and why I always use beam when I can, is that you can compose fragments of database statements using a library, in a way that cannot be replicated using string interpolators.
At work, I’d often like to take an existing query, and modify it by joining and filtering, for example. Unless you use an eDSL, you’ll have to write similar a new query from scratch.
I have not yet tested this but I think this approach is great. Everyone needs to know SQL anyway. SQL can do a lot so any approach of creating a DSL for it will naturally lead to a complicated DSL. I’ve been using Beam and I’m impressed by the library, but I will test this approach for my next project.
Not sure how much safety you’re looking for, but my StringInterpolation proposal would support this easily. You’d just allow SqlQuery to be interpolated verbatim.
Writer actually helped me out a lot with SQL (and may have been the only clear win I’ve had with Writer). I wanted to build some really gnarly CTEs and get some actual reuse out of them without having to chase my tail keeping them in order. Writer (NonEmpty CTE) CTE did some work on my behalf.
ah sure, you mean, could sqlc statically analyze the SQL fragments that are dynamically combined? Theoretically, sure, if sqlc can parse/generate a WHERE clause on its own it can theoretically check that “where clause on column FOO” fits in a hole inside a query with a FOO column in scope. But yeah, idk if sqlc would support that out of the box