{-# LANGUAGE FlexibleContexts, UndecidableInstances, TypeSynonymInstances, FlexibleInstances , MultiParamTypeClasses #-} ----------------------------------------------------------- -- | -- Module : FieldType -- Copyright : HWT Group (c) 2003, haskelldb-users@lists.sourceforge.net -- License : BSD-style -- -- Maintainer : haskelldb-users@lists.sourceforge.net -- Stability : experimental -- Portability : non-portable -- -- Defines the types of database columns, and functions -- for converting these between HSQL and internal formats -- -- ----------------------------------------------------------- module Database.HaskellDB.FieldType (FieldDesc, FieldType(..), toHaskellType, ExprType(..) , ExprTypes(..), queryFields) where import Data.Dynamic import System.Time import Database.HaskellDB.HDBRec (RecCons(..), Record, RecNil(..), ShowLabels) import Database.HaskellDB.BoundedString import Database.HaskellDB.BoundedList (listBound, Size) import Database.HaskellDB.Query (Expr, Rel, runQueryRel, Query, labels) -- | The type and @nullable@ flag of a database column type FieldDesc = (FieldType, Bool) -- | A database column type data FieldType = StringT | IntT | IntegerT | DoubleT | BoolT | CalendarTimeT | BStrT Int deriving (Eq,Ord,Show,Read) -- | Class which retrieves a field description from a given type. -- Instances are provided for most concrete types. Instances -- for Maybe automatically make the field nullable, and instances -- for all (Expr a) types where a has an ExprType instance allows -- type information to be recovered from a given column expression. class ExprType e where fromHaskellType :: e -> FieldDesc -- | Class which returns a list of field descriptions. Gets the -- descriptions of all columns in a Record/query. Most useful when -- the columns associated with each field in a (Rel r) type must be -- recovered. Note that this occurs at the type level only and no -- values are inspected. class ExprTypes r where fromHaskellTypes :: r -> [FieldDesc] toHaskellType :: FieldType -> String toHaskellType StringT = "String" toHaskellType IntT = "Int" toHaskellType IntegerT = "Integer" toHaskellType DoubleT = "Double" toHaskellType BoolT = "Bool" toHaskellType CalendarTimeT = "CalendarTime" toHaskellType (BStrT a) = "BStr" ++ show a -- | Given a query, returns a list of the field names and their -- types used by the query. Useful for recovering field information -- once a query has been built up. queryFields :: (ShowLabels r, ExprTypes r) => Query (Rel r) -> [(String, FieldDesc)] queryFields def = zip (labels query) types where query = unRel . snd . runQueryRel $ def types = fromHaskellTypes query unRel :: (Rel r) -> r unRel r = undefined -- Only used to get to type-level information. instance Typeable CalendarTime where -- not available in standard libraries typeOf _ = mkTyConApp (mkTyCon "System.Time.CalendarTime") [] instance Typeable (BoundedString n) where typeOf _ = mkTyConApp (mkTyCon "Database.HaskellDB.BoundedString") [] instance (ExprType a) => ExprType (Maybe a) where fromHaskellType ~(Just e) = ((fst . fromHaskellType $ e), True) instance (ExprType a) => ExprType (Expr a) where fromHaskellType e = let unExpr :: Expr a -> a unExpr _ = undefined in fromHaskellType . unExpr $ e instance (ExprType a) => ExprType (Rel a) where fromHaskellType e = let unRel :: Rel a -> a unRel _ = undefined in fromHaskellType . unRel $ e instance ExprType Bool where fromHaskellType _ = (BoolT, False) instance ExprType String where fromHaskellType _ = (StringT, False) instance ExprType Int where fromHaskellType _ = (IntT, False) instance ExprType Integer where fromHaskellType _ = (IntegerT, False) instance ExprType Double where fromHaskellType _ = (DoubleT, False) instance ExprType CalendarTime where fromHaskellType _ = (CalendarTimeT, False) instance (Size n) => ExprType (BoundedString n) where fromHaskellType b = (BStrT (listBound b), False) instance ExprTypes RecNil where fromHaskellTypes _ = [] instance (ExprType e, ExprTypes r) => ExprTypes (RecCons f e r) where fromHaskellTypes ~f@(RecCons e r) = let getFieldType :: RecCons f a r -> a getFieldType = undefined in (fromHaskellType . getFieldType $ f) : fromHaskellTypes r instance (ExprTypes r) => ExprTypes (Record r) where fromHaskellTypes r = fromHaskellTypes (r RecNil) instance (ExprTypes r) => ExprTypes (Rel r) where fromHaskellTypes r = let unRel :: Rel a -> a unRel _ = undefined in fromHaskellTypes . unRel $ r