yesodweb / yesodweb/persistent
Nano does not roundtrip as part of entity
Nobody has claimed this yet.
- Dominant language
- Haskell
- Stars
- 486
- Forks
- 306
- PR merge metrics
- No merged PRs in 30d
Description
Bug Reports
I'm using persistent as part of LTS 16.12 with sqlite.
I have this database definition:
Place sql=place
query Text -- Address
lat Nano
lon Nano
UniquePlaceQuery query
deriving Show
deriving Eq
deriving Generic
I noticed something really weird when running this in a property test:
liftIO $ pPrint place
mPlace <- DB.get placeId
liftIO $ pPrint mPlace
output
Place
{ placeQuery =
"\119188\844395\748003\773996\537954\635786\579726\1085648\596327\160180\526694\824331\996801\669722\926453\142441\1050632\260094\410357\477790\829171\521373"
, placeLat = 6778287944.859847017
, placeLon = -3037898653.585851994
}
Just
Place
{ placeQuery =
"\119188\844395\748003\773996\537954\635786\579726\1085648\596327\160180\526694\824331\996801\669722\926453\142441\1050632\260094\410357\477790\829171\521373"
, placeLat = 6778287944.859847068
, placeLon = -3037898653.585852147
}
As you can see, the latitude and logitude are different.
I did some digging already. (If you do so, watch out for this issue.)
> 6778287944.859847017 :: Nano
6778287944.859847017
> fromPersistValue (toPersistValue (6778287944.859847017 :: Nano)) :: Either Text Nano
Right 6778287944.859847017
So far so good, so it looks like the problem is between sqlite and persistent.
Repro script:
#!/usr/bin/env stack
-- stack --resolver lts-16.12 script
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
import Control.Monad
import Control.Monad.IO.Class (liftIO)
import Data.Fixed
import Data.Text (Text)
import Database.Persist
import Database.Persist.Sqlite
import Database.Persist.TH
import System.Exit
import Text.Show.Pretty (ppShow)
share
[mkPersist sqlSettings, mkMigrate "migrateAll"]
[persistLowerCase|
Place sql=place
lat Nano
lon Nano
deriving Show
deriving Eq
|]
main :: IO ()
main = runSqlite ":memory:" $ do
runMigration migrateAll
let expected =
Place
{ placeLat = 6778287944.859847017,
placeLon = -3037898653.585851994
}
placeId <- insert expected
mActual <- get placeId
liftIO $
forM_ mActual $ \actual ->
if expected == actual
then putStrLn "Done!"
else
die $
unlines
[ "Roundtrip failed.",
unwords ["expected:", ppShow expected],
unwords ["actual: ", ppShow actual]
]
Output:
Migrating: CREATE TABLE "place"("id" INTEGER PRIMARY KEY,"lat" NUMERIC(19,9) NOT NULL,"lon" NUMERIC(19,9) NOT NULL)
Roundtrip failed.
expected: Place
{ placeLat = 6778287944.859847017
, placeLon = -3037898653.585851994
}
actual: Place
{ placeLat = 6778287944.859847068
, placeLon = -3037898653.585852147
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the supplied Stack reproduction with LTS 16.12 and SQLite, then trace the conversion between the Nano value, SQLite's NUMERIC(19,9) column, and Persistent's retrieved value. Compare the insert and get paths and add a regression test showing that the latitude and longitude roundtrip unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- haskell, sqlite
- Domain
- database
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100