u/mzabani

▲ 20 r/haskell

[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.

reddit.com
u/mzabani — 8 hours ago