-- | Coverage for 'Pqi.resultErrorField': the structured fields carried by
-- a wire error response — SQLSTATE, severity, primary message, detail, hint,
-- positions, internal query, context, and source location.
--
-- These all come from the wire error response and are compared in full
-- (via 'Pqi.Conformance.Observation.observeResult', which captures every
-- 'Pqi.FieldCode').
module Pqi.Conformance.Operation.ResultErrorField
  ( spec,
  )
where

import qualified Pqi
import Pqi.Conformance.Harness
import Pqi.Conformance.Prelude
import Pqi.Conformance.Scenario (execAllScenario, execScenario)
import Test.Hspec

spec :: Pqi.Adapter -> SpecWith ByteString
spec :: Adapter -> SpecWith ByteString
spec Adapter
adapter =
  [Char] -> SpecWith ByteString -> SpecWith ByteString
forall a. HasCallStack => [Char] -> SpecWith a -> SpecWith a
describe [Char]
"resultErrorField" do
    let forCase :: [Char] -> ByteString -> SpecWith (Arg (ByteString -> IO ()))
forCase [Char]
title ByteString
sql =
          [Char]
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
[Char] -> a -> SpecWith (Arg a)
it [Char]
title \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 -> Connection -> IO (Maybe ResultObservation)
execScenario ByteString
sql)
    [Char] -> ByteString -> SpecWith (Arg (ByteString -> IO ()))
forCase [Char]
"syntax error" ByteString
"selct 1"
    [Char] -> ByteString -> SpecWith (Arg (ByteString -> IO ()))
forCase [Char]
"undefined table" ByteString
"select * from pqi_no_such_table"
    [Char] -> ByteString -> SpecWith (Arg (ByteString -> IO ()))
forCase [Char]
"undefined column" ByteString
"select no_such_column from (select 1) as t"
    [Char] -> ByteString -> SpecWith (Arg (ByteString -> IO ()))
forCase [Char]
"division by zero" ByteString
"select 1 / 0"
    [Char] -> ByteString -> SpecWith (Arg (ByteString -> IO ()))
forCase [Char]
"statement position past a prefix" ByteString
"select 1 where tlse"
    [Char] -> ByteString -> SpecWith (Arg (ByteString -> IO ()))
forCase
      [Char]
"detail, hint, and a custom errcode"
      ByteString
"do $$ begin raise exception 'boom' using detail = 'the detail', hint = 'the hint', errcode = 'P0123'; end $$"
    [Char] -> ByteString -> SpecWith (Arg (ByteString -> IO ()))
forCase [Char]
"internal query and position" ByteString
"do $$ begin execute 'selct 1'; end $$"
    [Char] -> ByteString -> SpecWith (Arg (ByteString -> IO ()))
forCase [Char]
"value too long" ByteString
"select 'abc' :: varchar(2)"

    [Char]
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
[Char] -> a -> SpecWith (Arg a)
it [Char]
"constraint violations" \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] -> Connection -> IO [Maybe ResultObservation]
execAllScenario
          [ ByteString
"create temporary table conformance_errors (id int4 primary key, label text not null)",
            ByteString
"insert into conformance_errors values (1, 'a')",
            ByteString
"insert into conformance_errors values (1, 'b')",
            ByteString
"insert into conformance_errors values (2, null)"
          ]

    [Char]
-> (ByteString -> IO ()) -> SpecWith (Arg (ByteString -> IO ()))
forall a.
(HasCallStack, Example a) =>
[Char] -> a -> SpecWith (Arg a)
it [Char]
"a failed transaction block rejects further commands" \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] -> Connection -> IO [Maybe ResultObservation]
execAllScenario [ByteString
"begin", ByteString
"select 1 / 0", ByteString
"select 1", ByteString
"rollback", ByteString
"select 1"]