esqueleto
esqueleto copied to clipboard
Cannot express runtime casts
I've run in to a number of situations where I actually want to explicitly cast data in sql. The current casting model is just type level casting and has no runtime effects. To combat this I have a casting implementation loosly based on Idris' casting model.
class PostgresCast a b where
castType :: IsString x => Proxy a -> Proxy b -> x
cast :: forall b a. PostgresCast a b => SqlExpr (Value a) -> SqlExpr (Value b)
cast x = unsafeSqlFunction "CAST" . unsafeSqlBinOp " AS " x . unsafeSqlValue $ castType (Proxy @a) (Proxy @b)
Currently using these impls, but a library proper implementation would probably need to be more explicit than Num n => PostgresCast n Double
instance Num n => PostgresCast n Double where
castType _ _ = "real"
instance Num n => PostgresCast n Int where
castType _ _ = "integer"
instance SqlString n => PostgresCast n Text where
castType _ _ = "text"
I'm open to adding this with a touch more rigor as you suggest.
Fair warning: Active cycles will be going into https://github.com/bitemyapp/bluetick which I am hoping can be a suitable migration target for Esqueleto users like y'all. Speaking of, if you have design/bug requests that aren't tractable in Esqueleto-as-it-exists-now please file them on the bluetick repository!
Oh also note the forall ordering in cast :: forall b a. for TypeApplications goodness: cast @Double someNum.
I'll take a look at bluetick tomorrow morning and throw some feedback.
@eborden it's just empty for now but the plan is to do a grammar/datatype-first approach like Bloodhound. If possible I'll keep the original API w/ refinements and better type-safety but we'll see how it shakes out. Parent ticket for some of the issues on my mind: https://github.com/bitemyapp/esqueleto/issues/50
That's a nice touch for the type application!