2022-03-16 03:39:21 +03:00
|
|
|
{-# LANGUAGE TemplateHaskell #-}
|
|
|
|
|
2021-11-04 19:08:33 +03:00
|
|
|
module Hasura.RQL.DDL.Schema.Source
|
2022-08-30 02:51:34 +03:00
|
|
|
( -- * Add Source
|
|
|
|
AddSource,
|
2021-11-04 19:08:33 +03:00
|
|
|
runAddSource,
|
2023-04-18 08:36:02 +03:00
|
|
|
|
|
|
|
-- * Drop Source
|
2022-08-30 02:51:34 +03:00
|
|
|
DropSource (..),
|
2021-11-04 19:08:33 +03:00
|
|
|
runDropSource,
|
2022-04-11 14:24:11 +03:00
|
|
|
runPostDropSourceHook,
|
2022-08-30 02:51:34 +03:00
|
|
|
|
|
|
|
-- * Rename Source
|
|
|
|
RenameSource,
|
|
|
|
runRenameSource,
|
|
|
|
|
|
|
|
-- * Update Source
|
|
|
|
UpdateSource,
|
2022-06-22 10:06:19 +03:00
|
|
|
runUpdateSource,
|
2022-08-30 02:51:34 +03:00
|
|
|
|
|
|
|
-- * Get Source Tables
|
|
|
|
GetSourceTables (..),
|
|
|
|
runGetSourceTables,
|
|
|
|
|
|
|
|
-- * Get Table Name
|
|
|
|
GetTableInfo (..),
|
|
|
|
runGetTableInfo,
|
2021-11-04 19:08:33 +03:00
|
|
|
)
|
|
|
|
where
|
2020-12-28 15:56:00 +03:00
|
|
|
|
2022-08-30 02:51:34 +03:00
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
2023-04-05 23:14:35 +03:00
|
|
|
import Control.Lens (at, (.~), (^.))
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
import Control.Monad.Trans.Control (MonadBaseControl)
|
2022-08-30 02:51:34 +03:00
|
|
|
import Data.Aeson qualified as Aeson
|
2022-04-29 05:13:13 +03:00
|
|
|
import Data.Aeson.Extended
|
|
|
|
import Data.Aeson.Extended qualified as J
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
import Data.Aeson.TH
|
2023-04-18 08:36:02 +03:00
|
|
|
import Data.Bifunctor (bimap)
|
2022-12-02 11:01:06 +03:00
|
|
|
import Data.Environment qualified as Env
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
import Data.Has
|
|
|
|
import Data.HashMap.Strict qualified as HM
|
2022-08-30 02:51:34 +03:00
|
|
|
import Data.HashMap.Strict.InsOrd qualified as InsOrdHashMap
|
2021-07-27 18:14:12 +03:00
|
|
|
import Data.HashMap.Strict.InsOrd qualified as OMap
|
2023-04-18 08:36:02 +03:00
|
|
|
import Data.HashMap.Strict.NonEmpty qualified as NEHashMap
|
|
|
|
import Data.HashSet qualified as HashSet
|
|
|
|
import Data.Semigroup.Foldable (Foldable1 (..))
|
2021-01-07 12:04:22 +03:00
|
|
|
import Data.Text.Extended
|
2022-08-30 02:51:34 +03:00
|
|
|
import Data.Text.Extended qualified as Text.E
|
|
|
|
import Hasura.Backends.DataConnector.API qualified as API
|
2023-04-18 08:36:02 +03:00
|
|
|
import Hasura.Backends.DataConnector.Adapter.Types qualified as DC.Types
|
|
|
|
import Hasura.Backends.Postgres.SQL.Types (getPGDescription)
|
2021-05-11 18:18:31 +03:00
|
|
|
import Hasura.Base.Error
|
2022-08-30 02:51:34 +03:00
|
|
|
import Hasura.Base.Error qualified as Error
|
2021-01-07 12:04:22 +03:00
|
|
|
import Hasura.EncJSON
|
2022-08-30 02:51:34 +03:00
|
|
|
import Hasura.EncJSON qualified as EncJSON
|
2021-07-27 18:14:12 +03:00
|
|
|
import Hasura.Logging qualified as L
|
2021-03-15 16:02:58 +03:00
|
|
|
import Hasura.Prelude
|
2022-04-27 16:57:28 +03:00
|
|
|
import Hasura.RQL.Types.Backend
|
2022-08-30 02:51:34 +03:00
|
|
|
import Hasura.RQL.Types.Backend qualified as RQL.Types
|
2023-04-24 21:35:48 +03:00
|
|
|
import Hasura.RQL.Types.BackendType
|
|
|
|
import Hasura.RQL.Types.BackendType qualified as Backend
|
2023-04-18 08:36:02 +03:00
|
|
|
import Hasura.RQL.Types.Column (ColumnMutability (..), RawColumnInfo (..))
|
2022-04-27 16:57:28 +03:00
|
|
|
import Hasura.RQL.Types.Common
|
2022-08-30 02:51:34 +03:00
|
|
|
import Hasura.RQL.Types.Common qualified as Common
|
2022-09-02 09:33:21 +03:00
|
|
|
import Hasura.RQL.Types.HealthCheck (HealthCheckConfig)
|
2022-04-27 16:57:28 +03:00
|
|
|
import Hasura.RQL.Types.Metadata
|
2022-08-30 02:51:34 +03:00
|
|
|
import Hasura.RQL.Types.Metadata qualified as Metadata
|
2022-04-27 16:57:28 +03:00
|
|
|
import Hasura.RQL.Types.Metadata.Backend
|
2022-05-27 18:40:02 +03:00
|
|
|
import Hasura.RQL.Types.Metadata.Instances ()
|
2022-04-27 16:57:28 +03:00
|
|
|
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
|
2023-04-18 08:36:02 +03:00
|
|
|
import Hasura.RQL.Types.Table (Constraint (..), DBTableMetadata (..), ForeignKey (..), ForeignKeyMetadata (..), PrimaryKey (..))
|
2023-01-12 02:11:56 +03:00
|
|
|
import Hasura.SQL.AnyBackend (AnyBackend)
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
import Hasura.SQL.AnyBackend qualified as AB
|
2022-08-30 02:51:34 +03:00
|
|
|
import Hasura.SQL.AnyBackend qualified as AnyBackend
|
2021-07-27 18:14:12 +03:00
|
|
|
import Hasura.Server.Logging (MetadataLog (..))
|
harmonize network manager handling
## Description
### I want to speak to the `Manager`
Oh boy. This PR is both fairly straightforward and overreaching, so let's break it down.
For most network access, we need a [`HTTP.Manager`](https://hackage.haskell.org/package/http-client-0.1.0.0/docs/Network-HTTP-Client-Manager.html). It is created only once, at the top level, when starting the engine, and is then threaded through the application to wherever we need to make a network call. As of main, the way we do this is not standardized: most of the GraphQL execution code passes it "manually" as a function argument throughout the code. We also have a custom monad constraint, `HasHttpManagerM`, that describes a monad's ability to provide a manager. And, finally, several parts of the code store the manager in some kind of argument structure, such as `RunT`'s `RunCtx`.
This PR's first goal is to harmonize all of this: we always create the manager at the root, and we already have it when we do our very first `runReaderT`. Wouldn't it make sense for the rest of the code to not manually pass it anywhere, to not store it anywhere, but to always rely on the current monad providing it? This is, in short, what this PR does: it implements a constraint on the base monads, so that they provide the manager, and removes most explicit passing from the code.
### First come, first served
One way this PR goes a tiny bit further than "just" doing the aforementioned harmonization is that it starts the process of implementing the "Services oriented architecture" roughly outlined in this [draft document](https://docs.google.com/document/d/1FAigqrST0juU1WcT4HIxJxe1iEBwTuBZodTaeUvsKqQ/edit?usp=sharing). Instead of using the existing `HasHTTPManagerM`, this PR revamps it into the `ProvidesNetwork` service.
The idea is, again, that we should make all "external" dependencies of the engine, all things that the core of the engine doesn't care about, a "service". This allows us to define clear APIs for features, to choose different implementations based on which version of the engine we're running, harmonizes our many scattered monadic constraints... Which is why this service is called "Network": we can refine it, moving forward, to be the constraint that defines how all network communication is to operate, instead of relying on disparate classes constraint or hardcoded decisions. A comment in the code clarifies this intent.
### Side-effects? In my Haskell?
This PR also unavoidably touches some other aspects of the codebase. One such example: it introduces `Hasura.App.AppContext`, named after `HasuraPro.Context.AppContext`: a name for the reader structure at the base level. It also transforms `Handler` from a type alias to a newtype, as `Handler` is where we actually enforce HTTP limits; but without `Handler` being a distinct type, any code path could simply do a `runExceptT $ runReader` and forget to enforce them.
(As a rule of thumb, i am starting to consider any straggling `runReaderT` or `runExceptT` as a code smell: we should not stack / unstack monads haphazardly, and every layer should be an opaque `newtype` with a corresponding run function.)
## Further work
In several places, i have left TODOs when i have encountered things that suggest that we should do further unrelated cleanups. I'll write down the follow-up steps, either in the aforementioned document or on slack. But, in short, at a glance, in approximate order, we could:
- delete `ExecutionCtx` as it is only a subset of `ServerCtx`, and remove one more `runReaderT` call
- delete `ServerConfigCtx` as it is only a subset of `ServerCtx`, and remove it from `RunCtx`
- remove `ServerCtx` from `HandlerCtx`, and make it part of `AppContext`, or even make it the `AppContext` altogether (since, at least for the OSS version, `AppContext` is there again only a subset)
- remove `CacheBuildParams` and `CacheBuild` altogether, as they're just a distinct stack that is a `ReaderT` on top of `IO` that contains, you guessed it, the same thing as `ServerCtx`
- move `RunT` out of `RQL.Types` and rename it, since after the previous cleanups **it only contains `UserInfo`**; it could be bundled with the authentication service, made a small implementation detail in `Hasura.Server.Auth`
- rename `PGMetadaStorageT` to something a bit more accurate, such as `App`, and enforce its IO base
This would significantly simply our complex stack. From there, or in parallel, we can start moving existing dependencies as Services. For the purpose of supporting read replicas entitlement, we could move `MonadResolveSource` to a `SourceResolver` service, as attempted in #7653, and transform `UserAuthenticationM` into a `Authentication` service.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7736
GitOrigin-RevId: 68cce710eb9e7d752bda1ba0c49541d24df8209f
2023-02-22 18:53:52 +03:00
|
|
|
import Hasura.Services
|
2023-04-18 08:36:02 +03:00
|
|
|
import Language.GraphQL.Draft.Syntax qualified as G
|
|
|
|
import Witch qualified
|
2020-12-28 15:56:00 +03:00
|
|
|
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- Add source
|
|
|
|
|
|
|
|
data AddSource b = AddSource
|
2022-08-01 12:32:04 +03:00
|
|
|
{ _asName :: SourceName,
|
|
|
|
_asBackendKind :: BackendSourceKind b,
|
|
|
|
_asConfiguration :: SourceConnConfiguration b,
|
|
|
|
_asReplaceConfiguration :: Bool,
|
2022-09-02 09:33:21 +03:00
|
|
|
_asCustomization :: SourceCustomization,
|
|
|
|
_asHealthCheckConfig :: Maybe (HealthCheckConfig b)
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
}
|
|
|
|
|
2022-04-29 05:13:13 +03:00
|
|
|
instance (Backend b) => FromJSONWithContext (BackendSourceKind b) (AddSource b) where
|
|
|
|
parseJSONWithContext backendKind = withObject "AddSource" $ \o ->
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
AddSource
|
2023-01-12 02:11:56 +03:00
|
|
|
<$> o
|
|
|
|
.: "name"
|
2022-04-29 05:13:13 +03:00
|
|
|
<*> pure backendKind
|
2023-01-12 02:11:56 +03:00
|
|
|
<*> o
|
|
|
|
.: "configuration"
|
|
|
|
<*> o
|
|
|
|
.:? "replace_configuration"
|
|
|
|
.!= False
|
|
|
|
<*> o
|
|
|
|
.:? "customization"
|
|
|
|
.!= emptySourceCustomization
|
|
|
|
<*> o
|
|
|
|
.:? "health_check"
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
|
2021-02-23 20:37:27 +03:00
|
|
|
runAddSource ::
|
|
|
|
forall m b.
|
2022-11-16 18:41:12 +03:00
|
|
|
(MonadIO m, MonadError QErr m, CacheRWM m, MetadataM m, BackendMetadata b) =>
|
2023-02-14 15:14:33 +03:00
|
|
|
Env.Environment ->
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
AddSource b ->
|
|
|
|
m EncJSON
|
2023-02-14 15:14:33 +03:00
|
|
|
runAddSource env (AddSource name backendKind sourceConfig replaceConfiguration sourceCustomization healthCheckConfig) = do
|
2021-02-23 20:37:27 +03:00
|
|
|
sources <- scSources <$> askSchemaCache
|
2022-11-16 18:41:12 +03:00
|
|
|
do
|
|
|
|
-- version check
|
2023-02-14 15:14:33 +03:00
|
|
|
result <- liftIO $ versionCheckImplementation @b env sourceConfig
|
2022-11-16 18:41:12 +03:00
|
|
|
liftEither result
|
2021-03-30 13:09:29 +03:00
|
|
|
|
|
|
|
metadataModifier <-
|
|
|
|
MetadataModifier
|
|
|
|
<$> if HM.member name sources
|
|
|
|
then
|
2021-06-09 15:12:25 +03:00
|
|
|
if replaceConfiguration
|
2022-06-22 10:06:19 +03:00
|
|
|
then do
|
|
|
|
let sMetadata = metaSources . ix name . toSourceMetadata @b
|
|
|
|
updateConfig = sMetadata . smConfiguration .~ sourceConfig
|
|
|
|
updateCustomization = sMetadata . smCustomization .~ sourceCustomization
|
|
|
|
pure $ updateConfig . updateCustomization
|
2021-03-30 13:09:29 +03:00
|
|
|
else throw400 AlreadyExists $ "source with name " <> name <<> " already exists"
|
2021-06-09 15:12:25 +03:00
|
|
|
else do
|
2022-08-10 12:40:57 +03:00
|
|
|
let sourceMetadata =
|
2022-09-02 09:33:21 +03:00
|
|
|
mkSourceMetadata @b name backendKind sourceConfig sourceCustomization healthCheckConfig
|
2021-06-09 15:12:25 +03:00
|
|
|
pure $ metaSources %~ OMap.insert name sourceMetadata
|
2021-03-30 13:09:29 +03:00
|
|
|
|
|
|
|
buildSchemaCacheFor (MOSource name) metadataModifier
|
2021-01-07 12:04:22 +03:00
|
|
|
pure successMsg
|
|
|
|
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- Rename source
|
|
|
|
|
|
|
|
data RenameSource = RenameSource
|
2022-08-01 12:32:04 +03:00
|
|
|
{ _rmName :: SourceName,
|
|
|
|
_rmNewName :: SourceName
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
}
|
2021-09-24 01:56:37 +03:00
|
|
|
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
$(deriveFromJSON hasuraJSON ''RenameSource)
|
|
|
|
|
2021-05-24 16:13:08 +03:00
|
|
|
runRenameSource ::
|
|
|
|
forall m.
|
|
|
|
(MonadError QErr m, CacheRWM m, MetadataM m) =>
|
|
|
|
RenameSource ->
|
|
|
|
m EncJSON
|
|
|
|
runRenameSource RenameSource {..} = do
|
|
|
|
sources <- scSources <$> askSchemaCache
|
|
|
|
|
|
|
|
unless (HM.member _rmName sources) $
|
|
|
|
throw400 NotExists $
|
|
|
|
"Could not find source with name " <>> _rmName
|
|
|
|
|
|
|
|
when (HM.member _rmNewName sources) $
|
|
|
|
throw400 AlreadyExists $
|
|
|
|
"Source with name " <> _rmNewName <<> " already exists"
|
|
|
|
|
|
|
|
let metadataModifier =
|
|
|
|
MetadataModifier $
|
|
|
|
metaSources %~ renameBackendSourceMetadata _rmName _rmNewName
|
|
|
|
buildSchemaCacheFor (MOSource _rmNewName) metadataModifier
|
|
|
|
|
|
|
|
pure successMsg
|
|
|
|
where
|
|
|
|
renameBackendSourceMetadata ::
|
|
|
|
SourceName ->
|
|
|
|
SourceName ->
|
|
|
|
OMap.InsOrdHashMap SourceName BackendSourceMetadata ->
|
|
|
|
OMap.InsOrdHashMap SourceName BackendSourceMetadata
|
|
|
|
renameBackendSourceMetadata oldKey newKey m =
|
|
|
|
case OMap.lookup oldKey m of
|
|
|
|
Just val ->
|
2022-08-29 03:58:03 +03:00
|
|
|
let renamedSource = BackendSourceMetadata (AB.mapBackend (unBackendSourceMetadata val) (renameSource newKey))
|
|
|
|
in OMap.insert newKey renamedSource $ OMap.delete oldKey $ m
|
2021-05-24 16:13:08 +03:00
|
|
|
Nothing -> m
|
|
|
|
|
|
|
|
renameSource :: forall b. SourceName -> SourceMetadata b -> SourceMetadata b
|
|
|
|
renameSource newName metadata = metadata {_smName = newName}
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- Drop source
|
|
|
|
|
|
|
|
data DropSource = DropSource
|
2022-08-01 12:32:04 +03:00
|
|
|
{ _dsName :: SourceName,
|
|
|
|
_dsCascade :: Bool
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
}
|
|
|
|
deriving (Show, Eq)
|
|
|
|
|
|
|
|
instance FromJSON DropSource where
|
2021-09-20 22:49:33 +03:00
|
|
|
parseJSON = withObject "DropSource" $ \o ->
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
DropSource <$> o .: "name" <*> o .:? "cascade" .!= False
|
|
|
|
|
2021-02-23 20:37:27 +03:00
|
|
|
runDropSource ::
|
2021-07-27 18:14:12 +03:00
|
|
|
forall m r.
|
|
|
|
( MonadError QErr m,
|
|
|
|
CacheRWM m,
|
|
|
|
MonadIO m,
|
|
|
|
MonadBaseControl IO m,
|
|
|
|
MetadataM m,
|
|
|
|
MonadReader r m,
|
|
|
|
Has (L.Logger L.Hasura) r
|
2021-02-23 20:37:27 +03:00
|
|
|
) =>
|
|
|
|
DropSource ->
|
|
|
|
m EncJSON
|
2022-04-11 14:24:11 +03:00
|
|
|
runDropSource dropSourceInfo@(DropSource name cascade) = do
|
|
|
|
schemaCache <- askSchemaCache
|
|
|
|
let sources = scSources schemaCache
|
2021-03-02 07:26:31 +03:00
|
|
|
case HM.lookup name sources of
|
|
|
|
Just backendSourceInfo ->
|
2023-03-17 18:50:04 +03:00
|
|
|
AB.dispatchAnyBackend @BackendMetadata backendSourceInfo $ dropSource dropSourceInfo
|
2021-03-02 07:26:31 +03:00
|
|
|
Nothing -> do
|
|
|
|
metadata <- getMetadata
|
|
|
|
void $
|
|
|
|
onNothing (metadata ^. metaSources . at name) $
|
|
|
|
throw400 NotExists $
|
|
|
|
"source with name " <> name <<> " does not exist"
|
|
|
|
if cascade
|
|
|
|
then -- Without sourceInfo we can't cascade, so throw an error
|
|
|
|
throw400 Unexpected $ "source with name " <> name <<> " is inconsistent"
|
|
|
|
else -- Drop source from metadata
|
2022-04-11 14:24:11 +03:00
|
|
|
buildSchemaCacheFor (MOSource name) (dropSourceMetadataModifier name)
|
2021-02-23 20:37:27 +03:00
|
|
|
pure successMsg
|
2022-04-11 14:24:11 +03:00
|
|
|
|
|
|
|
dropSourceMetadataModifier :: SourceName -> MetadataModifier
|
|
|
|
dropSourceMetadataModifier sourceName = MetadataModifier $ metaSources %~ OMap.delete 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 ()
|
2023-03-17 18:50:04 +03:00
|
|
|
dropSource (DropSource sourceName cascade) sourceInfo = do
|
2022-05-27 18:40:02 +03:00
|
|
|
schemaCache <- askSchemaCache
|
|
|
|
let remoteDeps = getRemoteDependencies schemaCache sourceName
|
2022-04-11 14:24:11 +03:00
|
|
|
|
2022-07-01 13:49:31 +03:00
|
|
|
unless (cascade || null remoteDeps) $
|
2022-05-27 18:40:02 +03:00
|
|
|
reportDependentObjectsExist remoteDeps
|
2022-04-11 14:24:11 +03:00
|
|
|
|
|
|
|
metadataModifier <- execWriterT $ do
|
2022-05-27 18:40:02 +03:00
|
|
|
traverse_ purgeSourceAndSchemaDependencies remoteDeps
|
2022-04-11 14:24:11 +03:00
|
|
|
tell $ dropSourceMetadataModifier sourceName
|
|
|
|
|
|
|
|
buildSchemaCacheFor (MOSource sourceName) metadataModifier
|
|
|
|
runPostDropSourceHook sourceName 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 sourceName sourceInfo = do
|
|
|
|
logger :: (L.Logger L.Hasura) <- asks getter
|
|
|
|
let sourceConfig = _siConfiguration sourceInfo
|
2022-07-19 14:39:44 +03:00
|
|
|
-- Create a hashmap: {TableName: [Triggers]}
|
|
|
|
let tableTriggersMap = HM.map (HM.keys . _tiEventTriggerInfoMap) (_siTables sourceInfo)
|
2022-04-11 14:24:11 +03:00
|
|
|
-- 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
|
2022-07-19 14:39:44 +03:00
|
|
|
runExceptT (postDropSourceHook @b sourceConfig tableTriggersMap) >>= either (logDropSourceHookError logger) pure
|
2021-02-23 20:37:27 +03:00
|
|
|
where
|
2022-04-11 14:24:11 +03:00
|
|
|
logDropSourceHookError logger err =
|
|
|
|
let msg =
|
|
|
|
"Error executing cleanup actions after removing source '"
|
|
|
|
<> toTxt sourceName
|
|
|
|
<> "'. Consider cleaning up tables in hdb_catalog schema manually."
|
|
|
|
in L.unLogger logger $ MetadataLog L.LevelWarn msg (J.toJSON err)
|
2022-06-22 10:06:19 +03:00
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- update source
|
|
|
|
|
|
|
|
data UpdateSource b = UpdateSource
|
2022-08-01 12:32:04 +03:00
|
|
|
{ _usName :: SourceName,
|
|
|
|
_usConfiguration :: Maybe (SourceConnConfiguration b),
|
2022-09-02 09:33:21 +03:00
|
|
|
_usCustomization :: Maybe SourceCustomization,
|
|
|
|
_usHealthCheckConfig :: Maybe (HealthCheckConfig b)
|
2022-06-22 10:06:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
instance (Backend b) => FromJSONWithContext (BackendSourceKind b) (UpdateSource b) where
|
|
|
|
parseJSONWithContext _ = withObject "UpdateSource" $ \o ->
|
|
|
|
UpdateSource
|
2023-01-12 02:11:56 +03:00
|
|
|
<$> o
|
|
|
|
.: "name"
|
|
|
|
<*> o
|
|
|
|
.:? "configuration"
|
|
|
|
<*> o
|
|
|
|
.:? "customization"
|
|
|
|
<*> o
|
|
|
|
.:? "health_check"
|
2022-06-22 10:06:19 +03:00
|
|
|
|
|
|
|
runUpdateSource ::
|
|
|
|
forall m b.
|
|
|
|
(MonadError QErr m, CacheRWM m, MetadataM m, BackendMetadata b) =>
|
|
|
|
UpdateSource b ->
|
|
|
|
m EncJSON
|
2022-09-02 09:33:21 +03:00
|
|
|
runUpdateSource (UpdateSource name sourceConfig sourceCustomization healthCheckConfig) = do
|
2022-06-22 10:06:19 +03:00
|
|
|
sources <- scSources <$> askSchemaCache
|
|
|
|
|
|
|
|
metadataModifier <-
|
|
|
|
MetadataModifier
|
|
|
|
<$> if HM.member name sources
|
|
|
|
then do
|
|
|
|
let sMetadata = metaSources . ix name . toSourceMetadata @b
|
|
|
|
updateConfig = maybe id (\scc -> sMetadata . smConfiguration .~ scc) sourceConfig
|
|
|
|
updateCustomization = maybe id (\scc -> sMetadata . smCustomization .~ scc) sourceCustomization
|
2022-09-02 09:33:21 +03:00
|
|
|
updateHealthCheckConfig = maybe id (\hcc -> sMetadata . smHealthCheckConfig .~ Just hcc) healthCheckConfig
|
|
|
|
pure $ updateHealthCheckConfig . updateConfig . updateCustomization
|
2022-06-22 10:06:19 +03:00
|
|
|
else do
|
|
|
|
throw400 NotExists $ "source with name " <> name <<> " does not exist"
|
|
|
|
|
|
|
|
buildSchemaCacheFor (MOSource name) metadataModifier
|
|
|
|
pure successMsg
|
2022-08-30 02:51:34 +03:00
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
2023-04-04 18:25:51 +03:00
|
|
|
newtype GetSourceTables (b :: BackendType) = GetSourceTables {_gstSourceName :: SourceName}
|
2022-08-30 02:51:34 +03:00
|
|
|
|
2023-04-04 18:25:51 +03:00
|
|
|
instance FromJSON (GetSourceTables b) where
|
2022-08-30 02:51:34 +03:00
|
|
|
parseJSON = Aeson.withObject "GetSourceTables" \o -> do
|
|
|
|
_gstSourceName <- o .: "source"
|
|
|
|
pure $ GetSourceTables {..}
|
|
|
|
|
2023-04-13 04:29:15 +03:00
|
|
|
-- | Fetch a list of tables for the request data source.
|
2022-08-30 02:51:34 +03:00
|
|
|
runGetSourceTables ::
|
2023-04-04 18:25:51 +03:00
|
|
|
forall b m r.
|
2023-04-05 23:14:35 +03:00
|
|
|
( BackendMetadata b,
|
2023-04-04 18:25:51 +03:00
|
|
|
CacheRM m,
|
2022-08-30 02:51:34 +03:00
|
|
|
MonadError Error.QErr m,
|
|
|
|
Metadata.MetadataM m,
|
2023-01-25 06:36:52 +03:00
|
|
|
MonadIO m,
|
harmonize network manager handling
## Description
### I want to speak to the `Manager`
Oh boy. This PR is both fairly straightforward and overreaching, so let's break it down.
For most network access, we need a [`HTTP.Manager`](https://hackage.haskell.org/package/http-client-0.1.0.0/docs/Network-HTTP-Client-Manager.html). It is created only once, at the top level, when starting the engine, and is then threaded through the application to wherever we need to make a network call. As of main, the way we do this is not standardized: most of the GraphQL execution code passes it "manually" as a function argument throughout the code. We also have a custom monad constraint, `HasHttpManagerM`, that describes a monad's ability to provide a manager. And, finally, several parts of the code store the manager in some kind of argument structure, such as `RunT`'s `RunCtx`.
This PR's first goal is to harmonize all of this: we always create the manager at the root, and we already have it when we do our very first `runReaderT`. Wouldn't it make sense for the rest of the code to not manually pass it anywhere, to not store it anywhere, but to always rely on the current monad providing it? This is, in short, what this PR does: it implements a constraint on the base monads, so that they provide the manager, and removes most explicit passing from the code.
### First come, first served
One way this PR goes a tiny bit further than "just" doing the aforementioned harmonization is that it starts the process of implementing the "Services oriented architecture" roughly outlined in this [draft document](https://docs.google.com/document/d/1FAigqrST0juU1WcT4HIxJxe1iEBwTuBZodTaeUvsKqQ/edit?usp=sharing). Instead of using the existing `HasHTTPManagerM`, this PR revamps it into the `ProvidesNetwork` service.
The idea is, again, that we should make all "external" dependencies of the engine, all things that the core of the engine doesn't care about, a "service". This allows us to define clear APIs for features, to choose different implementations based on which version of the engine we're running, harmonizes our many scattered monadic constraints... Which is why this service is called "Network": we can refine it, moving forward, to be the constraint that defines how all network communication is to operate, instead of relying on disparate classes constraint or hardcoded decisions. A comment in the code clarifies this intent.
### Side-effects? In my Haskell?
This PR also unavoidably touches some other aspects of the codebase. One such example: it introduces `Hasura.App.AppContext`, named after `HasuraPro.Context.AppContext`: a name for the reader structure at the base level. It also transforms `Handler` from a type alias to a newtype, as `Handler` is where we actually enforce HTTP limits; but without `Handler` being a distinct type, any code path could simply do a `runExceptT $ runReader` and forget to enforce them.
(As a rule of thumb, i am starting to consider any straggling `runReaderT` or `runExceptT` as a code smell: we should not stack / unstack monads haphazardly, and every layer should be an opaque `newtype` with a corresponding run function.)
## Further work
In several places, i have left TODOs when i have encountered things that suggest that we should do further unrelated cleanups. I'll write down the follow-up steps, either in the aforementioned document or on slack. But, in short, at a glance, in approximate order, we could:
- delete `ExecutionCtx` as it is only a subset of `ServerCtx`, and remove one more `runReaderT` call
- delete `ServerConfigCtx` as it is only a subset of `ServerCtx`, and remove it from `RunCtx`
- remove `ServerCtx` from `HandlerCtx`, and make it part of `AppContext`, or even make it the `AppContext` altogether (since, at least for the OSS version, `AppContext` is there again only a subset)
- remove `CacheBuildParams` and `CacheBuild` altogether, as they're just a distinct stack that is a `ReaderT` on top of `IO` that contains, you guessed it, the same thing as `ServerCtx`
- move `RunT` out of `RQL.Types` and rename it, since after the previous cleanups **it only contains `UserInfo`**; it could be bundled with the authentication service, made a small implementation detail in `Hasura.Server.Auth`
- rename `PGMetadaStorageT` to something a bit more accurate, such as `App`, and enforce its IO base
This would significantly simply our complex stack. From there, or in parallel, we can start moving existing dependencies as Services. For the purpose of supporting read replicas entitlement, we could move `MonadResolveSource` to a `SourceResolver` service, as attempted in #7653, and transform `UserAuthenticationM` into a `Authentication` service.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7736
GitOrigin-RevId: 68cce710eb9e7d752bda1ba0c49541d24df8209f
2023-02-22 18:53:52 +03:00
|
|
|
MonadBaseControl IO m,
|
2023-04-05 23:14:35 +03:00
|
|
|
MonadReader r m,
|
|
|
|
Has (L.Logger L.Hasura) r,
|
harmonize network manager handling
## Description
### I want to speak to the `Manager`
Oh boy. This PR is both fairly straightforward and overreaching, so let's break it down.
For most network access, we need a [`HTTP.Manager`](https://hackage.haskell.org/package/http-client-0.1.0.0/docs/Network-HTTP-Client-Manager.html). It is created only once, at the top level, when starting the engine, and is then threaded through the application to wherever we need to make a network call. As of main, the way we do this is not standardized: most of the GraphQL execution code passes it "manually" as a function argument throughout the code. We also have a custom monad constraint, `HasHttpManagerM`, that describes a monad's ability to provide a manager. And, finally, several parts of the code store the manager in some kind of argument structure, such as `RunT`'s `RunCtx`.
This PR's first goal is to harmonize all of this: we always create the manager at the root, and we already have it when we do our very first `runReaderT`. Wouldn't it make sense for the rest of the code to not manually pass it anywhere, to not store it anywhere, but to always rely on the current monad providing it? This is, in short, what this PR does: it implements a constraint on the base monads, so that they provide the manager, and removes most explicit passing from the code.
### First come, first served
One way this PR goes a tiny bit further than "just" doing the aforementioned harmonization is that it starts the process of implementing the "Services oriented architecture" roughly outlined in this [draft document](https://docs.google.com/document/d/1FAigqrST0juU1WcT4HIxJxe1iEBwTuBZodTaeUvsKqQ/edit?usp=sharing). Instead of using the existing `HasHTTPManagerM`, this PR revamps it into the `ProvidesNetwork` service.
The idea is, again, that we should make all "external" dependencies of the engine, all things that the core of the engine doesn't care about, a "service". This allows us to define clear APIs for features, to choose different implementations based on which version of the engine we're running, harmonizes our many scattered monadic constraints... Which is why this service is called "Network": we can refine it, moving forward, to be the constraint that defines how all network communication is to operate, instead of relying on disparate classes constraint or hardcoded decisions. A comment in the code clarifies this intent.
### Side-effects? In my Haskell?
This PR also unavoidably touches some other aspects of the codebase. One such example: it introduces `Hasura.App.AppContext`, named after `HasuraPro.Context.AppContext`: a name for the reader structure at the base level. It also transforms `Handler` from a type alias to a newtype, as `Handler` is where we actually enforce HTTP limits; but without `Handler` being a distinct type, any code path could simply do a `runExceptT $ runReader` and forget to enforce them.
(As a rule of thumb, i am starting to consider any straggling `runReaderT` or `runExceptT` as a code smell: we should not stack / unstack monads haphazardly, and every layer should be an opaque `newtype` with a corresponding run function.)
## Further work
In several places, i have left TODOs when i have encountered things that suggest that we should do further unrelated cleanups. I'll write down the follow-up steps, either in the aforementioned document or on slack. But, in short, at a glance, in approximate order, we could:
- delete `ExecutionCtx` as it is only a subset of `ServerCtx`, and remove one more `runReaderT` call
- delete `ServerConfigCtx` as it is only a subset of `ServerCtx`, and remove it from `RunCtx`
- remove `ServerCtx` from `HandlerCtx`, and make it part of `AppContext`, or even make it the `AppContext` altogether (since, at least for the OSS version, `AppContext` is there again only a subset)
- remove `CacheBuildParams` and `CacheBuild` altogether, as they're just a distinct stack that is a `ReaderT` on top of `IO` that contains, you guessed it, the same thing as `ServerCtx`
- move `RunT` out of `RQL.Types` and rename it, since after the previous cleanups **it only contains `UserInfo`**; it could be bundled with the authentication service, made a small implementation detail in `Hasura.Server.Auth`
- rename `PGMetadaStorageT` to something a bit more accurate, such as `App`, and enforce its IO base
This would significantly simply our complex stack. From there, or in parallel, we can start moving existing dependencies as Services. For the purpose of supporting read replicas entitlement, we could move `MonadResolveSource` to a `SourceResolver` service, as attempted in #7653, and transform `UserAuthenticationM` into a `Authentication` service.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7736
GitOrigin-RevId: 68cce710eb9e7d752bda1ba0c49541d24df8209f
2023-02-22 18:53:52 +03:00
|
|
|
ProvidesNetwork m
|
2022-08-30 02:51:34 +03:00
|
|
|
) =>
|
2023-04-04 18:25:51 +03:00
|
|
|
GetSourceTables b ->
|
2022-08-30 02:51:34 +03:00
|
|
|
m EncJSON
|
2023-04-13 04:29:15 +03:00
|
|
|
runGetSourceTables GetSourceTables {..} = do
|
|
|
|
fmap EncJSON.encJFromJValue (listAllTables @b _gstSourceName)
|
2022-08-30 02:51:34 +03:00
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
data GetTableInfo = GetTableInfo
|
|
|
|
{ _gtiSourceName :: Common.SourceName,
|
|
|
|
_gtiTableName :: API.TableName
|
|
|
|
}
|
|
|
|
|
|
|
|
instance FromJSON GetTableInfo where
|
|
|
|
parseJSON = Aeson.withObject "GetSourceTables" \o -> do
|
|
|
|
_gtiSourceName <- o .: "source"
|
|
|
|
_gtiTableName <- o .: "table"
|
|
|
|
pure $ GetTableInfo {..}
|
|
|
|
|
2023-04-18 08:36:02 +03:00
|
|
|
-- | Fetch a schema information about a table for the requested data source. Currently
|
2022-08-30 02:51:34 +03:00
|
|
|
-- this is only supported for Data Connectors.
|
|
|
|
runGetTableInfo ::
|
2022-12-21 02:38:24 +03:00
|
|
|
( CacheRM m,
|
2022-08-30 02:51:34 +03:00
|
|
|
MonadError Error.QErr m,
|
2023-04-18 08:36:02 +03:00
|
|
|
Metadata.MetadataM m
|
2022-08-30 02:51:34 +03:00
|
|
|
) =>
|
|
|
|
GetTableInfo ->
|
|
|
|
m EncJSON
|
2023-04-13 04:29:15 +03:00
|
|
|
runGetTableInfo GetTableInfo {..} = do
|
2022-08-30 02:51:34 +03:00
|
|
|
metadata <- Metadata.getMetadata
|
|
|
|
|
|
|
|
let sources = fmap Metadata.unBackendSourceMetadata $ Metadata._metaSources metadata
|
2023-01-12 02:11:56 +03:00
|
|
|
abSourceMetadata <- lookupSourceMetadata _gtiSourceName sources
|
2022-08-30 02:51:34 +03:00
|
|
|
|
|
|
|
AnyBackend.dispatchAnyBackend @RQL.Types.Backend abSourceMetadata $ \Metadata.SourceMetadata {_smKind, _smConfiguration} -> do
|
|
|
|
case _smKind of
|
2023-04-13 04:29:15 +03:00
|
|
|
Backend.DataConnectorKind _dcName -> do
|
2023-04-18 08:36:02 +03:00
|
|
|
sourceInfo <- askSourceInfo @'DataConnector _gtiSourceName
|
|
|
|
let tableName = Witch.from _gtiTableName
|
|
|
|
let table = HM.lookup tableName $ _rsTables $ _siDbObjectsIntrospection sourceInfo
|
|
|
|
pure . EncJSON.encJFromJValue $ convertTableMetadataToTableInfo tableName <$> table
|
|
|
|
backend ->
|
|
|
|
Error.throw500 ("Schema fetching is not supported for '" <> Text.E.toTxt backend <> "'")
|
2022-10-11 03:25:07 +03:00
|
|
|
|
2023-01-12 02:11:56 +03:00
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- Internal helper functions
|
|
|
|
|
|
|
|
lookupSourceMetadata :: (MonadError QErr m) => SourceName -> InsOrdHashMap SourceName (AnyBackend SourceMetadata) -> m (AnyBackend SourceMetadata)
|
|
|
|
lookupSourceMetadata sourceName sources =
|
|
|
|
InsOrdHashMap.lookup sourceName sources
|
|
|
|
`onNothing` Error.throw400 Error.DataConnectorError ("Source '" <> Text.E.toTxt sourceName <> "' not found")
|
2023-04-18 08:36:02 +03:00
|
|
|
|
|
|
|
convertTableMetadataToTableInfo :: TableName 'DataConnector -> DBTableMetadata 'DataConnector -> API.TableInfo
|
|
|
|
convertTableMetadataToTableInfo tableName DBTableMetadata {..} =
|
|
|
|
API.TableInfo
|
|
|
|
{ _tiName = Witch.from tableName,
|
|
|
|
_tiType = DC.Types._etmTableType _ptmiExtraTableMetadata,
|
|
|
|
_tiColumns = convertColumn <$> _ptmiColumns,
|
|
|
|
_tiPrimaryKey = fmap Witch.from . toNonEmpty . _pkColumns <$> _ptmiPrimaryKey,
|
|
|
|
_tiForeignKeys = convertForeignKeys _ptmiForeignKeys,
|
|
|
|
_tiDescription = getPGDescription <$> _ptmiDescription,
|
|
|
|
_tiInsertable = all viIsInsertable _ptmiViewInfo,
|
|
|
|
_tiUpdatable = all viIsUpdatable _ptmiViewInfo,
|
|
|
|
_tiDeletable = all viIsDeletable _ptmiViewInfo
|
|
|
|
}
|
|
|
|
where
|
|
|
|
convertColumn :: RawColumnInfo 'DataConnector -> API.ColumnInfo
|
|
|
|
convertColumn RawColumnInfo {..} =
|
|
|
|
API.ColumnInfo
|
|
|
|
{ _ciName = Witch.from rciName,
|
|
|
|
_ciType = Witch.from rciType,
|
|
|
|
_ciNullable = rciIsNullable,
|
|
|
|
_ciDescription = G.unDescription <$> rciDescription,
|
|
|
|
_ciInsertable = _cmIsInsertable rciMutability,
|
|
|
|
_ciUpdatable = _cmIsUpdatable rciMutability,
|
|
|
|
_ciValueGenerated = DC.Types._ecmValueGenerated =<< extraColumnMetadata
|
|
|
|
}
|
|
|
|
where
|
|
|
|
extraColumnMetadata = HM.lookup rciName . DC.Types._etmExtraColumnMetadata $ _ptmiExtraTableMetadata
|
|
|
|
|
|
|
|
convertForeignKeys :: HashSet (ForeignKeyMetadata 'DataConnector) -> API.ForeignKeys
|
|
|
|
convertForeignKeys foreignKeys =
|
|
|
|
foreignKeys
|
|
|
|
& HashSet.toList
|
|
|
|
& fmap
|
|
|
|
( \(ForeignKeyMetadata ForeignKey {..}) ->
|
|
|
|
let constraintName = Witch.from $ _cName _fkConstraint
|
|
|
|
constraint =
|
|
|
|
API.Constraint
|
|
|
|
{ _cForeignTable = Witch.from _fkForeignTable,
|
|
|
|
_cColumnMapping = HM.fromList $ bimap Witch.from Witch.from <$> NEHashMap.toList _fkColumnMapping
|
|
|
|
}
|
|
|
|
in (constraintName, constraint)
|
|
|
|
)
|
|
|
|
& HM.fromList
|
|
|
|
& API.ForeignKeys
|