module Hasura.RQL.DDL.Schema.Source
  ( -- * Add Source
    AddSource,
    runAddSource,

    -- * Drop Source
    DropSource (..),
    runDropSource,
    runPostDropSourceHook,

    -- * Rename Source
    RenameSource,
    runRenameSource,

    -- * Update Source
    UpdateSource,
    runUpdateSource,

    -- * Get Source Tables
    GetSourceTables (..),
    runGetSourceTables,

    -- * Get Source Functions
    GetSourceTrackables (..),
    runGetSourceTrackables,

    -- * Get Table Info
    GetTableInfo (..),
    runGetTableInfo,

    -- * Legacy Get Table Info
    GetTableInfo_ (..),
    runGetTableInfo_,
  )
where

--------------------------------------------------------------------------------

import Control.Lens (at, (.~), (^.))
import Control.Monad.Trans.Control (MonadBaseControl)
import Data.Aeson qualified as J
import Data.Aeson.Extended
import Data.Environment qualified as Env
import Data.Has
import Data.HashMap.Strict qualified as HashMap
import Data.HashMap.Strict.InsOrd qualified as InsOrdHashMap
import Data.Text.Extended
import Data.Text.Extended qualified as Text.E
import Hasura.Base.Error
import Hasura.Base.Error qualified as Error
import Hasura.EncJSON
import Hasura.EncJSON qualified as EncJSON
import Hasura.Logging qualified as L
import Hasura.Prelude
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Backend qualified as RQL.Types
import Hasura.RQL.Types.BackendType
import Hasura.RQL.Types.BackendType qualified as Backend
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.Common qualified as Common
import Hasura.RQL.Types.HealthCheck (HealthCheckConfig)
import Hasura.RQL.Types.Metadata
import Hasura.RQL.Types.Metadata qualified as Metadata
import Hasura.RQL.Types.Metadata.Backend
import Hasura.RQL.Types.Metadata.Instances ()
import Hasura.RQL.Types.Metadata.Object
import Hasura.RQL.Types.SchemaCache
import Hasura.RQL.Types.SchemaCache.Build
import Hasura.RQL.Types.SchemaCacheTypes
import Hasura.RQL.Types.Source
import Hasura.RQL.Types.SourceCustomization
import Hasura.SQL.AnyBackend (AnyBackend)
import Hasura.SQL.AnyBackend qualified as AB
import Hasura.SQL.AnyBackend qualified as AnyBackend
import Hasura.Server.Logging (MetadataLog (..))
import Hasura.Services

--------------------------------------------------------------------------------
-- Add source

data AddSource b = AddSource
  { forall (b :: BackendType). AddSource b -> SourceName
_asName :: SourceName,
    forall (b :: BackendType). AddSource b -> BackendSourceKind b
_asBackendKind :: BackendSourceKind b,
    forall (b :: BackendType). AddSource b -> SourceConnConfiguration b
_asConfiguration :: SourceConnConfiguration b,
    forall (b :: BackendType). AddSource b -> Bool
_asReplaceConfiguration :: Bool,
    forall (b :: BackendType). AddSource b -> SourceCustomization
_asCustomization :: SourceCustomization,
    forall (b :: BackendType).
AddSource b -> Maybe (HealthCheckConfig b)
_asHealthCheckConfig :: Maybe (HealthCheckConfig b)
  }

instance (Backend b) => FromJSONWithContext (BackendSourceKind b) (AddSource b) where
  parseJSONWithContext :: BackendSourceKind b -> Value -> Parser (AddSource b)
parseJSONWithContext BackendSourceKind b
backendKind = String
-> (Object -> Parser (AddSource b))
-> Value
-> Parser (AddSource b)
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"AddSource" ((Object -> Parser (AddSource b)) -> Value -> Parser (AddSource b))
-> (Object -> Parser (AddSource b))
-> Value
-> Parser (AddSource b)
forall a b. (a -> b) -> a -> b
$ \Object
o ->
    SourceName
-> BackendSourceKind b
-> SourceConnConfiguration b
-> Bool
-> SourceCustomization
-> Maybe (HealthCheckConfig b)
-> AddSource b
forall (b :: BackendType).
SourceName
-> BackendSourceKind b
-> SourceConnConfiguration b
-> Bool
-> SourceCustomization
-> Maybe (HealthCheckConfig b)
-> AddSource b
AddSource
      (SourceName
 -> BackendSourceKind b
 -> SourceConnConfiguration b
 -> Bool
 -> SourceCustomization
 -> Maybe (HealthCheckConfig b)
 -> AddSource b)
-> Parser SourceName
-> Parser
     (BackendSourceKind b
      -> SourceConnConfiguration b
      -> Bool
      -> SourceCustomization
      -> Maybe (HealthCheckConfig b)
      -> AddSource b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o
      Object -> Key -> Parser SourceName
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name"
      Parser
  (BackendSourceKind b
   -> SourceConnConfiguration b
   -> Bool
   -> SourceCustomization
   -> Maybe (HealthCheckConfig b)
   -> AddSource b)
-> Parser (BackendSourceKind b)
-> Parser
     (SourceConnConfiguration b
      -> Bool
      -> SourceCustomization
      -> Maybe (HealthCheckConfig b)
      -> AddSource b)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> BackendSourceKind b -> Parser (BackendSourceKind b)
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure BackendSourceKind b
backendKind
      Parser
  (SourceConnConfiguration b
   -> Bool
   -> SourceCustomization
   -> Maybe (HealthCheckConfig b)
   -> AddSource b)
-> Parser (SourceConnConfiguration b)
-> Parser
     (Bool
      -> SourceCustomization
      -> Maybe (HealthCheckConfig b)
      -> AddSource b)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o
      Object -> Key -> Parser (SourceConnConfiguration b)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"configuration"
      Parser
  (Bool
   -> SourceCustomization
   -> Maybe (HealthCheckConfig b)
   -> AddSource b)
-> Parser Bool
-> Parser
     (SourceCustomization -> Maybe (HealthCheckConfig b) -> AddSource b)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o
      Object -> Key -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"replace_configuration"
      Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= Bool
False
      Parser
  (SourceCustomization -> Maybe (HealthCheckConfig b) -> AddSource b)
-> Parser SourceCustomization
-> Parser (Maybe (HealthCheckConfig b) -> AddSource b)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o
      Object -> Key -> Parser (Maybe SourceCustomization)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"customization"
      Parser (Maybe SourceCustomization)
-> SourceCustomization -> Parser SourceCustomization
forall a. Parser (Maybe a) -> a -> Parser a
.!= SourceCustomization
emptySourceCustomization
      Parser (Maybe (HealthCheckConfig b) -> AddSource b)
-> Parser (Maybe (HealthCheckConfig b)) -> Parser (AddSource b)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o
      Object -> Key -> Parser (Maybe (HealthCheckConfig b))
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"health_check"

runAddSource ::
  forall m b.
  (MonadIO m, MonadError QErr m, CacheRWM m, MetadataM m, BackendMetadata b) =>
  Env.Environment ->
  AddSource b ->
  m EncJSON
runAddSource :: forall (m :: * -> *) (b :: BackendType).
(MonadIO m, MonadError QErr m, CacheRWM m, MetadataM m,
 BackendMetadata b) =>
Environment -> AddSource b -> m EncJSON
runAddSource Environment
env (AddSource SourceName
name BackendSourceKind b
backendKind SourceConnConfiguration b
sourceConfig Bool
replaceConfiguration SourceCustomization
sourceCustomization Maybe (HealthCheckConfig b)
healthCheckConfig) = do
  SourceCache
sources <- SchemaCache -> SourceCache
scSources (SchemaCache -> SourceCache) -> m SchemaCache -> m SourceCache
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m SchemaCache
forall (m :: * -> *). CacheRM m => m SchemaCache
askSchemaCache
  do
    -- version check
    Either QErr ()
result <- IO (Either QErr ()) -> m (Either QErr ())
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either QErr ()) -> m (Either QErr ()))
-> IO (Either QErr ()) -> m (Either QErr ())
forall a b. (a -> b) -> a -> b
$ forall (b :: BackendType).
Backend b =>
Environment -> SourceConnConfiguration b -> IO (Either QErr ())
versionCheckImplementation @b Environment
env SourceConnConfiguration b
sourceConfig
    Either QErr () -> m ()
forall e (m :: * -> *) a. MonadError e m => Either e a -> m a
liftEither Either QErr ()
result

  MetadataModifier
metadataModifier <-
    (Metadata -> Metadata) -> MetadataModifier
MetadataModifier
      ((Metadata -> Metadata) -> MetadataModifier)
-> m (Metadata -> Metadata) -> m MetadataModifier
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> if SourceName -> SourceCache -> Bool
forall k a. (Eq k, Hashable k) => k -> HashMap k a -> Bool
HashMap.member SourceName
name SourceCache
sources
        then
          if Bool
replaceConfiguration
            then do
              let sMetadata :: (SourceMetadata b -> Identity (SourceMetadata b))
-> Metadata -> Identity Metadata
sMetadata = (Sources -> Identity Sources) -> Metadata -> Identity Metadata
Lens' Metadata Sources
metaSources ((Sources -> Identity Sources) -> Metadata -> Identity Metadata)
-> ((SourceMetadata b -> Identity (SourceMetadata b))
    -> Sources -> Identity Sources)
-> (SourceMetadata b -> Identity (SourceMetadata b))
-> Metadata
-> Identity Metadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index Sources -> Traversal' Sources (IxValue Sources)
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Index Sources
SourceName
name ((BackendSourceMetadata -> Identity BackendSourceMetadata)
 -> Sources -> Identity Sources)
-> ((SourceMetadata b -> Identity (SourceMetadata b))
    -> BackendSourceMetadata -> Identity BackendSourceMetadata)
-> (SourceMetadata b -> Identity (SourceMetadata b))
-> Sources
-> Identity Sources
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (b :: BackendType).
Backend b =>
Prism' BackendSourceMetadata (SourceMetadata b)
toSourceMetadata @b
                  updateConfig :: Metadata -> Metadata
updateConfig = (SourceMetadata b -> Identity (SourceMetadata b))
-> Metadata -> Identity Metadata
sMetadata ((SourceMetadata b -> Identity (SourceMetadata b))
 -> Metadata -> Identity Metadata)
-> ((SourceConnConfiguration b
     -> Identity (SourceConnConfiguration b))
    -> SourceMetadata b -> Identity (SourceMetadata b))
-> (SourceConnConfiguration b
    -> Identity (SourceConnConfiguration b))
-> Metadata
-> Identity Metadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SourceConnConfiguration b -> Identity (SourceConnConfiguration b))
-> SourceMetadata b -> Identity (SourceMetadata b)
forall (b :: BackendType) (f :: * -> *).
Functor f =>
(SourceConnConfiguration b -> f (SourceConnConfiguration b))
-> SourceMetadata b -> f (SourceMetadata b)
smConfiguration ((SourceConnConfiguration b
  -> Identity (SourceConnConfiguration b))
 -> Metadata -> Identity Metadata)
-> SourceConnConfiguration b -> Metadata -> Metadata
forall s t a b. ASetter s t a b -> b -> s -> t
.~ SourceConnConfiguration b
sourceConfig
                  updateCustomization :: Metadata -> Metadata
updateCustomization = (SourceMetadata b -> Identity (SourceMetadata b))
-> Metadata -> Identity Metadata
sMetadata ((SourceMetadata b -> Identity (SourceMetadata b))
 -> Metadata -> Identity Metadata)
-> ((SourceCustomization -> Identity SourceCustomization)
    -> SourceMetadata b -> Identity (SourceMetadata b))
-> (SourceCustomization -> Identity SourceCustomization)
-> Metadata
-> Identity Metadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SourceCustomization -> Identity SourceCustomization)
-> SourceMetadata b -> Identity (SourceMetadata b)
forall (b :: BackendType) (f :: * -> *).
Functor f =>
(SourceCustomization -> f SourceCustomization)
-> SourceMetadata b -> f (SourceMetadata b)
smCustomization ((SourceCustomization -> Identity SourceCustomization)
 -> Metadata -> Identity Metadata)
-> SourceCustomization -> Metadata -> Metadata
forall s t a b. ASetter s t a b -> b -> s -> t
.~ SourceCustomization
sourceCustomization
              (Metadata -> Metadata) -> m (Metadata -> Metadata)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Metadata -> Metadata) -> m (Metadata -> Metadata))
-> (Metadata -> Metadata) -> m (Metadata -> Metadata)
forall a b. (a -> b) -> a -> b
$ Metadata -> Metadata
updateConfig (Metadata -> Metadata)
-> (Metadata -> Metadata) -> Metadata -> Metadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Metadata -> Metadata
updateCustomization
            else Code -> Text -> m (Metadata -> Metadata)
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
AlreadyExists (Text -> m (Metadata -> Metadata))
-> Text -> m (Metadata -> Metadata)
forall a b. (a -> b) -> a -> b
$ Text
"source with name " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> SourceName
name SourceName -> Text -> Text
forall t. ToTxt t => t -> Text -> Text
<<> Text
" already exists"
        else do
          let sourceMetadata :: BackendSourceMetadata
sourceMetadata =
                forall (b :: BackendType).
Backend b =>
SourceName
-> BackendSourceKind b
-> SourceConnConfiguration b
-> SourceCustomization
-> Maybe (HealthCheckConfig b)
-> BackendSourceMetadata
mkSourceMetadata @b SourceName
name BackendSourceKind b
backendKind SourceConnConfiguration b
sourceConfig SourceCustomization
sourceCustomization Maybe (HealthCheckConfig b)
healthCheckConfig
          (Metadata -> Metadata) -> m (Metadata -> Metadata)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Metadata -> Metadata) -> m (Metadata -> Metadata))
-> (Metadata -> Metadata) -> m (Metadata -> Metadata)
forall a b. (a -> b) -> a -> b
$ (Sources -> Identity Sources) -> Metadata -> Identity Metadata
Lens' Metadata Sources
metaSources ((Sources -> Identity Sources) -> Metadata -> Identity Metadata)
-> (Sources -> Sources) -> Metadata -> Metadata
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ SourceName -> BackendSourceMetadata -> Sources -> Sources
forall k v.
(Eq k, Hashable k) =>
k -> v -> InsOrdHashMap k v -> InsOrdHashMap k v
InsOrdHashMap.insert SourceName
name BackendSourceMetadata
sourceMetadata

  MetadataObjId -> MetadataModifier -> m ()
forall (m :: * -> *).
(QErrM m, CacheRWM m, MetadataM m) =>
MetadataObjId -> MetadataModifier -> m ()
buildSchemaCacheFor (SourceName -> MetadataObjId
MOSource SourceName
name) MetadataModifier
metadataModifier
  EncJSON -> m EncJSON
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure EncJSON
successMsg

--------------------------------------------------------------------------------
-- Rename source

data RenameSource = RenameSource
  { RenameSource -> SourceName
_rmName :: SourceName,
    RenameSource -> SourceName
_rmNewName :: SourceName
  }
  deriving stock ((forall x. RenameSource -> Rep RenameSource x)
-> (forall x. Rep RenameSource x -> RenameSource)
-> Generic RenameSource
forall x. Rep RenameSource x -> RenameSource
forall x. RenameSource -> Rep RenameSource x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. RenameSource -> Rep RenameSource x
from :: forall x. RenameSource -> Rep RenameSource x
$cto :: forall x. Rep RenameSource x -> RenameSource
to :: forall x. Rep RenameSource x -> RenameSource
Generic)

instance FromJSON RenameSource where
  parseJSON :: Value -> Parser RenameSource
parseJSON = Options -> Value -> Parser RenameSource
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON Options
hasuraJSON

runRenameSource ::
  forall m.
  (MonadError QErr m, CacheRWM m, MetadataM m) =>
  RenameSource ->
  m EncJSON
runRenameSource :: forall (m :: * -> *).
(MonadError QErr m, CacheRWM m, MetadataM m) =>
RenameSource -> m EncJSON
runRenameSource RenameSource {SourceName
_rmName :: RenameSource -> SourceName
_rmNewName :: RenameSource -> SourceName
_rmName :: SourceName
_rmNewName :: SourceName
..} = do
  SourceCache
sources <- SchemaCache -> SourceCache
scSources (SchemaCache -> SourceCache) -> m SchemaCache -> m SourceCache
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m SchemaCache
forall (m :: * -> *). CacheRM m => m SchemaCache
askSchemaCache

  Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (SourceName -> SourceCache -> Bool
forall k a. (Eq k, Hashable k) => k -> HashMap k a -> Bool
HashMap.member SourceName
_rmName SourceCache
sources)
    (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ Code -> Text -> m ()
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotExists
    (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"Could not find source with name "
    Text -> SourceName -> Text
forall t. ToTxt t => Text -> t -> Text
<>> SourceName
_rmName

  Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (SourceName -> SourceCache -> Bool
forall k a. (Eq k, Hashable k) => k -> HashMap k a -> Bool
HashMap.member SourceName
_rmNewName SourceCache
sources)
    (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ Code -> Text -> m ()
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
AlreadyExists
    (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"Source with name "
    Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> SourceName
_rmNewName
    SourceName -> Text -> Text
forall t. ToTxt t => t -> Text -> Text
<<> Text
" already exists"

  let metadataModifier :: MetadataModifier
metadataModifier =
        (Metadata -> Metadata) -> MetadataModifier
MetadataModifier
          ((Metadata -> Metadata) -> MetadataModifier)
-> (Metadata -> Metadata) -> MetadataModifier
forall a b. (a -> b) -> a -> b
$ (Sources -> Identity Sources) -> Metadata -> Identity Metadata
Lens' Metadata Sources
metaSources
          ((Sources -> Identity Sources) -> Metadata -> Identity Metadata)
-> (Sources -> Sources) -> Metadata -> Metadata
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ SourceName -> SourceName -> Sources -> Sources
renameBackendSourceMetadata SourceName
_rmName SourceName
_rmNewName
  MetadataObjId -> MetadataModifier -> m ()
forall (m :: * -> *).
(QErrM m, CacheRWM m, MetadataM m) =>
MetadataObjId -> MetadataModifier -> m ()
buildSchemaCacheFor (SourceName -> MetadataObjId
MOSource SourceName
_rmNewName) MetadataModifier
metadataModifier

  EncJSON -> m EncJSON
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure EncJSON
successMsg
  where
    renameBackendSourceMetadata ::
      SourceName ->
      SourceName ->
      InsOrdHashMap.InsOrdHashMap SourceName BackendSourceMetadata ->
      InsOrdHashMap.InsOrdHashMap SourceName BackendSourceMetadata
    renameBackendSourceMetadata :: SourceName -> SourceName -> Sources -> Sources
renameBackendSourceMetadata SourceName
oldKey SourceName
newKey Sources
m =
      case SourceName -> Sources -> Maybe BackendSourceMetadata
forall k v. (Eq k, Hashable k) => k -> InsOrdHashMap k v -> Maybe v
InsOrdHashMap.lookup SourceName
oldKey Sources
m of
        Just BackendSourceMetadata
val ->
          let renamedSource :: BackendSourceMetadata
renamedSource = AnyBackend SourceMetadata -> BackendSourceMetadata
BackendSourceMetadata (AnyBackend SourceMetadata
-> (forall (b :: BackendType).
    SourceMetadata b -> SourceMetadata b)
-> AnyBackend SourceMetadata
forall (i :: BackendType -> *) (j :: BackendType -> *).
AnyBackend i
-> (forall (b :: BackendType). i b -> j b) -> AnyBackend j
AB.mapBackend (BackendSourceMetadata -> AnyBackend SourceMetadata
unBackendSourceMetadata BackendSourceMetadata
val) (SourceName -> SourceMetadata b -> SourceMetadata b
forall (b :: BackendType).
SourceName -> SourceMetadata b -> SourceMetadata b
renameSource SourceName
newKey))
           in SourceName -> BackendSourceMetadata -> Sources -> Sources
forall k v.
(Eq k, Hashable k) =>
k -> v -> InsOrdHashMap k v -> InsOrdHashMap k v
InsOrdHashMap.insert SourceName
newKey BackendSourceMetadata
renamedSource (Sources -> Sources) -> Sources -> Sources
forall a b. (a -> b) -> a -> b
$ SourceName -> Sources -> Sources
forall k v.
(Eq k, Hashable k) =>
k -> InsOrdHashMap k v -> InsOrdHashMap k v
InsOrdHashMap.delete SourceName
oldKey (Sources -> Sources) -> Sources -> Sources
forall a b. (a -> b) -> a -> b
$ Sources
m
        Maybe BackendSourceMetadata
Nothing -> Sources
m

    renameSource :: forall b. SourceName -> SourceMetadata b -> SourceMetadata b
    renameSource :: forall (b :: BackendType).
SourceName -> SourceMetadata b -> SourceMetadata b
renameSource SourceName
newName SourceMetadata b
metadata = SourceMetadata b
metadata {_smName :: SourceName
_smName = SourceName
newName}

--------------------------------------------------------------------------------
-- Drop source

data DropSource = DropSource
  { DropSource -> SourceName
_dsName :: SourceName,
    DropSource -> Bool
_dsCascade :: Bool
  }
  deriving (Int -> DropSource -> ShowS
[DropSource] -> ShowS
DropSource -> String
(Int -> DropSource -> ShowS)
-> (DropSource -> String)
-> ([DropSource] -> ShowS)
-> Show DropSource
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DropSource -> ShowS
showsPrec :: Int -> DropSource -> ShowS
$cshow :: DropSource -> String
show :: DropSource -> String
$cshowList :: [DropSource] -> ShowS
showList :: [DropSource] -> ShowS
Show, DropSource -> DropSource -> Bool
(DropSource -> DropSource -> Bool)
-> (DropSource -> DropSource -> Bool) -> Eq DropSource
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DropSource -> DropSource -> Bool
== :: DropSource -> DropSource -> Bool
$c/= :: DropSource -> DropSource -> Bool
/= :: DropSource -> DropSource -> Bool
Eq)

instance FromJSON DropSource where
  parseJSON :: Value -> Parser DropSource
parseJSON = String
-> (Object -> Parser DropSource) -> Value -> Parser DropSource
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"DropSource" ((Object -> Parser DropSource) -> Value -> Parser DropSource)
-> (Object -> Parser DropSource) -> Value -> Parser DropSource
forall a b. (a -> b) -> a -> b
$ \Object
o ->
    SourceName -> Bool -> DropSource
DropSource (SourceName -> Bool -> DropSource)
-> Parser SourceName -> Parser (Bool -> DropSource)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser SourceName
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name" Parser (Bool -> DropSource) -> Parser Bool -> Parser DropSource
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"cascade" Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= Bool
False

runDropSource ::
  forall m r.
  ( MonadError QErr m,
    CacheRWM m,
    MonadIO m,
    MonadBaseControl IO m,
    MetadataM m,
    MonadReader r m,
    Has (L.Logger L.Hasura) r
  ) =>
  DropSource ->
  m EncJSON
runDropSource :: forall (m :: * -> *) r.
(MonadError QErr m, CacheRWM m, MonadIO m, MonadBaseControl IO m,
 MetadataM m, MonadReader r m, Has (Logger Hasura) r) =>
DropSource -> m EncJSON
runDropSource dropSourceInfo :: DropSource
dropSourceInfo@(DropSource SourceName
name Bool
cascade) = do
  SchemaCache
schemaCache <- m SchemaCache
forall (m :: * -> *). CacheRM m => m SchemaCache
askSchemaCache
  let sources :: SourceCache
sources = SchemaCache -> SourceCache
scSources SchemaCache
schemaCache
  case SourceName -> SourceCache -> Maybe BackendSourceInfo
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup SourceName
name SourceCache
sources of
    Just BackendSourceInfo
backendSourceInfo ->
      forall (c :: BackendType -> Constraint) (i :: BackendType -> *) r.
AllBackendsSatisfy c =>
AnyBackend i -> (forall (b :: BackendType). c b => i b -> r) -> r
AB.dispatchAnyBackend @BackendMetadata BackendSourceInfo
backendSourceInfo ((forall (b :: BackendType).
  BackendMetadata b =>
  SourceInfo b -> m ())
 -> m ())
-> (forall (b :: BackendType).
    BackendMetadata b =>
    SourceInfo b -> m ())
-> m ()
forall a b. (a -> b) -> a -> b
$ DropSource -> SourceInfo b -> m ()
forall (m :: * -> *) r (b :: BackendType).
(MonadError QErr m, CacheRWM m, MonadIO m, MonadBaseControl IO m,
 MetadataM m, MonadReader r m, Has (Logger Hasura) r,
 BackendMetadata b) =>
DropSource -> SourceInfo b -> m ()
dropSource DropSource
dropSourceInfo
    Maybe BackendSourceInfo
Nothing -> do
      Metadata
metadata <- m Metadata
forall (m :: * -> *). MetadataM m => m Metadata
getMetadata
      m BackendSourceMetadata -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void
        (m BackendSourceMetadata -> m ())
-> m BackendSourceMetadata -> m ()
forall a b. (a -> b) -> a -> b
$ Maybe BackendSourceMetadata
-> m BackendSourceMetadata -> m BackendSourceMetadata
forall (m :: * -> *) a. Applicative m => Maybe a -> m a -> m a
onNothing (Metadata
metadata Metadata
-> Getting
     (Maybe BackendSourceMetadata)
     Metadata
     (Maybe BackendSourceMetadata)
-> Maybe BackendSourceMetadata
forall s a. s -> Getting a s a -> a
^. (Sources -> Const (Maybe BackendSourceMetadata) Sources)
-> Metadata -> Const (Maybe BackendSourceMetadata) Metadata
Lens' Metadata Sources
metaSources ((Sources -> Const (Maybe BackendSourceMetadata) Sources)
 -> Metadata -> Const (Maybe BackendSourceMetadata) Metadata)
-> ((Maybe BackendSourceMetadata
     -> Const
          (Maybe BackendSourceMetadata) (Maybe BackendSourceMetadata))
    -> Sources -> Const (Maybe BackendSourceMetadata) Sources)
-> Getting
     (Maybe BackendSourceMetadata)
     Metadata
     (Maybe BackendSourceMetadata)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index Sources -> Lens' Sources (Maybe (IxValue Sources))
forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at Index Sources
SourceName
name)
        (m BackendSourceMetadata -> m BackendSourceMetadata)
-> m BackendSourceMetadata -> m BackendSourceMetadata
forall a b. (a -> b) -> a -> b
$ Code -> Text -> m BackendSourceMetadata
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotExists
        (Text -> m BackendSourceMetadata)
-> Text -> m BackendSourceMetadata
forall a b. (a -> b) -> a -> b
$ Text
"source with name "
        Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> SourceName
name
        SourceName -> Text -> Text
forall t. ToTxt t => t -> Text -> Text
<<> Text
" does not exist"
      if Bool
cascade
        then -- Without sourceInfo we can't cascade, so throw an error
          Code -> Text -> m ()
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
Unexpected (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"source with name " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> SourceName
name SourceName -> Text -> Text
forall t. ToTxt t => t -> Text -> Text
<<> Text
" is inconsistent"
        else -- Drop source from metadata
          MetadataObjId -> MetadataModifier -> m ()
forall (m :: * -> *).
(QErrM m, CacheRWM m, MetadataM m) =>
MetadataObjId -> MetadataModifier -> m ()
buildSchemaCacheFor (SourceName -> MetadataObjId
MOSource SourceName
name) (SourceName -> MetadataModifier
dropSourceMetadataModifier SourceName
name)
  EncJSON -> m EncJSON
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure EncJSON
successMsg

dropSourceMetadataModifier :: SourceName -> MetadataModifier
dropSourceMetadataModifier :: SourceName -> MetadataModifier
dropSourceMetadataModifier SourceName
sourceName = (Metadata -> Metadata) -> MetadataModifier
MetadataModifier ((Metadata -> Metadata) -> MetadataModifier)
-> (Metadata -> Metadata) -> MetadataModifier
forall a b. (a -> b) -> a -> b
$ (Sources -> Identity Sources) -> Metadata -> Identity Metadata
Lens' Metadata Sources
metaSources ((Sources -> Identity Sources) -> Metadata -> Identity Metadata)
-> (Sources -> Sources) -> Metadata -> Metadata
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ SourceName -> Sources -> Sources
forall k v.
(Eq k, Hashable k) =>
k -> InsOrdHashMap k v -> InsOrdHashMap k v
InsOrdHashMap.delete SourceName
sourceName

dropSource ::
  forall m r b.
  ( MonadError QErr m,
    CacheRWM m,
    MonadIO m,
    MonadBaseControl IO m,
    MetadataM m,
    MonadReader r m,
    Has (L.Logger L.Hasura) r,
    BackendMetadata b
  ) =>
  DropSource ->
  SourceInfo b ->
  m ()
dropSource :: forall (m :: * -> *) r (b :: BackendType).
(MonadError QErr m, CacheRWM m, MonadIO m, MonadBaseControl IO m,
 MetadataM m, MonadReader r m, Has (Logger Hasura) r,
 BackendMetadata b) =>
DropSource -> SourceInfo b -> m ()
dropSource (DropSource SourceName
sourceName Bool
cascade) SourceInfo b
sourceInfo = do
  SchemaCache
schemaCache <- m SchemaCache
forall (m :: * -> *). CacheRM m => m SchemaCache
askSchemaCache
  let remoteDeps :: [SchemaObjId]
remoteDeps = SchemaCache -> SourceName -> [SchemaObjId]
getRemoteDependencies SchemaCache
schemaCache SourceName
sourceName

  Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Bool
cascade Bool -> Bool -> Bool
|| [SchemaObjId] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [SchemaObjId]
remoteDeps)
    (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ [SchemaObjId] -> m ()
forall (m :: * -> *). MonadError QErr m => [SchemaObjId] -> m ()
reportDependentObjectsExist [SchemaObjId]
remoteDeps

  MetadataModifier
metadataModifier <- WriterT MetadataModifier m () -> m MetadataModifier
forall (m :: * -> *) w a. Monad m => WriterT w m a -> m w
execWriterT (WriterT MetadataModifier m () -> m MetadataModifier)
-> WriterT MetadataModifier m () -> m MetadataModifier
forall a b. (a -> b) -> a -> b
$ do
    (SchemaObjId -> WriterT MetadataModifier m ())
-> [SchemaObjId] -> WriterT MetadataModifier m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ SchemaObjId -> WriterT MetadataModifier m ()
forall (m :: * -> *).
MonadError QErr m =>
SchemaObjId -> WriterT MetadataModifier m ()
purgeSourceAndSchemaDependencies [SchemaObjId]
remoteDeps
    MetadataModifier -> WriterT MetadataModifier m ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (MetadataModifier -> WriterT MetadataModifier m ())
-> MetadataModifier -> WriterT MetadataModifier m ()
forall a b. (a -> b) -> a -> b
$ SourceName -> MetadataModifier
dropSourceMetadataModifier SourceName
sourceName

  MetadataObjId -> MetadataModifier -> m ()
forall (m :: * -> *).
(QErrM m, CacheRWM m, MetadataM m) =>
MetadataObjId -> MetadataModifier -> m ()
buildSchemaCacheFor (SourceName -> MetadataObjId
MOSource SourceName
sourceName) MetadataModifier
metadataModifier
  SourceName -> SourceInfo b -> m ()
forall (m :: * -> *) r (b :: BackendType).
(MonadError QErr m, MonadIO m, MonadBaseControl IO m,
 MonadReader r m, Has (Logger Hasura) r, BackendMetadata b) =>
SourceName -> SourceInfo b -> m ()
runPostDropSourceHook SourceName
sourceName SourceInfo b
sourceInfo

runPostDropSourceHook ::
  forall m r b.
  ( MonadError QErr m,
    MonadIO m,
    MonadBaseControl IO m,
    MonadReader r m,
    Has (L.Logger L.Hasura) r,
    BackendMetadata b
  ) =>
  SourceName ->
  SourceInfo b ->
  m ()
runPostDropSourceHook :: forall (m :: * -> *) r (b :: BackendType).
(MonadError QErr m, MonadIO m, MonadBaseControl IO m,
 MonadReader r m, Has (Logger Hasura) r, BackendMetadata b) =>
SourceName -> SourceInfo b -> m ()
runPostDropSourceHook SourceName
sourceName SourceInfo b
sourceInfo = do
  Logger Hasura
logger :: (L.Logger L.Hasura) <- (r -> Logger Hasura) -> m (Logger Hasura)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks r -> Logger Hasura
forall a t. Has a t => t -> a
getter
  let sourceConfig :: SourceConfig b
sourceConfig = SourceInfo b -> SourceConfig b
forall (b :: BackendType). SourceInfo b -> SourceConfig b
_siConfiguration SourceInfo b
sourceInfo
  -- Create a hashmap: {TableName: [Triggers]}
  let tableTriggersMap :: HashMap (TableName b) [TriggerName]
tableTriggersMap = (TableInfo b -> [TriggerName])
-> HashMap (TableName b) (TableInfo b)
-> HashMap (TableName b) [TriggerName]
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HashMap.map (HashMap TriggerName (EventTriggerInfo b) -> [TriggerName]
forall k v. HashMap k v -> [k]
HashMap.keys (HashMap TriggerName (EventTriggerInfo b) -> [TriggerName])
-> (TableInfo b -> HashMap TriggerName (EventTriggerInfo b))
-> TableInfo b
-> [TriggerName]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TableInfo b -> HashMap TriggerName (EventTriggerInfo b)
forall (b :: BackendType). TableInfo b -> EventTriggerInfoMap b
_tiEventTriggerInfoMap) (SourceInfo b -> HashMap (TableName b) (TableInfo b)
forall (b :: BackendType). SourceInfo b -> TableCache b
_siTables SourceInfo b
sourceInfo)
  -- We only log errors that arise from 'postDropSourceHook' here, and not
  -- surface them as end-user errors. See comment
  -- https://github.com/hasura/graphql-engine/issues/7092#issuecomment-873845282
  ExceptT QErr m () -> m (Either QErr ())
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (forall (b :: BackendType) (m :: * -> *).
(BackendMetadata b, MonadError QErr m, MonadIO m,
 MonadBaseControl IO m) =>
SourceConfig b -> TableEventTriggers b -> m ()
postDropSourceHook @b SourceConfig b
sourceConfig HashMap (TableName b) [TriggerName]
tableTriggersMap) m (Either QErr ()) -> (Either QErr () -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (QErr -> m ()) -> (() -> m ()) -> Either QErr () -> m ()
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Logger Hasura -> QErr -> m ()
logDropSourceHookError Logger Hasura
logger) () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
  where
    logDropSourceHookError :: Logger Hasura -> QErr -> m ()
logDropSourceHookError Logger Hasura
logger QErr
err =
      let msg :: Text
msg =
            Text
"Error executing cleanup actions after removing source '"
              Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> SourceName -> Text
forall a. ToTxt a => a -> Text
toTxt SourceName
sourceName
              Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"'. Consider cleaning up tables in hdb_catalog schema manually."
       in Logger Hasura
-> forall a (m :: * -> *).
   (ToEngineLog a Hasura, MonadIO m) =>
   a -> m ()
forall impl.
Logger impl
-> forall a (m :: * -> *).
   (ToEngineLog a impl, MonadIO m) =>
   a -> m ()
L.unLogger Logger Hasura
logger (MetadataLog -> m ()) -> MetadataLog -> m ()
forall a b. (a -> b) -> a -> b
$ LogLevel -> Text -> Value -> MetadataLog
MetadataLog LogLevel
L.LevelWarn Text
msg (QErr -> Value
forall a. ToJSON a => a -> Value
J.toJSON QErr
err)

--------------------------------------------------------------------------------
-- update source

data UpdateSource b = UpdateSource
  { forall (b :: BackendType). UpdateSource b -> SourceName
_usName :: SourceName,
    forall (b :: BackendType).
UpdateSource b -> Maybe (SourceConnConfiguration b)
_usConfiguration :: Maybe (SourceConnConfiguration b),
    forall (b :: BackendType).
UpdateSource b -> Maybe SourceCustomization
_usCustomization :: Maybe SourceCustomization,
    forall (b :: BackendType).
UpdateSource b -> Maybe (HealthCheckConfig b)
_usHealthCheckConfig :: Maybe (HealthCheckConfig b)
  }

instance (Backend b) => FromJSONWithContext (BackendSourceKind b) (UpdateSource b) where
  parseJSONWithContext :: BackendSourceKind b -> Value -> Parser (UpdateSource b)
parseJSONWithContext BackendSourceKind b
_ = String
-> (Object -> Parser (UpdateSource b))
-> Value
-> Parser (UpdateSource b)
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"UpdateSource" ((Object -> Parser (UpdateSource b))
 -> Value -> Parser (UpdateSource b))
-> (Object -> Parser (UpdateSource b))
-> Value
-> Parser (UpdateSource b)
forall a b. (a -> b) -> a -> b
$ \Object
o ->
    SourceName
-> Maybe (SourceConnConfiguration b)
-> Maybe SourceCustomization
-> Maybe (HealthCheckConfig b)
-> UpdateSource b
forall (b :: BackendType).
SourceName
-> Maybe (SourceConnConfiguration b)
-> Maybe SourceCustomization
-> Maybe (HealthCheckConfig b)
-> UpdateSource b
UpdateSource
      (SourceName
 -> Maybe (SourceConnConfiguration b)
 -> Maybe SourceCustomization
 -> Maybe (HealthCheckConfig b)
 -> UpdateSource b)
-> Parser SourceName
-> Parser
     (Maybe (SourceConnConfiguration b)
      -> Maybe SourceCustomization
      -> Maybe (HealthCheckConfig b)
      -> UpdateSource b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o
      Object -> Key -> Parser SourceName
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name"
      Parser
  (Maybe (SourceConnConfiguration b)
   -> Maybe SourceCustomization
   -> Maybe (HealthCheckConfig b)
   -> UpdateSource b)
-> Parser (Maybe (SourceConnConfiguration b))
-> Parser
     (Maybe SourceCustomization
      -> Maybe (HealthCheckConfig b) -> UpdateSource b)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o
      Object -> Key -> Parser (Maybe (SourceConnConfiguration b))
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"configuration"
      Parser
  (Maybe SourceCustomization
   -> Maybe (HealthCheckConfig b) -> UpdateSource b)
-> Parser (Maybe SourceCustomization)
-> Parser (Maybe (HealthCheckConfig b) -> UpdateSource b)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o
      Object -> Key -> Parser (Maybe SourceCustomization)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"customization"
      Parser (Maybe (HealthCheckConfig b) -> UpdateSource b)
-> Parser (Maybe (HealthCheckConfig b)) -> Parser (UpdateSource b)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o
      Object -> Key -> Parser (Maybe (HealthCheckConfig b))
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"health_check"

runUpdateSource ::
  forall m b.
  (MonadError QErr m, CacheRWM m, MetadataM m, BackendMetadata b) =>
  UpdateSource b ->
  m EncJSON
runUpdateSource :: forall (m :: * -> *) (b :: BackendType).
(MonadError QErr m, CacheRWM m, MetadataM m, BackendMetadata b) =>
UpdateSource b -> m EncJSON
runUpdateSource (UpdateSource SourceName
name Maybe (SourceConnConfiguration b)
sourceConfig Maybe SourceCustomization
sourceCustomization Maybe (HealthCheckConfig b)
healthCheckConfig) = do
  SourceCache
sources <- SchemaCache -> SourceCache
scSources (SchemaCache -> SourceCache) -> m SchemaCache -> m SourceCache
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m SchemaCache
forall (m :: * -> *). CacheRM m => m SchemaCache
askSchemaCache

  MetadataModifier
metadataModifier <-
    (Metadata -> Metadata) -> MetadataModifier
MetadataModifier
      ((Metadata -> Metadata) -> MetadataModifier)
-> m (Metadata -> Metadata) -> m MetadataModifier
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> if SourceName -> SourceCache -> Bool
forall k a. (Eq k, Hashable k) => k -> HashMap k a -> Bool
HashMap.member SourceName
name SourceCache
sources
        then do
          let sMetadata :: (SourceMetadata b -> Identity (SourceMetadata b))
-> Metadata -> Identity Metadata
sMetadata = (Sources -> Identity Sources) -> Metadata -> Identity Metadata
Lens' Metadata Sources
metaSources ((Sources -> Identity Sources) -> Metadata -> Identity Metadata)
-> ((SourceMetadata b -> Identity (SourceMetadata b))
    -> Sources -> Identity Sources)
-> (SourceMetadata b -> Identity (SourceMetadata b))
-> Metadata
-> Identity Metadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index Sources -> Traversal' Sources (IxValue Sources)
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Index Sources
SourceName
name ((BackendSourceMetadata -> Identity BackendSourceMetadata)
 -> Sources -> Identity Sources)
-> ((SourceMetadata b -> Identity (SourceMetadata b))
    -> BackendSourceMetadata -> Identity BackendSourceMetadata)
-> (SourceMetadata b -> Identity (SourceMetadata b))
-> Sources
-> Identity Sources
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (b :: BackendType).
Backend b =>
Prism' BackendSourceMetadata (SourceMetadata b)
toSourceMetadata @b
              updateConfig :: Metadata -> Metadata
updateConfig = (Metadata -> Metadata)
-> (SourceConnConfiguration b -> Metadata -> Metadata)
-> Maybe (SourceConnConfiguration b)
-> Metadata
-> Metadata
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Metadata -> Metadata
forall a. a -> a
id (\SourceConnConfiguration b
scc -> (SourceMetadata b -> Identity (SourceMetadata b))
-> Metadata -> Identity Metadata
sMetadata ((SourceMetadata b -> Identity (SourceMetadata b))
 -> Metadata -> Identity Metadata)
-> ((SourceConnConfiguration b
     -> Identity (SourceConnConfiguration b))
    -> SourceMetadata b -> Identity (SourceMetadata b))
-> (SourceConnConfiguration b
    -> Identity (SourceConnConfiguration b))
-> Metadata
-> Identity Metadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SourceConnConfiguration b -> Identity (SourceConnConfiguration b))
-> SourceMetadata b -> Identity (SourceMetadata b)
forall (b :: BackendType) (f :: * -> *).
Functor f =>
(SourceConnConfiguration b -> f (SourceConnConfiguration b))
-> SourceMetadata b -> f (SourceMetadata b)
smConfiguration ((SourceConnConfiguration b
  -> Identity (SourceConnConfiguration b))
 -> Metadata -> Identity Metadata)
-> SourceConnConfiguration b -> Metadata -> Metadata
forall s t a b. ASetter s t a b -> b -> s -> t
.~ SourceConnConfiguration b
scc) Maybe (SourceConnConfiguration b)
sourceConfig
              updateCustomization :: Metadata -> Metadata
updateCustomization = (Metadata -> Metadata)
-> (SourceCustomization -> Metadata -> Metadata)
-> Maybe SourceCustomization
-> Metadata
-> Metadata
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Metadata -> Metadata
forall a. a -> a
id (\SourceCustomization
scc -> (SourceMetadata b -> Identity (SourceMetadata b))
-> Metadata -> Identity Metadata
sMetadata ((SourceMetadata b -> Identity (SourceMetadata b))
 -> Metadata -> Identity Metadata)
-> ((SourceCustomization -> Identity SourceCustomization)
    -> SourceMetadata b -> Identity (SourceMetadata b))
-> (SourceCustomization -> Identity SourceCustomization)
-> Metadata
-> Identity Metadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SourceCustomization -> Identity SourceCustomization)
-> SourceMetadata b -> Identity (SourceMetadata b)
forall (b :: BackendType) (f :: * -> *).
Functor f =>
(SourceCustomization -> f SourceCustomization)
-> SourceMetadata b -> f (SourceMetadata b)
smCustomization ((SourceCustomization -> Identity SourceCustomization)
 -> Metadata -> Identity Metadata)
-> SourceCustomization -> Metadata -> Metadata
forall s t a b. ASetter s t a b -> b -> s -> t
.~ SourceCustomization
scc) Maybe SourceCustomization
sourceCustomization
              updateHealthCheckConfig :: Metadata -> Metadata
updateHealthCheckConfig = (Metadata -> Metadata)
-> (HealthCheckConfig b -> Metadata -> Metadata)
-> Maybe (HealthCheckConfig b)
-> Metadata
-> Metadata
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Metadata -> Metadata
forall a. a -> a
id (\HealthCheckConfig b
hcc -> (SourceMetadata b -> Identity (SourceMetadata b))
-> Metadata -> Identity Metadata
sMetadata ((SourceMetadata b -> Identity (SourceMetadata b))
 -> Metadata -> Identity Metadata)
-> ((Maybe (HealthCheckConfig b)
     -> Identity (Maybe (HealthCheckConfig b)))
    -> SourceMetadata b -> Identity (SourceMetadata b))
-> (Maybe (HealthCheckConfig b)
    -> Identity (Maybe (HealthCheckConfig b)))
-> Metadata
-> Identity Metadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe (HealthCheckConfig b)
 -> Identity (Maybe (HealthCheckConfig b)))
-> SourceMetadata b -> Identity (SourceMetadata b)
forall (b :: BackendType) (f :: * -> *).
Functor f =>
(Maybe (HealthCheckConfig b) -> f (Maybe (HealthCheckConfig b)))
-> SourceMetadata b -> f (SourceMetadata b)
smHealthCheckConfig ((Maybe (HealthCheckConfig b)
  -> Identity (Maybe (HealthCheckConfig b)))
 -> Metadata -> Identity Metadata)
-> Maybe (HealthCheckConfig b) -> Metadata -> Metadata
forall s t a b. ASetter s t a b -> b -> s -> t
.~ HealthCheckConfig b -> Maybe (HealthCheckConfig b)
forall a. a -> Maybe a
Just HealthCheckConfig b
hcc) Maybe (HealthCheckConfig b)
healthCheckConfig
          (Metadata -> Metadata) -> m (Metadata -> Metadata)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Metadata -> Metadata) -> m (Metadata -> Metadata))
-> (Metadata -> Metadata) -> m (Metadata -> Metadata)
forall a b. (a -> b) -> a -> b
$ Metadata -> Metadata
updateHealthCheckConfig (Metadata -> Metadata)
-> (Metadata -> Metadata) -> Metadata -> Metadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Metadata -> Metadata
updateConfig (Metadata -> Metadata)
-> (Metadata -> Metadata) -> Metadata -> Metadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Metadata -> Metadata
updateCustomization
        else do
          Code -> Text -> m (Metadata -> Metadata)
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotExists (Text -> m (Metadata -> Metadata))
-> Text -> m (Metadata -> Metadata)
forall a b. (a -> b) -> a -> b
$ Text
"source with name " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> SourceName
name SourceName -> Text -> Text
forall t. ToTxt t => t -> Text -> Text
<<> Text
" does not exist"

  MetadataObjId -> MetadataModifier -> m ()
forall (m :: * -> *).
(QErrM m, CacheRWM m, MetadataM m) =>
MetadataObjId -> MetadataModifier -> m ()
buildSchemaCacheFor (SourceName -> MetadataObjId
MOSource SourceName
name) MetadataModifier
metadataModifier
  EncJSON -> m EncJSON
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure EncJSON
successMsg

--------------------------------------------------------------------------------

newtype GetSourceTables (b :: BackendType) = GetSourceTables {forall (b :: BackendType). GetSourceTables b -> SourceName
_gstSourceName :: SourceName}

instance FromJSON (GetSourceTables b) where
  parseJSON :: Value -> Parser (GetSourceTables b)
parseJSON = String
-> (Object -> Parser (GetSourceTables b))
-> Value
-> Parser (GetSourceTables b)
forall a. String -> (Object -> Parser a) -> Value -> Parser a
J.withObject String
"GetSourceTables" \Object
o -> do
    SourceName
_gstSourceName <- Object
o Object -> Key -> Parser SourceName
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"source"
    GetSourceTables b -> Parser (GetSourceTables b)
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (GetSourceTables b -> Parser (GetSourceTables b))
-> GetSourceTables b -> Parser (GetSourceTables b)
forall a b. (a -> b) -> a -> b
$ GetSourceTables {SourceName
_gstSourceName :: SourceName
_gstSourceName :: SourceName
..}

-- | Fetch a list of tables for the request data source.
runGetSourceTrackables ::
  forall b m r.
  ( BackendMetadata b,
    CacheRM m,
    MonadError Error.QErr m,
    Metadata.MetadataM m,
    MonadIO m,
    MonadBaseControl IO m,
    MonadReader r m,
    Has (L.Logger L.Hasura) r,
    ProvidesNetwork m
  ) =>
  GetSourceTrackables b ->
  m EncJSON
runGetSourceTrackables :: forall (b :: BackendType) (m :: * -> *) r.
(BackendMetadata b, CacheRM m, MonadError QErr m, MetadataM m,
 MonadIO m, MonadBaseControl IO m, MonadReader r m,
 Has (Logger Hasura) r, ProvidesNetwork m) =>
GetSourceTrackables b -> m EncJSON
runGetSourceTrackables GetSourceTrackables {SourceName
_gstrSourceName :: SourceName
_gstrSourceName :: forall (b :: BackendType). GetSourceTrackables b -> SourceName
..} = do
  (TrackableInfo b -> EncJSON) -> m (TrackableInfo b) -> m EncJSON
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap TrackableInfo b -> EncJSON
forall a. ToJSON a => a -> EncJSON
EncJSON.encJFromJValue (forall (b :: BackendType) (m :: * -> *) r.
(BackendMetadata b, CacheRM m, MonadBaseControl IO m, MetadataM m,
 MonadError QErr m, MonadIO m, MonadReader r m,
 Has (Logger Hasura) r, ProvidesNetwork m) =>
SourceName -> m (TrackableInfo b)
listAllTrackables @b SourceName
_gstrSourceName)

newtype GetSourceTrackables (b :: BackendType) = GetSourceTrackables {forall (b :: BackendType). GetSourceTrackables b -> SourceName
_gstrSourceName :: SourceName}

instance FromJSON (GetSourceTrackables b) where
  parseJSON :: Value -> Parser (GetSourceTrackables b)
parseJSON = String
-> (Object -> Parser (GetSourceTrackables b))
-> Value
-> Parser (GetSourceTrackables b)
forall a. String -> (Object -> Parser a) -> Value -> Parser a
J.withObject String
"GetSourceFunctions" \Object
o -> do
    SourceName
_gstrSourceName <- Object
o Object -> Key -> Parser SourceName
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"source"
    GetSourceTrackables b -> Parser (GetSourceTrackables b)
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (GetSourceTrackables b -> Parser (GetSourceTrackables b))
-> GetSourceTrackables b -> Parser (GetSourceTrackables b)
forall a b. (a -> b) -> a -> b
$ GetSourceTrackables {SourceName
_gstrSourceName :: SourceName
_gstrSourceName :: SourceName
..}

-- | Fetch a list of tables for the request data source.
runGetSourceTables ::
  forall b m r.
  ( BackendMetadata b,
    CacheRM m,
    MonadError Error.QErr m,
    Metadata.MetadataM m,
    MonadIO m,
    MonadBaseControl IO m,
    MonadReader r m,
    Has (L.Logger L.Hasura) r,
    ProvidesNetwork m
  ) =>
  GetSourceTables b ->
  m EncJSON
runGetSourceTables :: forall (b :: BackendType) (m :: * -> *) r.
(BackendMetadata b, CacheRM m, MonadError QErr m, MetadataM m,
 MonadIO m, MonadBaseControl IO m, MonadReader r m,
 Has (Logger Hasura) r, ProvidesNetwork m) =>
GetSourceTables b -> m EncJSON
runGetSourceTables GetSourceTables {SourceName
_gstSourceName :: forall (b :: BackendType). GetSourceTables b -> SourceName
_gstSourceName :: SourceName
..} = do
  ([TableName b] -> EncJSON) -> m [TableName b] -> m EncJSON
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [TableName b] -> EncJSON
forall a. ToJSON a => a -> EncJSON
EncJSON.encJFromJValue (forall (b :: BackendType) (m :: * -> *) r.
(BackendMetadata b, CacheRM m, MonadBaseControl IO m, MetadataM m,
 MonadError QErr m, MonadIO m, MonadReader r m,
 Has (Logger Hasura) r, ProvidesNetwork m) =>
SourceName -> m [TableName b]
listAllTables @b SourceName
_gstSourceName)

--------------------------------------------------------------------------------

data GetTableInfo_ = GetTableInfo_
  { GetTableInfo_ -> SourceName
_gtiSourceName_ :: Common.SourceName,
    GetTableInfo_ -> TableName 'DataConnector
_gtiTableName_ :: TableName 'DataConnector
  }

instance FromJSON GetTableInfo_ where
  parseJSON :: Value -> Parser GetTableInfo_
parseJSON = String
-> (Object -> Parser GetTableInfo_)
-> Value
-> Parser GetTableInfo_
forall a. String -> (Object -> Parser a) -> Value -> Parser a
J.withObject String
"GetTableInfo_" \Object
o -> do
    SourceName
_gtiSourceName_ <- Object
o Object -> Key -> Parser SourceName
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"source"
    TableName
_gtiTableName_ <- Object
o Object -> Key -> Parser TableName
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"table"
    GetTableInfo_ -> Parser GetTableInfo_
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (GetTableInfo_ -> Parser GetTableInfo_)
-> GetTableInfo_ -> Parser GetTableInfo_
forall a b. (a -> b) -> a -> b
$ GetTableInfo_ {SourceName
TableName 'DataConnector
TableName
_gtiSourceName_ :: SourceName
_gtiTableName_ :: TableName 'DataConnector
_gtiSourceName_ :: SourceName
_gtiTableName_ :: TableName
..}

-- | Legacy data connector command. This doesn't use the DataConnector
-- 'ScalarType' to represent types.
runGetTableInfo_ ::
  ( CacheRM m,
    MonadError Error.QErr m,
    Metadata.MetadataM m,
    MonadBaseControl IO m,
    MonadIO m
  ) =>
  GetTableInfo_ ->
  m EncJSON
runGetTableInfo_ :: forall (m :: * -> *).
(CacheRM m, MonadError QErr m, MetadataM m, MonadBaseControl IO m,
 MonadIO m) =>
GetTableInfo_ -> m EncJSON
runGetTableInfo_ GetTableInfo_ {SourceName
TableName 'DataConnector
_gtiSourceName_ :: GetTableInfo_ -> SourceName
_gtiTableName_ :: GetTableInfo_ -> TableName 'DataConnector
_gtiSourceName_ :: SourceName
_gtiTableName_ :: TableName 'DataConnector
..} = do
  Metadata
metadata <- m Metadata
forall (m :: * -> *). MetadataM m => m Metadata
Metadata.getMetadata

  let sources :: InsOrdHashMap SourceName (AnyBackend SourceMetadata)
sources = (BackendSourceMetadata -> AnyBackend SourceMetadata)
-> Sources -> InsOrdHashMap SourceName (AnyBackend SourceMetadata)
forall a b.
(a -> b)
-> InsOrdHashMap SourceName a -> InsOrdHashMap SourceName b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap BackendSourceMetadata -> AnyBackend SourceMetadata
Metadata.unBackendSourceMetadata (Sources -> InsOrdHashMap SourceName (AnyBackend SourceMetadata))
-> Sources -> InsOrdHashMap SourceName (AnyBackend SourceMetadata)
forall a b. (a -> b) -> a -> b
$ Metadata -> Sources
Metadata._metaSources Metadata
metadata
  AnyBackend SourceMetadata
abSourceMetadata <- SourceName
-> InsOrdHashMap SourceName (AnyBackend SourceMetadata)
-> m (AnyBackend SourceMetadata)
forall (m :: * -> *).
MonadError QErr m =>
SourceName
-> InsOrdHashMap SourceName (AnyBackend SourceMetadata)
-> m (AnyBackend SourceMetadata)
lookupSourceMetadata SourceName
_gtiSourceName_ InsOrdHashMap SourceName (AnyBackend SourceMetadata)
sources

  forall (c :: BackendType -> Constraint) (i :: BackendType -> *) r.
AllBackendsSatisfy c =>
AnyBackend i -> (forall (b :: BackendType). c b => i b -> r) -> r
AnyBackend.dispatchAnyBackend @RQL.Types.Backend AnyBackend SourceMetadata
abSourceMetadata ((forall (b :: BackendType).
  Backend b =>
  SourceMetadata b -> m EncJSON)
 -> m EncJSON)
-> (forall (b :: BackendType).
    Backend b =>
    SourceMetadata b -> m EncJSON)
-> m EncJSON
forall a b. (a -> b) -> a -> b
$ \Metadata.SourceMetadata {BackendSourceKind b
_smKind :: BackendSourceKind b
_smKind :: forall (b :: BackendType). SourceMetadata b -> BackendSourceKind b
_smKind} -> do
    case BackendSourceKind b
_smKind of
      Backend.DataConnectorKind DataConnectorName
_dcName -> do
        (Maybe (SourceTableInfo 'DataConnector) -> EncJSON)
-> m (Maybe (SourceTableInfo 'DataConnector)) -> m EncJSON
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Maybe (SourceTableInfo 'DataConnector) -> EncJSON
forall a. ToJSON a => a -> EncJSON
EncJSON.encJFromJValue (forall (b :: BackendType) (m :: * -> *).
(BackendMetadata b, CacheRM m, MetadataM m, MonadError QErr m,
 MonadBaseControl IO m, MonadIO m) =>
SourceName -> TableName b -> m (Maybe (SourceTableInfo b))
getTableInfo @'DataConnector SourceName
_gtiSourceName_ TableName 'DataConnector
_gtiTableName_)
      BackendSourceKind b
backend ->
        Text -> m EncJSON
forall (m :: * -> *) a. QErrM m => Text -> m a
Error.throw500 (Text
"Schema fetching is not supported for '" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> BackendSourceKind b -> Text
forall a. ToTxt a => a -> Text
Text.E.toTxt BackendSourceKind b
backend Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"'")

data GetTableInfo (b :: BackendType) = GetTableInfo
  { forall (b :: BackendType). GetTableInfo b -> SourceName
_gtiSourceName :: Common.SourceName,
    forall (b :: BackendType). GetTableInfo b -> TableName b
_gtiTableName :: TableName b
  }

instance (Backend b) => FromJSON (GetTableInfo b) where
  parseJSON :: Value -> Parser (GetTableInfo b)
parseJSON = String
-> (Object -> Parser (GetTableInfo b))
-> Value
-> Parser (GetTableInfo b)
forall a. String -> (Object -> Parser a) -> Value -> Parser a
J.withObject String
"GetTableInfo_" \Object
o -> do
    SourceName
_gtiSourceName <- Object
o Object -> Key -> Parser SourceName
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"source"
    TableName b
_gtiTableName <- Object
o Object -> Key -> Parser (TableName b)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"table"
    GetTableInfo b -> Parser (GetTableInfo b)
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (GetTableInfo b -> Parser (GetTableInfo b))
-> GetTableInfo b -> Parser (GetTableInfo b)
forall a b. (a -> b) -> a -> b
$ GetTableInfo {SourceName
TableName b
_gtiSourceName :: SourceName
_gtiTableName :: TableName b
_gtiSourceName :: SourceName
_gtiTableName :: TableName b
..}

-- | Get information about the given table.
runGetTableInfo ::
  forall b m.
  ( BackendMetadata b,
    CacheRM m,
    MonadError Error.QErr m,
    Metadata.MetadataM m,
    MonadBaseControl IO m,
    MonadIO m
  ) =>
  GetTableInfo b ->
  m EncJSON
runGetTableInfo :: forall (b :: BackendType) (m :: * -> *).
(BackendMetadata b, CacheRM m, MonadError QErr m, MetadataM m,
 MonadBaseControl IO m, MonadIO m) =>
GetTableInfo b -> m EncJSON
runGetTableInfo GetTableInfo {SourceName
TableName b
_gtiSourceName :: forall (b :: BackendType). GetTableInfo b -> SourceName
_gtiTableName :: forall (b :: BackendType). GetTableInfo b -> TableName b
_gtiSourceName :: SourceName
_gtiTableName :: TableName b
..} = do
  (Maybe (SourceTableInfo b) -> EncJSON)
-> m (Maybe (SourceTableInfo b)) -> m EncJSON
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Maybe (SourceTableInfo b) -> EncJSON
forall a. ToJSON a => a -> EncJSON
EncJSON.encJFromJValue (forall (b :: BackendType) (m :: * -> *).
(BackendMetadata b, CacheRM m, MetadataM m, MonadError QErr m,
 MonadBaseControl IO m, MonadIO m) =>
SourceName -> TableName b -> m (Maybe (SourceTableInfo b))
getTableInfo @b SourceName
_gtiSourceName TableName b
_gtiTableName)

--------------------------------------------------------------------------------
-- Internal helper functions

lookupSourceMetadata :: (MonadError QErr m) => SourceName -> InsOrdHashMap SourceName (AnyBackend SourceMetadata) -> m (AnyBackend SourceMetadata)
lookupSourceMetadata :: forall (m :: * -> *).
MonadError QErr m =>
SourceName
-> InsOrdHashMap SourceName (AnyBackend SourceMetadata)
-> m (AnyBackend SourceMetadata)
lookupSourceMetadata SourceName
sourceName InsOrdHashMap SourceName (AnyBackend SourceMetadata)
sources =
  SourceName
-> InsOrdHashMap SourceName (AnyBackend SourceMetadata)
-> Maybe (AnyBackend SourceMetadata)
forall k v. (Eq k, Hashable k) => k -> InsOrdHashMap k v -> Maybe v
InsOrdHashMap.lookup SourceName
sourceName InsOrdHashMap SourceName (AnyBackend SourceMetadata)
sources
    Maybe (AnyBackend SourceMetadata)
-> m (AnyBackend SourceMetadata) -> m (AnyBackend SourceMetadata)
forall (m :: * -> *) a. Applicative m => Maybe a -> m a -> m a
`onNothing` Code -> Text -> m (AnyBackend SourceMetadata)
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
Error.throw400 Code
Error.DataConnectorError (Text
"Source '" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> SourceName -> Text
forall a. ToTxt a => a -> Text
Text.E.toTxt SourceName
sourceName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"' not found")