module Database.PostgreSQL.Store.ColumnEntity (
ColumnType (..),
ColumnEntity (..)
) where
import Data.Proxy
import Data.Int
import Data.Word
import Data.Scientific
import Numeric.Natural
import qualified Data.Aeson as A
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import Database.PostgreSQL.Store.Entity
import Database.PostgreSQL.Store.Utilities
import Database.PostgreSQL.Store.Query.Builder
data ColumnType = ColumnType {
colTypeName :: B.ByteString,
colTypeNotNull :: Bool,
colTypeCheck :: Maybe (B.ByteString -> QueryBuilder)
}
class (Entity a) => ColumnEntity a where
describeColumnType :: proxy a -> ColumnType
instance (ColumnEntity a) => ColumnEntity (Maybe a) where
describeColumnType _ =
(describeColumnType (Proxy :: Proxy a)) {
colTypeNotNull = False
}
newtype PGInt2 = PGInt2 Int16
deriving (Show, Read, Eq, Ord, Enum, Bounded, Integral, Num, Real)
instance Entity PGInt2 where
insertEntity (PGInt2 x) =
insertEntity x
parseEntity =
PGInt2 <$> parseEntity
instance ColumnEntity PGInt2 where
describeColumnType _ =
ColumnType "int2" True Nothing
newtype PGInt4 = PGInt4 Int32
deriving (Show, Read, Eq, Ord, Enum, Bounded, Integral, Num, Real)
instance Entity PGInt4 where
insertEntity (PGInt4 x) =
insertEntity x
parseEntity =
PGInt4 <$> parseEntity
instance ColumnEntity PGInt4 where
describeColumnType _ =
ColumnType "int4" True Nothing
newtype PGInt8 = PGInt8 Int64
deriving (Show, Read, Eq, Ord, Enum, Bounded, Integral, Num, Real)
instance Entity PGInt8 where
insertEntity (PGInt8 x) =
insertEntity x
parseEntity =
PGInt8 <$> parseEntity
instance ColumnEntity PGInt8 where
describeColumnType _ =
ColumnType "int8" True Nothing
selectBestColumnType :: (Show a, Num a, Ord a, Bounded a) => proxy a -> ColumnType
selectBestColumnType proxy
| 32768 <= lower && upper <= 32767 =
ColumnType "int2" True Nothing
| 2147483648 <= lower && upper <= 2147483647 =
ColumnType "int4" True Nothing
| 9223372036854775808 <= lower && upper <= 9223372036854775807 =
ColumnType "int8" True Nothing
| otherwise =
ColumnType (buildByteString ("numeric(" ++ show digits ++ ",0)")) True Nothing
where
upper = (const maxBound :: (Bounded a) => proxy a -> a) proxy
lower = (const minBound :: (Bounded a) => proxy a -> a) proxy
digits = max (length (show upper)) (length (show lower))
instance ColumnEntity Bool where
describeColumnType _ =
ColumnType "bool" True Nothing
instance ColumnEntity Integer where
describeColumnType _ =
ColumnType "numeric" True Nothing
instance ColumnEntity Int where
describeColumnType = selectBestColumnType
instance ColumnEntity Int8 where
describeColumnType = selectBestColumnType
instance ColumnEntity Int16 where
describeColumnType = selectBestColumnType
instance ColumnEntity Int32 where
describeColumnType = selectBestColumnType
instance ColumnEntity Int64 where
describeColumnType = selectBestColumnType
instance ColumnEntity Natural where
describeColumnType _ =
ColumnType "numeric" True Nothing
instance ColumnEntity Word where
describeColumnType = selectBestColumnType
instance ColumnEntity Word8 where
describeColumnType = selectBestColumnType
instance ColumnEntity Word16 where
describeColumnType = selectBestColumnType
instance ColumnEntity Word32 where
describeColumnType = selectBestColumnType
instance ColumnEntity Word64 where
describeColumnType = selectBestColumnType
instance ColumnEntity Float where
describeColumnType _ =
ColumnType "real" True Nothing
instance ColumnEntity Double where
describeColumnType _ =
ColumnType "double precision" True Nothing
instance ColumnEntity Scientific where
describeColumnType _ =
ColumnType "numeric" True Nothing
instance ColumnEntity String where
describeColumnType _ =
ColumnType "text" True Nothing
instance ColumnEntity T.Text where
describeColumnType _ =
ColumnType "text" True Nothing
instance ColumnEntity TL.Text where
describeColumnType _ =
ColumnType "text" True Nothing
instance ColumnEntity B.ByteString where
describeColumnType _ =
ColumnType "bytea" True Nothing
instance ColumnEntity BL.ByteString where
describeColumnType _ =
ColumnType "bytea" True Nothing
instance ColumnEntity A.Value where
describeColumnType _ =
ColumnType "json" True Nothing