packages feed

hasql-dynamic-statements-0.3.1.6: test/Main.hs

module Main where

import Data.ByteString qualified as ByteString
import Data.ByteString.Char8 qualified as ByteStringChar8
import Hasql.Connection qualified as Connection
import Hasql.Decoders qualified as Decoders
import Hasql.DynamicStatements.Session qualified as Session
import Hasql.DynamicStatements.Snippet qualified as Snippet
import Hasql.DynamicStatements.Statement qualified as Statement
import Hasql.Session qualified as Session
import Hasql.Statement qualified as Statement
import Test.Tasty
import Test.Tasty.HUnit
import Prelude hiding (assert)

main :: IO ()
main =
  defaultMain tree

tree :: TestTree
tree =
  testGroup
    "All tests"
    [ testCase "Select substring"
        $ let sample string from to =
                let snippet =
                      "select substring("
                        <> Snippet.param @Text string
                        <> foldMap (mappend " from " . Snippet.param @Int32) from
                        <> foldMap (mappend " for " . Snippet.param @Int32) to
                        <> ")"
                    decoder = Decoders.singleRow (Decoders.column (Decoders.nonNullable Decoders.text))
                 in runSession (Session.dynamicallyParameterizedStatement snippet decoder True)
           in do
                assertEqual "" (Right (Right "bc")) =<< sample "abcd" (Just 2) (Just 2)
                assertEqual "" (Right (Right "bcd")) =<< sample "abcd" (Just 2) (Just 3)
                assertEqual "" (Right (Right "abc")) =<< sample "abcd" Nothing (Just 3)
                assertEqual "" (Right (Right "bcd")) =<< sample "abcd" (Just 2) Nothing,
      testGroup
        "Regression"
        [ testCase "Missing $ for 1000th parameter string #2"
            $ let snippet =
                    "SELECT 1 " <> (foldMap @[] ("," <>) $ replicate 1001 $ Snippet.param (10 :: Int64))
                  statement =
                    Statement.dynamicallyParameterized snippet Decoders.noResult True
                  sql =
                    case statement of
                      Statement.Statement x _ _ _ -> x
               in do
                    assertBool (ByteStringChar8.unpack sql) (ByteString.isInfixOf "$1000" sql)
        ]
    ]

runSession :: Session.Session a -> IO (Either Connection.ConnectionError (Either Session.SessionError a))
runSession = withConnection . Session.run

withConnection :: (Connection.Connection -> IO a) -> IO (Either Connection.ConnectionError a)
withConnection handler =
  runExceptT $ acquire >>= \connection -> use connection <* release connection
  where
    acquire =
      ExceptT $ Connection.acquire settings
      where
        settings =
          Connection.settings host port user password database
          where
            host = "localhost"
            port = 5432
            user = "postgres"
            password = "postgres"
            database = "postgres"
    use connection =
      lift $ handler connection
    release connection =
      lift $ Connection.release connection