hasql-dynamic-statements-0.3.1: Toolkit for constructing Hasql statements dynamically

Safe HaskellNone
LanguageHaskell2010

Hasql.DynamicStatements.Statement

Synopsis

Documentation

dynamicallyParameterized :: Snippet -> Result result -> Bool -> Statement () result Source #

Construct a statement dynamically, specifying the parameters in-place in the declaration of snippet and providing a result decoder and specifying whether the statement should be prepared.

The injection of the parameters is handled automatically, generating parametric statements with binary encoders under the hood.

This is useful when the SQL of your statement depends on the parameters. Here's an example:

selectSubstring :: Text -> Maybe Int32 -> Maybe Int32 -> Statement () Text
selectSubstring string from to = let
  snippet =
    "select substring(" <> Snippet.param string <>
    foldMap (mappend " from " . Snippet.param) from <>
    foldMap (mappend " for " . Snippet.param) to <>
    ")"
  decoder = Decoders.singleRow (Decoders.column (Decoders.nonNullable Decoders.text))
  in dynamicallyParameterized snippet decoder True

Without the Snippet API you would have had to implement the same functionality thus:

selectSubstring' :: Text -> Maybe Int32 -> Maybe Int32 -> Statement () Text
selectSubstring' string from to = let
  sql = case (from, to) of
    (Just _, Just _) -> "select substring($1 from $2 to $3)"
    (Just _, Nothing) -> "select substring($1 from $2)"
    (Nothing, Just _) -> "select substring($1 to $2)"
    (Nothing, Nothing) -> "select substring($1)"
  encoder = 
    Encoders.param (string >$ Encoders.text) <>
    foldMap (\ x -> Encoders.param (x >$ Encoders.int8)) from <>
    foldMap (\ x -> Encoders.param (x >$ Encoders.int8)) to
  decoder = Decoders.singleRow (Decoders.column Decoders.text)
  in Statement sql encoder decoder True

As you can see, the Snippet API abstracts over placeholders and matching encoder generation, thus also protecting you from all sorts of related bugs.