[ANN] hpgsql, a pure Haskell PostgreSQL driver (no libpq)
It’s a pleasure to announce hpgsql, a PostgreSQL driver written in pure Haskell (no libpq), with an API largely inspired by the great postgresql-simple library, but featuring:
- Usage of PostgreSQL’s binary protocol
- Query arguments passed via the protocol instead of being escaped into the query string
- Pipelining
- Prepared statements
- Ability to stream query results directly from the socket (not just with cursors)
- Interruption safety, except for very specific (and documented) edge cases
- Thread safety, unless specific (and documented) instructions say otherwise
- A SQL quasiquoter like the one in postgresql-query and hasql-interpolate
Here’s an example of a pipeline mixing streams, prepared and non prepared statements:
f :: Int -> IO (Stream (Of Aeson.Value) IO ())
f val = do
(updateTbl :: IO (), aggRes :: IO (Only Int), largeResults) <-
runPipeline conn $
(,,)
<$> pipelineExec_ [sql|UPDATE tbl SET val=#{val}|]
<*> pipeline1 [sql|SELECT SUM(val) FROM tbl|]
<*> pipelineSWith
(rowDecoder @(Vector Int, Vector Text))
-- We use a prepared statement for the query below
[sqlPrep|SELECT x, y FROM tbl|]
updateTbl
Only total <- aggRes
Streaming.map Aeson.toJSON <$> largeResults
Also, I am maintaining hpgsql-simple-compat, a fork of postgresql-simple that preserves its API as much as I could make it, but with internals rewritten to use hpgsql. The idea is to provide a simpler migration path from postgresql-simple; one that allows a smaller initial changeset and then the possibility of migrating queries to hpgsql one at a time. I have even migrated a CLI tool of mine, codd, as an example.
hpgsql-simple-compat is not in Hackage as I wasn’t sure duplicating the search space with modules, types, and functions already in postgresql-simple would annoy users. It’s in the “hpgsql-simple-compat” folder in the repository.
Some initial benchmarks show hpgsql can materialize rows from a query in ~38% the time postgresql-simple takes, and ~70% the time hasql takes (on my computer, Linux x64, GHC 9.10.3, compiled with -O1). Peak memory usage is trickier to analyze, and I therefore welcome people that know more to read the benchmarks page and help me better understand them. Also, please scrutinize these benchmarks as much as you can.
I want to encourage and welcome contributions, bug reports, questions, suggestions. Nothing’s off the table: what would you want or what do you need from such a library?
I really want to hear from the community, both those eager to switch and potential future users.
- Link to the repository: GitHub - mzabani/hpgsql: A pure Haskell (no libpq) postgresql driver that draws inspiration from postgresql-simple, has streaming built into its core, speaks postgresql's binary protocol, has pipelining, interruption safety, and (reasonable) thread safety. · GitHub (contains both hpgsql and hpgsql-simple-compat)
- Link to hackage: https://hackage.haskell.org/package/hpgsql