{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE UndecidableInstances #-}

-- | More leaves peeled from `RQL.IR.Select` for compilation speed
module Hasura.RQL.IR.Select.From
  ( FIIdentifier (..),
    SelectFrom,
    SelectFromG (..),
  )
where

import Hasura.Backends.Postgres.SQL.Types qualified as Postgres
import Hasura.Function.Cache
import Hasura.NativeQuery.IR (NativeQuery)
import Hasura.Prelude
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BackendType
import Hasura.StoredProcedure.IR (StoredProcedure)

data SelectFromG (b :: BackendType) v
  = FromTable (TableName b)
  | FromIdentifier FIIdentifier -- TODO: Make this into TableIdentifier?
  | FromFunction
      (FunctionName b)
      (FunctionArgsExp b v)
      -- a definition list
      (Maybe [(Column b, ScalarType b)])
  | FromNativeQuery (NativeQuery b v)
  | FromStoredProcedure (StoredProcedure b v)
  deriving stock ((forall x. SelectFromG b v -> Rep (SelectFromG b v) x)
-> (forall x. Rep (SelectFromG b v) x -> SelectFromG b v)
-> Generic (SelectFromG b v)
forall x. Rep (SelectFromG b v) x -> SelectFromG b v
forall x. SelectFromG b v -> Rep (SelectFromG b v) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (b :: BackendType) v x.
Rep (SelectFromG b v) x -> SelectFromG b v
forall (b :: BackendType) v x.
SelectFromG b v -> Rep (SelectFromG b v) x
$cfrom :: forall (b :: BackendType) v x.
SelectFromG b v -> Rep (SelectFromG b v) x
from :: forall x. SelectFromG b v -> Rep (SelectFromG b v) x
$cto :: forall (b :: BackendType) v x.
Rep (SelectFromG b v) x -> SelectFromG b v
to :: forall x. Rep (SelectFromG b v) x -> SelectFromG b v
Generic)

deriving stock instance (Backend b) => Functor (SelectFromG b)

deriving stock instance (Backend b) => Foldable (SelectFromG b)

deriving stock instance (Backend b) => Traversable (SelectFromG b)

deriving stock instance
  ( Backend b,
    Eq v,
    Eq (FunctionArgumentExp b v),
    Eq (NativeQuery b v),
    Eq (StoredProcedure b v)
  ) =>
  Eq (SelectFromG b v)

deriving stock instance
  ( Backend b,
    Show v,
    Show (FunctionArgumentExp b v),
    Show (NativeQuery b v),
    Show (StoredProcedure b v)
  ) =>
  Show (SelectFromG b v)

instance
  ( Backend b,
    Hashable v,
    Hashable (FunctionArgumentExp b v),
    Hashable (NativeQuery b v),
    Hashable (StoredProcedure b v)
  ) =>
  Hashable (SelectFromG b v)

type SelectFrom b = SelectFromG b (SQLExpression b)

-- | Identifier used exclusively as the argument to 'FromIdentifier'
newtype FIIdentifier = FIIdentifier
  { FIIdentifier -> Text
unFIIdentifier :: Text
  }
  deriving stock ((forall x. FIIdentifier -> Rep FIIdentifier x)
-> (forall x. Rep FIIdentifier x -> FIIdentifier)
-> Generic FIIdentifier
forall x. Rep FIIdentifier x -> FIIdentifier
forall x. FIIdentifier -> Rep FIIdentifier x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. FIIdentifier -> Rep FIIdentifier x
from :: forall x. FIIdentifier -> Rep FIIdentifier x
$cto :: forall x. Rep FIIdentifier x -> FIIdentifier
to :: forall x. Rep FIIdentifier x -> FIIdentifier
Generic)
  deriving newtype (FIIdentifier -> FIIdentifier -> Bool
(FIIdentifier -> FIIdentifier -> Bool)
-> (FIIdentifier -> FIIdentifier -> Bool) -> Eq FIIdentifier
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FIIdentifier -> FIIdentifier -> Bool
== :: FIIdentifier -> FIIdentifier -> Bool
$c/= :: FIIdentifier -> FIIdentifier -> Bool
/= :: FIIdentifier -> FIIdentifier -> Bool
Eq, Int -> FIIdentifier -> ShowS
[FIIdentifier] -> ShowS
FIIdentifier -> String
(Int -> FIIdentifier -> ShowS)
-> (FIIdentifier -> String)
-> ([FIIdentifier] -> ShowS)
-> Show FIIdentifier
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FIIdentifier -> ShowS
showsPrec :: Int -> FIIdentifier -> ShowS
$cshow :: FIIdentifier -> String
show :: FIIdentifier -> String
$cshowList :: [FIIdentifier] -> ShowS
showList :: [FIIdentifier] -> ShowS
Show)
  deriving anyclass (Eq FIIdentifier
Eq FIIdentifier
-> (Int -> FIIdentifier -> Int)
-> (FIIdentifier -> Int)
-> Hashable FIIdentifier
Int -> FIIdentifier -> Int
FIIdentifier -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> FIIdentifier -> Int
hashWithSalt :: Int -> FIIdentifier -> Int
$chash :: FIIdentifier -> Int
hash :: FIIdentifier -> Int
Hashable)

instance Postgres.IsIdentifier FIIdentifier where
  toIdentifier :: FIIdentifier -> Identifier
toIdentifier = FIIdentifier -> Identifier
forall a b. Coercible a b => a -> b
coerce
  {-# INLINE toIdentifier #-}