mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-10-26 10:20:54 +03:00
chore(server): add experiment feature flag to disable Postgres arrays in introspection
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9804 GitOrigin-RevId: eeb378153df070ffedcada6a91d3117a0a83dde9
This commit is contained in:
parent
e4ebbbccd7
commit
213f64c061
@ -512,14 +512,14 @@ Postgres.
|
||||
|
||||
List of experimental features to be enabled.
|
||||
|
||||
| | |
|
||||
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Flag** | `--experimental-features <FEATURES>` |
|
||||
| **Env var** | `HASURA_GRAPHQL_EXPERIMENTAL_FEATURES` |
|
||||
| **Accepted values** | String (Comma-separated list) |
|
||||
| **Options** | `inherited_roles`, `optimise_permission_filters`, `naming_convention`, `streaming_subscriptions`, `apollo_federation`, `hide_update_many_fields`, `bigquery_string_numeric_input`, `hide_aggregation_predicates`, `hide_stream_fields` |
|
||||
| **Default** | `null` |
|
||||
| **Supported in** | CE, Enterprise Edition, Cloud |
|
||||
| | |
|
||||
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Flag** | `--experimental-features <FEATURES>` |
|
||||
| **Env var** | `HASURA_GRAPHQL_EXPERIMENTAL_FEATURES` |
|
||||
| **Accepted values** | String (Comma-separated list) |
|
||||
| **Options** | `inherited_roles`, `optimise_permission_filters`, `naming_convention`, `streaming_subscriptions`, `apollo_federation`, `hide_update_many_fields`, `bigquery_string_numeric_input`, `hide_aggregation_predicates`, `hide_stream_fields`, `disable_postgres_arrays` |
|
||||
| **Default** | `null` |
|
||||
| **Supported in** | CE, Enterprise Edition, Cloud |
|
||||
|
||||
### Graceful Shutdown Timeout
|
||||
|
||||
|
@ -15,7 +15,7 @@ import Harness.Quoter.Yaml (interpolateYaml, yaml)
|
||||
import Harness.Schema qualified as Schema
|
||||
import Harness.Test.Fixture qualified as Fixture
|
||||
import Harness.TestEnvironment (GlobalTestEnvironment, TestEnvironment)
|
||||
import Harness.Yaml (shouldReturnYaml)
|
||||
import Harness.Yaml (shouldBeYaml, shouldReturnYaml)
|
||||
import Hasura.Prelude
|
||||
import Test.Hspec (SpecWith, describe, it)
|
||||
|
||||
@ -23,102 +23,89 @@ spec :: SpecWith GlobalTestEnvironment
|
||||
spec = do
|
||||
Fixture.run
|
||||
( NE.fromList
|
||||
[ (Fixture.fixture $ Fixture.Backend Postgres.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnvironment, _) ->
|
||||
[ Fixture.SetupAction
|
||||
{ Fixture.setupAction =
|
||||
Postgres.run_ testEnvironment setup,
|
||||
Fixture.teardownAction = \_ ->
|
||||
pure ()
|
||||
},
|
||||
Postgres.setupTablesAction schema testEnvironment
|
||||
]
|
||||
},
|
||||
(Fixture.fixture $ Fixture.Backend Citus.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnvironment, _) ->
|
||||
[ Fixture.SetupAction
|
||||
{ Fixture.setupAction =
|
||||
Citus.run_ testEnvironment setup,
|
||||
Fixture.teardownAction = \_ ->
|
||||
pure ()
|
||||
},
|
||||
Citus.setupTablesAction schema testEnvironment
|
||||
]
|
||||
},
|
||||
(Fixture.fixture $ Fixture.Backend Cockroach.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnvironment, _) ->
|
||||
[ Fixture.SetupAction
|
||||
{ Fixture.setupAction =
|
||||
Cockroach.run_ testEnvironment setup,
|
||||
Fixture.teardownAction = \_ ->
|
||||
pure ()
|
||||
},
|
||||
Cockroach.setupTablesAction schema testEnvironment
|
||||
]
|
||||
}
|
||||
[ postgresFixture,
|
||||
citusFixture,
|
||||
cockroachFixture
|
||||
]
|
||||
)
|
||||
singleArrayTests
|
||||
|
||||
-- run these tests with Arrays switched off
|
||||
Fixture.hgeWithEnv [("HASURA_GRAPHQL_EXPERIMENTAL_FEATURES", "disable_postgres_arrays")]
|
||||
$ Fixture.run
|
||||
( NE.fromList
|
||||
[postgresFixture, citusFixture]
|
||||
)
|
||||
$ do
|
||||
singleArrayTests -- we check these still work with the flag on
|
||||
introspectionWithDisabledFeatureTests
|
||||
|
||||
-- CockroachDB introspection looks different, let's not do it
|
||||
Fixture.run
|
||||
( NE.fromList
|
||||
[postgresFixture, citusFixture]
|
||||
)
|
||||
introspectionTests
|
||||
|
||||
-- CockroachDB does not support nested arrays
|
||||
-- https://www.cockroachlabs.com/docs/stable/array.html
|
||||
Fixture.run
|
||||
( NE.fromList
|
||||
[ (Fixture.fixture $ Fixture.Backend Postgres.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnvironment, _) ->
|
||||
[ Fixture.SetupAction
|
||||
{ Fixture.setupAction =
|
||||
Postgres.run_ testEnvironment setup,
|
||||
Fixture.teardownAction = \_ ->
|
||||
pure ()
|
||||
},
|
||||
Postgres.setupTablesAction schema testEnvironment
|
||||
]
|
||||
},
|
||||
(Fixture.fixture $ Fixture.Backend Citus.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnvironment, _) ->
|
||||
[ Fixture.SetupAction
|
||||
{ Fixture.setupAction =
|
||||
Citus.run_ testEnvironment setup,
|
||||
Fixture.teardownAction = \_ ->
|
||||
pure ()
|
||||
},
|
||||
Citus.setupTablesAction schema testEnvironment
|
||||
]
|
||||
}
|
||||
]
|
||||
[postgresFixture, citusFixture]
|
||||
)
|
||||
nestedArrayTests
|
||||
|
||||
-- CockroachDB does not support json arrays
|
||||
Fixture.run
|
||||
( NE.fromList
|
||||
[ (Fixture.fixture $ Fixture.Backend Postgres.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnvironment, _) ->
|
||||
[ Fixture.SetupAction
|
||||
{ Fixture.setupAction =
|
||||
Postgres.run_ testEnvironment setup,
|
||||
Fixture.teardownAction = \_ -> pure ()
|
||||
},
|
||||
Postgres.setupTablesAction schema testEnvironment
|
||||
]
|
||||
},
|
||||
(Fixture.fixture $ Fixture.Backend Citus.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnvironment, _) ->
|
||||
[ Fixture.SetupAction
|
||||
{ Fixture.setupAction =
|
||||
Citus.run_ testEnvironment setup,
|
||||
Fixture.teardownAction = \_ -> pure ()
|
||||
},
|
||||
Citus.setupTablesAction schema testEnvironment
|
||||
]
|
||||
}
|
||||
]
|
||||
[postgresFixture, citusFixture]
|
||||
)
|
||||
jsonArrayTests
|
||||
|
||||
postgresFixture :: Fixture.Fixture ()
|
||||
postgresFixture =
|
||||
(Fixture.fixture $ Fixture.Backend Postgres.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnvironment, _) ->
|
||||
[ Fixture.SetupAction
|
||||
{ Fixture.setupAction =
|
||||
Postgres.run_ testEnvironment setup,
|
||||
Fixture.teardownAction = \_ ->
|
||||
pure ()
|
||||
},
|
||||
Postgres.setupTablesAction schema testEnvironment
|
||||
]
|
||||
}
|
||||
|
||||
citusFixture :: Fixture.Fixture ()
|
||||
citusFixture =
|
||||
(Fixture.fixture $ Fixture.Backend Citus.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnvironment, _) ->
|
||||
[ Fixture.SetupAction
|
||||
{ Fixture.setupAction =
|
||||
Citus.run_ testEnvironment setup,
|
||||
Fixture.teardownAction = \_ ->
|
||||
pure ()
|
||||
},
|
||||
Citus.setupTablesAction schema testEnvironment
|
||||
]
|
||||
}
|
||||
|
||||
cockroachFixture :: Fixture.Fixture ()
|
||||
cockroachFixture =
|
||||
(Fixture.fixture $ Fixture.Backend Cockroach.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnvironment, _) ->
|
||||
[ Fixture.SetupAction
|
||||
{ Fixture.setupAction =
|
||||
Cockroach.run_ testEnvironment setup,
|
||||
Fixture.teardownAction = \_ ->
|
||||
pure ()
|
||||
},
|
||||
Cockroach.setupTablesAction schema testEnvironment
|
||||
]
|
||||
}
|
||||
|
||||
setup :: Text
|
||||
setup = "create type \"made_up_type\" as enum ('a', 'b', 'c');"
|
||||
setup = "create type \"_made_up_type\" as enum ('a', 'b', 'c');"
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Schema
|
||||
@ -154,9 +141,9 @@ enumArrayType :: Schema.ScalarType
|
||||
enumArrayType =
|
||||
Schema.TCustomType
|
||||
$ Schema.defaultBackendScalarType
|
||||
{ Schema.bstPostgres = Just "made_up_type[]",
|
||||
Schema.bstCitus = Just "made_up_type[]",
|
||||
Schema.bstCockroach = Just "made_up_type[]"
|
||||
{ Schema.bstPostgres = Just "_made_up_type[]",
|
||||
Schema.bstCitus = Just "_made_up_type[]",
|
||||
Schema.bstCockroach = Just "_made_up_type[]"
|
||||
}
|
||||
|
||||
schema :: [Schema.Table]
|
||||
@ -530,3 +517,279 @@ nestedArrayTests = do
|
||||
|]
|
||||
|
||||
shouldReturnYaml testEnvironment actual expected
|
||||
|
||||
introspectionTests :: SpecWith TestEnvironment
|
||||
introspectionTests = do
|
||||
describe "Array types become GraphQL arrays via introspection" $ do
|
||||
it "Produces GraphQL arrays" $ \testEnvironment -> do
|
||||
let queryTypesIntrospection :: Value
|
||||
queryTypesIntrospection =
|
||||
[graphql|
|
||||
{
|
||||
__type(name:"hasura_author") {
|
||||
kind
|
||||
name
|
||||
fields {
|
||||
name
|
||||
type {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|]
|
||||
|
||||
expected =
|
||||
[yaml|
|
||||
{
|
||||
"data": {
|
||||
"__type": {
|
||||
"name": "hasura_author",
|
||||
"kind": "OBJECT",
|
||||
"fields": [
|
||||
{
|
||||
"name": "emails",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "grid",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "jsons",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "json",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "made_up",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "_made_up_type",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|]
|
||||
|
||||
actual <- postGraphql testEnvironment queryTypesIntrospection
|
||||
|
||||
actual `shouldBeYaml` expected
|
||||
|
||||
introspectionWithDisabledFeatureTests :: SpecWith TestEnvironment
|
||||
introspectionWithDisabledFeatureTests = do
|
||||
describe "Array types remain unknown types via introspection" $ do
|
||||
it "Produces unknown types" $ \testEnvironment -> do
|
||||
let queryTypesIntrospection :: Value
|
||||
queryTypesIntrospection =
|
||||
[graphql|
|
||||
{
|
||||
__type(name:"hasura_author") {
|
||||
kind
|
||||
name
|
||||
fields {
|
||||
name
|
||||
type {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|]
|
||||
|
||||
expected =
|
||||
[yaml|
|
||||
{
|
||||
"data": {
|
||||
"__type": {
|
||||
"name": "hasura_author",
|
||||
"kind": "OBJECT",
|
||||
"fields": [
|
||||
{
|
||||
"name": "emails",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "_text",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "grid",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "_integer",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "jsons",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "_json",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "made_up",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "__made_up_type",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|]
|
||||
|
||||
actual <- postGraphql testEnvironment queryTypesIntrospection
|
||||
|
||||
actual `shouldBeYaml` expected
|
||||
|
@ -437,13 +437,26 @@ columnParser columnType nullability = case columnType of
|
||||
-- TODO: introduce new dedicated scalars for Postgres column types.
|
||||
(name, schemaType) <- case scalarType of
|
||||
PGArray innerScalar -> do
|
||||
name <- mkScalarTypeName innerScalar
|
||||
pure
|
||||
( name,
|
||||
P.TList
|
||||
P.NonNullable
|
||||
(P.TNamed P.NonNullable $ P.Definition name Nothing Nothing [] P.TIScalar)
|
||||
)
|
||||
-- postgres arrays break introspection for some clients so allow them
|
||||
-- to disable it
|
||||
disableArrays <- retrieve Options.soPostgresArrays
|
||||
case disableArrays of
|
||||
Options.UsePostgresArrays -> do
|
||||
name <- mkScalarTypeName innerScalar
|
||||
pure
|
||||
( name,
|
||||
P.TList
|
||||
P.NonNullable
|
||||
(P.TNamed P.NonNullable $ P.Definition name Nothing Nothing [] P.TIScalar)
|
||||
)
|
||||
Options.DontUsePostgresArrays -> do
|
||||
-- previously, we represented text[] as `_text` - recover this
|
||||
-- naming:
|
||||
arrayName <- mkScalarTypeName (PGUnknown $ "_" <> pgScalarTypeToText innerScalar)
|
||||
pure
|
||||
( arrayName,
|
||||
P.TNamed P.NonNullable $ P.Definition arrayName Nothing Nothing [] P.TIScalar
|
||||
)
|
||||
_ -> do
|
||||
name <- mkScalarTypeName scalarType
|
||||
pure (name, P.TNamed P.NonNullable $ P.Definition name Nothing Nothing [] P.TIScalar)
|
||||
|
@ -268,7 +268,11 @@ buildSchemaOptions
|
||||
soIncludeGroupByAggregateFields =
|
||||
if EFGroupByAggregations `Set.member` expFeatures
|
||||
then Options.IncludeGroupByAggregateFields
|
||||
else Options.ExcludeGroupByAggregateFields
|
||||
else Options.ExcludeGroupByAggregateFields,
|
||||
soPostgresArrays =
|
||||
if EFDisablePostgresArrays `Set.member` expFeatures
|
||||
then Options.DontUsePostgresArrays
|
||||
else Options.UsePostgresArrays
|
||||
}
|
||||
|
||||
-- | Build the @QueryHasura@ context for a given role.
|
||||
|
@ -12,6 +12,7 @@ module Hasura.RQL.Types.Schema.Options
|
||||
IncludeUpdateManyFields (..),
|
||||
BigQueryStringNumericInput (..),
|
||||
IncludeGroupByAggregateFields (..),
|
||||
UsePostgresArrays (..),
|
||||
)
|
||||
where
|
||||
|
||||
@ -29,7 +30,8 @@ data SchemaOptions = SchemaOptions
|
||||
soIncludeAggregationPredicates :: IncludeAggregationPredicates,
|
||||
soIncludeStreamFields :: IncludeStreamFields,
|
||||
soBigQueryStringNumericInput :: BigQueryStringNumericInput,
|
||||
soIncludeGroupByAggregateFields :: IncludeGroupByAggregateFields
|
||||
soIncludeGroupByAggregateFields :: IncludeGroupByAggregateFields,
|
||||
soPostgresArrays :: UsePostgresArrays
|
||||
}
|
||||
|
||||
-- | Should we represent numbers in our responses as numbers, or strings?
|
||||
@ -144,3 +146,11 @@ data IncludeGroupByAggregateFields
|
||||
= IncludeGroupByAggregateFields
|
||||
| ExcludeGroupByAggregateFields
|
||||
deriving (Eq, Show)
|
||||
|
||||
-- | if we use Postgres arrays then an array of `text` becomes `[String!]`,
|
||||
-- however we want users to have the option to make it output `_text` like it
|
||||
-- did before for compatibility.
|
||||
data UsePostgresArrays
|
||||
= UsePostgresArrays
|
||||
| DontUsePostgresArrays
|
||||
deriving (Eq, Show)
|
||||
|
@ -87,6 +87,7 @@ data ExperimentalFeature
|
||||
| EFHideAggregationPredicates
|
||||
| EFHideStreamFields
|
||||
| EFGroupByAggregations
|
||||
| EFDisablePostgresArrays
|
||||
deriving (Bounded, Enum, Eq, Generic, Show)
|
||||
|
||||
experimentalFeatureKey :: ExperimentalFeature -> Text
|
||||
@ -101,6 +102,7 @@ experimentalFeatureKey = \case
|
||||
EFHideAggregationPredicates -> "hide_aggregation_predicates"
|
||||
EFHideStreamFields -> "hide_stream_fields"
|
||||
EFGroupByAggregations -> "group_by_aggregations"
|
||||
EFDisablePostgresArrays -> "disable_postgres_arrays"
|
||||
|
||||
instance Hashable ExperimentalFeature
|
||||
|
||||
|
@ -11,7 +11,7 @@ import Prelude
|
||||
|
||||
spec :: Spec
|
||||
spec =
|
||||
describe "parse array scalar types" $ do
|
||||
describe "parse array scalar types with arrays switched on" $ do
|
||||
let expectations =
|
||||
[ ("text", PGText),
|
||||
("text[]", PGArray PGText),
|
||||
|
@ -70,7 +70,8 @@ defaultSchemaOptions =
|
||||
soIncludeAggregationPredicates = Options.IncludeAggregationPredicates,
|
||||
soIncludeStreamFields = Options.IncludeStreamFields,
|
||||
soBigQueryStringNumericInput = Options.EnableBigQueryStringNumericInput,
|
||||
soIncludeGroupByAggregateFields = Options.IncludeGroupByAggregateFields
|
||||
soIncludeGroupByAggregateFields = Options.IncludeGroupByAggregateFields,
|
||||
soPostgresArrays = Options.UsePostgresArrays
|
||||
}
|
||||
|
||||
instance Has NamingCase SchemaEnvironment where
|
||||
|
Loading…
Reference in New Issue
Block a user