{-# language FlexibleContexts #-}
{-# language MonoLocalBinds #-}

module Rel8.Query.Function
  ( queryFunction
  )
where

-- base
import Prelude

-- opaleye
import qualified Opaleye.Internal.Operators as Opaleye

-- rel8
import Rel8.Expr (Expr)
import Rel8.Expr.Function (Arguments, primFunction)
import Rel8.Query (Query)
import Rel8.Query.Opaleye (fromOpaleye)
import Rel8.Schema.QualifiedName (QualifiedName)
import Rel8.Table (Table)
import Rel8.Table.Opaleye (castTable, relExprPP)


-- | Select each row from a function that returns a relation. This is
-- equivalent to @FROM function(input)@.
queryFunction :: (Arguments input, Table Expr output)
  => QualifiedName -> input -> Query output
queryFunction :: forall input output.
(Arguments input, Table Expr output) =>
QualifiedName -> input -> Query output
queryFunction QualifiedName
name input
input = (output -> output) -> Query output -> Query output
forall a b. (a -> b) -> Query a -> Query b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap output -> output
forall a. Table Expr a => a -> a
castTable (Query output -> Query output) -> Query output -> Query output
forall a b. (a -> b) -> a -> b
$ Select output -> Query output
forall a. Select a -> Query a
fromOpaleye (Select output -> Query output) -> Select output -> Query output
forall a b. (a -> b) -> a -> b
$
  RelExprPP output output -> (() -> PrimExpr) -> Select output
forall columns a.
RelExprPP columns columns -> (a -> PrimExpr) -> QueryArr a columns
Opaleye.relationValuedExprExplicit RelExprPP output output
forall a. Table Expr a => RelExprPP a a
relExprPP (PrimExpr -> () -> PrimExpr
forall a b. a -> b -> a
const PrimExpr
expr)
  where
    expr :: PrimExpr
expr = QualifiedName -> input -> PrimExpr
forall arguments.
Arguments arguments =>
QualifiedName -> arguments -> PrimExpr
primFunction QualifiedName
name input
input