| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Hpgsql
Contents
Description
Hpgsql is a PostgreSQL driver written entirely in Haskell, with no bindings to libpq.
It communicates with the database using the PostgreSQL wire protocol directly.
Quick start
Connect to the database and run a simple query:
{-# LANGUAGE QuasiQuotes #-}
import Hpgsql
import Hpgsql.Connection (withConnection, ConnectionString(..))
import Hpgsql.Query (sql)
main :: IO ()
main = do
let connstr = ConnectionString
{ hostname = "localhost"
, port = 5432
, user = "postgres"
, password = ""
, database = "mydb"
, options = ""
}
-- Connect with a 10-second timeout
withConnection connstr 10 $ \conn -> do
rows <- query conn [sql|SELECT 1 + 1|]
print (rows :: [Only Int])
-- [Only {fromOnly = 2}]Building queries
Use the [sql|...|] quasiquoter from Hpgsql.Query to build queries. Interpolate Haskell
values with #{}:
let name = "Alice" :: Text
rows <- query conn [sql|SELECT id, email FROM users WHERE name = #{name}|]
print (rows :: [(Int, Text)])Values interpolated with #{} are sent as query parameters, so they are safe from SQL injection.
To embed a Query fragment (e.g. an identifier or a sub-query), use ^{}:
let tableName = escapeIdentifier "users"
rows <- query conn [sql|SELECT * FROM ^{tableName}|]You can also use mkQuery with dollar-numbered query arguments:
query conn (mkQuery "SELECT * FROM users WHERE age BETWEEN $1 AND $2" (18 :: Int, 60 :: Int))
And finally, you can use the [sqlPrep|...|] quasiquoter to build prepared statements.
Fetching results
queryreturns all rows as a list.querySreturns all rows as a Stream, streaming directly from the socket (without cursors).query1returns exactly one row, throwing if zero or more than one row is returned.queryMayreturns zero or one row, throwing if more than one is returned.executeruns a statement and returns the count of affected rows.execute_runs a statement and discards the result.
All these methods have equivalents in Hpgsql.Pipeline that can be composed together to reduce the number of round-trips.
Encoders and decoders
To define your own encoder and decoder instances, take a look at Hpgsql.Encoding.
Handling errors
- Hpgsql is interruption-safe (with one exception for COPY inside transactions; see Hpgsql.Copy), so a query can be interrupted by asynchronous exceptions and you should still be able to run new queries on the same connection without any other side-effects. Naturally, it is up to you to determine which queries ran or not to completion, since they might have side-effects.
- Hpgsql will throw either
PostgresErrororIrrecoverableHpgsqlError, and: - If you receive a
IrrecoverableHpgsqlError, Hpgsql makes no promises about which statements ran to completion and what connection state is, and you shouldcloseForcefullythe connection without running any other queries. These errors should only be thrown for "obvious" developer mistakes from which usually there would be no way to proceed, anyway. - If you receive a
PostgresErrorexception, postgres and Hpgsql's states are synced and you can issue new queries afterwards.
What's in this module
This module re-exports some of the essentials: querying and the core types. We recommend importing from this module instead of others whenever possible. For more functionality, see:
- Hpgsql.Connection for connecting and connection state resetting.
- Hpgsql.Copy for
COPYprotocol support. - Hpgsql.Pipeline for building pipelines of queries.
- Hpgsql.Query for the
sqlandsqlPrepquasiquoters, and query-building helpers. - Hpgsql.Transaction for transaction management.
- Hpgsql.Types for extra types that might be useful.
- Hpgsql.Cancellation for cancelling active queries.
Synopsis
- query :: FromPgRow a => HPgConnection -> Query -> IO [a]
- queryWith :: RowDecoder a -> HPgConnection -> Query -> IO [a]
- queryMWith :: RowDecoderMonadic a -> HPgConnection -> Query -> IO [a]
- queryS :: FromPgRow a => HPgConnection -> Query -> IO (Stream (Of a) IO ())
- querySWith :: RowDecoder a -> HPgConnection -> Query -> IO (Stream (Of a) IO ())
- querySMWith :: RowDecoderMonadic a -> HPgConnection -> Query -> IO (Stream (Of a) IO ())
- query1 :: FromPgRow a => HPgConnection -> Query -> IO a
- query1With :: RowDecoder a -> HPgConnection -> Query -> IO a
- queryMay :: FromPgRow a => HPgConnection -> Query -> IO (Maybe a)
- queryMayWith :: RowDecoder a -> HPgConnection -> Query -> IO (Maybe a)
- execute :: HPgConnection -> Query -> IO Int64
- execute_ :: HPgConnection -> Query -> IO ()
- data HPgConnection
- data PostgresError = PostgresError {}
- data IrrecoverableHpgsqlError = IrrecoverableHpgsqlError {}
- data ErrorDetail
Query
query :: FromPgRow a => HPgConnection -> Query -> IO [a] Source #
Fetches any number of rows from a query.
query conn "SELECT * FROM table"
queryWith :: RowDecoder a -> HPgConnection -> Query -> IO [a] Source #
Fetches any number of rows from a query with a custom row decoder.
queryWith rowDecoder conn "SELECT * FROM table"
queryMWith :: RowDecoderMonadic a -> HPgConnection -> Query -> IO [a] Source #
Prefer to use query and queryWith, because RowDecoder can typecheck PostgreSQL results
even when no rows are returned by queries, and RowDecoderMonadic cannot.
queryS :: FromPgRow a => HPgConnection -> Query -> IO (Stream (Of a) IO ()) Source #
Runs a query and streams results directly from the connection's socket, i.e. without using cursors.
Note on thread safety: it is important to note the same thread that runs this must be the thread that consumes the returned Stream, and the returned Stream must be consumed completely (up to the last row or a postgres error) before you are able to run other queries.
querySWith :: RowDecoder a -> HPgConnection -> Query -> IO (Stream (Of a) IO ()) Source #
Runs a query and streams results directly from the connection's socket, i.e. without using cursors.
Note on thread safety: it is important to note the same thread that runs this must be the thread that consumes the returned Stream, and the returned Stream must be consumed completely (up to the last row or a postgres error) before you are able to run other queries.
querySMWith :: RowDecoderMonadic a -> HPgConnection -> Query -> IO (Stream (Of a) IO ()) Source #
Runs a query and streams results directly from the connection's socket, i.e. without using cursors.
Prefer to use queryS and querySWith, because RowDecoder can typecheck PostgreSQL results
even when no rows are returned by queries, and RowDecoderMonadic cannot.
Note on thread safety: it is important to note the same thread that runs this must be the thread that consumes the returned Stream, and the returned Stream must be consumed completely (up to the last row or a postgres error) before you are able to run other queries.
query1 :: FromPgRow a => HPgConnection -> Query -> IO a Source #
Fetch exactly one row (not zero, not more than one) or throw an exception otherwise.
query1With :: RowDecoder a -> HPgConnection -> Query -> IO a Source #
Fetch exactly one row (not zero, not more than one) or throw an exception otherwise.
queryMay :: FromPgRow a => HPgConnection -> Query -> IO (Maybe a) Source #
Fetch one or zero rows (not more than one) or throw an exception otherwise.
queryMayWith :: RowDecoder a -> HPgConnection -> Query -> IO (Maybe a) Source #
Fetch one or zero rows (not more than one) or throw an exception otherwise.
execute :: HPgConnection -> Query -> IO Int64 Source #
Executes a SQL statement (that may or may not be row-returning) and returns the count of affected rows of the given query.
execute_ :: HPgConnection -> Query -> IO () Source #
Executes a SQL statement that may or may not be row-returning.
Useful re-exports
data HPgConnection Source #
Instances
| Eq HPgConnection Source # | |
Defined in Hpgsql.InternalTypes Methods (==) :: HPgConnection -> HPgConnection -> Bool # (/=) :: HPgConnection -> HPgConnection -> Bool # | |
data PostgresError Source #
An error coming from PostgreSQL. You can safely handle this and continue using the connection.
Constructors
| PostgresError | |
Fields | |
Instances
| Exception PostgresError Source # | |
Defined in Hpgsql.InternalTypes Methods toException :: PostgresError -> SomeException # fromException :: SomeException -> Maybe PostgresError # displayException :: PostgresError -> String # backtraceDesired :: PostgresError -> Bool # | |
| Show PostgresError Source # | |
Defined in Hpgsql.InternalTypes Methods showsPrec :: Int -> PostgresError -> ShowS # show :: PostgresError -> String # showList :: [PostgresError] -> ShowS # | |
data IrrecoverableHpgsqlError Source #
If you receive this exception, don't run any further SQL statements or use it for anything. Just close the connection with closeForcefully and discard it.
Constructors
| IrrecoverableHpgsqlError | |
Fields | |
Instances
| Exception IrrecoverableHpgsqlError Source # | |
Defined in Hpgsql.InternalTypes | |
| Show IrrecoverableHpgsqlError Source # | |
Defined in Hpgsql.InternalTypes Methods showsPrec :: Int -> IrrecoverableHpgsqlError -> ShowS # show :: IrrecoverableHpgsqlError -> String # showList :: [IrrecoverableHpgsqlError] -> ShowS # | |
data ErrorDetail Source #
Constructors
Instances
| Show ErrorDetail Source # | |
Defined in Hpgsql.InternalTypes Methods showsPrec :: Int -> ErrorDetail -> ShowS # show :: ErrorDetail -> String # showList :: [ErrorDetail] -> ShowS # | |
| Eq ErrorDetail Source # | |
Defined in Hpgsql.InternalTypes | |
| Ord ErrorDetail Source # | |
Defined in Hpgsql.InternalTypes Methods compare :: ErrorDetail -> ErrorDetail -> Ordering # (<) :: ErrorDetail -> ErrorDetail -> Bool # (<=) :: ErrorDetail -> ErrorDetail -> Bool # (>) :: ErrorDetail -> ErrorDetail -> Bool # (>=) :: ErrorDetail -> ErrorDetail -> Bool # max :: ErrorDetail -> ErrorDetail -> ErrorDetail # min :: ErrorDetail -> ErrorDetail -> ErrorDetail # | |