mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-17 20:41:49 +03:00
1afa4ac3cc
Co-authored-by: Vladimir Ciobanu <1017953+vladciobanu@users.noreply.github.com> Co-authored-by: Antoine Leblanc <1618949+nicuveo@users.noreply.github.com> Co-authored-by: Ikechukwu Eze <22247592+iykekings@users.noreply.github.com> Co-authored-by: Philip Lykke Carlsen <358550+plcplc@users.noreply.github.com> Co-authored-by: Phil Freeman <630306+paf31@users.noreply.github.com> GitOrigin-RevId: 1b964fe5f5f50380172cb702b6a328fed782b6b7
129 lines
5.4 KiB
Haskell
129 lines
5.4 KiB
Haskell
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
|
{-# LANGUAGE UndecidableInstances #-}
|
|
|
|
module Hasura.Backends.Postgres.Instances.Metadata () where
|
|
|
|
|
|
import Hasura.Prelude
|
|
|
|
import qualified Data.HashMap.Strict as Map
|
|
|
|
import Data.Text.Extended
|
|
|
|
import qualified Hasura.Backends.Postgres.DDL as PG
|
|
|
|
import Hasura.Backends.Postgres.SQL.Types (QualifiedTable)
|
|
import Hasura.Backends.Postgres.Types.CitusExtraTableMetadata
|
|
import Hasura.Base.Error
|
|
import Hasura.RQL.Types.Backend (Backend)
|
|
import Hasura.RQL.Types.Metadata.Backend
|
|
import Hasura.RQL.Types.Relationship
|
|
import Hasura.RQL.Types.Table
|
|
import Hasura.SQL.Backend
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- PostgresMetadata
|
|
|
|
-- | We differentiate the handling of metadata between Citus and Vanilla
|
|
-- Postgres because Citus imposes limitations on the types of joins that it
|
|
-- permits, which then limits the types of relations that we can track.
|
|
class PostgresMetadata (pgKind :: PostgresKind) where
|
|
-- TODO: find a better name
|
|
validateRel
|
|
:: MonadError QErr m
|
|
=> TableCache ('Postgres pgKind)
|
|
-> QualifiedTable
|
|
-> Either (ObjRelDef ('Postgres pgKind)) (ArrRelDef ('Postgres pgKind))
|
|
-> m ()
|
|
|
|
instance PostgresMetadata 'Vanilla where
|
|
validateRel _ _ _ = pure ()
|
|
|
|
instance PostgresMetadata 'Citus where
|
|
validateRel
|
|
:: forall m
|
|
. MonadError QErr m
|
|
=> TableCache ('Postgres 'Citus)
|
|
-> QualifiedTable
|
|
-> Either (ObjRelDef ('Postgres 'Citus)) (ArrRelDef ('Postgres 'Citus))
|
|
-> m ()
|
|
validateRel tableCache sourceTable relInfo = do
|
|
sourceTableInfo <- lookupTableInfo sourceTable
|
|
case relInfo of
|
|
Left (RelDef _ obj _) ->
|
|
case obj of
|
|
RUFKeyOn (SameTable _) -> pure ()
|
|
RUFKeyOn (RemoteTable targetTable _) -> checkObjectRelationship sourceTableInfo targetTable
|
|
RUManual RelManualConfig { } -> pure ()
|
|
Right (RelDef _ obj _) ->
|
|
case obj of
|
|
RUFKeyOn (ArrRelUsingFKeyOn targetTable _col) -> checkArrayRelationship sourceTableInfo targetTable
|
|
RUManual RelManualConfig { } -> pure ()
|
|
where
|
|
lookupTableInfo tableName = Map.lookup tableName tableCache
|
|
`onNothing` throw400 NotFound ("no such table " <>> tableName)
|
|
|
|
checkObjectRelationship sourceTableInfo targetTable = do
|
|
targetTableInfo <- lookupTableInfo targetTable
|
|
let notSupported = throwNotSupportedError sourceTableInfo targetTableInfo "object"
|
|
case ( _tciExtraTableMetadata $ _tiCoreInfo sourceTableInfo
|
|
, _tciExtraTableMetadata $ _tiCoreInfo targetTableInfo
|
|
) of
|
|
(Distributed{}, Local) -> notSupported
|
|
(Distributed{}, Reference) -> pure ()
|
|
(Distributed{}, Distributed{}) -> pure ()
|
|
(_, Distributed{}) -> notSupported
|
|
(_, _) -> pure ()
|
|
|
|
checkArrayRelationship sourceTableInfo targetTable = do
|
|
targetTableInfo <- lookupTableInfo targetTable
|
|
let notSupported = throwNotSupportedError sourceTableInfo targetTableInfo "array"
|
|
case ( _tciExtraTableMetadata $ _tiCoreInfo sourceTableInfo
|
|
, _tciExtraTableMetadata $ _tiCoreInfo targetTableInfo
|
|
) of
|
|
(Distributed{}, Distributed{}) -> pure ()
|
|
(Distributed{}, _) -> notSupported
|
|
(_, Distributed{}) -> notSupported
|
|
(_, _) -> pure ()
|
|
|
|
showDistributionType :: ExtraTableMetadata -> Text
|
|
showDistributionType = \case
|
|
Local -> "local"
|
|
Distributed _ -> "distributed"
|
|
Reference -> "reference"
|
|
|
|
throwNotSupportedError :: TableInfo ('Postgres 'Citus) -> TableInfo ('Postgres 'Citus) -> Text -> m ()
|
|
throwNotSupportedError sourceTableInfo targetTableInfo t =
|
|
let tciSrc = _tiCoreInfo sourceTableInfo
|
|
tciTgt = _tiCoreInfo targetTableInfo
|
|
in
|
|
throw400 NotSupported (
|
|
showDistributionType (_tciExtraTableMetadata tciSrc) <>
|
|
" tables (" <> toTxt (_tciName tciSrc) <> ") cannot have an " <> t <> " relationship against a " <>
|
|
showDistributionType (_tciExtraTableMetadata $ _tiCoreInfo targetTableInfo) <>
|
|
" table (" <> toTxt (_tciName tciTgt) <> ")")
|
|
|
|
|
|
----------------------------------------------------------------
|
|
-- BackendMetadata instance
|
|
|
|
instance
|
|
( Backend ('Postgres pgKind)
|
|
, PostgresMetadata pgKind
|
|
, PG.ToMetadataFetchQuery pgKind
|
|
) => BackendMetadata ('Postgres pgKind) where
|
|
buildComputedFieldInfo = PG.buildComputedFieldInfo
|
|
buildRemoteFieldInfo = PG.buildRemoteFieldInfo
|
|
fetchAndValidateEnumValues = PG.fetchAndValidateEnumValues
|
|
resolveSourceConfig = PG.resolveSourceConfig
|
|
resolveDatabaseMetadata = PG.resolveDatabaseMetadata
|
|
createTableEventTrigger = PG.createTableEventTrigger
|
|
buildEventTriggerInfo = PG.buildEventTriggerInfo @pgKind
|
|
parseBoolExpOperations = PG.parseBoolExpOperations
|
|
buildFunctionInfo = PG.buildFunctionInfo
|
|
updateColumnInEventTrigger = PG.updateColumnInEventTrigger
|
|
parseCollectableType = PG.parseCollectableType
|
|
postDropSourceHook = PG.postDropSourceHook
|
|
validateRelationship = validateRel @pgKind
|