{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}

module Opaleye.SQLite.Internal.Join where

import qualified Opaleye.SQLite.Internal.Tag as T
import qualified Opaleye.SQLite.Internal.PackMap as PM
import           Opaleye.SQLite.Internal.Column (Column, Nullable)
import qualified Opaleye.SQLite.Column as C

import           Data.Profunctor (Profunctor, dimap)
import           Data.Profunctor.Product (ProductProfunctor, empty, (***!))
import qualified Data.Profunctor.Product.Default as D

import qualified Opaleye.SQLite.Internal.HaskellDB.PrimQuery as HPQ

newtype NullMaker a b = NullMaker (a -> b)

toNullable :: NullMaker a b -> a -> b
toNullable :: NullMaker a b -> a -> b
toNullable (NullMaker a -> b
f) = a -> b
f

extractLeftJoinFields :: Int -> T.Tag -> HPQ.PrimExpr
            -> PM.PM [(HPQ.Symbol, HPQ.PrimExpr)] HPQ.PrimExpr
extractLeftJoinFields :: Int -> Tag -> PrimExpr -> PM [(Symbol, PrimExpr)] PrimExpr
extractLeftJoinFields Int
n = String -> Tag -> PrimExpr -> PM [(Symbol, PrimExpr)] PrimExpr
forall primExpr.
String -> Tag -> primExpr -> PM [(Symbol, primExpr)] PrimExpr
PM.extractAttr (String
"result" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_")

instance D.Default NullMaker (Column a) (Column (Nullable a)) where
  def :: NullMaker (Column a) (Column (Nullable a))
def = (Column a -> Column (Nullable a))
-> NullMaker (Column a) (Column (Nullable a))
forall a b. (a -> b) -> NullMaker a b
NullMaker Column a -> Column (Nullable a)
forall a b. Column a -> Column b
C.unsafeCoerceColumn

instance D.Default NullMaker (Column (Nullable a)) (Column (Nullable a)) where
  def :: NullMaker (Column (Nullable a)) (Column (Nullable a))
def = (Column (Nullable a) -> Column (Nullable a))
-> NullMaker (Column (Nullable a)) (Column (Nullable a))
forall a b. (a -> b) -> NullMaker a b
NullMaker Column (Nullable a) -> Column (Nullable a)
forall a b. Column a -> Column b
C.unsafeCoerceColumn

-- { Boilerplate instances

instance Profunctor NullMaker where
  dimap :: (a -> b) -> (c -> d) -> NullMaker b c -> NullMaker a d
dimap a -> b
f c -> d
g (NullMaker b -> c
h) = (a -> d) -> NullMaker a d
forall a b. (a -> b) -> NullMaker a b
NullMaker ((a -> b) -> (c -> d) -> (b -> c) -> a -> d
forall (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> p b c -> p a d
dimap a -> b
f c -> d
g b -> c
h)

instance ProductProfunctor NullMaker where
  empty :: NullMaker () ()
empty = (() -> ()) -> NullMaker () ()
forall a b. (a -> b) -> NullMaker a b
NullMaker () -> ()
forall (p :: * -> * -> *). ProductProfunctor p => p () ()
empty
  NullMaker a -> b
f ***! :: NullMaker a b -> NullMaker a' b' -> NullMaker (a, a') (b, b')
***! NullMaker a' -> b'
f' = ((a, a') -> (b, b')) -> NullMaker (a, a') (b, b')
forall a b. (a -> b) -> NullMaker a b
NullMaker (a -> b
f (a -> b) -> (a' -> b') -> (a, a') -> (b, b')
forall (p :: * -> * -> *) a b a' b'.
ProductProfunctor p =>
p a b -> p a' b' -> p (a, a') (b, b')
***! a' -> b'
f')

--