opium
An opionated Haskell Postgres library.
Quick Start
We assume that our database contains this table:
CREATE TABLE person (
name TEXT NOT NULL,
age INT NOT NULL,
score DOUBLE PRECISION NOT NULL,
motto TEXT
)
We can use opium
to decode query results into Haskell data types:
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
import GHC.Generics (Generic)
import Database.PostgreSQL.LibPQ (Connection)
import qualified Database.PostgreSQL.Opium as Opium
data User = User
{ name :: String
, age :: Int
, score :: Double
} deriving (Eq, Generic, Show)
instance Opium.FromRow User where
getUsers :: Connection -> IO (Either Opium.Error [User])
getUsers = Opium.fetch_ "SELECT * FROM user"
The Opium.FromRow
instance is implemented generically for all product types ("records"). It looks up the field name in the query result and decodes the column value using Opium.FromField
.
The intended use case for this library is to enable us to write ad-hoc types for query results without having to manually write instances. For example, if we wanted to figure out how user age influences their score:
data ScoreByAge = ScoreByAge { t :: Double, m :: Double }
deriving (Eq, Generic, Show)
instance Opium.FromRow ScoreByAge where
getScoreByAge :: Connection -> IO ScoreByAge
getScoreByAge conn = do
let query = "SELECT regr_intercept(score, age) AS t, regr_slope(score, age) AS m FROM user"
Right (Identity x) <- Opium.fetch_ query conn
pure x
TO DO
- Implement
String
andText
decoding - Implement
Int
decoding - Implement error reporting i.e. use
Either OpiumError
instead ofMaybe
- Implement
Float
andDouble
decoding - Clean up and document column table stuff
- Decode
LibPQ.Binary
- Implement
date -> Day
decoding - Implement
UTCTime
- Implement
ByteString
decoding (bytea
) - Test negative integer decoding, especially for
Integer
- Implement time intervals
- and zoned time decoding
- How about
timezone
? This could prove problematic when the server and application have different time zones - Implement
fetch
(fetch_
but with parameter passing) - Implement JSON decoding
- Implement (anonymous) composite types
- Catch UnicodeException when decoding text
- This might not be necessary if Postgres guarantees us that having a textual OID on a field means that the field is encoded correctly.
- Implement array decoding
- Better docs and structure for
FromRow
module - Lexer for PostgreSQL that replaces $name by $1, $2, etc.
- Tutorial
- Rationale
FromRow
- Custom
FromField
impls
- Improve type errors when trying to
instance
a type that isn't a record (e.g. sum type) - Improve documentation for
fromRow
module
Description
Languages
Haskell
96.2%
Shell
2.2%
Nix
1.6%