@@ -1,3 +1,4 @@
1+{-# language BlockArguments #-}
12{-# language DisambiguateRecordFields #-}
23{-# language FlexibleContexts #-}
34{-# language NamedFieldPuns #-}
@@ -12,6 +13,7 @@ module Rel8.Table.Opaleye
1213 , tableFields
1314 , unpackspec
1415 , valuesspec
16+ , castTable
1517 )
1618where
1719
@@ -38,9 +40,10 @@ import Rel8.Expr.Opaleye
3840 ( fromPrimExpr, toPrimExpr
3941 , traversePrimExpr
4042 , fromColumn, toColumn
43+ , scastExpr
4144 )
4245import Rel8.Kind.Necessity ( SNecessity( SRequired, SOptional ) )
43−import Rel8.Schema.HTable ( htabulateA, hfield, htraverse, hspecs )
46+import Rel8.Schema.HTable ( htabulateA, hfield, htraverse, hspecs, htabulate )
4447import Rel8.Schema.Insert ( Insert, Inserts, Col(..) )
4548import Rel8.Schema.Name ( Name, Selects, Col(..) )
4649import Rel8.Schema.Spec ( SSpec(..) )
@@ -124,3 +127,15 @@ toPackMap as = Opaleye.PackMap $ \f () ->
124127 unwrapApplicative .
125128 htraverse (\(DB a) -> WrapApplicative $ DB <$> traversePrimExpr f a) $
126129 toColumns as
130+
131+
132+-- | Transform a table by adding 'CAST' to all columns. This is most useful for
133+-- finalising a SELECT or RETURNING statement, guaranteed that the output
134+-- matches what is encoded in each columns TypeInformation.
135+castTable :: Table Expr a => a -> a
136+castTable (toColumns -> as) = fromColumns $ htabulate \i ->
137+ case hfield hspecs i of
138+ SSpec{info} ->
139+ case hfield as i of
140+ DB expr ->
141+ DB (scastExpr info expr)