module Main where
import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Char8 as ByteStringChar8
import qualified Hasql.Connection as Connection
import qualified Hasql.Decoders as Decoders
import qualified Hasql.DynamicStatements.Session as Session
import qualified Hasql.DynamicStatements.Snippet as Snippet
import qualified Hasql.DynamicStatements.Statement as Statement
import qualified Hasql.Encoders as Encoders
import qualified Hasql.Session as Session
import qualified Hasql.Statement as Statement
import qualified Test.QuickCheck as QuickCheck
import Test.QuickCheck.Instances
import Test.Tasty
import Test.Tasty.HUnit
import Test.Tasty.QuickCheck
import Test.Tasty.Runners
import Prelude hiding (assert)
main =
defaultMain tree
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.QueryError 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