packages feed

hasql-check 0.5.1.0 → 0.5.2.0

raw patch · 5 files changed

+49/−5 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Hasql.Check.Finding: instance GHC.Classes.Eq Hasql.Check.Finding.Rule
- Hasql.Check.Finding: instance GHC.Classes.Ord Hasql.Check.Finding.Rule
- Hasql.Check.Inferred: instance GHC.Classes.Eq Hasql.Check.Inferred.Piece
- Hasql.Check.Inferred: instance GHC.Classes.Eq Hasql.Check.Inferred.Template
- Hasql.Check.Inferred: instance GHC.Classes.Eq Hasql.Check.Inferred.Wrapped
- Hasql.Check.Inferred: instance Hasql.Check.Inferred.Value GHC.Types.Bool
- Hasql.Check.Inferred: instance Hasql.Check.Inferred.Value GHC.Types.Double
- Hasql.Check.Inferred: instance Hasql.Check.Inferred.Value GHC.Types.Float
- Hasql.Check.Inferred.TH: instance GHC.Classes.Eq Hasql.Check.Inferred.TH.Parsed
- Hasql.Check.Inferred.TH: instance GHC.Classes.Eq Hasql.Check.Inferred.TH.Slot
- Hasql.Check.Inferred.TH: instance GHC.Classes.Eq Hasql.Check.Inferred.TH.Tgt
- Hasql.Check.Lexer: instance GHC.Classes.Eq Hasql.Check.Lexer.AlexPosn
- Hasql.Check.Lexer: instance GHC.Classes.Eq Hasql.Check.Lexer.Lexeme
- Hasql.Check.Lexer: instance GHC.Classes.Eq Hasql.Check.Lexer.LexemeClass
- Hasql.Check.Lexer: instance GHC.Classes.Ord Hasql.Check.Lexer.AlexPosn
- Hasql.Check.Parser: instance GHC.Classes.Eq Hasql.Check.Parser.QuasiQuote
+ Hasql.Check.Finding: instance GHC.Internal.Classes.Eq Hasql.Check.Finding.Rule
+ Hasql.Check.Finding: instance GHC.Internal.Classes.Ord Hasql.Check.Finding.Rule
+ Hasql.Check.Inferred: instance (s GHC.Internal.Types.~ Hasql.Check.Inferred.PgColumnType (GHC.Internal.Maybe.Maybe a), l GHC.Internal.Types.~ Hasql.Check.Inferred.PgColumnLabels (GHC.Internal.Maybe.Maybe a)) => Hasql.Check.Inferred.SlotType (GHC.Internal.Maybe.Maybe a) s l
+ Hasql.Check.Inferred: instance (s GHC.Internal.Types.~ Hasql.Check.Inferred.PgColumnType a, l GHC.Internal.Types.~ Hasql.Check.Inferred.PgColumnLabels a) => Hasql.Check.Inferred.SlotType a s l
+ Hasql.Check.Inferred: instance GHC.Internal.Classes.Eq Hasql.Check.Inferred.Piece
+ Hasql.Check.Inferred: instance GHC.Internal.Classes.Eq Hasql.Check.Inferred.Template
+ Hasql.Check.Inferred: instance GHC.Internal.Classes.Eq Hasql.Check.Inferred.Wrapped
+ Hasql.Check.Inferred: instance Hasql.Check.Inferred.Value GHC.Internal.Types.Bool
+ Hasql.Check.Inferred: instance Hasql.Check.Inferred.Value GHC.Internal.Types.Double
+ Hasql.Check.Inferred: instance Hasql.Check.Inferred.Value GHC.Internal.Types.Float
+ Hasql.Check.Inferred.TH: instance GHC.Internal.Classes.Eq Hasql.Check.Inferred.TH.Parsed
+ Hasql.Check.Inferred.TH: instance GHC.Internal.Classes.Eq Hasql.Check.Inferred.TH.Slot
+ Hasql.Check.Inferred.TH: instance GHC.Internal.Classes.Eq Hasql.Check.Inferred.TH.Tgt
+ Hasql.Check.Lexer: instance GHC.Internal.Classes.Eq Hasql.Check.Lexer.AlexPosn
+ Hasql.Check.Lexer: instance GHC.Internal.Classes.Eq Hasql.Check.Lexer.Lexeme
+ Hasql.Check.Lexer: instance GHC.Internal.Classes.Eq Hasql.Check.Lexer.LexemeClass
+ Hasql.Check.Lexer: instance GHC.Internal.Classes.Ord Hasql.Check.Lexer.AlexPosn
+ Hasql.Check.Parser: instance GHC.Internal.Classes.Eq Hasql.Check.Parser.QuasiQuote
- Hasql.Check.Inferred: slotsOne :: Column a => (p -> a) -> Slots '[PgColumnType a] '[PgColumnLabels a] '[a] p
+ Hasql.Check.Inferred: slotsOne :: forall a p (s :: Symbol) (l :: [Symbol]). (Column a, SlotType a s l) => (p -> a) -> Slots '[s] '[l] '[a] p
- Hasql.Check.Lexer: AlexError :: !AlexInput -> AlexReturn a
+ Hasql.Check.Lexer: AlexError :: AlexInput -> AlexReturn a
- Hasql.Check.Lexer: AlexLastAcc :: !Int -> !AlexInput -> !Int -> AlexLastAcc
+ Hasql.Check.Lexer: AlexLastAcc :: Int -> AlexInput -> Int -> AlexLastAcc
- Hasql.Check.Lexer: AlexLastSkip :: !AlexInput -> !Int -> AlexLastAcc
+ Hasql.Check.Lexer: AlexLastSkip :: AlexInput -> Int -> AlexLastAcc
- Hasql.Check.Lexer: AlexPn :: !Int -> !Int -> !Int -> AlexPosn
+ Hasql.Check.Lexer: AlexPn :: Int -> Int -> Int -> AlexPosn
- Hasql.Check.Lexer: AlexSkip :: !AlexInput -> !Int -> AlexReturn a
+ Hasql.Check.Lexer: AlexSkip :: AlexInput -> Int -> AlexReturn a
- Hasql.Check.Lexer: AlexState :: !AlexPosn -> !Int64 -> ByteString -> !Char -> !Int -> AlexUserState -> AlexState
+ Hasql.Check.Lexer: AlexState :: AlexPosn -> Int64 -> ByteString -> Char -> Int -> AlexUserState -> AlexState
- Hasql.Check.Lexer: AlexToken :: !AlexInput -> !Int -> a -> AlexReturn a
+ Hasql.Check.Lexer: AlexToken :: AlexInput -> Int -> a -> AlexReturn a
- Hasql.Check.Lexer: [alex_bpos] :: AlexState -> !Int64
+ Hasql.Check.Lexer: [alex_bpos] :: AlexState -> Int64
- Hasql.Check.Lexer: [alex_chr] :: AlexState -> !Char
+ Hasql.Check.Lexer: [alex_chr] :: AlexState -> Char
- Hasql.Check.Lexer: [alex_pos] :: AlexState -> !AlexPosn
+ Hasql.Check.Lexer: [alex_pos] :: AlexState -> AlexPosn
- Hasql.Check.Lexer: [alex_scd] :: AlexState -> !Int
+ Hasql.Check.Lexer: [alex_scd] :: AlexState -> Int

Files

ChangeLog.md view
@@ -1,5 +1,21 @@ # Changelog +## 0.5.2.0++A statement with `$1.$field` param fields could not be checked from a `.hie`+file, nor by the plugin: `hasql-check-hie` said its types were not known+where it is written. A field's type is only known once GHC has solved its+`HasField`, after it has already settled each slot's Postgres type as an+unsolved `PgColumnType a`; so GHC recorded `PgColumnType Text` rather than+`"text"`, which `hasql-check-hie` cannot reduce. A slot's Postgres type and+labels now come from `SlotType`, whose instances GHC cannot choose between+until the field's type is known, so they are recorded reduced.++`--inferred` took the number of parameters a statement with param fields is+sent to be its number of placeholders, so it reported each placeholder past+the first parameter's as a parameter the statement does not use. It now+counts the statement's parameters, as the quoter's pattern takes them.+ ## 0.5.1.0  The quoters of `Hasql.Check.Inferred.TH` now take the Haskell targets and
hasql-check.cabal view
@@ -1,6 +1,6 @@ cabal-version:   3.0 name:            hasql-check-version:         0.5.1.0+version:         0.5.2.0 synopsis:        Check hasql-th statements against a live PostgreSQL schema description:   Finds the hasql-th quasiquotes in Haskell source files and PREPAREs each
src/Hasql/Check/Inferred.hs view
@@ -1033,8 +1033,25 @@ slotsNone = Slots mempty  -- | One parameter slot, sending what the projection picks out.-slotsOne :: forall a p. (Column a) => (p -> a) -> Slots '[PgColumnType a] '[PgColumnLabels a] '[a] p+slotsOne :: forall a p s l. (Column a, SlotType a s l) => (p -> a) -> Slots '[s] '[l] '[a] p slotsOne f = Slots (f >$< E.param encodeColumn)++{- | A slot's Postgres type and labels, 'PgColumnType' and 'PgColumnLabels'+of the type it sends, worked out only once that type is known.++A param field's type is only known once GHC has solved its 'HasField',+after it has settled the slot's type. Had the slot carried+@'PgColumnType' a@ itself, GHC would have recorded the family unreduced,+as @'PgColumnType' Text@ rather than @"text"@, and @hasql-check-hie@,+which cannot reduce it, could not check the statement. Like 'Column''s,+these instances cannot be told apart until the type is known, so GHC waits+for it before reducing the families.+-}+class SlotType a (s :: Symbol) (l :: [Symbol]) | a -> s l++instance {-# OVERLAPPABLE #-} (s ~ PgColumnType a, l ~ PgColumnLabels a) => SlotType a s l++instance (s ~ PgColumnType (Maybe a), l ~ PgColumnLabels (Maybe a)) => SlotType (Maybe a) s l  -- | One more slot, appending its type. slotsAp :: Slots ps ls hs p -> Slots qs ms is p -> Slots (Append ps qs) (Append ls ms) (Append hs is) p
src/Hasql/Check/Inferred/Quote.hs view
@@ -38,7 +38,7 @@ import Hasql.Check.Annotate (annotate, typename, untypedLiterals) import Hasql.Check.Finding (Finding (..), statementHash) import Hasql.Check.Inferred (Template (..), render)-import Hasql.Check.Inferred.TH (Parsed (..), parsed)+import Hasql.Check.Inferred.TH (Parsed (..), Slot (..), parsed) import Hasql.Check.Nullability (Catalogue, query) import Hasql.Check.Nullability qualified as Nullability import Hasql.Check.Types qualified as Types@@ -190,9 +190,14 @@                         -- types hasql sends, it takes them all, used or not.                         -- In the numbering the statement was written in,                         -- which lowering renumbers: each slot knows the-                        -- parameter it came from.+                        -- parameter it came from. A param field sends a+                        -- field of its parameter, so where there are any the+                        -- Haskell type sends as many parameters as the quoter+                        -- made its pattern take, not one per slot.                         let used = p.parsedUsed-                            sends = length q.params+                            sends+                                | or [True | Slot _ (Just _) <- p.parsedSlots] = p.parsedArity+                                | otherwise = length q.params                             paramErrors =                                 [ concat ["the Haskell type sends parameter $", show n, ", which the statement does not use"]                                 | n <- [1 .. sends]
test/Main.hs view
@@ -225,6 +225,12 @@     itWithOuter "annotates the parameters in the order they are sent, not written" \conn ->         runInferred conn [] [inferredQuote "resultlessStatement" "insert into tag (label, id) values ($2, $1)" [text, int32] Nothing]             `shouldReturn` (ExitSuccess, "")++    -- A type per slot, so three for two parameters: the record's two fields,+    -- and $2. None of them is a parameter the statement does not use.+    itWithOuter "counts a record parameter once, however many fields it sends" \conn ->+        runInferred conn [] [inferredQuote "resultlessStatement" "update tag set id = $1.$id where id = $1.$other and label = $2" [int32, int32, text] Nothing]+            `shouldReturn` (ExitSuccess, "") #else syntaxSpec =     itWithOuter "rejects Haskell targets, which upstream hasql-th does not accept" \conn -> do