| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Hasql.Statement
Contents
Synopsis
- data Statement params result
- preparable :: Text -> Params params -> Result result -> Statement params result
- unpreparable :: Text -> Params params -> Result result -> Statement params result
- refineResult :: (a -> Either Text b) -> Statement params a -> Statement params b
- toSql :: Statement params result -> Text
Documentation
data Statement params result Source #
Specification of a strictly single-statement query, which can be parameterized and prepared. It encapsulates the mapping of parameters and results in association with an SQL template.
Following is an example of a declaration of a prepared statement with its associated codecs.
selectSum ::Statement(Int64, Int64) Int64 selectSum =preparablesql encoder decoder where sql = "select ($1 + $2)" encoder = (fst>$<Encoders.param(Encoders.nonNullableEncoders.int8))<>(snd>$<Encoders.param(Encoders.nonNullableEncoders.int8)) decoder = Decoders.singleRow(Decoders.column(Decoders.nonNullableDecoders.int8))
The statement above accepts a product of two parameters of type Int64
and produces a single result of type Int64.
Instances
| Profunctor Statement Source # | |
Defined in Hasql.Engine.Statement Methods dimap :: (a -> b) -> (c -> d) -> Statement b c -> Statement a d Source # lmap :: (a -> b) -> Statement b c -> Statement a c Source # rmap :: (b -> c) -> Statement a b -> Statement a c Source # (#.) :: forall a b c q. Coercible c b => q b c -> Statement a b -> Statement a c Source # (.#) :: forall a b c q. Coercible b a => Statement b c -> q a b -> Statement a c Source # | |
| Functor (Statement params) Source # | |
| Filterable (Statement params) Source # | |
Defined in Hasql.Engine.Statement | |
Arguments
| :: Text | SQL template with parameters in positional notation ( |
| -> Params params | Parameters encoder |
| -> Result result | Result decoder |
| -> Statement params result |
Construct a preparable statement.
Use this for statements that will be executed multiple times with different parameters. Preparable statements are cached by PostgreSQL, which avoids reconstructing the execution plan each time.
Suitable for applications with a limited amount of queries that don't generate SQL dynamically.
Arguments
| :: Text | SQL template with parameters in positional notation ( |
| -> Params params | Parameters encoder |
| -> Result result | Result decoder |
| -> Statement params result |
Construct an unpreparable statement.
Use this for statements that are dynamically generated or executed only once. Unpreparable statements are not cached by PostgreSQL.
Suitable for dynamic SQL or one-off queries.
refineResult :: (a -> Either Text b) -> Statement params a -> Statement params b Source #
Refine the result of a statement,
causing the running session to fail with the UnexpectedResultStatementError error in case of a refinement failure.
This function is especially useful for refining the results of statements produced with the "hasql-th" library.
Recipes
Insert many
Starting from PostgreSQL 9.4 there is an unnest function which we can use in an analogous way
to haskell's zip to pass in multiple arrays of values
to be zipped into the rows to insert as in the following example:
insertMultipleLocations ::Statement(Vector (UUID, Double, Double)) () insertMultipleLocations =preparablesql encoder decoder where sql = "insert into location (id, x, y) select * from unnest ($1, $2, $3)" encoder = Data.Vector.unzip3>$<Contravariant.Extras.contrazip3 (Encoders.param$ Encoders.nonNullable$ Encoders.foldableArray$ Encoders.nonNullableEncoders.uuid) (Encoders.param$ Encoders.nonNullable$ Encoders.foldableArray$ Encoders.nonNullableEncoders.float8) (Encoders.param$ Encoders.nonNullable$ Encoders.foldableArray$ Encoders.nonNullableEncoders.float8) decoder = Decoders.noResult
While this approach is much more efficient than executing a single-row insert-statement multiple times from within Session, a comparable performance can also be achieved by executing a single-insert statement from within a Pipeline.
IN and NOT IN
There is a common misconception that PostgreSQL supports array
as the parameter for the IN operator.
However Postgres only supports a syntactical list of values with it,
i.e., you have to specify each option as an individual parameter.
E.g., some_expression IN ($1, $2, $3).
Fortunately, Postgres does provide the expected functionality for arrays with other operators:
- Use
some_expression = ANY($1)instead ofsome_expression IN ($1) - Use
some_expression <> ALL($1)instead ofsome_expression NOT IN ($1)
For details refer to the PostgreSQL docs.