{-# language DataKinds #-}
{-# language FlexibleInstances #-}
{-# language MultiParamTypeClasses #-}
{-# language ScopedTypeVariables #-}
{-# language StandaloneKindSignatures #-}
{-# language TypeApplications #-}
{-# language TypeFamilies #-}
{-# language UndecidableInstances #-}

{-# options_ghc -fno-warn-orphans #-}

module Rel8.Table.Rel8able
  (
  )
where

-- base
import Prelude ()

-- rel8
import Rel8.Expr ( Expr )
import qualified Rel8.Kind.Algebra as K
import Rel8.Kind.Context ( Reifiable, contextSing )
import Rel8.Generic.Rel8able
  ( Rel8able, Algebra
  , GColumns, gfromColumns, gtoColumns
  , GFromExprs, gfromResult, gtoResult
  )
import qualified Rel8.Schema.Kind as K
import Rel8.Schema.HTable ( HConstrainTable, hdicts )
import Rel8.Schema.Null ( Sql )
import Rel8.Schema.Result ( Result )
import Rel8.Table
  ( Table, Columns, Context, fromColumns, toColumns
  , FromExprs, fromResult, toResult
  , Transpose
  )
import Rel8.Table.ADT ( ADT )
import Rel8.Table.Eq ( EqTable, eqTable )
import Rel8.Table.Ord ( OrdTable, ordTable )
import Rel8.Table.Serialize ( ToExprs )
import Rel8.Type.Eq ( DBEq )
import Rel8.Type.Ord ( DBOrd )


instance (Rel8able t, Reifiable context, context ~ context') =>
  Table context' (t context)
 where
  type Columns (t context) = GColumns t
  type Context (t context) = context
  type FromExprs (t context) = GFromExprs t
  type Transpose to (t context) = t to

  fromColumns :: Columns (t context) context' -> t context
fromColumns = SContext context -> GColumns t context -> t context
forall (t :: Rel8able) (context :: Context).
Rel8able t =>
SContext context -> GColumns t context -> t context
gfromColumns SContext context
forall (context :: Context). Reifiable context => SContext context
contextSing
  toColumns :: t context -> Columns (t context) context'
toColumns = SContext context -> t context -> GColumns t context
forall (t :: Rel8able) (context :: Context).
Rel8able t =>
SContext context -> t context -> GColumns t context
gtoColumns SContext context
forall (context :: Context). Reifiable context => SContext context
contextSing
  fromResult :: Columns (t context) Result -> FromExprs (t context)
fromResult = Rel8able t => GColumns t Result -> GFromExprs t
forall (t :: Rel8able).
Rel8able t =>
GColumns t Result -> GFromExprs t
gfromResult @t
  toResult :: FromExprs (t context) -> Columns (t context) Result
toResult = Rel8able t => GFromExprs t -> GColumns t Result
forall (t :: Rel8able).
Rel8able t =>
GFromExprs t -> GColumns t Result
gtoResult @t


instance
  ( context ~ Expr
  , Rel8able t
  , HConstrainTable (Columns (t context)) (Sql DBEq)
  )
  => EqTable (t context)
 where
  eqTable :: Columns (t context) (Dict (Sql DBEq))
eqTable = HConstrainTable (Columns (t context)) (Sql DBEq) =>
Columns (t context) (Dict (Sql DBEq))
forall (t :: Rel8able) (c :: * -> Constraint).
(HTable t, HConstrainTable t c) =>
t (Dict c)
hdicts @(Columns (t context)) @(Sql DBEq)


instance
  ( context ~ Expr
  , Rel8able t
  , HConstrainTable (Columns (t context)) (Sql DBEq)
  , HConstrainTable (Columns (t context)) (Sql DBOrd)
  )
  => OrdTable (t context)
 where
  ordTable :: Columns (t context) (Dict (Sql DBOrd))
ordTable = HConstrainTable (Columns (t context)) (Sql DBOrd) =>
Columns (t context) (Dict (Sql DBOrd))
forall (t :: Rel8able) (c :: * -> Constraint).
(HTable t, HConstrainTable t c) =>
t (Dict c)
hdicts @(Columns (t context)) @(Sql DBOrd)


instance
  ( Rel8able t', t' ~ Choose (Algebra t) t
  , x ~ t' Expr
  , result ~ Result
  )
  => ToExprs x (t result)


type Choose :: K.Algebra -> K.Rel8able -> K.Rel8able
type family Choose algebra t where
  Choose 'K.Sum t = ADT t
  Choose 'K.Product t = t