Skip to content

sum_ and friends can cause runtime type errors #148

@enolan

Description

@enolan

sum_'s type is (PersistField a, PersistField b) => expr (Value a) -> expr (Value (Maybe b)). But sum of course cannot return any type. In Postgres, it returns numeric for bigints, which is represented as PersistRational. Details here. Example:

module Main where

import Control.Monad.IO.Class
import Control.Monad.Logger
import Database.Esqueleto
import Database.Persist
import Database.Persist.Postgresql
import Database.Persist.TH

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Number
   value Int
|]

connStr = "host=localhost dbname=test user=test password=test port=5432"

main :: IO ()
main = runStderrLoggingT $ withPostgresqlPool connStr 10 $ \pool -> liftIO $ do
    flip runSqlPersistMPool pool $ do
        runMigration migrateAll

        johnId <- insert $ Number 5
        janeId <- insert $ Number 22
        return ()
        _ :: [Value (Maybe Int)] <- select $
          from $ \number -> do
            return $ sum_ $ number ^. NumberValue
        return ()
enolan at behemoth in ~/junk/esqueleto-bug  
$ stack exec esqueleto-bug
[Debug#SQL] INSERT INTO "number"("value") VALUES(?) RETURNING "id"; [PersistInt64 5]
[Debug#SQL] INSERT INTO "number"("value") VALUES(?) RETURNING "id"; [PersistInt64 22]
[Debug#SQL] SELECT SUM("number"."value")
FROM "number"
; []
esqueleto-bug: PersistMarshalError "int Expected Integer, received: PersistRational (27 % 1)"

I suppose it needs a type family/fundep. Test case repo here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions