packages feed

squeal-postgresql-0.7.0.0: bench/Gauge/Schema.hs

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DeriveGeneric #-}

module Gauge.Schema where

import           Squeal.PostgreSQL
import           GHC.Generics
import qualified Generics.SOP                  as SOP


-- Type

data DeviceOS = Android | IOS
    deriving (Show, Read, Eq, Generic)
-- DeviceOS is converted to PG Enum type
instance SOP.Generic DeviceOS
instance SOP.HasDatatypeInfo DeviceOS

-- Defined extra types for the database
-- Operating system enum
type PGDeviceOS = PG (Enumerated DeviceOS)
type DeviceOSType = 'Typedef PGDeviceOS

-- For composite type
data IPLocation = IPLocation
  { countryShort :: String
  , region       :: String
  , city         :: String
  }
  deriving (Show, Read, Eq, Generic)

instance SOP.Generic IPLocation
instance SOP.HasDatatypeInfo IPLocation

-- IPLocation Composite type
type PGIPLocation = PG (Composite IPLocation)
type IPLocationType = 'Typedef PGIPLocation

-- SCHEMA

-- Users

type UsersColumns = '[
    "id"   :::   'Def :=> 'NotNull 'PGint8
    , "email" ::: 'NoDef :=> 'NotNull 'PGtext
    , "password" ::: 'NoDef :=> 'NotNull 'PGtext
    , "first_name" ::: 'NoDef :=> 'Null 'PGtext
    , "birthyear" ::: 'NoDef :=> 'Null 'PGint2
    ]

type UsersConstraints = '[
    "pk_users" ::: 'PrimaryKey '["id"]
    , "email" ::: 'Unique '["email"]
    ]

type UsersTable = 'Table (UsersConstraints :=> UsersColumns)

-- User devices
type UserDevicesColumns = '[
  "id" ::: 'Def :=> 'NotNull 'PGint8 -- ID as PK because user might have many same OS devices
  , "user_id" ::: 'NoDef :=> 'NotNull 'PGint8
  , "token" ::: 'NoDef :=> 'NotNull 'PGtext
  , "os" ::: 'NoDef :=> 'NotNull PGDeviceOS
  ]

type UserDevicesConstraints = '[
  "pk_user_devices" ::: 'PrimaryKey '["id"]
  , "fk_user_id" ::: 'ForeignKey '["user_id"] "public" "users" '["id"]
  , "token" ::: 'Unique '["token"]
  ]

type UserDevicesTable = 'Table (UserDevicesConstraints :=> UserDevicesColumns)

-- Schema
-- Make sure to put types before tables, otherwise won't compile
type Schema = '[
  -- Enum types:
    "device_os" ::: DeviceOSType
  -- Composite types:
  , "ip_location" ::: IPLocationType
  -- Tables:
  , "users" ::: UsersTable
  , "user_devices" ::: UserDevicesTable
  ]

type Schemas = '["public" ::: Schema]