# opium > An opionated Haskell Postgres library. ## Quick Start We assume that our database contains this table: ```sql 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: ```haskell {-# 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 [Users]) getUsers conn = Opium.fetch_ conn "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: ```haskell 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 [x] <- Opium.fetch_ conn query pure x ``` ## TO DO - [x] Implement `String` and `Text` decoding - [x] Implement `Int` decoding - [x] Implement error reporting i.e. use `Either OpiumError` instead of `Maybe` - [x] Implement `Float` and `Double` decoding - [x] Clean up and document column table stuff - [ ] Implement `fetch` (`fetch_` but with parameter passing) - [ ] Implement `UTCTime` and zoned time decoding - [ ] Implement JSON decoding - [ ] Implement `ByteString` decoding (`bytea`) - Can we make the fromField instance choose whether it wants binary or text? - [ ] Implement (anonymous) composite types - It seems that in order to decode these, we'd need to use binary mode. In order to avoid writing everything twice it would be wise to move the whole `FromField` machinery to decoding from binary first