{-# LANGUAGE TemplateHaskell #-}

-- |
-- Description: Schema cache types related to computed field
module Hasura.RQL.Types.ComputedField
  ( ComputedFieldFunction (..),
    ComputedFieldInfo (..),
    ComputedFieldName (..),
    CustomFunctionNames (..),
    FunctionTrackedAs (..),
    cfiDescription,
    cfiFunction,
    cfiName,
    cfiReturnType,
    cfiXComputedFieldInfo,
    computedFieldNameToText,
    fromComputedField,
    removeComputedFieldsReturningExistingTable,
  )
where

import Control.Lens hiding ((.=))
import Data.Aeson
import Data.Sequence qualified as Seq
import Data.Text.Extended
import Data.Text.NonEmpty (NonEmptyText (..))
import Database.PG.Query qualified as Q
import Hasura.Backends.Postgres.SQL.Types hiding (FunctionName, TableName)
import Hasura.Incremental (Cacheable)
import Hasura.Prelude
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Common
import Hasura.SQL.Backend
import Language.GraphQL.Draft.Syntax (Name)

newtype ComputedFieldName = ComputedFieldName {ComputedFieldName -> NonEmptyText
unComputedFieldName :: NonEmptyText}
  deriving (Int -> ComputedFieldName -> ShowS
[ComputedFieldName] -> ShowS
ComputedFieldName -> String
(Int -> ComputedFieldName -> ShowS)
-> (ComputedFieldName -> String)
-> ([ComputedFieldName] -> ShowS)
-> Show ComputedFieldName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ComputedFieldName] -> ShowS
$cshowList :: [ComputedFieldName] -> ShowS
show :: ComputedFieldName -> String
$cshow :: ComputedFieldName -> String
showsPrec :: Int -> ComputedFieldName -> ShowS
$cshowsPrec :: Int -> ComputedFieldName -> ShowS
Show, ComputedFieldName -> ComputedFieldName -> Bool
(ComputedFieldName -> ComputedFieldName -> Bool)
-> (ComputedFieldName -> ComputedFieldName -> Bool)
-> Eq ComputedFieldName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ComputedFieldName -> ComputedFieldName -> Bool
$c/= :: ComputedFieldName -> ComputedFieldName -> Bool
== :: ComputedFieldName -> ComputedFieldName -> Bool
$c== :: ComputedFieldName -> ComputedFieldName -> Bool
Eq, Eq ComputedFieldName
Eq ComputedFieldName
-> (ComputedFieldName -> ComputedFieldName -> Ordering)
-> (ComputedFieldName -> ComputedFieldName -> Bool)
-> (ComputedFieldName -> ComputedFieldName -> Bool)
-> (ComputedFieldName -> ComputedFieldName -> Bool)
-> (ComputedFieldName -> ComputedFieldName -> Bool)
-> (ComputedFieldName -> ComputedFieldName -> ComputedFieldName)
-> (ComputedFieldName -> ComputedFieldName -> ComputedFieldName)
-> Ord ComputedFieldName
ComputedFieldName -> ComputedFieldName -> Bool
ComputedFieldName -> ComputedFieldName -> Ordering
ComputedFieldName -> ComputedFieldName -> ComputedFieldName
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ComputedFieldName -> ComputedFieldName -> ComputedFieldName
$cmin :: ComputedFieldName -> ComputedFieldName -> ComputedFieldName
max :: ComputedFieldName -> ComputedFieldName -> ComputedFieldName
$cmax :: ComputedFieldName -> ComputedFieldName -> ComputedFieldName
>= :: ComputedFieldName -> ComputedFieldName -> Bool
$c>= :: ComputedFieldName -> ComputedFieldName -> Bool
> :: ComputedFieldName -> ComputedFieldName -> Bool
$c> :: ComputedFieldName -> ComputedFieldName -> Bool
<= :: ComputedFieldName -> ComputedFieldName -> Bool
$c<= :: ComputedFieldName -> ComputedFieldName -> Bool
< :: ComputedFieldName -> ComputedFieldName -> Bool
$c< :: ComputedFieldName -> ComputedFieldName -> Bool
compare :: ComputedFieldName -> ComputedFieldName -> Ordering
$ccompare :: ComputedFieldName -> ComputedFieldName -> Ordering
$cp1Ord :: Eq ComputedFieldName
Ord, ComputedFieldName -> ()
(ComputedFieldName -> ()) -> NFData ComputedFieldName
forall a. (a -> ()) -> NFData a
rnf :: ComputedFieldName -> ()
$crnf :: ComputedFieldName -> ()
NFData, Value -> Parser [ComputedFieldName]
Value -> Parser ComputedFieldName
(Value -> Parser ComputedFieldName)
-> (Value -> Parser [ComputedFieldName])
-> FromJSON ComputedFieldName
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [ComputedFieldName]
$cparseJSONList :: Value -> Parser [ComputedFieldName]
parseJSON :: Value -> Parser ComputedFieldName
$cparseJSON :: Value -> Parser ComputedFieldName
FromJSON, [ComputedFieldName] -> Value
[ComputedFieldName] -> Encoding
ComputedFieldName -> Value
ComputedFieldName -> Encoding
(ComputedFieldName -> Value)
-> (ComputedFieldName -> Encoding)
-> ([ComputedFieldName] -> Value)
-> ([ComputedFieldName] -> Encoding)
-> ToJSON ComputedFieldName
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [ComputedFieldName] -> Encoding
$ctoEncodingList :: [ComputedFieldName] -> Encoding
toJSONList :: [ComputedFieldName] -> Value
$ctoJSONList :: [ComputedFieldName] -> Value
toEncoding :: ComputedFieldName -> Encoding
$ctoEncoding :: ComputedFieldName -> Encoding
toJSON :: ComputedFieldName -> Value
$ctoJSON :: ComputedFieldName -> Value
ToJSON, ToJSONKeyFunction [ComputedFieldName]
ToJSONKeyFunction ComputedFieldName
ToJSONKeyFunction ComputedFieldName
-> ToJSONKeyFunction [ComputedFieldName]
-> ToJSONKey ComputedFieldName
forall a.
ToJSONKeyFunction a -> ToJSONKeyFunction [a] -> ToJSONKey a
toJSONKeyList :: ToJSONKeyFunction [ComputedFieldName]
$ctoJSONKeyList :: ToJSONKeyFunction [ComputedFieldName]
toJSONKey :: ToJSONKeyFunction ComputedFieldName
$ctoJSONKey :: ToJSONKeyFunction ComputedFieldName
ToJSONKey, ComputedFieldName -> PrepArg
(ComputedFieldName -> PrepArg) -> ToPrepArg ComputedFieldName
forall a. (a -> PrepArg) -> ToPrepArg a
toPrepVal :: ComputedFieldName -> PrepArg
$ctoPrepVal :: ComputedFieldName -> PrepArg
Q.ToPrepArg, ComputedFieldName -> Text
(ComputedFieldName -> Text) -> ToTxt ComputedFieldName
forall a. (a -> Text) -> ToTxt a
toTxt :: ComputedFieldName -> Text
$ctoTxt :: ComputedFieldName -> Text
ToTxt, Int -> ComputedFieldName -> Int
ComputedFieldName -> Int
(Int -> ComputedFieldName -> Int)
-> (ComputedFieldName -> Int) -> Hashable ComputedFieldName
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: ComputedFieldName -> Int
$chash :: ComputedFieldName -> Int
hashWithSalt :: Int -> ComputedFieldName -> Int
$chashWithSalt :: Int -> ComputedFieldName -> Int
Hashable, Maybe ByteString -> Either Text ComputedFieldName
(Maybe ByteString -> Either Text ComputedFieldName)
-> FromCol ComputedFieldName
forall a. (Maybe ByteString -> Either Text a) -> FromCol a
fromCol :: Maybe ByteString -> Either Text ComputedFieldName
$cfromCol :: Maybe ByteString -> Either Text ComputedFieldName
Q.FromCol, (forall x. ComputedFieldName -> Rep ComputedFieldName x)
-> (forall x. Rep ComputedFieldName x -> ComputedFieldName)
-> Generic ComputedFieldName
forall x. Rep ComputedFieldName x -> ComputedFieldName
forall x. ComputedFieldName -> Rep ComputedFieldName x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ComputedFieldName x -> ComputedFieldName
$cfrom :: forall x. ComputedFieldName -> Rep ComputedFieldName x
Generic, Eq ComputedFieldName
Eq ComputedFieldName
-> (Accesses -> ComputedFieldName -> ComputedFieldName -> Bool)
-> Cacheable ComputedFieldName
Accesses -> ComputedFieldName -> ComputedFieldName -> Bool
forall a. Eq a -> (Accesses -> a -> a -> Bool) -> Cacheable a
unchanged :: Accesses -> ComputedFieldName -> ComputedFieldName -> Bool
$cunchanged :: Accesses -> ComputedFieldName -> ComputedFieldName -> Bool
$cp1Cacheable :: Eq ComputedFieldName
Cacheable)

computedFieldNameToText :: ComputedFieldName -> Text
computedFieldNameToText :: ComputedFieldName -> Text
computedFieldNameToText = NonEmptyText -> Text
unNonEmptyText (NonEmptyText -> Text)
-> (ComputedFieldName -> NonEmptyText) -> ComputedFieldName -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ComputedFieldName -> NonEmptyText
unComputedFieldName

fromComputedField :: ComputedFieldName -> FieldName
fromComputedField :: ComputedFieldName -> FieldName
fromComputedField = Text -> FieldName
FieldName (Text -> FieldName)
-> (ComputedFieldName -> Text) -> ComputedFieldName -> FieldName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ComputedFieldName -> Text
computedFieldNameToText

data FunctionTrackedAs (b :: BackendType)
  = FTAComputedField ComputedFieldName SourceName (TableName b)
  | FTACustomFunction CustomFunctionNames
  deriving ((forall x. FunctionTrackedAs b -> Rep (FunctionTrackedAs b) x)
-> (forall x. Rep (FunctionTrackedAs b) x -> FunctionTrackedAs b)
-> Generic (FunctionTrackedAs b)
forall x. Rep (FunctionTrackedAs b) x -> FunctionTrackedAs b
forall x. FunctionTrackedAs b -> Rep (FunctionTrackedAs b) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (b :: BackendType) x.
Rep (FunctionTrackedAs b) x -> FunctionTrackedAs b
forall (b :: BackendType) x.
FunctionTrackedAs b -> Rep (FunctionTrackedAs b) x
$cto :: forall (b :: BackendType) x.
Rep (FunctionTrackedAs b) x -> FunctionTrackedAs b
$cfrom :: forall (b :: BackendType) x.
FunctionTrackedAs b -> Rep (FunctionTrackedAs b) x
Generic)

-- | The function name and input arguments name for the "args" field parser.
--
-- > function_name(args: args_name)
data CustomFunctionNames = CustomFunctionNames
  { CustomFunctionNames -> Name
cfnFunctionName :: Name,
    CustomFunctionNames -> Name
cfnArgsName :: Name
  }
  deriving (Int -> CustomFunctionNames -> ShowS
[CustomFunctionNames] -> ShowS
CustomFunctionNames -> String
(Int -> CustomFunctionNames -> ShowS)
-> (CustomFunctionNames -> String)
-> ([CustomFunctionNames] -> ShowS)
-> Show CustomFunctionNames
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CustomFunctionNames] -> ShowS
$cshowList :: [CustomFunctionNames] -> ShowS
show :: CustomFunctionNames -> String
$cshow :: CustomFunctionNames -> String
showsPrec :: Int -> CustomFunctionNames -> ShowS
$cshowsPrec :: Int -> CustomFunctionNames -> ShowS
Show, CustomFunctionNames -> CustomFunctionNames -> Bool
(CustomFunctionNames -> CustomFunctionNames -> Bool)
-> (CustomFunctionNames -> CustomFunctionNames -> Bool)
-> Eq CustomFunctionNames
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CustomFunctionNames -> CustomFunctionNames -> Bool
$c/= :: CustomFunctionNames -> CustomFunctionNames -> Bool
== :: CustomFunctionNames -> CustomFunctionNames -> Bool
$c== :: CustomFunctionNames -> CustomFunctionNames -> Bool
Eq, (forall x. CustomFunctionNames -> Rep CustomFunctionNames x)
-> (forall x. Rep CustomFunctionNames x -> CustomFunctionNames)
-> Generic CustomFunctionNames
forall x. Rep CustomFunctionNames x -> CustomFunctionNames
forall x. CustomFunctionNames -> Rep CustomFunctionNames x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CustomFunctionNames x -> CustomFunctionNames
$cfrom :: forall x. CustomFunctionNames -> Rep CustomFunctionNames x
Generic)

deriving instance Backend b => Show (FunctionTrackedAs b)

deriving instance Backend b => Eq (FunctionTrackedAs b)

data ComputedFieldFunction (b :: BackendType) = ComputedFieldFunction
  { ComputedFieldFunction b -> FunctionName b
_cffName :: FunctionName b,
    ComputedFieldFunction b -> Seq (FunctionArgument b)
_cffInputArgs :: Seq.Seq (FunctionArgument b),
    ComputedFieldFunction b -> ComputedFieldImplicitArguments b
_cffComputedFieldImplicitArgs :: ComputedFieldImplicitArguments b,
    ComputedFieldFunction b -> Maybe PGDescription
_cffDescription :: Maybe PGDescription
  }
  deriving ((forall x.
 ComputedFieldFunction b -> Rep (ComputedFieldFunction b) x)
-> (forall x.
    Rep (ComputedFieldFunction b) x -> ComputedFieldFunction b)
-> Generic (ComputedFieldFunction b)
forall x.
Rep (ComputedFieldFunction b) x -> ComputedFieldFunction b
forall x.
ComputedFieldFunction b -> Rep (ComputedFieldFunction b) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (b :: BackendType) x.
Rep (ComputedFieldFunction b) x -> ComputedFieldFunction b
forall (b :: BackendType) x.
ComputedFieldFunction b -> Rep (ComputedFieldFunction b) x
$cto :: forall (b :: BackendType) x.
Rep (ComputedFieldFunction b) x -> ComputedFieldFunction b
$cfrom :: forall (b :: BackendType) x.
ComputedFieldFunction b -> Rep (ComputedFieldFunction b) x
Generic)

deriving instance (Backend b) => Show (ComputedFieldFunction b)

deriving instance (Backend b) => Eq (ComputedFieldFunction b)

instance (Backend b) => Cacheable (ComputedFieldFunction b)

instance (Backend b) => NFData (ComputedFieldFunction b)

instance (Backend b) => Hashable (ComputedFieldFunction b)

instance (Backend b) => ToJSON (ComputedFieldFunction b) where
  toJSON :: ComputedFieldFunction b -> Value
toJSON = Options -> ComputedFieldFunction b -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON Options
hasuraJSON

data ComputedFieldInfo (b :: BackendType) = ComputedFieldInfo
  { ComputedFieldInfo b -> XComputedField b
_cfiXComputedFieldInfo :: XComputedField b,
    ComputedFieldInfo b -> ComputedFieldName
_cfiName :: ComputedFieldName,
    ComputedFieldInfo b -> ComputedFieldFunction b
_cfiFunction :: ComputedFieldFunction b,
    ComputedFieldInfo b -> ComputedFieldReturn b
_cfiReturnType :: ComputedFieldReturn b,
    ComputedFieldInfo b -> Maybe Text
_cfiDescription :: Maybe Text
  }
  deriving ((forall x. ComputedFieldInfo b -> Rep (ComputedFieldInfo b) x)
-> (forall x. Rep (ComputedFieldInfo b) x -> ComputedFieldInfo b)
-> Generic (ComputedFieldInfo b)
forall x. Rep (ComputedFieldInfo b) x -> ComputedFieldInfo b
forall x. ComputedFieldInfo b -> Rep (ComputedFieldInfo b) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (b :: BackendType) x.
Rep (ComputedFieldInfo b) x -> ComputedFieldInfo b
forall (b :: BackendType) x.
ComputedFieldInfo b -> Rep (ComputedFieldInfo b) x
$cto :: forall (b :: BackendType) x.
Rep (ComputedFieldInfo b) x -> ComputedFieldInfo b
$cfrom :: forall (b :: BackendType) x.
ComputedFieldInfo b -> Rep (ComputedFieldInfo b) x
Generic)

deriving instance (Backend b) => Eq (ComputedFieldInfo b)

deriving instance (Backend b) => Show (ComputedFieldInfo b)

instance (Backend b) => NFData (ComputedFieldInfo b)

instance (Backend b) => Cacheable (ComputedFieldInfo b)

instance (Backend b) => Hashable (ComputedFieldInfo b)

instance (Backend b) => ToJSON (ComputedFieldInfo b) where
  -- spelling out the JSON instance in order to skip the Trees That Grow field
  toJSON :: ComputedFieldInfo b -> Value
toJSON (ComputedFieldInfo XComputedField b
_ ComputedFieldName
name ComputedFieldFunction b
func ComputedFieldReturn b
tp Maybe Text
description) =
    [Pair] -> Value
object [Key
"name" Key -> ComputedFieldName -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= ComputedFieldName
name, Key
"function" Key -> ComputedFieldFunction b -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= ComputedFieldFunction b
func, Key
"return_type" Key -> ComputedFieldReturn b -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= ComputedFieldReturn b
tp, Key
"description" Key -> Maybe Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Text
description]

$(makeLenses ''ComputedFieldInfo)

-- | Filter computed fields not returning rows of existing table
removeComputedFieldsReturningExistingTable ::
  forall backend.
  (Backend backend) =>
  [ComputedFieldInfo backend] ->
  [ComputedFieldInfo backend]
removeComputedFieldsReturningExistingTable :: [ComputedFieldInfo backend] -> [ComputedFieldInfo backend]
removeComputedFieldsReturningExistingTable =
  (ComputedFieldInfo backend -> Bool)
-> [ComputedFieldInfo backend] -> [ComputedFieldInfo backend]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> (ComputedFieldInfo backend -> Bool)
-> ComputedFieldInfo backend
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting Any (ComputedFieldReturnType backend) (TableName backend)
-> ComputedFieldReturnType backend -> Bool
forall s a. Getting Any s a -> s -> Bool
has Getting Any (ComputedFieldReturnType backend) (TableName backend)
forall (b :: BackendType).
Prism' (ComputedFieldReturnType b) (TableName b)
_ReturnsTable (ComputedFieldReturnType backend -> Bool)
-> (ComputedFieldInfo backend -> ComputedFieldReturnType backend)
-> ComputedFieldInfo backend
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Backend backend =>
ComputedFieldReturn backend -> ComputedFieldReturnType backend
forall (b :: BackendType).
Backend b =>
ComputedFieldReturn b -> ComputedFieldReturnType b
computedFieldReturnType @backend (ComputedFieldReturn backend -> ComputedFieldReturnType backend)
-> (ComputedFieldInfo backend -> ComputedFieldReturn backend)
-> ComputedFieldInfo backend
-> ComputedFieldReturnType backend
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ComputedFieldInfo backend -> ComputedFieldReturn backend
forall (b :: BackendType).
ComputedFieldInfo b -> ComputedFieldReturn b
_cfiReturnType)