mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-13 19:33:55 +03:00
Fix several issues with remote relationships.
## Remaining Work - [x] changelog entry - [x] more tests: `<backend>_delete_remote_relationship` is definitely untested - [x] negative tests: we probably want to assert that there are some APIs we DON'T support - [x] update the console to use the new API, if necessary - [x] ~~adding the corresponding documentation for the API for other backends (only `pg_` was added here)~~ - deferred to https://github.com/hasura/graphql-engine-mono/issues/3170 - [x] ~~deciding which backends should support this API~~ - deferred to https://github.com/hasura/graphql-engine-mono/issues/3170 - [x] ~~deciding what to do about potentially overlapping schematic representations~~ - ~~cf. https://github.com/hasura/graphql-engine-mono/pull/3157#issuecomment-995307624~~ - deferred to https://github.com/hasura/graphql-engine-mono/issues/3171 - [x] ~~add more descriptive versioning information to some of the types that are changing in this PR~~ - cf. https://github.com/hasura/graphql-engine-mono/pull/3157#discussion_r769830920 - deferred to https://github.com/hasura/graphql-engine-mono/issues/3172 ## Description This PR fixes several important issues wrt. the remote relationship API. - it fixes a regression introduced by [#3124](https://github.com/hasura/graphql-engine-mono/pull/3124), which prevented `<backend>_create_remote_relationship` from accepting the old argument format (break of backwards compatibility, broke the console) - it removes the command `create_remote_relationship` added to the v1/metadata API as a work-around as part of [#3124](https://github.com/hasura/graphql-engine-mono/pull/3124) - it reverts the subsequent fix in the console: [#3149](https://github.com/hasura/graphql-engine-mono/pull/3149) Furthermore, this PR also addresses two other issues: - THE DOCUMENTATION OF THE METADATA API WAS WRONG, and documented `create_remote_relationship` instead of `<backend>_create_remote_relationship`: this PR fixes this by adding `pg_` everywhere, but does not attempt to add the corresponding documentation for other backends, partly because: - `<backend>_delete_remote_relationship` WAS BROKEN ON NON-POSTGRES BACKENDS; it always expected an argument parameterized by Postgres. As of main, the `<backend>_(create|update|delete)_remote_relationship` commands are supported on Postgres, Citus, BigQuery, but **NOT MSSQL**. I do not know if this is intentional or not, if it even should be publicized or not, and as a result this PR doesn't change this. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3157 Co-authored-by: jkachmar <8461423+jkachmar@users.noreply.github.com> GitOrigin-RevId: 37e2f41522a9229a11c595574c3f4984317d652a
This commit is contained in:
parent
40678855d0
commit
bacadc30da
@ -7,6 +7,7 @@
|
||||
(Add entries below in the order of server, console, cli, docs, others)
|
||||
|
||||
- server: implement update mutations for MS SQL Server (closes #7834)
|
||||
- server: provides a more comprehensive fix for the JSON ser/de backwards incompatibility that was initially addressed by 45481db (#7906)
|
||||
|
||||
## v2.1.0
|
||||
|
||||
|
@ -140,7 +140,7 @@ export const getMetadataQuery = (
|
||||
prefix = 'pg_';
|
||||
}
|
||||
return {
|
||||
type: type !== 'create_remote_relationship' ? `${prefix}${type}` : type,
|
||||
type: `${prefix}${type}`,
|
||||
args: { ...args, source },
|
||||
};
|
||||
};
|
||||
|
@ -376,7 +376,7 @@ The various types of queries are listed in the following table:
|
||||
- :ref:`create_scheduled_event_args <metadata_create_scheduled_event_syntax>`
|
||||
- 1
|
||||
- Create a new scheduled event
|
||||
|
||||
|
||||
* - :ref:`metadata_delete_scheduled_event`
|
||||
- :ref:`delete_scheduled_event_args <metadata_delete_scheduled_event_syntax>`
|
||||
- 1
|
||||
@ -412,18 +412,18 @@ The various types of queries are listed in the following table:
|
||||
- 1
|
||||
- Drop existing permissions defined for a role for a remote schema
|
||||
|
||||
* - :ref:`metadata_create_remote_relationship`
|
||||
- :ref:`create_remote_relationship_args <metadata_create_remote_relationship_syntax>`
|
||||
* - :ref:`metadata_pg_create_remote_relationship`
|
||||
- :ref:`pg_create_remote_relationship_args <metadata_pg_create_remote_relationship_syntax>`
|
||||
- 1
|
||||
- Create a remote relationship with an existing remote schema
|
||||
|
||||
* - :ref:`metadata_update_remote_relationship`
|
||||
- :ref:`update_remote_relationship_args <metadata_update_remote_relationship_syntax>`
|
||||
* - :ref:`metadata_pg_update_remote_relationship`
|
||||
- :ref:`pg_update_remote_relationship_args <metadata_pg_update_remote_relationship_syntax>`
|
||||
- 1
|
||||
- Update an existing remote relationship
|
||||
|
||||
* - :ref:`metadata_delete_remote_relationship`
|
||||
- :ref:`delete_remote_relationship_args <metadata_delete_remote_relationship_syntax>`
|
||||
* - :ref:`metadata_pg_delete_remote_relationship`
|
||||
- :ref:`pg_delete_remote_relationship_args <metadata_pg_delete_remote_relationship_syntax>`
|
||||
- 1
|
||||
- Delete an existing remote relationship
|
||||
|
||||
|
@ -20,12 +20,12 @@ Remote Relationships allow you to join tables with remote schemas.
|
||||
The metadata API is supported for versions ``v2.0.0`` and above and replaces the older
|
||||
:ref:`schema/metadata API <schema_metadata_apis>`.
|
||||
|
||||
.. _metadata_create_remote_relationship:
|
||||
.. _metadata_pg_create_remote_relationship:
|
||||
|
||||
create_remote_relationship
|
||||
pg_create_remote_relationship
|
||||
--------------------------
|
||||
|
||||
``create_remote_relationship`` is used to create a new remote relationship with an existing remote schema.
|
||||
``pg_create_remote_relationship`` is used to create a new remote relationship with an existing remote schema.
|
||||
|
||||
.. code-block:: http
|
||||
|
||||
@ -34,7 +34,7 @@ create_remote_relationship
|
||||
X-Hasura-Role: admin
|
||||
|
||||
{
|
||||
"type":"create_remote_relationship",
|
||||
"type":"pg_create_remote_relationship",
|
||||
"args":{
|
||||
"name": "sample_remote_relationship",
|
||||
"table": "users",
|
||||
@ -50,7 +50,7 @@ create_remote_relationship
|
||||
}
|
||||
}
|
||||
|
||||
.. _metadata_create_remote_relationship_syntax:
|
||||
.. _metadata_pg_create_remote_relationship_syntax:
|
||||
|
||||
Args syntax
|
||||
^^^^^^^^^^^
|
||||
@ -83,12 +83,12 @@ Args syntax
|
||||
- :ref:`RemoteField`
|
||||
- The schema tree ending at the field in remote schema which needs to be joined with.
|
||||
|
||||
.. _metadata_update_remote_relationship:
|
||||
.. _metadata_pg_update_remote_relationship:
|
||||
|
||||
update_remote_relationship
|
||||
pg_update_remote_relationship
|
||||
--------------------------
|
||||
|
||||
``update_remote_relationship`` is used to update an existing remote relationship.
|
||||
``pg_update_remote_relationship`` is used to update an existing remote relationship.
|
||||
|
||||
.. code-block:: http
|
||||
|
||||
@ -97,7 +97,7 @@ update_remote_relationship
|
||||
X-Hasura-Role: admin
|
||||
|
||||
{
|
||||
"type": "update_remote_relationship",
|
||||
"type": "pg_update_remote_relationship",
|
||||
"args": {
|
||||
"name": "sample_remote_relationship",
|
||||
"table": "users",
|
||||
@ -116,7 +116,7 @@ update_remote_relationship
|
||||
}
|
||||
}
|
||||
|
||||
.. _metadata_update_remote_relationship_syntax:
|
||||
.. _metadata_pg_update_remote_relationship_syntax:
|
||||
|
||||
Args syntax
|
||||
^^^^^^^^^^^
|
||||
@ -149,12 +149,12 @@ Args syntax
|
||||
- :ref:`RemoteField`
|
||||
- The schema tree ending at the field in remote schema which needs to be joined with.
|
||||
|
||||
.. _metadata_delete_remote_relationship:
|
||||
.. _metadata_pg_delete_remote_relationship:
|
||||
|
||||
delete_remote_relationship
|
||||
pg_delete_remote_relationship
|
||||
--------------------------
|
||||
|
||||
``delete_remote_relationship`` is used to delete an existing remote relationship.
|
||||
``pg_delete_remote_relationship`` is used to delete an existing remote relationship.
|
||||
|
||||
.. code-block:: http
|
||||
|
||||
@ -163,7 +163,7 @@ delete_remote_relationship
|
||||
X-Hasura-Role: admin
|
||||
|
||||
{
|
||||
"type" : "delete_remote_relationship",
|
||||
"type" : "pg_delete_remote_relationship",
|
||||
"args" : {
|
||||
"table":{
|
||||
"name":"users",
|
||||
@ -173,7 +173,7 @@ delete_remote_relationship
|
||||
}
|
||||
}
|
||||
|
||||
.. _metadata_delete_remote_relationship_syntax:
|
||||
.. _metadata_pg_delete_remote_relationship_syntax:
|
||||
|
||||
Args syntax
|
||||
^^^^^^^^^^^
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
module Hasura.RQL.DDL.RemoteRelationship
|
||||
( CreateFromSourceRelationship (..),
|
||||
LegacyCreateRemoteRelationship (..),
|
||||
runCreateRemoteRelationship,
|
||||
runDeleteRemoteRelationship,
|
||||
runUpdateRemoteRelationship,
|
||||
@ -13,10 +12,8 @@ module Hasura.RQL.DDL.RemoteRelationship
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Lens (foldOf, to)
|
||||
import Data.Aeson (FromJSON (..), ToJSON (..), (.!=), (.:), (.:?), (.=))
|
||||
import Data.Aeson qualified as J
|
||||
import Data.Aeson.Lens (_Object)
|
||||
import Data.HashMap.Strict qualified as Map
|
||||
import Data.HashMap.Strict.InsOrd qualified as OMap
|
||||
import Data.HashSet qualified as S
|
||||
@ -61,65 +58,42 @@ instance Backend b => FromJSON (CreateFromSourceRelationship b) where
|
||||
_crrSource <- o .:? "source" .!= defaultSource
|
||||
_crrTable <- o .: "table"
|
||||
_crrName <- o .: "name"
|
||||
_crrDefinition <- o .: "definition"
|
||||
-- In the old format, the definition is inlined; in the new format, the
|
||||
-- definition is in the "definition" object.
|
||||
remoteSchema :: Maybe J.Value <- o .:? "remote_schema"
|
||||
definition <- o .:? "definition"
|
||||
_crrDefinition <- case (remoteSchema, definition) of
|
||||
-- old format
|
||||
(Just _, Nothing) -> parseJSON $ J.Object o
|
||||
-- new format
|
||||
(Nothing, Just def) -> parseJSON def
|
||||
-- both or neither
|
||||
_ -> fail "create_remote_relationship expects exactly one of: remote_schema, definition"
|
||||
pure $ CreateFromSourceRelationship {..}
|
||||
|
||||
instance (Backend b) => ToJSON (CreateFromSourceRelationship b) where
|
||||
toJSON (CreateFromSourceRelationship {..}) =
|
||||
J.toJSON . J.object $
|
||||
[ "source" .= _crrSource,
|
||||
"table" .= _crrTable,
|
||||
"name" .= _crrName,
|
||||
"definition" .= _crrDefinition
|
||||
]
|
||||
|
||||
toEncoding (CreateFromSourceRelationship {..}) =
|
||||
J.pairs $
|
||||
"source" .= _crrSource
|
||||
<> "table" .= _crrTable
|
||||
<> "name" .= _crrName
|
||||
<> "definition" .= _crrDefinition
|
||||
|
||||
-- | Opaque type wrapper around 'CreateFromSourceRelationship' which exists
|
||||
-- solely to provide customized 'FromJSON' and 'ToJSON' instances that
|
||||
-- preserves legacy JSON ser/de behavior.
|
||||
--
|
||||
-- See the associated 'FromJSON' and 'ToJSON' instances for details.
|
||||
newtype LegacyCreateRemoteRelationship = LegacyCreateRemoteRelationship
|
||||
{ unLegacyCreateRemoteRelationship ::
|
||||
CreateFromSourceRelationship ('Postgres 'Vanilla)
|
||||
}
|
||||
deriving newtype (Eq, Show)
|
||||
|
||||
instance FromJSON LegacyCreateRemoteRelationship where
|
||||
parseJSON = J.withObject "LegacyCreateRemoteRelationship" $ \o -> do
|
||||
_crrSource <- o .:? "source" .!= defaultSource
|
||||
_crrTable <- o .: "table"
|
||||
_crrName <- o .: "name"
|
||||
_crrDefinition <- parseJSON (J.Object o)
|
||||
pure . LegacyCreateRemoteRelationship $ CreateFromSourceRelationship {..}
|
||||
|
||||
instance ToJSON LegacyCreateRemoteRelationship where
|
||||
toJSON (LegacyCreateRemoteRelationship (CreateFromSourceRelationship {..})) =
|
||||
-- The "legacy" serialization logic included the fields that are now a part
|
||||
-- of the nested '_crrDefinition'.
|
||||
--
|
||||
-- To work around this, while sharing as much serialization logic with
|
||||
-- 'RemoteRelationshipDefinition' as possible, '_crrDefinition' is
|
||||
-- serialized to a 'J.Value' and then immediately converted back to a list
|
||||
-- of key/value pairs.
|
||||
--
|
||||
-- 'definitionKeyValues' will be an empty list if this conversion fails
|
||||
-- (which it should _never_ do), in which case those fields will be omitted
|
||||
-- from the serialized JSON.
|
||||
let definitionKeyValues =
|
||||
foldOf (_Object . to Map.toList) (J.toJSON _crrDefinition)
|
||||
in J.toJSON . J.object $
|
||||
[ "source" .= _crrSource,
|
||||
"table" .= _crrTable,
|
||||
"name" .= _crrName
|
||||
]
|
||||
<> definitionKeyValues
|
||||
-- We need to introspect the definition, to know whether we need to inline
|
||||
-- it, or if it needs to be in a distinct "definition" object.
|
||||
J.object $ case _crrDefinition of
|
||||
-- old format
|
||||
RelationshipToSchema RRFOldDBToRemoteSchema _ ->
|
||||
case J.toJSON _crrDefinition of
|
||||
-- The result of this serialization will be an empty list if this
|
||||
-- conversion fails (which it should _never_ do), in which case those
|
||||
-- fields will be omitted from the serialized JSON. This could only
|
||||
-- happen if the ToJSON instance of RemoteRelationshipDefinition were
|
||||
-- changed to return something that isn't an object.
|
||||
J.Object obj -> commonFields <> Map.toList obj
|
||||
_ -> []
|
||||
-- new format
|
||||
_ -> ("definition" .= _crrDefinition) : commonFields
|
||||
where
|
||||
commonFields =
|
||||
[ "source" .= _crrSource,
|
||||
"table" .= _crrTable,
|
||||
"name" .= _crrName
|
||||
]
|
||||
|
||||
runCreateRemoteRelationship ::
|
||||
forall b m.
|
||||
|
@ -115,7 +115,7 @@ relationshipCommands =
|
||||
remoteRelationshipCommands =
|
||||
[ commandParser "create_remote_relationship" $ RMCreateRemoteRelationship . mkAnyBackend @b,
|
||||
commandParser "update_remote_relationship" $ RMUpdateRemoteRelationship . mkAnyBackend @b,
|
||||
commandParser "delete_remote_relationship" $ RMDeleteRemoteRelationship
|
||||
commandParser "delete_remote_relationship" $ RMDeleteRemoteRelationship . mkAnyBackend @b
|
||||
]
|
||||
eventTriggerCommands =
|
||||
[ commandParser "invoke_event_trigger" $ RMInvokeEventTrigger . mkAnyBackend @b,
|
||||
|
@ -82,10 +82,9 @@ data RQLMetadataV1
|
||||
| RMSetRelationshipComment !(AnyBackend SetRelComment)
|
||||
| RMRenameRelationship !(AnyBackend RenameRel)
|
||||
| -- Tables remote relationships
|
||||
-- (backend)_create_remote_relationship, create_remote_relationship
|
||||
RMCreateRemoteRelationship !(AnyBackend CreateFromSourceRelationship)
|
||||
| RMUpdateRemoteRelationship !(AnyBackend CreateFromSourceRelationship)
|
||||
| RMDeleteRemoteRelationship !(DeleteFromSourceRelationship ('Postgres 'Vanilla))
|
||||
| RMDeleteRemoteRelationship !(AnyBackend DeleteFromSourceRelationship)
|
||||
| -- Functions
|
||||
RMTrackFunction !(AnyBackend TrackFunctionV2)
|
||||
| RMUntrackFunction !(AnyBackend UnTrackFunction)
|
||||
@ -222,7 +221,6 @@ instance FromJSON RQLMetadataV1 where
|
||||
"test_webhook_transform" -> RMTestWebhookTransform <$> args
|
||||
"set_query_tags" -> RMSetQueryTagsConfig <$> args
|
||||
"bulk" -> RMBulk <$> args
|
||||
"create_remote_relationship" -> RMCreateRemoteRelationship . mkAnyBackend . unLegacyCreateRemoteRelationship <$> args
|
||||
-- backend specific
|
||||
_ -> do
|
||||
let (prefix, T.drop 1 -> cmd) = T.breakOn "_" queryType
|
||||
@ -419,7 +417,7 @@ runMetadataQueryV1M env currentResourceVersion = \case
|
||||
RMRenameRelationship q -> dispatchMetadata runRenameRel q
|
||||
RMCreateRemoteRelationship q -> dispatchMetadata runCreateRemoteRelationship q
|
||||
RMUpdateRemoteRelationship q -> dispatchMetadata runUpdateRemoteRelationship q
|
||||
RMDeleteRemoteRelationship q -> runDeleteRemoteRelationship q
|
||||
RMDeleteRemoteRelationship q -> dispatchMetadata runDeleteRemoteRelationship q
|
||||
RMTrackFunction q -> dispatchMetadata runTrackFunctionV2 q
|
||||
RMUntrackFunction q -> dispatchMetadata runUntrackFunc q
|
||||
RMCreateFunctionPermission q -> dispatchMetadata runCreateFunctionPermission q
|
||||
|
@ -48,7 +48,7 @@ data RQLMetadataV1
|
||||
| -- Tables remote relationships
|
||||
RMCreateRemoteRelationship !(AnyBackend CreateFromSourceRelationship)
|
||||
| RMUpdateRemoteRelationship !(AnyBackend CreateFromSourceRelationship)
|
||||
| RMDeleteRemoteRelationship !(DeleteFromSourceRelationship ('Postgres 'Vanilla))
|
||||
| RMDeleteRemoteRelationship !(AnyBackend DeleteFromSourceRelationship)
|
||||
| -- Functions
|
||||
RMTrackFunction !(AnyBackend TrackFunctionV2)
|
||||
| RMUntrackFunction !(AnyBackend UnTrackFunction)
|
||||
|
@ -65,8 +65,8 @@ data RQLQueryV1
|
||||
| -- computed fields related
|
||||
RQAddComputedField !(AddComputedField ('Postgres 'Vanilla))
|
||||
| RQDropComputedField !(DropComputedField ('Postgres 'Vanilla))
|
||||
| RQCreateRemoteRelationship !LegacyCreateRemoteRelationship
|
||||
| RQUpdateRemoteRelationship !LegacyCreateRemoteRelationship
|
||||
| RQCreateRemoteRelationship !(CreateFromSourceRelationship ('Postgres 'Vanilla))
|
||||
| RQUpdateRemoteRelationship !(CreateFromSourceRelationship ('Postgres 'Vanilla))
|
||||
| RQDeleteRemoteRelationship !(DeleteFromSourceRelationship ('Postgres 'Vanilla))
|
||||
| RQCreateInsertPermission !(CreatePerm InsPerm ('Postgres 'Vanilla))
|
||||
| RQCreateSelectPermission !(CreatePerm SelPerm ('Postgres 'Vanilla))
|
||||
@ -418,8 +418,8 @@ runQueryM env rq = withPathK "args" $ case rq of
|
||||
RQRemoveRemoteSchema q -> runRemoveRemoteSchema q
|
||||
RQReloadRemoteSchema q -> runReloadRemoteSchema q
|
||||
RQIntrospectRemoteSchema q -> runIntrospectRemoteSchema q
|
||||
RQCreateRemoteRelationship q -> runCreateRemoteRelationship $ unLegacyCreateRemoteRelationship q
|
||||
RQUpdateRemoteRelationship q -> runUpdateRemoteRelationship $ unLegacyCreateRemoteRelationship q
|
||||
RQCreateRemoteRelationship q -> runCreateRemoteRelationship q
|
||||
RQUpdateRemoteRelationship q -> runUpdateRemoteRelationship q
|
||||
RQDeleteRemoteRelationship q -> runDeleteRemoteRelationship q
|
||||
RQCreateEventTrigger q -> runCreateEventTriggerQuery q
|
||||
RQDeleteEventTrigger q -> runDeleteEventTriggerQuery q
|
||||
|
@ -10,17 +10,17 @@ where
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
import Control.Lens ((%~), (^?!))
|
||||
import Control.Lens ((%~), (.~), (^?!))
|
||||
import Data.Aeson (FromJSON, ToJSON)
|
||||
import Data.Aeson qualified as Aeson
|
||||
import Data.Aeson.Lens (key, _Object)
|
||||
import Data.HashMap.Strict qualified as HM
|
||||
import Data.Text qualified as T
|
||||
import Data.Yaml.TH (yamlQQ)
|
||||
import GHC.Stack (HasCallStack)
|
||||
import Hasura.Prelude hiding ((%~))
|
||||
import Hasura.RQL.DDL.RemoteRelationship
|
||||
( CreateFromSourceRelationship,
|
||||
LegacyCreateRemoteRelationship,
|
||||
)
|
||||
import Hasura.RQL.Types.Metadata (Metadata)
|
||||
import Hasura.SQL.Backend (BackendType (BigQuery, MSSQL, Postgres), PostgresKind (Vanilla))
|
||||
@ -42,9 +42,9 @@ spec = describe "Remote Relationship Metadata" do
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
spec_roundtrip :: Spec
|
||||
spec_roundtrip = describe "Roundtrip" do
|
||||
spec_roundtrip = describe "JSON Roundtrip" do
|
||||
describe "Metadata" do
|
||||
it "passes JSON roundtrip tests for an example remote relationship fragment" $
|
||||
it "example remote relationship fragment" $
|
||||
hedgehog do
|
||||
metadata :: Metadata <-
|
||||
evalAesonResult $
|
||||
@ -52,35 +52,34 @@ spec_roundtrip = describe "Roundtrip" do
|
||||
trippingJSONValue metadata
|
||||
|
||||
describe "CreateFromSourceRelationship" do
|
||||
it "passes JSON roundtrip tests for a 'pg_create_remote_relationship' query fragment" $
|
||||
it "'pg_create_remote_relationship' query" $
|
||||
hedgehog $ do
|
||||
let fragment = pg_create_remote_relationship_fragment ^?! key "args"
|
||||
let argument = mk_pg_remote_relationship_argument "create" ^?! key "args"
|
||||
cfsr :: (CreateFromSourceRelationship ('Postgres 'Vanilla)) <-
|
||||
evalAesonResult $ Aeson.fromJSON fragment
|
||||
evalAesonResult $ Aeson.fromJSON argument
|
||||
trippingJSON cfsr
|
||||
|
||||
it "passes JSON roundtrip tests for an 'mssql_create_remote_relationship' query fragment" $
|
||||
it "'pg_create_remote_relationship' query with the 'old' schema" $
|
||||
hedgehog $ do
|
||||
let fragment = mssql_create_remote_relationship_fragment ^?! key "args"
|
||||
let argument = mk_pg_remote_relationship_old_argument "create" ^?! key "args"
|
||||
cfsr :: (CreateFromSourceRelationship ('Postgres 'Vanilla)) <-
|
||||
evalAesonResult $ Aeson.fromJSON argument
|
||||
trippingJSON cfsr
|
||||
|
||||
it "'mssql_create_remote_relationship' query" $
|
||||
hedgehog $ do
|
||||
let argument = mk_mssql_remote_relationship_argument "create" ^?! key "args"
|
||||
cfsr :: (CreateFromSourceRelationship 'MSSQL) <-
|
||||
evalAesonResult $ Aeson.fromJSON fragment
|
||||
evalAesonResult $ Aeson.fromJSON argument
|
||||
trippingJSON cfsr
|
||||
|
||||
it "passes JSON roundtrip tests for a 'bigquery_create_remote_relationship' query fragment" $
|
||||
it "'bigquery_create_remote_relationship' query" $
|
||||
hedgehog $ do
|
||||
let fragment = bigquery_create_remote_relationship_fragment ^?! key "args"
|
||||
let argument = mk_bigquery_remote_relationship_argument "create" ^?! key "args"
|
||||
cfsr :: (CreateFromSourceRelationship 'BigQuery) <-
|
||||
evalAesonResult $ Aeson.fromJSON fragment
|
||||
evalAesonResult $ Aeson.fromJSON argument
|
||||
trippingJSON cfsr
|
||||
|
||||
describe "LegacyCreateRemoteRelationship" do
|
||||
it "passes JSON roundtrip tests for a 'create_remote_relationship' query fragment" $
|
||||
hedgehog do
|
||||
let fragment = create_remote_relationship_fragment ^?! key "args"
|
||||
lcrr :: LegacyCreateRemoteRelationship <-
|
||||
evalAesonResult $ Aeson.fromJSON fragment
|
||||
trippingJSON lcrr
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
spec_Metadata_examples :: Spec
|
||||
@ -94,8 +93,8 @@ spec_Metadata_examples = describe "Metadata" $ do
|
||||
|
||||
spec_RQLQuery_examples :: Spec
|
||||
spec_RQLQuery_examples = describe "V1 RQLQuery" do
|
||||
it "parses a 'create_remote_relationship' query fragment as a V1 'RQLQuery' type" do
|
||||
case Aeson.fromJSON @V1.RQLQuery create_remote_relationship_fragment of
|
||||
it "parses a 'create_remote_relationship' query with the 'old' schema" do
|
||||
case Aeson.fromJSON @V1.RQLQuery create_remote_relationship_argument of
|
||||
Aeson.Success _ -> pure ()
|
||||
Aeson.Error err -> expectationFailure err
|
||||
|
||||
@ -103,20 +102,39 @@ spec_RQLQuery_examples = describe "V1 RQLQuery" do
|
||||
|
||||
spec_RQLMetadataV1_examples :: Spec
|
||||
spec_RQLMetadataV1_examples = describe "RQLMetadataV1" do
|
||||
it "parses a 'create_remote_relationship' query fragment" do
|
||||
case Aeson.fromJSON @RQLMetadataV1 create_remote_relationship_fragment of
|
||||
Aeson.Success _ -> pure ()
|
||||
Aeson.Error err -> expectationFailure err
|
||||
describe "Success" do
|
||||
for_ ["create", "update", "delete"] \action ->
|
||||
it ("parses a 'pg_" <> T.unpack action <> "_remote_relationship query") do
|
||||
case Aeson.fromJSON @RQLMetadataV1 (mk_pg_remote_relationship_argument action) of
|
||||
Aeson.Success _ -> pure ()
|
||||
Aeson.Error err -> expectationFailure err
|
||||
|
||||
it "parses a 'pg_create_remote_relationship' query fragment" do
|
||||
case Aeson.fromJSON @RQLMetadataV1 pg_create_remote_relationship_fragment of
|
||||
Aeson.Success _ -> pure ()
|
||||
Aeson.Error err -> expectationFailure err
|
||||
for_ ["create", "update", "delete"] \action ->
|
||||
it ("parses a 'pg_" <> T.unpack action <> "_remote_relationship query using the 'old' schema") do
|
||||
case Aeson.fromJSON @RQLMetadataV1 (mk_pg_remote_relationship_old_argument action) of
|
||||
Aeson.Success _ -> pure ()
|
||||
Aeson.Error err -> expectationFailure err
|
||||
|
||||
it "parses a 'bigquery_create_remote_relationship' query fragment" do
|
||||
case Aeson.fromJSON @RQLMetadataV1 bigquery_create_remote_relationship_fragment of
|
||||
Aeson.Success _ -> pure ()
|
||||
Aeson.Error err -> expectationFailure err
|
||||
for_ ["create", "update", "delete"] \action ->
|
||||
it ("parses a 'citus_" <> T.unpack action <> "_remote_relationship query") do
|
||||
case Aeson.fromJSON @RQLMetadataV1 (mk_citus_remote_relationship_argument action) of
|
||||
Aeson.Success _ -> pure ()
|
||||
Aeson.Error err -> expectationFailure err
|
||||
|
||||
for_ ["create", "update", "delete"] \action ->
|
||||
it ("parses a 'bigquery_" <> T.unpack action <> "_remote_relationship query") do
|
||||
case Aeson.fromJSON @RQLMetadataV1 (mk_bigquery_remote_relationship_argument action) of
|
||||
Aeson.Success _ -> pure ()
|
||||
Aeson.Error err -> expectationFailure err
|
||||
|
||||
describe "Failure" do
|
||||
for_ ["create", "update", "delete"] \action ->
|
||||
it ("fails to parse an 'mssql_" <> T.unpack action <> "_remote_relationship query") do
|
||||
case Aeson.fromJSON @RQLMetadataV1 (mk_mssql_remote_relationship_argument action) of
|
||||
Aeson.Error _ -> pure ()
|
||||
Aeson.Success _ ->
|
||||
let errMsg = "expected 'mssql_" <> T.unpack action <> "' query to fail to parse"
|
||||
in expectationFailure errMsg
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Example YAML fragments for the metadata and query tests above.
|
||||
@ -144,8 +162,8 @@ sources:
|
||||
remote_schema: some_remote_schema_name
|
||||
|]
|
||||
|
||||
create_remote_relationship_fragment :: Aeson.Value
|
||||
create_remote_relationship_fragment =
|
||||
create_remote_relationship_argument :: Aeson.Value
|
||||
create_remote_relationship_argument =
|
||||
[yamlQQ|
|
||||
type: create_remote_relationship
|
||||
args:
|
||||
@ -161,12 +179,13 @@ args:
|
||||
id: "$id"
|
||||
|]
|
||||
|
||||
-- | Backend-agnostic query fragment which omits the @type@ field.
|
||||
-- | Backend-agnostic @v1/metadata@ argument fragment which omits the @type@
|
||||
-- field.
|
||||
--
|
||||
-- This should be used to construct backend-specific fragments by adding the
|
||||
-- correct type and/or modifying any of the fields specified here as needed.
|
||||
--
|
||||
-- See 'pg_create_remote_relationship_fragment' for details.
|
||||
-- See 'mk_backend_remote_relationship_argument for example usage.
|
||||
backend_create_remote_relationship_fragment :: Aeson.Value
|
||||
backend_create_remote_relationship_fragment =
|
||||
[yamlQQ|
|
||||
@ -185,41 +204,76 @@ args:
|
||||
id: "$id"
|
||||
|]
|
||||
|
||||
pg_create_remote_relationship_fragment :: Aeson.Value
|
||||
pg_create_remote_relationship_fragment =
|
||||
-- | Constructor for @v1/metadata@ @<backend>_(create|update|delete)_remote_relationship@
|
||||
-- arguments using the new, unified schema.
|
||||
--
|
||||
-- See 'mk_pg_backend_remote_relationship_argument for example usage.
|
||||
mk_backend_remote_relationship_argument :: Text -> Text -> Aeson.Value
|
||||
mk_backend_remote_relationship_argument backend action =
|
||||
backend_create_remote_relationship_fragment
|
||||
& _Object %~ HM.insert ("type" :: Text) "pg_create_remote_relationship"
|
||||
& _Object
|
||||
%~ HM.insert
|
||||
("type" :: Text)
|
||||
(Aeson.String $ backend <> "_" <> action <> "_remote_relationship")
|
||||
|
||||
mssql_create_remote_relationship_fragment :: Aeson.Value
|
||||
mssql_create_remote_relationship_fragment =
|
||||
backend_create_remote_relationship_fragment
|
||||
& _Object %~ HM.insert ("type" :: Text) "mssql_create_remote_relationship"
|
||||
-- | Constructor for @v1/metadata@ @mssql_(create|update|delete)_remote_relationship@
|
||||
-- arguments using the new, unified schema.
|
||||
mk_mssql_remote_relationship_argument :: Text -> Aeson.Value
|
||||
mk_mssql_remote_relationship_argument action =
|
||||
mk_backend_remote_relationship_argument "mssql" action
|
||||
|
||||
-- | Constructor for @v1/metadata@ @citus_(create|update|delete)_remote_relationship@
|
||||
-- arguments using the new, unified schema.
|
||||
mk_citus_remote_relationship_argument :: Text -> Aeson.Value
|
||||
mk_citus_remote_relationship_argument action =
|
||||
mk_backend_remote_relationship_argument "citus" action
|
||||
|
||||
-- | Constructor for @v1/metadata@ @pg_(create|update|delete)_remote_relationship@
|
||||
-- arguments using the new, unified schema.
|
||||
mk_pg_remote_relationship_argument :: Text -> Aeson.Value
|
||||
mk_pg_remote_relationship_argument action =
|
||||
mk_backend_remote_relationship_argument "pg" action
|
||||
|
||||
-- | Constructor for @v1/metadata@ @bigquery_(create|update|delete)_remote_relationship@
|
||||
-- arguments using the new, unified schema.
|
||||
--
|
||||
-- NOTE: The 'BigQuery' backend expects its @table@ argument to be of type
|
||||
-- 'Aeson.Object' (all of the other backends support 'Aeson.String').
|
||||
--
|
||||
-- Rather than trying to wrangle even more of this with @lens-aeson@, it's
|
||||
-- easier to just duplicate the structure in-place for the time being.
|
||||
bigquery_create_remote_relationship_fragment :: Aeson.Value
|
||||
bigquery_create_remote_relationship_fragment =
|
||||
[yamlQQ|
|
||||
type: bigquery_create_remote_relationship
|
||||
mk_bigquery_remote_relationship_argument :: Text -> Aeson.Value
|
||||
mk_bigquery_remote_relationship_argument action =
|
||||
mk_backend_remote_relationship_argument "bigquery" action
|
||||
& key "args" . key "table"
|
||||
.~ ( Aeson.Object $
|
||||
HM.fromList
|
||||
[ ("name" :: Text, "profiles"),
|
||||
("dataset" :: Text, "test")
|
||||
]
|
||||
)
|
||||
|
||||
-- | Constructor for @v1/metadata@ @pg_(create|update|delete)_remote_relationship@
|
||||
-- arguments using the old, non-unified schema.
|
||||
mk_pg_remote_relationship_old_argument :: Text -> Aeson.Value
|
||||
mk_pg_remote_relationship_old_argument action =
|
||||
fragment
|
||||
& _Object
|
||||
%~ HM.insert
|
||||
("type" :: Text)
|
||||
(Aeson.String $ "pg_" <> action <> "_remote_relationship")
|
||||
where
|
||||
fragment =
|
||||
[yamlQQ|
|
||||
args:
|
||||
name: message
|
||||
table:
|
||||
name: profiles
|
||||
dataset: test
|
||||
definition:
|
||||
to_remote_schema:
|
||||
lhs_fields:
|
||||
- id
|
||||
- name
|
||||
remote_schema: my-remote-schema
|
||||
remote_field:
|
||||
message:
|
||||
arguments:
|
||||
id: "$id"
|
||||
|]
|
||||
table: profiles
|
||||
hasura_fields:
|
||||
- id
|
||||
- name
|
||||
remote_schema: my-remote-schema
|
||||
remote_field:
|
||||
message:
|
||||
arguments:
|
||||
id: "$id"
|
||||
|]
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Utility functions.
|
||||
|
Loading…
Reference in New Issue
Block a user