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