{-# LANGUAGE UndecidableInstances #-}

module Hasura.RQL.IR.Value
  ( UnpreparedValue (..),
    Provenance (..),
    ValueWithOrigin (..),
    openValueOrigin,
    mkParameter,
  )
where

import Hasura.GraphQL.Parser.Variable
import Hasura.Prelude
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BackendType
import Hasura.RQL.Types.Column
import Hasura.Session (SessionVariable)

-- | Where did this variable come from?
data Provenance
  = FromGraphQL VariableInfo
  | -- | An internal source
    FromInternal Text
  | -- | A unique, fresh occurrence of a variable.
    -- E.g. a native query argument, or generated
    -- values that benefit from being prepared rather
    -- than inlined.
    FreshVar
  deriving stock (Provenance -> Provenance -> Bool
(Provenance -> Provenance -> Bool)
-> (Provenance -> Provenance -> Bool) -> Eq Provenance
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Provenance -> Provenance -> Bool
== :: Provenance -> Provenance -> Bool
$c/= :: Provenance -> Provenance -> Bool
/= :: Provenance -> Provenance -> Bool
Eq, Int -> Provenance -> ShowS
[Provenance] -> ShowS
Provenance -> String
(Int -> Provenance -> ShowS)
-> (Provenance -> String)
-> ([Provenance] -> ShowS)
-> Show Provenance
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Provenance -> ShowS
showsPrec :: Int -> Provenance -> ShowS
$cshow :: Provenance -> String
show :: Provenance -> String
$cshowList :: [Provenance] -> ShowS
showList :: [Provenance] -> ShowS
Show)

data UnpreparedValue (b :: BackendType)
  = -- | A SQL value that can be parameterized over.
    UVParameter Provenance (ColumnValue b)
  | -- | A literal SQL expression that /cannot/ be parameterized over.
    UVLiteral (SQLExpression b)
  | -- | The entire session variables JSON object.
    UVSession
  | -- | A single session variable.
    UVSessionVar (SessionVarType b) SessionVariable

deriving instance
  ( Backend b,
    Eq (ColumnValue b)
  ) =>
  Eq (UnpreparedValue b)

deriving instance
  ( Backend b,
    Show (ColumnValue b)
  ) =>
  Show (UnpreparedValue b)

-- | This indicates whether a variable value came from a certain GraphQL variable
data ValueWithOrigin a
  = ValueWithOrigin VariableInfo a
  | ValueNoOrigin a
  deriving ((forall a b. (a -> b) -> ValueWithOrigin a -> ValueWithOrigin b)
-> (forall a b. a -> ValueWithOrigin b -> ValueWithOrigin a)
-> Functor ValueWithOrigin
forall a b. a -> ValueWithOrigin b -> ValueWithOrigin a
forall a b. (a -> b) -> ValueWithOrigin a -> ValueWithOrigin b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> ValueWithOrigin a -> ValueWithOrigin b
fmap :: forall a b. (a -> b) -> ValueWithOrigin a -> ValueWithOrigin b
$c<$ :: forall a b. a -> ValueWithOrigin b -> ValueWithOrigin a
<$ :: forall a b. a -> ValueWithOrigin b -> ValueWithOrigin a
Functor)

openValueOrigin :: ValueWithOrigin a -> a
openValueOrigin :: forall a. ValueWithOrigin a -> a
openValueOrigin (ValueWithOrigin VariableInfo
_ a
a) = a
a
openValueOrigin (ValueNoOrigin a
a) = a
a

mkParameter :: ValueWithOrigin (ColumnValue b) -> UnpreparedValue b
mkParameter :: forall (b :: BackendType).
ValueWithOrigin (ColumnValue b) -> UnpreparedValue b
mkParameter (ValueWithOrigin VariableInfo
valInfo ColumnValue b
columnValue) =
  Provenance -> ColumnValue b -> UnpreparedValue b
forall (b :: BackendType).
Provenance -> ColumnValue b -> UnpreparedValue b
UVParameter (VariableInfo -> Provenance
FromGraphQL VariableInfo
valInfo) ColumnValue b
columnValue
mkParameter (ValueNoOrigin ColumnValue b
columnValue) =
  Provenance -> ColumnValue b -> UnpreparedValue b
forall (b :: BackendType).
Provenance -> ColumnValue b -> UnpreparedValue b
UVParameter Provenance
FreshVar ColumnValue b
columnValue