-- | Coverage for 'Pqi.execParams': the extended query protocol over
-- parameter formats, result formats, inferred types, nulls, and its error
-- paths.
module Pqi.Conformance.Operation.ExecParams
  ( spec,
  )
where

import qualified Pqi as Lq
import Pqi.Conformance.Harness
import Pqi.Conformance.Observation
import Pqi.Conformance.Prelude
import Pqi.Conformance.Scenario
import Test.Hspec

spec :: Lq.Adapter -> SpecWith ByteString
spec :: Adapter -> SpecWith ByteString
spec Adapter
adapter =
  String -> SpecWith ByteString -> SpecWith ByteString
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"execParams" do
    String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"text result format" \ByteString
conninfo ->
      Adapter
-> ByteString
-> (Connection -> IO (Maybe ResultObservation))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo (Format -> Connection -> IO (Maybe ResultObservation)
paramsScenario Format
Lq.Text)
    String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"binary result format" \ByteString
conninfo ->
      Adapter
-> ByteString
-> (Connection -> IO (Maybe ResultObservation))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo (Format -> Connection -> IO (Maybe ResultObservation)
paramsScenario Format
Lq.Binary)
    String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"null parameter" \ByteString
conninfo ->
      Adapter
-> ByteString
-> (Connection -> IO (Maybe ResultObservation))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo (ByteString
-> [Maybe (Word32, ByteString, Format)]
-> Format
-> Connection
-> IO (Maybe ResultObservation)
observed ByteString
"select $1 :: int4 as maybe_value" [Maybe (Word32, ByteString, Format)
forall a. Maybe a
Nothing] Format
Lq.Text)
    String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"no parameters" \ByteString
conninfo ->
      Adapter
-> ByteString
-> (Connection -> IO (Maybe ResultObservation))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo (ByteString
-> [Maybe (Word32, ByteString, Format)]
-> Format
-> Connection
-> IO (Maybe ResultObservation)
observed ByteString
"select 'none' :: text" [] Format
Lq.Text)
    String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"binary parameter" \ByteString
conninfo ->
      Adapter
-> ByteString
-> (Connection -> IO (Maybe ResultObservation))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo
        ((Connection -> IO (Maybe ResultObservation)) -> IO ())
-> (Connection -> IO (Maybe ResultObservation)) -> IO ()
forall a b. (a -> b) -> a -> b
$ ByteString
-> [Maybe (Word32, ByteString, Format)]
-> Format
-> Connection
-> IO (Maybe ResultObservation)
observed ByteString
"select $1 :: int4 * 2" [(Word32, ByteString, Format) -> Maybe (Word32, ByteString, Format)
forall a. a -> Maybe a
Just (Word32
int4Oid, ByteString
"\NUL\NUL\NUL*", Format
Lq.Binary)] Format
Lq.Text
    String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"binary bytea round-trip" \ByteString
conninfo ->
      Adapter
-> ByteString
-> (Connection -> IO (Maybe ResultObservation))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo
        ((Connection -> IO (Maybe ResultObservation)) -> IO ())
-> (Connection -> IO (Maybe ResultObservation)) -> IO ()
forall a b. (a -> b) -> a -> b
$ ByteString
-> [Maybe (Word32, ByteString, Format)]
-> Format
-> Connection
-> IO (Maybe ResultObservation)
observed ByteString
"select $1 :: bytea" [(Word32, ByteString, Format) -> Maybe (Word32, ByteString, Format)
forall a. a -> Maybe a
Just (Word32
byteaOid, ByteString
"\NUL\1\2\255", Format
Lq.Binary)] Format
Lq.Binary
    String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"inferred parameter type" \ByteString
conninfo ->
      Adapter
-> ByteString
-> (Connection -> IO (Maybe ResultObservation))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo
        ((Connection -> IO (Maybe ResultObservation)) -> IO ())
-> (Connection -> IO (Maybe ResultObservation)) -> IO ()
forall a b. (a -> b) -> a -> b
$ ByteString
-> [Maybe (Word32, ByteString, Format)]
-> Format
-> Connection
-> IO (Maybe ResultObservation)
observed ByteString
"select $1 :: int4 + 1" [(Word32, ByteString, Format) -> Maybe (Word32, ByteString, Format)
forall a. a -> Maybe a
Just (Word32
0, ByteString
"41", Format
Lq.Text)] Format
Lq.Text
    String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"empty string is not null" \ByteString
conninfo ->
      Adapter
-> ByteString
-> (Connection -> IO (Maybe ResultObservation))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo
        ((Connection -> IO (Maybe ResultObservation)) -> IO ())
-> (Connection -> IO (Maybe ResultObservation)) -> IO ()
forall a b. (a -> b) -> a -> b
$ ByteString
-> [Maybe (Word32, ByteString, Format)]
-> Format
-> Connection
-> IO (Maybe ResultObservation)
observed ByteString
"select $1 :: text, length ($1 :: text)" [(Word32, ByteString, Format) -> Maybe (Word32, ByteString, Format)
forall a. a -> Maybe a
Just (Word32
textOid, ByteString
"", Format
Lq.Text)] Format
Lq.Text
    String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"many mixed parameters" \ByteString
conninfo ->
      Adapter
-> ByteString
-> (Connection -> IO (Maybe ResultObservation))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo
        ((Connection -> IO (Maybe ResultObservation)) -> IO ())
-> (Connection -> IO (Maybe ResultObservation)) -> IO ()
forall a b. (a -> b) -> a -> b
$ ByteString
-> [Maybe (Word32, ByteString, Format)]
-> Format
-> Connection
-> IO (Maybe ResultObservation)
observed
          ByteString
"select $1 :: int8, $2 :: float8, $3 :: bool, $4 :: text, $5 :: int4, $6 :: text"
          [ (Word32, ByteString, Format) -> Maybe (Word32, ByteString, Format)
forall a. a -> Maybe a
Just (Word32
int8Oid, ByteString
"9000000000000000000", Format
Lq.Text),
            (Word32, ByteString, Format) -> Maybe (Word32, ByteString, Format)
forall a. a -> Maybe a
Just (Word32
float8Oid, ByteString
"2.5", Format
Lq.Text),
            (Word32, ByteString, Format) -> Maybe (Word32, ByteString, Format)
forall a. a -> Maybe a
Just (Word32
boolOid, ByteString
"t", Format
Lq.Text),
            Maybe (Word32, ByteString, Format)
forall a. Maybe a
Nothing,
            (Word32, ByteString, Format) -> Maybe (Word32, ByteString, Format)
forall a. a -> Maybe a
Just (Word32
int4Oid, ByteString
"-1", Format
Lq.Text),
            (Word32, ByteString, Format) -> Maybe (Word32, ByteString, Format)
forall a. a -> Maybe a
Just (Word32
textOid, ByteString
"héllo", Format
Lq.Text)
          ]
          Format
Lq.Text
    String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"DML with parameters" \ByteString
conninfo ->
      Adapter
-> ByteString
-> (Connection
    -> IO (Maybe ResultObservation, Maybe ResultObservation))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo \Connection
connection -> do
        _ <- Connection -> ByteString -> IO (Maybe Result)
Lq.exec Connection
connection ByteString
"create temporary table conformance_exec_params (id int4)"
        insert <-
          observed
            "insert into conformance_exec_params values ($1), ($2)"
            [Just (int4Oid, "1", Lq.Text), Just (int4Oid, "2", Lq.Text)]
            Lq.Text
            connection
        check <-
          observed
            "select count(*) from conformance_exec_params where id <= $1"
            [Just (int4Oid, "2", Lq.Text)]
            Lq.Text
            connection
        pure (insert, check)
    String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"too few parameters" \ByteString
conninfo ->
      Adapter
-> ByteString
-> (Connection -> IO (Maybe ResultObservation))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo
        ((Connection -> IO (Maybe ResultObservation)) -> IO ())
-> (Connection -> IO (Maybe ResultObservation)) -> IO ()
forall a b. (a -> b) -> a -> b
$ ByteString
-> [Maybe (Word32, ByteString, Format)]
-> Format
-> Connection
-> IO (Maybe ResultObservation)
observed ByteString
"select $1 :: int4 + $2 :: int4" [(Word32, ByteString, Format) -> Maybe (Word32, ByteString, Format)
forall a. a -> Maybe a
Just (Word32
int4Oid, ByteString
"1", Format
Lq.Text)] Format
Lq.Text
    String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"malformed parameter value" \ByteString
conninfo ->
      Adapter
-> ByteString
-> (Connection -> IO (Maybe ResultObservation))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo
        ((Connection -> IO (Maybe ResultObservation)) -> IO ())
-> (Connection -> IO (Maybe ResultObservation)) -> IO ()
forall a b. (a -> b) -> a -> b
$ ByteString
-> [Maybe (Word32, ByteString, Format)]
-> Format
-> Connection
-> IO (Maybe ResultObservation)
observed ByteString
"select $1 :: int4" [(Word32, ByteString, Format) -> Maybe (Word32, ByteString, Format)
forall a. a -> Maybe a
Just (Word32
int4Oid, ByteString
"not-a-number", Format
Lq.Text)] Format
Lq.Text
    String
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"multiple statements are rejected" \ByteString
conninfo ->
      Adapter
-> ByteString
-> (Connection -> IO (Maybe ResultObservation))
-> IO ()
forall a.
(Eq a, Show a, HasCallStack) =>
Adapter -> ByteString -> (Connection -> IO a) -> IO ()
differential Adapter
adapter ByteString
conninfo (ByteString
-> [Maybe (Word32, ByteString, Format)]
-> Format
-> Connection
-> IO (Maybe ResultObservation)
observed ByteString
"select 1; select 2" [] Format
Lq.Text)

paramsScenario :: Lq.Format -> Lq.Connection -> IO (Maybe ResultObservation)
paramsScenario :: Format -> Connection -> IO (Maybe ResultObservation)
paramsScenario Format
resultFormat =
  ByteString
-> [Maybe (Word32, ByteString, Format)]
-> Format
-> Connection
-> IO (Maybe ResultObservation)
observed
    ByteString
"select $1 :: int4 + $2 :: int4 as sum, $3 :: text as label"
    [ (Word32, ByteString, Format) -> Maybe (Word32, ByteString, Format)
forall a. a -> Maybe a
Just (Word32
int4Oid, ByteString
"40", Format
Lq.Text),
      (Word32, ByteString, Format) -> Maybe (Word32, ByteString, Format)
forall a. a -> Maybe a
Just (Word32
int4Oid, ByteString
"2", Format
Lq.Text),
      (Word32, ByteString, Format) -> Maybe (Word32, ByteString, Format)
forall a. a -> Maybe a
Just (Word32
textOid, ByteString
"hi", Format
Lq.Text)
    ]
    Format
resultFormat