beam
beam copied to clipboard
Literal expressions fail to parse when returned from Postgres query
Hey again!
Running this:
import Database.Beam
import Database.Beam.Postgres
import Database.Beam.Postgres.Syntax
import Data.Text (Text)
test :: Connection -> IO ()
test conn = do
let
t :: QExpr PgExpressionSyntax s Text
t = "abc"
result <- withDatabaseDebug putStrLn conn (runSelectReturningOne (select (pure t)) :: Pg (Maybe Text))
print result
results in:
SELECT 'abc' AS "res0"
testapp: PgRowParseError (PgRowCouldNotParseField 0)
It seems like the error can be fixed by casting the value to the right type, i.e. by making the query SELECT ('abc'::text) AS "res0". I suppose the parser (which might be inherited from postgres-simple?) is strict about what types it allows whereas the printer outputs string literals which have unknown type until you cast them (pg_typeof('abc') is unknown).
Several (most?) other types also have this problem.
Cheers!
Opaleye chose to cast all literals explicitly. There might be some useful information in the pull request (https://github.com/tomjaguarpaw/haskell-opaleye/pull/412) and issue (https://github.com/tomjaguarpaw/haskell-opaleye/issues/253). https://github.com/tomjaguarpaw/haskell-opaleye/issues/377 was a result of this work, so it may be worth also pre-empting that.
Interesting. I hadn't thought of that use case, but yeah, explicit casting is a good idea.
So I've been trying to implement this. One issue is that there is no 1-to-1 mapping of haskell to postgres types, so it's not always clear what type should be given.
There is a notion of default type, but it's not necessarily the only type that could fit. For example, beam would normally allow a literal Int to be used as a byte-value integer, even if that's not 100% correct. This fix could introduce many type errors.
Any thoughts?
In rel8 I decided that one Haskell type = one postgresql type (note that doesn't imply the other direction). I just found that much easier, you're basically generating SQL from Haskell so it's easiest to be able to say "this type maps to this database type".
That certainly seems reasonable...