{-# 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]