@@ -105,17 +105,38 @@ module Squeal.PostgreSQL.Schema
105105 , SchemumType (..)
106106 , SchemaType
107107 , With
108+ -- * STUFF
109+ , PG
110+ , PGenumWith
111+ , PGcompositeWith
112+ , ConstructorsOf
113+ , ConstructorNameOf
114+ , ConstructorNamesOf
115+ , FieldsOf
116+ , FieldNameOf
117+ , FieldNamesOf
118+ , FieldTypeOf
119+ , FieldTypesOf
120+ , RecordFieldTypesOf
121+ , Zip
108122 ) where
109123
110124import Control.DeepSeq
111−import Data.ByteString
125+import Data.Aeson (Value)
126+import Data.ByteString (ByteString)
127+import Data.Int
112128import Data.Kind
113129import Data.Monoid hiding (All)
130+import Data.Scientific
114131import Data.String
132+import Data.Text (Text)
133+import Data.Time
115134import Data.Word
116135import Data.Type.Bool
136+import Data.UUID.Types (UUID)
117137import GHC.OverloadedLabels
118138import GHC.TypeLits
139+import Network.IP.Addr
119140
120141import qualified GHC.Generics as GHC
121142import qualified Generics.SOP as SOP
@@ -653,3 +674,79 @@ type family LabelsOf (conss :: [Type.ConstructorInfo]) :: [Symbol] where
653674
654675type family DatatypeLabels (info :: Type.DatatypeInfo) :: [Symbol] where
655676 DatatypeLabels ('Type.ADT _module _datatype constructors) = LabelsOf constructors
677+
678+type family PG (hask :: Type) = (pg :: PGType) | pg -> hask where
679+ PG Bool = 'PGbool
680+ PG Int16 = 'PGint2
681+ PG Int32 = 'PGint4
682+ PG Int64 = 'PGint8
683+ PG Scientific = 'PGnumeric
684+ PG Float = 'PGfloat4
685+ PG Double = 'PGfloat8
686+ PG Text = 'PGtext
687+ PG ByteString = 'PGbytea
688+ PG LocalTime = 'PGtimestamp
689+ PG UTCTime = 'PGtimestamptz
690+ PG Day = 'PGdate
691+ PG TimeOfDay = 'PGtime
692+ PG (TimeOfDay, TimeZone) = 'PGtimetz
693+ PG DiffTime = 'PGinterval
694+ PG UUID = 'PGuuid
695+ PG (NetAddr IP) = 'PGinet
696+ PG Value = 'PGjson
697+
698+type family PGenumWith (hask :: Type) :: PGType where
699+ PGenumWith hask =
700+ 'PGenum (ConstructorNamesOf (ConstructorsOf (SOP.DatatypeInfoOf hask)))
701+
702+type family PGcompositeWith (hask :: Type) :: PGType where
703+ PGcompositeWith hask =
704+ 'PGcomposite (Zip
705+ (FieldNamesOf (FieldsOf (SOP.DatatypeInfoOf hask)))
706+ (RecordFieldTypesOf (SOP.Code hask)))
707+
708+type family ConstructorsOf (datatype :: Type.DatatypeInfo)
709+ :: [Type.ConstructorInfo] where
710+ ConstructorsOf ('Type.ADT _module _datatype constructors) =
711+ constructors
712+ ConstructorsOf ('Type.Newtype _module _datatype constructor) =
713+ '[constructor]
714+
715+type family ConstructorNameOf (constructors :: Type.ConstructorInfo)
716+ :: Type.ConstructorName where
717+ ConstructorNameOf ('Type.Constructor name) = name
718+ ConstructorNameOf ('Type.Infix name _assoc _fix) = name
719+ ConstructorNameOf ('Type.Record name _fields) = name
720+
721+type family ConstructorNamesOf (constructors :: [Type.ConstructorInfo])
722+ :: [Type.ConstructorName] where
723+ ConstructorNamesOf '[] = '[]
724+ ConstructorNamesOf (constructor ': constructors) =
725+ ConstructorNameOf constructor ': ConstructorNamesOf constructors
726+
727+type family FieldsOf (constructor :: Type.DatatypeInfo)
728+ :: [Type.FieldInfo] where
729+ FieldsOf ('Type.ADT _module _datatype '[ 'Type.Record _name fields]) =
730+ fields
731+
732+type family FieldNameOf (field :: Type.FieldInfo) :: Type.FieldName where
733+ FieldNameOf ('Type.FieldInfo name) = name
734+
735+type family FieldNamesOf (fields :: [Type.FieldInfo])
736+ :: [Type.FieldName] where
737+ FieldNamesOf '[] = '[]
738+ FieldNamesOf (field ': fields) = FieldNameOf field ': FieldNamesOf fields
739+
740+type family FieldTypeOf (maybe :: Type) where
741+ FieldTypeOf (Maybe hask) = PG hask
742+
743+type family FieldTypesOf (fields :: [Type]) where
744+ FieldTypesOf '[] = '[]
745+ FieldTypesOf (field ': fields) = FieldTypeOf field ': FieldTypesOf fields
746+
747+type family RecordFieldTypesOf (code :: [[Type]]) where
748+ RecordFieldTypesOf '[fields] = FieldTypesOf fields
749+
750+type family Zip xs ys where
751+ Zip '[] '[] = '[]
752+ Zip (x ': xs) (y ': ys) = '(x,y) ': Zip xs ys