-- | Postgres DDL
--
-- Implements the DDL related methods of the 'Hasura.RQL.Types.Metadata.Backend.BackendMetadata'
-- type class for the Postgres backend, which provides an interface for fetching information about
-- the objects in the database, such as tables, relationships, etc.
module Hasura.Backends.Postgres.DDL
  ( parseCollectableType,
    module M,
  )
where

import Data.Aeson
import Hasura.Backends.Postgres.DDL.BoolExp as M
import Hasura.Backends.Postgres.DDL.ComputedField as M
import Hasura.Backends.Postgres.DDL.EventTrigger as M
import Hasura.Backends.Postgres.DDL.Function as M
import Hasura.Backends.Postgres.DDL.Source as M
import Hasura.Backends.Postgres.DDL.Table as M
import Hasura.Backends.Postgres.SQL.DML
import Hasura.Backends.Postgres.Translate.Column
import Hasura.Backends.Postgres.Types.Column
import Hasura.Base.Error
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BackendType
import Hasura.RQL.Types.Column
import Hasura.SQL.Types
import Hasura.Server.Utils
import Hasura.Session

parseCollectableType ::
  forall pgKind m.
  (Backend ('Postgres pgKind), MonadError QErr m) =>
  CollectableType (ColumnType ('Postgres pgKind)) ->
  Value ->
  m (PartialSQLExp ('Postgres pgKind))
parseCollectableType :: forall (pgKind :: PostgresKind) (m :: * -> *).
(Backend ('Postgres pgKind), MonadError QErr m) =>
CollectableType (ColumnType ('Postgres pgKind))
-> Value -> m (PartialSQLExp ('Postgres pgKind))
parseCollectableType CollectableType (ColumnType ('Postgres pgKind))
pgType = \case
  -- When it is a special variable
  String Text
t
    | Text -> Bool
isSessionVariable Text
t -> PartialSQLExp ('Postgres pgKind)
-> m (PartialSQLExp ('Postgres pgKind))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (PartialSQLExp ('Postgres pgKind)
 -> m (PartialSQLExp ('Postgres pgKind)))
-> PartialSQLExp ('Postgres pgKind)
-> m (PartialSQLExp ('Postgres pgKind))
forall a b. (a -> b) -> a -> b
$ CollectableType (ColumnType ('Postgres pgKind))
-> SessionVariable -> PartialSQLExp ('Postgres pgKind)
forall (pgKind :: PostgresKind).
CollectableType (ColumnType ('Postgres pgKind))
-> SessionVariable -> PartialSQLExp ('Postgres pgKind)
mkTypedSessionVar CollectableType (ColumnType ('Postgres pgKind))
pgType (SessionVariable -> PartialSQLExp ('Postgres pgKind))
-> SessionVariable -> PartialSQLExp ('Postgres pgKind)
forall a b. (a -> b) -> a -> b
$ Text -> SessionVariable
mkSessionVariable Text
t
    | Text -> Bool
isReqUserId Text
t -> PartialSQLExp ('Postgres pgKind)
-> m (PartialSQLExp ('Postgres pgKind))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (PartialSQLExp ('Postgres pgKind)
 -> m (PartialSQLExp ('Postgres pgKind)))
-> PartialSQLExp ('Postgres pgKind)
-> m (PartialSQLExp ('Postgres pgKind))
forall a b. (a -> b) -> a -> b
$ CollectableType (ColumnType ('Postgres pgKind))
-> SessionVariable -> PartialSQLExp ('Postgres pgKind)
forall (pgKind :: PostgresKind).
CollectableType (ColumnType ('Postgres pgKind))
-> SessionVariable -> PartialSQLExp ('Postgres pgKind)
mkTypedSessionVar CollectableType (ColumnType ('Postgres pgKind))
pgType SessionVariable
forall a. IsString a => a
userIdHeader
  -- Typical value as Aeson's value
  Value
val -> case CollectableType (ColumnType ('Postgres pgKind))
pgType of
    CollectableTypeScalar ColumnType ('Postgres pgKind)
cvType ->
      SQLExpression ('Postgres pgKind)
-> PartialSQLExp ('Postgres pgKind)
SQLExp -> PartialSQLExp ('Postgres pgKind)
forall (backend :: BackendType).
SQLExpression backend -> PartialSQLExp backend
PSESQLExp (SQLExp -> PartialSQLExp ('Postgres pgKind))
-> (PGScalarValue -> SQLExp)
-> PGScalarValue
-> PartialSQLExp ('Postgres pgKind)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ColumnValue ('Postgres pgKind) -> SQLExp
forall (pgKind :: PostgresKind).
ColumnValue ('Postgres pgKind) -> SQLExp
toTxtValue (ColumnValue ('Postgres pgKind) -> SQLExp)
-> (PGScalarValue -> ColumnValue ('Postgres pgKind))
-> PGScalarValue
-> SQLExp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ColumnType ('Postgres pgKind)
-> ScalarValue ('Postgres pgKind) -> ColumnValue ('Postgres pgKind)
forall (b :: BackendType).
ColumnType b -> ScalarValue b -> ColumnValue b
ColumnValue ColumnType ('Postgres pgKind)
cvType (PGScalarValue -> PartialSQLExp ('Postgres pgKind))
-> m PGScalarValue -> m (PartialSQLExp ('Postgres pgKind))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ScalarTypeParsingContext ('Postgres pgKind)
-> ColumnType ('Postgres pgKind)
-> Value
-> m (ScalarValue ('Postgres pgKind))
forall (m :: * -> *) (b :: BackendType).
(MonadError QErr m, Backend b) =>
ScalarTypeParsingContext b
-> ColumnType b -> Value -> m (ScalarValue b)
parseScalarValueColumnTypeWithContext () ColumnType ('Postgres pgKind)
cvType Value
val
    CollectableTypeArray ColumnType ('Postgres pgKind)
ofType -> do
      [Value]
vals <- (Value -> Parser [Value]) -> Value -> m [Value]
forall (m :: * -> *) v a. QErrM m => (v -> Parser a) -> v -> m a
runAesonParser Value -> Parser [Value]
forall a. FromJSON a => Value -> Parser a
parseJSON Value
val
      [PGScalarValue]
scalarValues <- ScalarTypeParsingContext ('Postgres pgKind)
-> ColumnType ('Postgres pgKind)
-> [Value]
-> m [ScalarValue ('Postgres pgKind)]
forall (m :: * -> *) (b :: BackendType).
(MonadError QErr m, Backend b) =>
ScalarTypeParsingContext b
-> ColumnType b -> [Value] -> m [ScalarValue b]
parseScalarValuesColumnTypeWithContext () ColumnType ('Postgres pgKind)
ofType [Value]
vals
      PartialSQLExp ('Postgres pgKind)
-> m (PartialSQLExp ('Postgres pgKind))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return
        (PartialSQLExp ('Postgres pgKind)
 -> m (PartialSQLExp ('Postgres pgKind)))
-> (SQLExp -> PartialSQLExp ('Postgres pgKind))
-> SQLExp
-> m (PartialSQLExp ('Postgres pgKind))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SQLExpression ('Postgres pgKind)
-> PartialSQLExp ('Postgres pgKind)
SQLExp -> PartialSQLExp ('Postgres pgKind)
forall (backend :: BackendType).
SQLExpression backend -> PartialSQLExp backend
PSESQLExp
        (SQLExp -> m (PartialSQLExp ('Postgres pgKind)))
-> SQLExp -> m (PartialSQLExp ('Postgres pgKind))
forall a b. (a -> b) -> a -> b
$ SQLExp -> TypeAnn -> SQLExp
SETyAnn
          ([SQLExp] -> SQLExp
SEArray ([SQLExp] -> SQLExp) -> [SQLExp] -> SQLExp
forall a b. (a -> b) -> a -> b
$ (PGScalarValue -> SQLExp) -> [PGScalarValue] -> [SQLExp]
forall a b. (a -> b) -> [a] -> [b]
map (ColumnValue ('Postgres pgKind) -> SQLExp
forall (pgKind :: PostgresKind).
ColumnValue ('Postgres pgKind) -> SQLExp
toTxtValue (ColumnValue ('Postgres pgKind) -> SQLExp)
-> (PGScalarValue -> ColumnValue ('Postgres pgKind))
-> PGScalarValue
-> SQLExp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ColumnType ('Postgres pgKind)
-> ScalarValue ('Postgres pgKind) -> ColumnValue ('Postgres pgKind)
forall (b :: BackendType).
ColumnType b -> ScalarValue b -> ColumnValue b
ColumnValue ColumnType ('Postgres pgKind)
ofType) [PGScalarValue]
scalarValues)
          (CollectableType PGScalarType -> TypeAnn
mkTypeAnn (CollectableType PGScalarType -> TypeAnn)
-> CollectableType PGScalarType -> TypeAnn
forall a b. (a -> b) -> a -> b
$ PGScalarType -> CollectableType PGScalarType
forall a. a -> CollectableType a
CollectableTypeArray (ColumnType ('Postgres pgKind) -> PGScalarType
forall (pgKind :: PostgresKind).
ColumnType ('Postgres pgKind) -> PGScalarType
unsafePGColumnToBackend ColumnType ('Postgres pgKind)
ofType))

mkTypedSessionVar ::
  CollectableType (ColumnType ('Postgres pgKind)) ->
  SessionVariable ->
  PartialSQLExp ('Postgres pgKind)
mkTypedSessionVar :: forall (pgKind :: PostgresKind).
CollectableType (ColumnType ('Postgres pgKind))
-> SessionVariable -> PartialSQLExp ('Postgres pgKind)
mkTypedSessionVar CollectableType (ColumnType ('Postgres pgKind))
columnType =
  SessionVarType ('Postgres pgKind)
-> SessionVariable -> PartialSQLExp ('Postgres pgKind)
forall (backend :: BackendType).
SessionVarType backend -> SessionVariable -> PartialSQLExp backend
PSESessVar (ColumnType ('Postgres pgKind) -> PGScalarType
forall (pgKind :: PostgresKind).
ColumnType ('Postgres pgKind) -> PGScalarType
unsafePGColumnToBackend (ColumnType ('Postgres pgKind) -> PGScalarType)
-> CollectableType (ColumnType ('Postgres pgKind))
-> CollectableType PGScalarType
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CollectableType (ColumnType ('Postgres pgKind))
columnType)