packages feed

hasql-1.9.3.2: hspec/Hasql/SessionSpec.hs

module Hasql.SessionSpec (spec) where

import Contravariant.Extras
import Hasql.Decoders qualified as Decoders
import Hasql.Encoders qualified as Encoders
import Hasql.Session qualified as Session
import Hasql.Statement qualified as Statement
import Hasql.TestingKit.Testcontainers qualified as Testcontainers
import Test.Hspec
import Test.QuickCheck.Instances ()
import Prelude

spec :: Spec
spec = aroundAll Testcontainers.withConnection do
  describe "Basic Session Operations" do
    describe "Roundtrips" do
      it "handles simple values correctly" \connection -> do
        let statement =
              Statement.Statement
                "select $1"
                (Encoders.param (Encoders.nonNullable Encoders.int8))
                (Decoders.singleRow (Decoders.column (Decoders.nonNullable Decoders.int8)))
                True
        result <- Session.run (Session.statement (42 :: Int64) statement) connection
        result `shouldBe` Right 42

    describe "Error Handling" do
      it "captures query errors correctly" \connection -> do
        let statement =
              Statement.Statement
                "select true where 1 = any ($1) and $2"
                ( contrazip2
                    (Encoders.param (Encoders.nonNullable (Encoders.array (Encoders.dimension foldl' (Encoders.element (Encoders.nonNullable Encoders.int8))))))
                    (Encoders.param (Encoders.nonNullable Encoders.text))
                )
                (fmap (maybe False (const True)) (Decoders.rowMaybe (Decoders.column (Decoders.nonNullable Decoders.bool))))
                True
        result <- Session.run (Session.statement ([3, 7] :: [Int64], "a") statement) connection
        case result of
          Left (Session.QueryError "select true where 1 = any ($1) and $2" ["[3, 7]", "\"a\""] _) -> pure ()
          _ -> expectationFailure $ "Unexpected result: " <> show result

    describe "IN simulation" do
      it "works with arrays" \connection -> do
        let statement =
              Statement.Statement
                "select true where 1 = any ($1)"
                (Encoders.param (Encoders.nonNullable (Encoders.array (Encoders.dimension foldl' (Encoders.element (Encoders.nonNullable Encoders.int8))))))
                (fmap (maybe False (const True)) (Decoders.rowMaybe (Decoders.column (Decoders.nonNullable Decoders.bool))))
                True
        result <-
          Session.run
            ( do
                result1 <- Session.statement ([1, 2] :: [Int64]) statement
                result2 <- Session.statement ([2, 3] :: [Int64]) statement
                return (result1, result2)
            )
            connection
        result `shouldBe` Right (True, False)

    describe "NOT IN simulation" do
      it "works with arrays" \connection -> do
        let statement =
              Statement.Statement
                "select true where 3 <> all ($1)"
                (Encoders.param (Encoders.nonNullable (Encoders.array (Encoders.dimension foldl' (Encoders.element (Encoders.nonNullable Encoders.int8))))))
                (fmap (maybe False (const True)) (Decoders.rowMaybe (Decoders.column (Decoders.nonNullable Decoders.bool))))
                True
        result <-
          Session.run
            ( do
                result1 <- Session.statement ([1, 2] :: [Int64]) statement
                result2 <- Session.statement ([2, 3] :: [Int64]) statement
                return (result1, result2)
            )
            connection
        result `shouldBe` Right (True, False)