mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-09-17 13:37:26 +03:00
Rename "Logical Models" → "Native Queries"
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8769 GitOrigin-RevId: 66f2cbfb620d641e672a4074554d9d324a18c591
This commit is contained in:
parent
ef5377a09e
commit
0346224444
@ -31,7 +31,7 @@ type SourceWithNormalFields struct {
|
||||
Customization yaml.Node `yaml:"customization,omitempty"`
|
||||
HealthCheck yaml.Node `yaml:"health_check,omitempty"`
|
||||
CustomReturnTypes yaml.Node `yaml:"custom_return_types,omitempty"`
|
||||
LogicalModels yaml.Node `yaml:"logical_models,omitempty"`
|
||||
NativeQueries yaml.Node `yaml:"native_queries,omitempty"`
|
||||
}
|
||||
type Source struct {
|
||||
SourceWithNormalFields `yaml:",inline"`
|
||||
|
@ -51,7 +51,7 @@
|
||||
- question
|
||||
filter: {}
|
||||
role: user
|
||||
logical_models:
|
||||
native_queries:
|
||||
- arguments:
|
||||
unused:
|
||||
description: An integer argument that we completely ignore
|
||||
|
@ -81,7 +81,7 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"logical_models": [
|
||||
"native_queries": [
|
||||
{
|
||||
"arguments": {
|
||||
"unused": {
|
||||
|
@ -81,7 +81,7 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"logical_models": [
|
||||
"native_queries": [
|
||||
{
|
||||
"arguments": {
|
||||
"unused": {
|
||||
|
@ -51,7 +51,7 @@
|
||||
- question
|
||||
filter: {}
|
||||
role: user
|
||||
logical_models:
|
||||
native_queries:
|
||||
- arguments:
|
||||
unused:
|
||||
description: An integer argument that we completely ignore
|
||||
|
@ -25012,7 +25012,7 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"logical_models": null,
|
||||
"native_queries": null,
|
||||
"custom_return_types": null,
|
||||
"functions": [
|
||||
{
|
||||
|
@ -12990,7 +12990,7 @@ sources:
|
||||
_in: X-Hasura-Conference-Ids
|
||||
- subconferenceId:
|
||||
_in: X-Hasura-Subconference-Ids
|
||||
logical_models: null
|
||||
native_queries: null
|
||||
custom_return_types: null
|
||||
functions:
|
||||
- function:
|
||||
|
@ -145,7 +145,7 @@ Here are samples of all the types of telemetry sent by the Enterprise Edition se
|
||||
"permissions_roles": 0,
|
||||
"event_triggers": 0,
|
||||
"functions": 0,
|
||||
"logical_models": 0,
|
||||
"native_queries": 0,
|
||||
"query_tags_enabled": false,
|
||||
"connection_templates_enabled": false
|
||||
}
|
||||
|
@ -809,8 +809,8 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"BigqueryLogicalModelMetadata": {
|
||||
"description": "A logical model as represented in metadata.",
|
||||
"BigqueryNativeQueryMetadata": {
|
||||
"description": "A native query as represented in metadata.",
|
||||
"properties": {
|
||||
"arguments": {
|
||||
"additionalProperties": {
|
||||
@ -825,7 +825,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "A description of the logical model which appears in the graphql schema",
|
||||
"description": "A description of the native query which appears in the graphql schema",
|
||||
"type": "string"
|
||||
},
|
||||
"returns": {
|
||||
@ -833,7 +833,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"root_field_name": {
|
||||
"description": "Root field name for the logical model",
|
||||
"description": "Root field name for the native query",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -1055,17 +1055,17 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"logical_models": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"native_queries": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/BigqueryLogicalModelMetadata"
|
||||
"$ref": "#/components/schemas/BigqueryNativeQueryMetadata"
|
||||
},
|
||||
"nullable": true,
|
||||
"type": "array"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"query_tags": {
|
||||
"$ref": "#/components/schemas/QueryTagsConfig"
|
||||
},
|
||||
@ -1641,8 +1641,8 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CitusLogicalModelMetadata": {
|
||||
"description": "A logical model as represented in metadata.",
|
||||
"CitusNativeQueryMetadata": {
|
||||
"description": "A native query as represented in metadata.",
|
||||
"properties": {
|
||||
"arguments": {
|
||||
"additionalProperties": {
|
||||
@ -1657,7 +1657,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "A description of the logical model which appears in the graphql schema",
|
||||
"description": "A description of the native query which appears in the graphql schema",
|
||||
"type": "string"
|
||||
},
|
||||
"returns": {
|
||||
@ -1665,7 +1665,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"root_field_name": {
|
||||
"description": "Root field name for the logical model",
|
||||
"description": "Root field name for the native query",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -1915,17 +1915,17 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"logical_models": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"native_queries": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/CitusLogicalModelMetadata"
|
||||
"$ref": "#/components/schemas/CitusNativeQueryMetadata"
|
||||
},
|
||||
"nullable": true,
|
||||
"type": "array"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"query_tags": {
|
||||
"$ref": "#/components/schemas/QueryTagsConfig"
|
||||
},
|
||||
@ -2508,8 +2508,8 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CockroachLogicalModelMetadata": {
|
||||
"description": "A logical model as represented in metadata.",
|
||||
"CockroachNativeQueryMetadata": {
|
||||
"description": "A native query as represented in metadata.",
|
||||
"properties": {
|
||||
"arguments": {
|
||||
"additionalProperties": {
|
||||
@ -2524,7 +2524,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "A description of the logical model which appears in the graphql schema",
|
||||
"description": "A description of the native query which appears in the graphql schema",
|
||||
"type": "string"
|
||||
},
|
||||
"returns": {
|
||||
@ -2532,7 +2532,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"root_field_name": {
|
||||
"description": "Root field name for the logical model",
|
||||
"description": "Root field name for the native query",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -2782,17 +2782,17 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"logical_models": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"native_queries": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/CockroachLogicalModelMetadata"
|
||||
"$ref": "#/components/schemas/CockroachNativeQueryMetadata"
|
||||
},
|
||||
"nullable": true,
|
||||
"type": "array"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"query_tags": {
|
||||
"$ref": "#/components/schemas/QueryTagsConfig"
|
||||
},
|
||||
@ -3530,8 +3530,8 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"DataconnectorLogicalModelMetadata": {
|
||||
"description": "A logical model as represented in metadata.",
|
||||
"DataconnectorNativeQueryMetadata": {
|
||||
"description": "A native query as represented in metadata.",
|
||||
"properties": {
|
||||
"arguments": {
|
||||
"additionalProperties": {
|
||||
@ -3546,7 +3546,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "A description of the logical model which appears in the graphql schema",
|
||||
"description": "A description of the native query which appears in the graphql schema",
|
||||
"type": "string"
|
||||
},
|
||||
"returns": {
|
||||
@ -3554,7 +3554,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"root_field_name": {
|
||||
"description": "Root field name for the logical model",
|
||||
"description": "Root field name for the native query",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -3790,17 +3790,17 @@
|
||||
"kind": {
|
||||
"$ref": "#/components/schemas/GraphQLName"
|
||||
},
|
||||
"logical_models": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"native_queries": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/DataconnectorLogicalModelMetadata"
|
||||
"$ref": "#/components/schemas/DataconnectorNativeQueryMetadata"
|
||||
},
|
||||
"nullable": true,
|
||||
"type": "array"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"query_tags": {
|
||||
"$ref": "#/components/schemas/QueryTagsConfig"
|
||||
},
|
||||
@ -5022,8 +5022,8 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MssqlLogicalModelMetadata": {
|
||||
"description": "A logical model as represented in metadata.",
|
||||
"MssqlNativeQueryMetadata": {
|
||||
"description": "A native query as represented in metadata.",
|
||||
"properties": {
|
||||
"arguments": {
|
||||
"additionalProperties": {
|
||||
@ -5038,7 +5038,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "A description of the logical model which appears in the graphql schema",
|
||||
"description": "A description of the native query which appears in the graphql schema",
|
||||
"type": "string"
|
||||
},
|
||||
"returns": {
|
||||
@ -5046,7 +5046,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"root_field_name": {
|
||||
"description": "Root field name for the logical model",
|
||||
"description": "Root field name for the native query",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -5295,17 +5295,17 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"logical_models": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"native_queries": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/MssqlLogicalModelMetadata"
|
||||
"$ref": "#/components/schemas/MssqlNativeQueryMetadata"
|
||||
},
|
||||
"nullable": true,
|
||||
"type": "array"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"query_tags": {
|
||||
"$ref": "#/components/schemas/QueryTagsConfig"
|
||||
},
|
||||
@ -5852,8 +5852,8 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MysqlLogicalModelMetadata": {
|
||||
"description": "A logical model as represented in metadata.",
|
||||
"MysqlNativeQueryMetadata": {
|
||||
"description": "A native query as represented in metadata.",
|
||||
"properties": {
|
||||
"arguments": {
|
||||
"additionalProperties": {
|
||||
@ -5868,7 +5868,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "A description of the logical model which appears in the graphql schema",
|
||||
"description": "A description of the native query which appears in the graphql schema",
|
||||
"type": "string"
|
||||
},
|
||||
"returns": {
|
||||
@ -5876,7 +5876,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"root_field_name": {
|
||||
"description": "Root field name for the logical model",
|
||||
"description": "Root field name for the native query",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -6153,17 +6153,17 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"logical_models": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"native_queries": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/MysqlLogicalModelMetadata"
|
||||
"$ref": "#/components/schemas/MysqlNativeQueryMetadata"
|
||||
},
|
||||
"nullable": true,
|
||||
"type": "array"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"query_tags": {
|
||||
"$ref": "#/components/schemas/QueryTagsConfig"
|
||||
},
|
||||
@ -6983,8 +6983,8 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PostgresLogicalModelMetadata": {
|
||||
"description": "A logical model as represented in metadata.",
|
||||
"PostgresNativeQueryMetadata": {
|
||||
"description": "A native query as represented in metadata.",
|
||||
"properties": {
|
||||
"arguments": {
|
||||
"additionalProperties": {
|
||||
@ -6999,7 +6999,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "A description of the logical model which appears in the graphql schema",
|
||||
"description": "A description of the native query which appears in the graphql schema",
|
||||
"type": "string"
|
||||
},
|
||||
"returns": {
|
||||
@ -7007,7 +7007,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"root_field_name": {
|
||||
"description": "Root field name for the logical model",
|
||||
"description": "Root field name for the native query",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -7371,17 +7371,17 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"logical_models": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"native_queries": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/PostgresLogicalModelMetadata"
|
||||
"$ref": "#/components/schemas/PostgresNativeQueryMetadata"
|
||||
},
|
||||
"nullable": true,
|
||||
"type": "array"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"query_tags": {
|
||||
"$ref": "#/components/schemas/QueryTagsConfig"
|
||||
},
|
||||
|
@ -130,26 +130,26 @@ test-integration-postgres: remove-tix-file
|
||||
HASURA_GRAPHQL_DATABASE_URL='$(TEST_POSTGRES_URL)' \
|
||||
cabal run graphql-engine:test:graphql-engine-test-postgres
|
||||
|
||||
.PHONY: test-logical-models
|
||||
## test-logical-models: run all tests for the Logical Model feature
|
||||
test-logical-models:
|
||||
.PHONY: test-native-queries
|
||||
## test-native-queries: run all tests for the Native Query feature
|
||||
test-native-queries:
|
||||
cabal build exe:graphql-engine
|
||||
docker compose up -d --wait postgres citus sqlserver-healthcheck
|
||||
HSPEC_MATCH=LogicalModels make test-unit
|
||||
HSPEC_MATCH=NativeQueries make test-unit
|
||||
HASURA_TEST_BACKEND_TYPE=Postgres \
|
||||
HSPEC_MATCH=LogicalModels \
|
||||
HSPEC_MATCH=NativeQueries \
|
||||
GRAPHQL_ENGINE=$(GRAPHQL_ENGINE_PATH) \
|
||||
cabal run api-tests:exe:api-tests
|
||||
HASURA_TEST_BACKEND_TYPE=Citus \
|
||||
HSPEC_MATCH=LogicalModels \
|
||||
HSPEC_MATCH=NativeQueries \
|
||||
GRAPHQL_ENGINE=$(GRAPHQL_ENGINE_PATH) \
|
||||
cabal run api-tests:exe:api-tests
|
||||
HASURA_TEST_BACKEND_TYPE=BigQuery \
|
||||
HSPEC_MATCH=LogicalModel \
|
||||
HSPEC_MATCH=NativeQuery \
|
||||
GRAPHQL_ENGINE=$(GRAPHQL_ENGINE_PATH) \
|
||||
cabal run api-tests:exe:api-tests
|
||||
HASURA_TEST_BACKEND_TYPE=SQLServer \
|
||||
HSPEC_MATCH=LogicalModel \
|
||||
HSPEC_MATCH=NativeQuery \
|
||||
GRAPHQL_ENGINE=$(GRAPHQL_ENGINE_PATH) \
|
||||
cabal run api-tests:exe:api-tests
|
||||
|
||||
|
@ -612,7 +612,7 @@ library
|
||||
, Hasura.Backends.Postgres.Instances.API
|
||||
, Hasura.Backends.Postgres.Instances.Execute
|
||||
, Hasura.Backends.Postgres.Instances.Metadata
|
||||
, Hasura.Backends.Postgres.Instances.LogicalModels
|
||||
, Hasura.Backends.Postgres.Instances.NativeQueries
|
||||
, Hasura.Backends.Postgres.Instances.PingSource
|
||||
, Hasura.Backends.Postgres.Instances.Schema
|
||||
, Hasura.Backends.Postgres.Instances.SchemaCache
|
||||
@ -760,12 +760,12 @@ library
|
||||
, Hasura.Server.Auth.JWT
|
||||
, Hasura.GC
|
||||
|
||||
, Hasura.LogicalModel.IR
|
||||
, Hasura.LogicalModel.Cache
|
||||
, Hasura.LogicalModel.Metadata
|
||||
, Hasura.LogicalModel.API
|
||||
, Hasura.LogicalModel.Schema
|
||||
, Hasura.LogicalModel.Types
|
||||
, Hasura.NativeQuery.IR
|
||||
, Hasura.NativeQuery.Cache
|
||||
, Hasura.NativeQuery.Metadata
|
||||
, Hasura.NativeQuery.API
|
||||
, Hasura.NativeQuery.Schema
|
||||
, Hasura.NativeQuery.Types
|
||||
|
||||
, Hasura.Tracing
|
||||
, Hasura.Tracing.Class
|
||||
@ -1188,7 +1188,7 @@ test-suite graphql-engine-tests
|
||||
Hasura.Backends.MySQL.TypesSpec
|
||||
Hasura.Backends.Postgres.Connection.VersionCheckSpec
|
||||
Hasura.Backends.Postgres.Execute.PrepareSpec
|
||||
Hasura.Backends.Postgres.LogicalModels.LogicalModelsSpec
|
||||
Hasura.Backends.Postgres.NativeQueries.NativeQueriesSpec
|
||||
Hasura.Backends.Postgres.RQLGenerator
|
||||
Hasura.Backends.Postgres.RQLGenerator.GenAnnSelectG
|
||||
Hasura.Backends.Postgres.RQLGenerator.GenAssociatedTypes
|
||||
|
@ -98,9 +98,9 @@ library
|
||||
Test.API.Metadata.ComputedFieldsSpec
|
||||
Test.API.Metadata.CustomTypeSpec
|
||||
Test.API.Metadata.InconsistentSpec
|
||||
Test.API.Metadata.LogicalModelsSpec
|
||||
Test.API.Metadata.LogicalModels.TypeCheckingSpec
|
||||
Test.API.Metadata.LogicalModels.ValidationSpec
|
||||
Test.API.Metadata.NativeQueriesSpec
|
||||
Test.API.Metadata.NativeQueries.TypeCheckingSpec
|
||||
Test.API.Metadata.NativeQueries.ValidationSpec
|
||||
Test.API.Metadata.SuggestRelationshipsSpec
|
||||
Test.API.Metadata.TablesSpec
|
||||
Test.API.Metadata.TestConnectionTemplateSpec
|
||||
@ -131,19 +131,19 @@ library
|
||||
Test.DataConnector.MockAgent.UpdateMutationsSpec
|
||||
Test.DataConnector.QuerySpec
|
||||
Test.DataConnector.SelectPermissionsSpec
|
||||
Test.Databases.BigQuery.LogicalModelsSpec
|
||||
Test.Databases.BigQuery.NativeQueriesSpec
|
||||
Test.Databases.BigQuery.Queries.SpatialTypesSpec
|
||||
Test.Databases.BigQuery.Queries.TypeInterpretationSpec
|
||||
Test.Databases.BigQuery.Schema.ComputedFields.TableSpec
|
||||
Test.Databases.Postgres.BackendOnlyPermissionsSpec
|
||||
Test.Databases.Postgres.DataValidation.PermissionSpec
|
||||
Test.Databases.Postgres.JsonbSpec
|
||||
Test.Databases.Postgres.LogicalModelsSpec
|
||||
Test.Databases.Postgres.NativeQueriesSpec
|
||||
Test.Databases.Postgres.TimestampSpec
|
||||
Test.Databases.Postgres.UniqueConstraintsSpec
|
||||
Test.Databases.SQLServer.DefaultValues.OnConflictSpec
|
||||
Test.Databases.SQLServer.InsertVarcharColumnSpec
|
||||
Test.Databases.SQLServer.LogicalModelsSpec
|
||||
Test.Databases.SQLServer.NativeQueriesSpec
|
||||
Test.Databases.SQLServer.VarcharLiteralsSpec
|
||||
Test.EventTriggers.EventTriggersSpecialCharactersSpec
|
||||
Test.EventTriggers.MSSQL.EventTriggerDropSourceCleanupSpec
|
||||
@ -184,8 +184,8 @@ library
|
||||
Test.Queries.Errors.NoQueriesAvailableSpec
|
||||
Test.Queries.FilterSearch.AggregationPredicatesSpec
|
||||
Test.Queries.FilterSearch.FilterSearchSpec
|
||||
Test.Queries.LogicalModels.LogicalModelsQueriesSpec
|
||||
Test.Queries.LogicalModels.SubscriptionsSpec
|
||||
Test.Queries.NativeQueries.NativeQueriesSpec
|
||||
Test.Queries.NativeQueries.SubscriptionsSpec
|
||||
Test.Queries.NestedObjectSpec
|
||||
Test.Queries.Paginate.LimitSpec
|
||||
Test.Queries.Paginate.OffsetSpec
|
||||
|
@ -24,8 +24,8 @@ import Test.Hspec (SpecWith, describe, it)
|
||||
|
||||
-- ** Preamble
|
||||
|
||||
featureFlagForLogicalModels :: String
|
||||
featureFlagForLogicalModels = "HASURA_FF_LOGICAL_MODEL_INTERFACE"
|
||||
featureFlagForNativeQueries :: String
|
||||
featureFlagForNativeQueries = "HASURA_FF_NATIVE_QUERY_INTERFACE"
|
||||
|
||||
spec :: SpecWith GlobalTestEnvironment
|
||||
spec = do
|
||||
@ -38,7 +38,7 @@ spec = do
|
||||
}
|
||||
]
|
||||
|
||||
Fixture.hgeWithEnv [(featureFlagForLogicalModels, "True")] do
|
||||
Fixture.hgeWithEnv [(featureFlagForNativeQueries, "True")] do
|
||||
traverse_
|
||||
(Fixture.runClean fixtures)
|
||||
[ testImplementation,
|
||||
@ -58,13 +58,13 @@ testImplementation = do
|
||||
(Schema.customType "nice")
|
||||
{ Schema.customTypeDescription = Just "hello",
|
||||
Schema.customTypeColumns =
|
||||
[ (Schema.logicalModelColumn "divided" Schema.TInt)
|
||||
{ Schema.logicalModelColumnDescription = Just "a divided thing"
|
||||
[ (Schema.nativeQueryColumn "divided" Schema.TInt)
|
||||
{ Schema.nativeQueryColumnDescription = Just "a divided thing"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
describe "When logical models are disabled" do
|
||||
describe "When native queries are disabled" do
|
||||
let customTypesMetadata =
|
||||
[yaml|
|
||||
fields:
|
||||
@ -167,12 +167,12 @@ testImplementation = do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
logicalModel :: Schema.LogicalModel
|
||||
logicalModel =
|
||||
(Schema.logicalModel "logical_model" "SELECT 1 as divided" "nice")
|
||||
nativeQuery :: Schema.NativeQuery
|
||||
nativeQuery =
|
||||
(Schema.nativeQuery "native_query" "SELECT 1 as divided" "nice")
|
||||
|
||||
Schema.trackCustomType sourceName myCustomType testEnvironment
|
||||
Schema.trackLogicalModel sourceName logicalModel testEnvironment
|
||||
Schema.trackNativeQuery sourceName nativeQuery testEnvironment
|
||||
|
||||
shouldReturnYaml
|
||||
testEnvironment
|
||||
@ -181,7 +181,7 @@ testImplementation = do
|
||||
)
|
||||
[yaml|
|
||||
code: constraint-violation
|
||||
error: Custom type "nice" still being used by logical model "logical_model".
|
||||
error: Custom type "nice" still being used by native query "native_query".
|
||||
path: $.args
|
||||
|]
|
||||
|
||||
@ -195,8 +195,8 @@ testPermissions = do
|
||||
customReturnType =
|
||||
(Schema.customType "divided_stuff")
|
||||
{ Schema.customTypeColumns =
|
||||
[ (Schema.logicalModelColumn "divided" Schema.TInt)
|
||||
{ Schema.logicalModelColumnDescription = Just "a divided thing"
|
||||
[ (Schema.nativeQueryColumn "divided" Schema.TInt)
|
||||
{ Schema.nativeQueryColumnDescription = Just "a divided thing"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -257,7 +257,7 @@ testPermissions = do
|
||||
filter: {}
|
||||
|]
|
||||
|
||||
it "Adds a logical model, removes it, and returns 200" $ \testEnvironment -> do
|
||||
it "Adds a native query, removes it, and returns 200" $ \testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
backendType = BackendType.backendTypeString backendTypeMetadata
|
||||
|
@ -1,7 +1,7 @@
|
||||
{-# LANGUAGE AllowAmbiguousTypes #-}
|
||||
|
||||
-- | Check the typechecking validation of logical model's custom return types.
|
||||
module Test.API.Metadata.LogicalModels.TypeCheckingSpec where
|
||||
-- | Check the typechecking validation of native query's custom return types.
|
||||
module Test.API.Metadata.NativeQueries.TypeCheckingSpec where
|
||||
|
||||
import Data.List.NonEmpty qualified as NE
|
||||
import Harness.Backend.Citus qualified as Citus
|
||||
@ -19,12 +19,12 @@ import Hasura.Prelude
|
||||
import Test.Hspec (SpecWith, describe, it)
|
||||
import Test.QuickCheck
|
||||
|
||||
featureFlagForLogicalModels :: String
|
||||
featureFlagForLogicalModels = "HASURA_FF_LOGICAL_MODEL_INTERFACE"
|
||||
featureFlagForNativeQueries :: String
|
||||
featureFlagForNativeQueries = "HASURA_FF_NATIVE_QUERY_INTERFACE"
|
||||
|
||||
spec :: SpecWith GlobalTestEnvironment
|
||||
spec = do
|
||||
Fixture.hgeWithEnv [(featureFlagForLogicalModels, "True")] do
|
||||
Fixture.hgeWithEnv [(featureFlagForNativeQueries, "True")] do
|
||||
Fixture.run
|
||||
( NE.fromList
|
||||
[ (Fixture.fixture $ Fixture.Backend Postgres.backendTypeMetadata)
|
||||
@ -82,7 +82,7 @@ allTypesReturnType :: Schema.CustomType
|
||||
allTypesReturnType =
|
||||
(Schema.customType "stuff_type")
|
||||
{ Schema.customTypeColumns =
|
||||
(\t -> Schema.logicalModelColumn t (customType t)) <$> types
|
||||
(\t -> Schema.nativeQueryColumn t (customType t)) <$> types
|
||||
}
|
||||
|
||||
types :: [Text]
|
||||
@ -112,7 +112,7 @@ types =
|
||||
|
||||
tests :: BackendDifferences -> SpecWith TestEnvironment
|
||||
tests BackendDifferences {..} = do
|
||||
describe "Validation succeeds tracking a logical model" do
|
||||
describe "Validation succeeds tracking a native query" do
|
||||
it "for all supported types" $
|
||||
\testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
@ -121,9 +121,9 @@ tests BackendDifferences {..} = do
|
||||
let simpleQuery :: Text
|
||||
simpleQuery = "SELECT * FROM stuff"
|
||||
|
||||
let logicalModel :: Schema.LogicalModel
|
||||
logicalModel =
|
||||
(Schema.logicalModel "typed_model" simpleQuery "stuff_type")
|
||||
let nativeQuery :: Schema.NativeQuery
|
||||
nativeQuery =
|
||||
(Schema.nativeQuery "typed_model" simpleQuery "stuff_type")
|
||||
|
||||
Schema.trackCustomType sourceName allTypesReturnType testEnvironment
|
||||
|
||||
@ -131,13 +131,13 @@ tests BackendDifferences {..} = do
|
||||
testEnvironment
|
||||
( GraphqlEngine.postMetadata
|
||||
testEnvironment
|
||||
(Schema.trackLogicalModelCommand sourceName backendTypeMetadata logicalModel)
|
||||
(Schema.trackNativeQueryCommand sourceName backendTypeMetadata nativeQuery)
|
||||
)
|
||||
[yaml|
|
||||
message: success
|
||||
|]
|
||||
|
||||
describe "Validation fails tracking a logical model" do
|
||||
describe "Validation fails tracking a native query" do
|
||||
it "when there's a type mismatch" $ \testEnvironment ->
|
||||
withMaxSuccess maxSuccesses $
|
||||
forAll (generator isDifferentTypeThan) $ \DifferentTypes {..} -> do
|
||||
@ -147,12 +147,12 @@ tests BackendDifferences {..} = do
|
||||
let wrongQuery :: Text
|
||||
wrongQuery = "SELECT " <> tableType <> " AS " <> customtypeType <> " FROM stuff_" <> tableType
|
||||
|
||||
let logicalModel :: Schema.LogicalModel
|
||||
logicalModel =
|
||||
(Schema.logicalModel ("typed_model_" <> customtypeType) wrongQuery ("stuff_type_" <> customtypeType))
|
||||
let nativeQuery :: Schema.NativeQuery
|
||||
nativeQuery =
|
||||
(Schema.nativeQuery ("typed_model_" <> customtypeType) wrongQuery ("stuff_type_" <> customtypeType))
|
||||
|
||||
-- Possible cleanup after last test that may have tracked this custom type
|
||||
_ <- Schema.untrackLogicalModel sourceName logicalModel testEnvironment `catch` \(_ :: SomeException) -> pure ()
|
||||
_ <- Schema.untrackNativeQuery sourceName nativeQuery testEnvironment `catch` \(_ :: SomeException) -> pure ()
|
||||
_ <- Schema.untrackCustomType sourceName (mkCustomType customtypeType) testEnvironment `catch` \(_ :: SomeException) -> pure ()
|
||||
Schema.trackCustomType sourceName (mkCustomType customtypeType) testEnvironment
|
||||
|
||||
@ -176,7 +176,7 @@ tests BackendDifferences {..} = do
|
||||
GraphqlEngine.postMetadataWithStatus
|
||||
400
|
||||
testEnvironment
|
||||
(Schema.trackLogicalModelCommand sourceName backendTypeMetadata logicalModel)
|
||||
(Schema.trackNativeQueryCommand sourceName backendTypeMetadata nativeQuery)
|
||||
actual `shouldAtLeastBe` expected
|
||||
|
||||
-- ** Utils
|
||||
@ -185,7 +185,7 @@ mkCustomType :: Text -> Schema.CustomType
|
||||
mkCustomType typ =
|
||||
(Schema.customType ("stuff_type_" <> typ))
|
||||
{ Schema.customTypeColumns =
|
||||
[Schema.logicalModelColumn typ (customType typ)]
|
||||
[Schema.nativeQueryColumn typ (customType typ)]
|
||||
}
|
||||
|
||||
-- | Match a column from a table type and the custom type.
|
@ -1,4 +1,4 @@
|
||||
module Test.API.Metadata.LogicalModels.ValidationSpec where
|
||||
module Test.API.Metadata.NativeQueries.ValidationSpec where
|
||||
|
||||
import Data.List.NonEmpty qualified as NE
|
||||
import Harness.Backend.Citus qualified as Citus
|
||||
@ -14,12 +14,12 @@ import Harness.Yaml (shouldAtLeastBe, shouldReturnYaml)
|
||||
import Hasura.Prelude
|
||||
import Test.Hspec (SpecWith, describe, it)
|
||||
|
||||
featureFlagForLogicalModels :: String
|
||||
featureFlagForLogicalModels = "HASURA_FF_LOGICAL_MODEL_INTERFACE"
|
||||
featureFlagForNativeQueries :: String
|
||||
featureFlagForNativeQueries = "HASURA_FF_NATIVE_QUERY_INTERFACE"
|
||||
|
||||
spec :: SpecWith GlobalTestEnvironment
|
||||
spec = do
|
||||
Fixture.hgeWithEnv [(featureFlagForLogicalModels, "True")] do
|
||||
Fixture.hgeWithEnv [(featureFlagForNativeQueries, "True")] do
|
||||
Fixture.runClean
|
||||
( NE.fromList
|
||||
[ (Fixture.fixture $ Fixture.Backend Postgres.backendTypeMetadata)
|
||||
@ -64,8 +64,8 @@ tests = do
|
||||
conflictingReturnType =
|
||||
(Schema.customType "conflicting")
|
||||
{ Schema.customTypeColumns =
|
||||
[ Schema.logicalModelColumn "thing" Schema.TInt,
|
||||
Schema.logicalModelColumn "date" Schema.TUTCTime
|
||||
[ Schema.nativeQueryColumn "thing" Schema.TInt,
|
||||
Schema.nativeQueryColumn "date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
@ -73,27 +73,27 @@ tests = do
|
||||
dividedReturnType =
|
||||
(Schema.customType "divided_stuff")
|
||||
{ Schema.customTypeColumns =
|
||||
[ Schema.logicalModelColumn "divided" Schema.TInt
|
||||
[ Schema.nativeQueryColumn "divided" Schema.TInt
|
||||
]
|
||||
}
|
||||
|
||||
describe "Validation fails on untrack a logical model" do
|
||||
it "when a logical model does not exist" $
|
||||
describe "Validation fails on untrack a native query" do
|
||||
it "when a native query does not exist" $
|
||||
\testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
nonExistentLogicalModel :: Schema.LogicalModel
|
||||
nonExistentLogicalModel = Schema.logicalModel "some_logical_model" "" ""
|
||||
nonExistentNativeQuery :: Schema.NativeQuery
|
||||
nonExistentNativeQuery = Schema.nativeQuery "some_native_query" "" ""
|
||||
|
||||
expectedError = "Logical model \"some_logical_model\" not found in source \"" <> sourceName <> "\"."
|
||||
expectedError = "Native query \"some_native_query\" not found in source \"" <> sourceName <> "\"."
|
||||
|
||||
shouldReturnYaml
|
||||
testEnvironment
|
||||
( GraphqlEngine.postMetadataWithStatus
|
||||
400
|
||||
testEnvironment
|
||||
(Schema.untrackLogicalModelCommand sourceName backendTypeMetadata nonExistentLogicalModel)
|
||||
(Schema.untrackNativeQueryCommand sourceName backendTypeMetadata nonExistentNativeQuery)
|
||||
)
|
||||
[yaml|
|
||||
code: not-found
|
||||
@ -101,7 +101,7 @@ tests = do
|
||||
path: "$.args"
|
||||
|]
|
||||
|
||||
describe "Validation fails on track a logical model" do
|
||||
describe "Validation fails on track a native query" do
|
||||
it "when the query has a syntax error" $
|
||||
\testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
@ -117,12 +117,12 @@ tests = do
|
||||
path: "$.args"
|
||||
|]
|
||||
|
||||
syntaxErrorLogicalModel :: Schema.LogicalModel
|
||||
syntaxErrorLogicalModel =
|
||||
(Schema.logicalModel "divided_stuff" spicyQuery "divided_stuff")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "denominator" Schema.TInt,
|
||||
Schema.logicalModelColumn "target_date" Schema.TUTCTime
|
||||
syntaxErrorNativeQuery :: Schema.NativeQuery
|
||||
syntaxErrorNativeQuery =
|
||||
(Schema.nativeQuery "divided_stuff" spicyQuery "divided_stuff")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "denominator" Schema.TInt,
|
||||
Schema.nativeQueryColumn "target_date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
@ -132,7 +132,7 @@ tests = do
|
||||
GraphqlEngine.postMetadataWithStatus
|
||||
400
|
||||
testEnvironment
|
||||
(Schema.trackLogicalModelCommand sourceName backendTypeMetadata syntaxErrorLogicalModel)
|
||||
(Schema.trackNativeQueryCommand sourceName backendTypeMetadata syntaxErrorNativeQuery)
|
||||
|
||||
actual `shouldAtLeastBe` expected
|
||||
|
||||
@ -144,12 +144,12 @@ tests = do
|
||||
let spicyQuery :: Text
|
||||
spicyQuery = "SELECT thing / {{denominator}} AS divided FROM does_not_exist WHERE date = {{target_date}}"
|
||||
|
||||
brokenLogicalModel :: Schema.LogicalModel
|
||||
brokenLogicalModel =
|
||||
(Schema.logicalModel "divided_stuff" spicyQuery "divided_stuff")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "denominator" Schema.TInt,
|
||||
Schema.logicalModelColumn "target_date" Schema.TUTCTime
|
||||
brokenNativeQuery :: Schema.NativeQuery
|
||||
brokenNativeQuery =
|
||||
(Schema.nativeQuery "divided_stuff" spicyQuery "divided_stuff")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "denominator" Schema.TInt,
|
||||
Schema.nativeQueryColumn "target_date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
@ -169,11 +169,11 @@ tests = do
|
||||
GraphqlEngine.postMetadataWithStatus
|
||||
400
|
||||
testEnvironment
|
||||
(Schema.trackLogicalModelCommand sourceName backendTypeMetadata brokenLogicalModel)
|
||||
(Schema.trackNativeQueryCommand sourceName backendTypeMetadata brokenNativeQuery)
|
||||
|
||||
actual `shouldAtLeastBe` expected
|
||||
|
||||
it "when the logical model has the same name as an already tracked table" $
|
||||
it "when the native query has the same name as an already tracked table" $
|
||||
\testEnv -> do
|
||||
let spicyQuery :: Text
|
||||
spicyQuery = "select * from stuff"
|
||||
@ -182,16 +182,16 @@ tests = do
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
schemaName = Schema.getSchemaName testEnv
|
||||
|
||||
conflictingLogicalModel :: Schema.LogicalModel
|
||||
conflictingLogicalModel =
|
||||
(Schema.logicalModel (Schema.unSchemaName schemaName <> "_stuff") spicyQuery "conflicting")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "denominator" Schema.TInt,
|
||||
Schema.logicalModelColumn "target_date" Schema.TUTCTime
|
||||
conflictingNativeQuery :: Schema.NativeQuery
|
||||
conflictingNativeQuery =
|
||||
(Schema.nativeQuery (Schema.unSchemaName schemaName <> "_stuff") spicyQuery "conflicting")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "denominator" Schema.TInt,
|
||||
Schema.nativeQueryColumn "target_date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
expectedError = "Encountered conflicting definitions in the selection set for 'subscription_root' for field 'hasura_stuff' defined in [table hasura.stuff in source " <> sourceName <> ", logical_model hasura_stuff in source " <> sourceName <> "]. Fields must not be defined more than once across all sources."
|
||||
expectedError = "Encountered conflicting definitions in the selection set for 'subscription_root' for field 'hasura_stuff' defined in [table hasura.stuff in source " <> sourceName <> ", native_query hasura_stuff in source " <> sourceName <> "]. Fields must not be defined more than once across all sources."
|
||||
|
||||
Schema.trackCustomType sourceName conflictingReturnType testEnv
|
||||
|
||||
@ -200,7 +200,7 @@ tests = do
|
||||
( GraphqlEngine.postMetadataWithStatus
|
||||
500
|
||||
testEnv
|
||||
(Schema.trackLogicalModelCommand sourceName backendTypeMetadata conflictingLogicalModel)
|
||||
(Schema.trackNativeQueryCommand sourceName backendTypeMetadata conflictingNativeQuery)
|
||||
)
|
||||
[yaml|
|
||||
code: unexpected
|
||||
@ -208,7 +208,7 @@ tests = do
|
||||
path: $.args
|
||||
|]
|
||||
|
||||
it "when the logical model has the same name as an already tracked logical model" $
|
||||
it "when the native query has the same name as an already tracked native query" $
|
||||
\testEnv -> do
|
||||
let spicyQuery :: Text
|
||||
spicyQuery = "select * from stuff"
|
||||
@ -217,12 +217,12 @@ tests = do
|
||||
source = BackendType.backendSourceName backendTypeMetadata
|
||||
schemaName = Schema.getSchemaName testEnv
|
||||
|
||||
conflictingLogicalModel :: Schema.LogicalModel
|
||||
conflictingLogicalModel =
|
||||
(Schema.logicalModel (Schema.unSchemaName schemaName <> "_stuff_exist") spicyQuery "conflicting")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "denominator" Schema.TInt,
|
||||
Schema.logicalModelColumn "target_date" Schema.TUTCTime
|
||||
conflictingNativeQuery :: Schema.NativeQuery
|
||||
conflictingNativeQuery =
|
||||
(Schema.nativeQuery (Schema.unSchemaName schemaName <> "_stuff_exist") spicyQuery "conflicting")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "denominator" Schema.TInt,
|
||||
Schema.nativeQueryColumn "target_date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
@ -232,7 +232,7 @@ tests = do
|
||||
testEnv
|
||||
( GraphqlEngine.postMetadata
|
||||
testEnv
|
||||
(Schema.trackLogicalModelCommand source backendTypeMetadata conflictingLogicalModel)
|
||||
(Schema.trackNativeQueryCommand source backendTypeMetadata conflictingNativeQuery)
|
||||
)
|
||||
[yaml|
|
||||
message: success
|
||||
@ -243,11 +243,11 @@ tests = do
|
||||
( GraphqlEngine.postMetadataWithStatus
|
||||
400
|
||||
testEnv
|
||||
(Schema.trackLogicalModelCommand source backendTypeMetadata conflictingLogicalModel)
|
||||
(Schema.trackNativeQueryCommand source backendTypeMetadata conflictingNativeQuery)
|
||||
)
|
||||
[yaml|
|
||||
code: already-tracked
|
||||
error: Logical model 'hasura_stuff_exist' is already tracked.
|
||||
error: Native query 'hasura_stuff_exist' is already tracked.
|
||||
path: $.args
|
||||
|]
|
||||
|
||||
@ -258,11 +258,11 @@ tests = do
|
||||
|
||||
query = "SELECT 10 / {{denominator}} AS divided"
|
||||
|
||||
brokenTypesLogicalModel :: Schema.LogicalModel
|
||||
brokenTypesLogicalModel =
|
||||
(Schema.logicalModel "divided_falling" query "divided_stuff")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "denominator" Schema.TStr
|
||||
brokenTypesNativeQuery :: Schema.NativeQuery
|
||||
brokenTypesNativeQuery =
|
||||
(Schema.nativeQuery "divided_falling" query "divided_stuff")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "denominator" Schema.TStr
|
||||
]
|
||||
}
|
||||
|
||||
@ -278,7 +278,7 @@ tests = do
|
||||
GraphqlEngine.postMetadataWithStatus
|
||||
400
|
||||
testEnvironment
|
||||
(Schema.trackLogicalModelCommand sourceName backendTypeMetadata brokenTypesLogicalModel)
|
||||
(Schema.trackNativeQueryCommand sourceName backendTypeMetadata brokenTypesNativeQuery)
|
||||
|
||||
actual `shouldAtLeastBe` expected
|
||||
|
||||
@ -302,15 +302,15 @@ tests = do
|
||||
brokenColumnsReturn =
|
||||
(Schema.customType "failing")
|
||||
{ Schema.customTypeColumns =
|
||||
[ Schema.logicalModelColumn "text" Schema.TStr
|
||||
[ Schema.nativeQueryColumn "text" Schema.TStr
|
||||
]
|
||||
}
|
||||
|
||||
brokenColumnsLogicalModel :: Schema.LogicalModel
|
||||
brokenColumnsLogicalModel =
|
||||
(Schema.logicalModel "text_failing" query "failing")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "text" Schema.TStr
|
||||
brokenColumnsNativeQuery :: Schema.NativeQuery
|
||||
brokenColumnsNativeQuery =
|
||||
(Schema.nativeQuery "text_failing" query "failing")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "text" Schema.TStr
|
||||
]
|
||||
}
|
||||
|
||||
@ -320,7 +320,7 @@ tests = do
|
||||
GraphqlEngine.postMetadataWithStatus
|
||||
400
|
||||
testEnvironment
|
||||
(Schema.trackLogicalModelCommand sourceName backendTypeMetadata brokenColumnsLogicalModel)
|
||||
(Schema.trackNativeQueryCommand sourceName backendTypeMetadata brokenColumnsNativeQuery)
|
||||
|
||||
actual `shouldAtLeastBe` expected
|
||||
|
||||
@ -331,9 +331,9 @@ tests = do
|
||||
|
||||
query = "SELECT 10 / {{denominator}} AS divided"
|
||||
|
||||
missingArgsLogicalModel :: Schema.LogicalModel
|
||||
missingArgsLogicalModel =
|
||||
(Schema.logicalModel "divided_falling" query "divided_stuff")
|
||||
missingArgsNativeQuery :: Schema.NativeQuery
|
||||
missingArgsNativeQuery =
|
||||
(Schema.nativeQuery "divided_falling" query "divided_stuff")
|
||||
|
||||
Schema.trackCustomType sourceName dividedReturnType testEnvironment
|
||||
|
||||
@ -342,7 +342,7 @@ tests = do
|
||||
( GraphqlEngine.postMetadataWithStatus
|
||||
400
|
||||
testEnvironment
|
||||
(Schema.trackLogicalModelCommand sourceName backendTypeMetadata missingArgsLogicalModel)
|
||||
(Schema.trackNativeQueryCommand sourceName backendTypeMetadata missingArgsNativeQuery)
|
||||
)
|
||||
[yaml|
|
||||
code: validation-failed
|
||||
@ -351,24 +351,24 @@ tests = do
|
||||
|]
|
||||
|
||||
describe "Validation succeeds" do
|
||||
it "when tracking then untracking then re-tracking a logical model" $
|
||||
it "when tracking then untracking then re-tracking a native query" $
|
||||
\testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
dividedStuffLogicalModel :: Schema.LogicalModel
|
||||
dividedStuffLogicalModel =
|
||||
(Schema.logicalModel "divided_stuff2" simpleQuery "divided_stuff")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "denominator" Schema.TInt,
|
||||
Schema.logicalModelColumn "target_date" Schema.TUTCTime
|
||||
dividedStuffNativeQuery :: Schema.NativeQuery
|
||||
dividedStuffNativeQuery =
|
||||
(Schema.nativeQuery "divided_stuff2" simpleQuery "divided_stuff")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "denominator" Schema.TInt,
|
||||
Schema.nativeQueryColumn "target_date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
Schema.trackCustomType sourceName dividedReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel sourceName dividedStuffLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery sourceName dividedStuffNativeQuery testEnvironment
|
||||
|
||||
Schema.untrackLogicalModel sourceName dividedStuffLogicalModel testEnvironment
|
||||
Schema.untrackNativeQuery sourceName dividedStuffNativeQuery testEnvironment
|
||||
|
||||
Schema.trackLogicalModel sourceName dividedStuffLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery sourceName dividedStuffNativeQuery testEnvironment
|
@ -1,7 +1,7 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
-- | Tests of the Logical Models feature.
|
||||
module Test.API.Metadata.LogicalModelsSpec (spec) where
|
||||
-- | Tests of the Native Queries feature.
|
||||
module Test.API.Metadata.NativeQueriesSpec (spec) where
|
||||
|
||||
import Control.Lens
|
||||
import Data.Aeson qualified as A
|
||||
@ -29,11 +29,11 @@ import Test.Hspec (SpecWith, describe, it)
|
||||
|
||||
-- ** Preamble
|
||||
|
||||
-- We currently don't need the table to exist in order to set up a logical model
|
||||
-- We currently don't need the table to exist in order to set up a native query
|
||||
-- stanza.
|
||||
|
||||
featureFlagForLogicalModels :: String
|
||||
featureFlagForLogicalModels = "HASURA_FF_LOGICAL_MODEL_INTERFACE"
|
||||
featureFlagForNativeQueries :: String
|
||||
featureFlagForNativeQueries = "HASURA_FF_NATIVE_QUERY_INTERFACE"
|
||||
|
||||
spec :: SpecWith GlobalTestEnvironment
|
||||
spec = do
|
||||
@ -66,7 +66,7 @@ spec = do
|
||||
}
|
||||
]
|
||||
|
||||
Fixture.hgeWithEnv [(featureFlagForLogicalModels, "True")] do
|
||||
Fixture.hgeWithEnv [(featureFlagForNativeQueries, "True")] do
|
||||
traverse_
|
||||
(Fixture.runClean fixtures)
|
||||
[ testAdminAccess,
|
||||
@ -91,8 +91,8 @@ dividedStuffReturnType :: Schema.CustomType
|
||||
dividedStuffReturnType =
|
||||
(Schema.customType "divided_stuff")
|
||||
{ Schema.customTypeColumns =
|
||||
[ (Schema.logicalModelColumn "divided" Schema.TInt)
|
||||
{ Schema.logicalModelColumnDescription = Just "a divided thing"
|
||||
[ (Schema.nativeQueryColumn "divided" Schema.TInt)
|
||||
{ Schema.nativeQueryColumnDescription = Just "a divided thing"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -103,16 +103,16 @@ testAdminAccess = do
|
||||
query = "SELECT (thing / {{denominator}})::integer AS divided FROM stuff WHERE date = {{target_date}}"
|
||||
|
||||
describe "Admin access" do
|
||||
let dividedStuffLogicalModel :: Schema.LogicalModel
|
||||
dividedStuffLogicalModel =
|
||||
(Schema.logicalModel "divided_stuff" query "divided_stuff")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "denominator" Schema.TInt,
|
||||
Schema.logicalModelColumn "target_date" Schema.TUTCTime
|
||||
let dividedStuffNativeQuery :: Schema.NativeQuery
|
||||
dividedStuffNativeQuery =
|
||||
(Schema.nativeQuery "divided_stuff" query "divided_stuff")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "denominator" Schema.TInt,
|
||||
Schema.nativeQueryColumn "target_date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
it "Fails to track a Logical Model without admin access" $
|
||||
it "Fails to track a Native Query without admin access" $
|
||||
\testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
@ -126,7 +126,7 @@ testAdminAccess = do
|
||||
testEnvironment
|
||||
[ ("X-Hasura-Role", "not-admin")
|
||||
]
|
||||
(Schema.trackLogicalModelCommand sourceName backendTypeMetadata dividedStuffLogicalModel)
|
||||
(Schema.trackNativeQueryCommand sourceName backendTypeMetadata dividedStuffNativeQuery)
|
||||
)
|
||||
[yaml|
|
||||
code: access-denied
|
||||
@ -134,7 +134,7 @@ testAdminAccess = do
|
||||
path: "$.args"
|
||||
|]
|
||||
|
||||
it "Fails to untrack a Logical Model without admin access" $
|
||||
it "Fails to untrack a Native Query without admin access" $
|
||||
\testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
@ -148,7 +148,7 @@ testAdminAccess = do
|
||||
testEnvironment
|
||||
[ ("X-Hasura-Role", "not-admin")
|
||||
]
|
||||
(Schema.untrackLogicalModelCommand sourceName backendTypeMetadata dividedStuffLogicalModel)
|
||||
(Schema.untrackNativeQueryCommand sourceName backendTypeMetadata dividedStuffNativeQuery)
|
||||
)
|
||||
[yaml|
|
||||
code: access-denied
|
||||
@ -156,12 +156,12 @@ testAdminAccess = do
|
||||
path: "$.args"
|
||||
|]
|
||||
|
||||
it "Fails to list a Logical Model without admin access" $
|
||||
it "Fails to list a Native Query without admin access" $
|
||||
\testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
backendType = BackendType.backendTypeString backendTypeMetadata
|
||||
getRequestType = backendType <> "_get_logical_model"
|
||||
getRequestType = backendType <> "_get_native_query"
|
||||
|
||||
shouldReturnYaml
|
||||
testEnvironment
|
||||
@ -195,30 +195,30 @@ testImplementation = do
|
||||
query = "SELECT (thing / {{denominator}})::integer AS divided FROM stuff WHERE date = {{target_date}}"
|
||||
|
||||
describe "Implementation" $ do
|
||||
it "Adds a simple logical model of a function with no arguments and returns a 200" $ \testEnvironment -> do
|
||||
it "Adds a simple native query of a function with no arguments and returns a 200" $ \testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
dividedStuffLogicalModel :: Schema.LogicalModel
|
||||
dividedStuffLogicalModel =
|
||||
(Schema.logicalModel "divided_stuff" simpleQuery "divided_stuff")
|
||||
{ Schema.logicalModelArguments =
|
||||
[Schema.logicalModelColumn "unused" Schema.TInt]
|
||||
dividedStuffNativeQuery :: Schema.NativeQuery
|
||||
dividedStuffNativeQuery =
|
||||
(Schema.nativeQuery "divided_stuff" simpleQuery "divided_stuff")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[Schema.nativeQueryColumn "unused" Schema.TInt]
|
||||
}
|
||||
|
||||
Schema.trackCustomType sourceName dividedStuffReturnType testEnvironment
|
||||
Schema.trackLogicalModel sourceName dividedStuffLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery sourceName dividedStuffNativeQuery testEnvironment
|
||||
|
||||
it "Adding a logical model of a function with broken SQL returns a 400" $ \testEnvironment -> do
|
||||
it "Adding a native query of a function with broken SQL returns a 400" $ \testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
brokenQuery = "SELECT * FROM dogs WHERE name = {{name"
|
||||
|
||||
brokenQueryLogicalModel :: Schema.LogicalModel
|
||||
brokenQueryLogicalModel =
|
||||
(Schema.logicalModel "divided_stuff" brokenQuery "divided_stuff")
|
||||
{ Schema.logicalModelArguments =
|
||||
[Schema.logicalModelColumn "unused" Schema.TInt]
|
||||
brokenQueryNativeQuery :: Schema.NativeQuery
|
||||
brokenQueryNativeQuery =
|
||||
(Schema.nativeQuery "divided_stuff" brokenQuery "divided_stuff")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[Schema.nativeQueryColumn "unused" Schema.TInt]
|
||||
}
|
||||
|
||||
shouldReturnYaml
|
||||
@ -226,7 +226,7 @@ testImplementation = do
|
||||
( GraphqlEngine.postMetadataWithStatus
|
||||
400
|
||||
testEnvironment
|
||||
(Schema.trackLogicalModelCommand sourceName backendTypeMetadata brokenQueryLogicalModel)
|
||||
(Schema.trackNativeQueryCommand sourceName backendTypeMetadata brokenQueryNativeQuery)
|
||||
)
|
||||
[yaml|
|
||||
code: parse-failed
|
||||
@ -234,26 +234,26 @@ testImplementation = do
|
||||
path: "$.args"
|
||||
|]
|
||||
|
||||
it "Checks for the logical model of a function" $ \testEnvironment -> do
|
||||
it "Checks for the native query of a function" $ \testEnvironment -> do
|
||||
let rootfield :: Text
|
||||
rootfield = "divided_stuff2"
|
||||
|
||||
backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
backendType = BackendType.backendTypeString backendTypeMetadata
|
||||
getRequestType = backendType <> "_get_logical_model"
|
||||
getRequestType = backendType <> "_get_native_query"
|
||||
|
||||
dividedStuffLogicalModel :: Schema.LogicalModel
|
||||
dividedStuffLogicalModel =
|
||||
(Schema.logicalModel rootfield query "divided_stuff")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "denominator" Schema.TInt,
|
||||
Schema.logicalModelColumn "target_date" Schema.TUTCTime
|
||||
dividedStuffNativeQuery :: Schema.NativeQuery
|
||||
dividedStuffNativeQuery =
|
||||
(Schema.nativeQuery rootfield query "divided_stuff")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "denominator" Schema.TInt,
|
||||
Schema.nativeQueryColumn "target_date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
Schema.trackCustomType sourceName dividedStuffReturnType testEnvironment
|
||||
Schema.trackLogicalModel sourceName dividedStuffLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery sourceName dividedStuffNativeQuery testEnvironment
|
||||
|
||||
shouldReturnYaml
|
||||
testEnvironment
|
||||
@ -278,43 +278,43 @@ testImplementation = do
|
||||
returns: divided_stuff
|
||||
|]
|
||||
|
||||
it "Drops a logical model of a function and returns a 200" $ \testEnvironment -> do
|
||||
it "Drops a native query of a function and returns a 200" $ \testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
dividedStuffLogicalModel :: Schema.LogicalModel
|
||||
dividedStuffLogicalModel =
|
||||
(Schema.logicalModel "divided_stuff" query "divided_stuff")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "denominator" Schema.TInt,
|
||||
Schema.logicalModelColumn "target_date" Schema.TUTCTime
|
||||
dividedStuffNativeQuery :: Schema.NativeQuery
|
||||
dividedStuffNativeQuery =
|
||||
(Schema.nativeQuery "divided_stuff" query "divided_stuff")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "denominator" Schema.TInt,
|
||||
Schema.nativeQueryColumn "target_date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
Schema.trackCustomType sourceName dividedStuffReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel sourceName dividedStuffLogicalModel testEnvironment
|
||||
Schema.untrackLogicalModel sourceName dividedStuffLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery sourceName dividedStuffNativeQuery testEnvironment
|
||||
Schema.untrackNativeQuery sourceName dividedStuffNativeQuery testEnvironment
|
||||
|
||||
it "Checks the logical model of a function can be deleted" $ \testEnvironment -> do
|
||||
it "Checks the native query of a function can be deleted" $ \testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
backendType = BackendType.backendTypeString backendTypeMetadata
|
||||
getRequestType = backendType <> "_get_logical_model"
|
||||
getRequestType = backendType <> "_get_native_query"
|
||||
|
||||
dividedStuffLogicalModel :: Schema.LogicalModel
|
||||
dividedStuffLogicalModel =
|
||||
(Schema.logicalModel "divided_stuff" query "divided_stuff")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "denominator" Schema.TInt,
|
||||
Schema.logicalModelColumn "target_date" Schema.TUTCTime
|
||||
dividedStuffNativeQuery :: Schema.NativeQuery
|
||||
dividedStuffNativeQuery =
|
||||
(Schema.nativeQuery "divided_stuff" query "divided_stuff")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "denominator" Schema.TInt,
|
||||
Schema.nativeQueryColumn "target_date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
Schema.trackCustomType sourceName dividedStuffReturnType testEnvironment
|
||||
Schema.trackLogicalModel sourceName dividedStuffLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery sourceName dividedStuffNativeQuery testEnvironment
|
||||
|
||||
Schema.untrackLogicalModel sourceName dividedStuffLogicalModel testEnvironment
|
||||
Schema.untrackNativeQuery sourceName dividedStuffNativeQuery testEnvironment
|
||||
|
||||
shouldReturnYaml
|
||||
testEnvironment
|
||||
@ -330,23 +330,23 @@ testImplementation = do
|
||||
[]
|
||||
|]
|
||||
|
||||
it "Fails to add a logical model with a non-existent return type" $ \testEnvironment -> do
|
||||
it "Fails to add a native query with a non-existent return type" $ \testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
dividedStuffLogicalModel :: Schema.LogicalModel
|
||||
dividedStuffLogicalModel =
|
||||
(Schema.logicalModel "divided_stuff" query "bad_return_type")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "denominator" Schema.TInt,
|
||||
Schema.logicalModelColumn "target_date" Schema.TUTCTime
|
||||
dividedStuffNativeQuery :: Schema.NativeQuery
|
||||
dividedStuffNativeQuery =
|
||||
(Schema.nativeQuery "divided_stuff" query "bad_return_type")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "denominator" Schema.TInt,
|
||||
Schema.nativeQueryColumn "target_date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
shouldReturnYaml
|
||||
testEnvironment
|
||||
( GraphqlEngine.postMetadataWithStatus 400 testEnvironment $
|
||||
Schema.trackLogicalModelCommand sourceName backendTypeMetadata dividedStuffLogicalModel
|
||||
Schema.trackNativeQueryCommand sourceName backendTypeMetadata dividedStuffNativeQuery
|
||||
)
|
||||
[yaml|
|
||||
code: not-found
|
||||
@ -354,25 +354,25 @@ testImplementation = do
|
||||
path: $.args
|
||||
|]
|
||||
|
||||
it "Adds two logical models with the same return type" $ \testEnvironment -> do
|
||||
it "Adds two native queries with the same return type" $ \testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
logicalModelOne :: Schema.LogicalModel
|
||||
logicalModelOne =
|
||||
(Schema.logicalModel "first" query "divided_stuff")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "denominator" Schema.TInt,
|
||||
Schema.logicalModelColumn "target_date" Schema.TUTCTime
|
||||
nativeQueryOne :: Schema.NativeQuery
|
||||
nativeQueryOne =
|
||||
(Schema.nativeQuery "first" query "divided_stuff")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "denominator" Schema.TInt,
|
||||
Schema.nativeQueryColumn "target_date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
logicalModelTwo :: Schema.LogicalModel
|
||||
logicalModelTwo =
|
||||
(Schema.logicalModel "second" query "divided_stuff")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "denominator" Schema.TInt,
|
||||
Schema.logicalModelColumn "target_date" Schema.TUTCTime
|
||||
nativeQueryTwo :: Schema.NativeQuery
|
||||
nativeQueryTwo =
|
||||
(Schema.nativeQuery "second" query "divided_stuff")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "denominator" Schema.TInt,
|
||||
Schema.nativeQueryColumn "target_date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
@ -381,14 +381,14 @@ testImplementation = do
|
||||
shouldReturnYaml
|
||||
testEnvironment
|
||||
( GraphqlEngine.postMetadata testEnvironment $
|
||||
Schema.trackLogicalModelCommand sourceName backendTypeMetadata logicalModelOne
|
||||
Schema.trackNativeQueryCommand sourceName backendTypeMetadata nativeQueryOne
|
||||
)
|
||||
[yaml| message: success |]
|
||||
|
||||
shouldReturnYaml
|
||||
testEnvironment
|
||||
( GraphqlEngine.postMetadata testEnvironment $
|
||||
Schema.trackLogicalModelCommand sourceName backendTypeMetadata logicalModelTwo
|
||||
Schema.trackNativeQueryCommand sourceName backendTypeMetadata nativeQueryTwo
|
||||
)
|
||||
[yaml| message: success |]
|
||||
|
||||
@ -396,15 +396,15 @@ testImplementation = do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
dividedStuffLogicalModel :: Schema.LogicalModel
|
||||
dividedStuffLogicalModel =
|
||||
(Schema.logicalModel "divided_stuff" simpleQuery "divided_stuff")
|
||||
{ Schema.logicalModelArguments =
|
||||
[Schema.logicalModelColumn "unused" Schema.TInt]
|
||||
dividedStuffNativeQuery :: Schema.NativeQuery
|
||||
dividedStuffNativeQuery =
|
||||
(Schema.nativeQuery "divided_stuff" simpleQuery "divided_stuff")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[Schema.nativeQueryColumn "unused" Schema.TInt]
|
||||
}
|
||||
|
||||
Schema.trackCustomType sourceName dividedStuffReturnType testEnvironment
|
||||
Schema.trackLogicalModel sourceName dividedStuffLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery sourceName dividedStuffNativeQuery testEnvironment
|
||||
|
||||
metadata <-
|
||||
GraphqlEngine.postMetadata
|
||||
@ -445,19 +445,19 @@ testImplementation = do
|
||||
code: SELECT (thing / 2)::integer AS divided FROM stuff
|
||||
returns: divided_stuff
|
||||
root_field_name: divided_stuff
|
||||
name: logical_model divided_stuff in source #{sourceName}
|
||||
name: native_query divided_stuff in source #{sourceName}
|
||||
reason: "Inconsistent object: The custom return type divided_stuff could not be found"
|
||||
type: logical_model
|
||||
type: native_query
|
||||
path: $.args
|
||||
|]
|
||||
|
||||
metadataHandlingWhenDisabledSpec :: SpecWith GlobalTestEnvironment
|
||||
metadataHandlingWhenDisabledSpec = do
|
||||
describe "When logical models are enabled" do
|
||||
describe "When native queries are enabled" do
|
||||
withHge
|
||||
( emptyHgeConfig
|
||||
{ hgeConfigEnvironmentVars =
|
||||
[ (featureFlagForLogicalModels, "True")
|
||||
[ (featureFlagForNativeQueries, "True")
|
||||
]
|
||||
}
|
||||
)
|
||||
@ -468,7 +468,7 @@ metadataHandlingWhenDisabledSpec = do
|
||||
_ <- hgePost env 200 "/v1/metadata" [] command
|
||||
|
||||
currentMetadata <- export_metadata env
|
||||
actual <- replace_metadata env (metadataWithLogicalModel currentMetadata)
|
||||
actual <- replace_metadata env (metadataWithNativeQuery currentMetadata)
|
||||
|
||||
actual
|
||||
`shouldBeYaml` [yaml|
|
||||
@ -481,7 +481,7 @@ metadataHandlingWhenDisabledSpec = do
|
||||
_ <- hgePost env 200 "/v1/metadata" [] command
|
||||
|
||||
currentMetadata <- export_metadata env
|
||||
_res <- replace_metadata env (metadataWithLogicalModel currentMetadata)
|
||||
_res <- replace_metadata env (metadataWithNativeQuery currentMetadata)
|
||||
|
||||
let expected =
|
||||
[yaml|
|
||||
@ -493,12 +493,12 @@ metadataHandlingWhenDisabledSpec = do
|
||||
actual <- hgePostGraphql env queryTypesIntrospection
|
||||
actual `shouldBeYaml` expected
|
||||
|
||||
describe "When logical models are disabled" do
|
||||
describe "When native queries are disabled" do
|
||||
withHge emptyHgeConfig $ do
|
||||
withPostgresSource "default" $ do
|
||||
it "They do not appear in the schema" $ \env -> do
|
||||
currentMetadata <- export_metadata env
|
||||
_res <- replace_metadata env (metadataWithLogicalModel currentMetadata)
|
||||
_res <- replace_metadata env (metadataWithNativeQuery currentMetadata)
|
||||
|
||||
let expected =
|
||||
[yaml|
|
||||
@ -509,7 +509,7 @@ metadataHandlingWhenDisabledSpec = do
|
||||
actual <- hgePostGraphql env queryTypesIntrospection
|
||||
actual `shouldBeYaml` expected
|
||||
where
|
||||
logicalModelsMetadata =
|
||||
nativeQueriesMetadata =
|
||||
[yaml|
|
||||
arguments:
|
||||
divided:
|
||||
@ -520,13 +520,13 @@ metadataHandlingWhenDisabledSpec = do
|
||||
root_field_name: divided_stuff
|
||||
|]
|
||||
|
||||
metadataWithLogicalModel :: A.Value -> A.Value
|
||||
metadataWithLogicalModel currentMetadata =
|
||||
metadataWithNativeQuery :: A.Value -> A.Value
|
||||
metadataWithNativeQuery currentMetadata =
|
||||
currentMetadata
|
||||
& key "sources"
|
||||
. nth 0
|
||||
. atKey "logical_models"
|
||||
.~ Just [yaml| - *logicalModelsMetadata |]
|
||||
. atKey "native_queries"
|
||||
.~ Just [yaml| - *nativeQueriesMetadata |]
|
||||
|
||||
queryTypesIntrospection :: A.Value
|
||||
queryTypesIntrospection =
|
@ -1,7 +1,7 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
-- | Access to the SQL
|
||||
module Test.Databases.BigQuery.LogicalModelsSpec (spec) where
|
||||
module Test.Databases.BigQuery.NativeQueriesSpec (spec) where
|
||||
|
||||
import Data.Aeson (Value)
|
||||
import Data.List.NonEmpty qualified as NE
|
||||
@ -24,12 +24,12 @@ import Test.Hspec (SpecWith, describe, it)
|
||||
|
||||
-- ** Preamble
|
||||
|
||||
featureFlagForLogicalModels :: String
|
||||
featureFlagForLogicalModels = "HASURA_FF_LOGICAL_MODEL_INTERFACE"
|
||||
featureFlagForNativeQueries :: String
|
||||
featureFlagForNativeQueries = "HASURA_FF_NATIVE_QUERY_INTERFACE"
|
||||
|
||||
spec :: SpecWith GlobalTestEnvironment
|
||||
spec =
|
||||
Fixture.hgeWithEnv [(featureFlagForLogicalModels, "True")] $
|
||||
Fixture.hgeWithEnv [(featureFlagForNativeQueries, "True")] $
|
||||
Fixture.runClean -- re-run fixture setup on every test
|
||||
( NE.fromList
|
||||
[ (Fixture.fixture $ Fixture.Backend BigQuery.backendTypeMetadata)
|
||||
@ -75,16 +75,16 @@ tests = do
|
||||
let query :: Text
|
||||
query = "SELECT * FROM UNNEST([STRUCT('hello' as one, 'world' as two), ('welcome', 'friend')])"
|
||||
|
||||
helloWorldLogicalModel :: Schema.LogicalModel
|
||||
helloWorldLogicalModel =
|
||||
(Schema.logicalModel "hello_world_function" query "hello_world_function")
|
||||
helloWorldNativeQuery :: Schema.NativeQuery
|
||||
helloWorldNativeQuery =
|
||||
(Schema.nativeQuery "hello_world_function" query "hello_world_function")
|
||||
|
||||
helloWorldReturnType :: Schema.CustomType
|
||||
helloWorldReturnType =
|
||||
(Schema.customType "hello_world_function")
|
||||
{ Schema.customTypeColumns =
|
||||
[ Schema.logicalModelColumn "one" Schema.TStr,
|
||||
Schema.logicalModelColumn "two" Schema.TStr
|
||||
[ Schema.nativeQueryColumn "one" Schema.TStr,
|
||||
Schema.nativeQueryColumn "two" Schema.TStr
|
||||
]
|
||||
}
|
||||
|
||||
@ -92,14 +92,14 @@ tests = do
|
||||
articleWithExcerptReturnType =
|
||||
(Schema.customType "article_with_excerpt")
|
||||
{ Schema.customTypeColumns =
|
||||
[ Schema.logicalModelColumn "id" Schema.TInt,
|
||||
Schema.logicalModelColumn "title" Schema.TStr,
|
||||
Schema.logicalModelColumn "excerpt" Schema.TStr,
|
||||
Schema.logicalModelColumn "date" Schema.TUTCTime
|
||||
[ Schema.nativeQueryColumn "id" Schema.TInt,
|
||||
Schema.nativeQueryColumn "title" Schema.TStr,
|
||||
Schema.nativeQueryColumn "excerpt" Schema.TStr,
|
||||
Schema.nativeQueryColumn "date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
describe "Testing Logical Models" $ do
|
||||
describe "Testing Native Queries" $ do
|
||||
it "Descriptions and nullability appear in the schema" $ \testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
@ -110,27 +110,27 @@ tests = do
|
||||
descriptionsAndNullableReturnType =
|
||||
(Schema.customType "divided_stuff")
|
||||
{ Schema.customTypeColumns =
|
||||
[ (Schema.logicalModelColumn "divided" Schema.TInt)
|
||||
{ Schema.logicalModelColumnDescription = Just "A divided thing"
|
||||
[ (Schema.nativeQueryColumn "divided" Schema.TInt)
|
||||
{ Schema.nativeQueryColumnDescription = Just "A divided thing"
|
||||
},
|
||||
(Schema.logicalModelColumn "something_nullable" Schema.TInt)
|
||||
{ Schema.logicalModelColumnDescription = Just "Something nullable",
|
||||
Schema.logicalModelColumnNullable = True
|
||||
(Schema.nativeQueryColumn "something_nullable" Schema.TInt)
|
||||
{ Schema.nativeQueryColumnDescription = Just "Something nullable",
|
||||
Schema.nativeQueryColumnNullable = True
|
||||
}
|
||||
],
|
||||
Schema.customTypeDescription = Just "Return type description"
|
||||
}
|
||||
|
||||
descriptionsAndNullableLogicalModel :: Schema.LogicalModel
|
||||
descriptionsAndNullableLogicalModel =
|
||||
(Schema.logicalModel "divided_stuff" nullableQuery "divided_stuff")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "unused" Schema.TInt
|
||||
descriptionsAndNullableNativeQuery :: Schema.NativeQuery
|
||||
descriptionsAndNullableNativeQuery =
|
||||
(Schema.nativeQuery "divided_stuff" nullableQuery "divided_stuff")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "unused" Schema.TInt
|
||||
]
|
||||
}
|
||||
|
||||
Schema.trackCustomType sourceName descriptionsAndNullableReturnType testEnvironment
|
||||
Schema.trackLogicalModel sourceName descriptionsAndNullableLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery sourceName descriptionsAndNullableNativeQuery testEnvironment
|
||||
|
||||
let queryTypesIntrospection :: Value
|
||||
queryTypesIntrospection =
|
||||
@ -197,7 +197,7 @@ tests = do
|
||||
source = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
Schema.trackLogicalModel source helloWorldLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery source helloWorldNativeQuery testEnvironment
|
||||
|
||||
let expected =
|
||||
[yaml|
|
||||
@ -230,7 +230,7 @@ tests = do
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source helloWorldLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery source helloWorldNativeQuery testEnvironment
|
||||
|
||||
let expected =
|
||||
[yaml|
|
||||
@ -262,13 +262,13 @@ tests = do
|
||||
queryWithDuplicates :: Text
|
||||
queryWithDuplicates = "SELECT * FROM UNNEST([STRUCT('hello' as one, 'world' as two), ('hello', 'friend')])"
|
||||
|
||||
helloWorldLogicalModelWithDuplicates :: Schema.LogicalModel
|
||||
helloWorldLogicalModelWithDuplicates =
|
||||
(Schema.logicalModel "hello_world_function" queryWithDuplicates "hello_world_function")
|
||||
helloWorldNativeQueryWithDuplicates :: Schema.NativeQuery
|
||||
helloWorldNativeQueryWithDuplicates =
|
||||
(Schema.nativeQuery "hello_world_function" queryWithDuplicates "hello_world_function")
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source helloWorldLogicalModelWithDuplicates testEnvironment
|
||||
Schema.trackNativeQuery source helloWorldNativeQueryWithDuplicates testEnvironment
|
||||
|
||||
let expected =
|
||||
[yaml|
|
||||
@ -302,7 +302,7 @@ tests = do
|
||||
|
||||
Schema.trackCustomType sourceName helloWorldReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel sourceName helloWorldLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery sourceName helloWorldNativeQuery testEnvironment
|
||||
|
||||
let expected =
|
||||
[yaml|
|
||||
@ -331,17 +331,17 @@ tests = do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
source = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
helloWorldLogicalModelWithDummyArgument :: Schema.LogicalModel
|
||||
helloWorldLogicalModelWithDummyArgument =
|
||||
(Schema.logicalModel "hello_world_function_with_dummy" query "hello_world_function")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "dummy" Schema.TStr
|
||||
helloWorldNativeQueryWithDummyArgument :: Schema.NativeQuery
|
||||
helloWorldNativeQueryWithDummyArgument =
|
||||
(Schema.nativeQuery "hello_world_function_with_dummy" query "hello_world_function")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "dummy" Schema.TStr
|
||||
]
|
||||
}
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source helloWorldLogicalModelWithDummyArgument testEnvironment
|
||||
Schema.trackNativeQuery source helloWorldNativeQueryWithDummyArgument testEnvironment
|
||||
|
||||
let expected =
|
||||
[yaml|
|
||||
@ -372,13 +372,13 @@ tests = do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
source = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
helloCommentLogicalModel :: Schema.LogicalModel
|
||||
helloCommentLogicalModel =
|
||||
(Schema.logicalModel "hello_comment_function" spicyQuery "hello_world_function")
|
||||
helloCommentNativeQuery :: Schema.NativeQuery
|
||||
helloCommentNativeQuery =
|
||||
(Schema.nativeQuery "hello_comment_function" spicyQuery "hello_world_function")
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source helloCommentLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery source helloCommentNativeQuery testEnvironment
|
||||
|
||||
let expected =
|
||||
[yaml|
|
||||
@ -411,13 +411,13 @@ tests = do
|
||||
backendType = BackendType.backendTypeString backendTypeMetadata
|
||||
createPermRequestType = backendType <> "_create_custom_return_type_select_permission"
|
||||
|
||||
helloWorldPermLogicalModel :: Schema.LogicalModel
|
||||
helloWorldPermLogicalModel =
|
||||
(Schema.logicalModel "hello_world_perms" query "hello_world_function")
|
||||
helloWorldPermNativeQuery :: Schema.NativeQuery
|
||||
helloWorldPermNativeQuery =
|
||||
(Schema.nativeQuery "hello_world_perms" query "hello_world_function")
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source helloWorldPermLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery source helloWorldPermNativeQuery testEnvironment
|
||||
|
||||
shouldReturnYaml
|
||||
testEnvironment
|
||||
@ -470,13 +470,13 @@ tests = do
|
||||
backendType = BackendType.backendTypeString backendTypeMetadata
|
||||
createPermRequestType = backendType <> "_create_custom_return_type_select_permission"
|
||||
|
||||
helloWorldPermLogicalModel :: Schema.LogicalModel
|
||||
helloWorldPermLogicalModel =
|
||||
(Schema.logicalModel "hello_world_perms" query "hello_world_function")
|
||||
helloWorldPermNativeQuery :: Schema.NativeQuery
|
||||
helloWorldPermNativeQuery =
|
||||
(Schema.nativeQuery "hello_world_perms" query "hello_world_function")
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source helloWorldPermLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery source helloWorldPermNativeQuery testEnvironment
|
||||
|
||||
shouldReturnYaml
|
||||
testEnvironment
|
||||
@ -530,13 +530,13 @@ tests = do
|
||||
backendType = BackendType.backendTypeString backendTypeMetadata
|
||||
createPermRequestType = backendType <> "_create_custom_return_type_select_permission"
|
||||
|
||||
helloWorldPermLogicalModel :: Schema.LogicalModel
|
||||
helloWorldPermLogicalModel =
|
||||
(Schema.logicalModel "hello_world_perms" query "hello_world_function")
|
||||
helloWorldPermNativeQuery :: Schema.NativeQuery
|
||||
helloWorldPermNativeQuery =
|
||||
(Schema.nativeQuery "hello_world_perms" query "hello_world_function")
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source helloWorldPermLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery source helloWorldPermNativeQuery testEnvironment
|
||||
|
||||
shouldReturnYaml
|
||||
testEnvironment
|
||||
@ -600,7 +600,7 @@ tests = do
|
||||
from #{unSchemaName schemaName}.article
|
||||
|]
|
||||
|
||||
describe "Testing Logical Models" $ do
|
||||
describe "Testing Native Queries" $ do
|
||||
it "Runs a simple query that takes one parameter and uses it multiple times" $ \testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
source = BackendType.backendSourceName backendTypeMetadata
|
||||
@ -608,17 +608,17 @@ tests = do
|
||||
schemaName :: Schema.SchemaName
|
||||
schemaName = Schema.getSchemaName testEnvironment
|
||||
|
||||
articleWithExcerptLogicalModel :: Schema.LogicalModel
|
||||
articleWithExcerptLogicalModel =
|
||||
(Schema.logicalModel "article_with_excerpt" (articleQuery schemaName) "article_with_excerpt")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "length" Schema.TInt
|
||||
articleWithExcerptNativeQuery :: Schema.NativeQuery
|
||||
articleWithExcerptNativeQuery =
|
||||
(Schema.nativeQuery "article_with_excerpt" (articleQuery schemaName) "article_with_excerpt")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "length" Schema.TInt
|
||||
]
|
||||
}
|
||||
|
||||
Schema.trackCustomType source articleWithExcerptReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source articleWithExcerptLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery source articleWithExcerptNativeQuery testEnvironment
|
||||
|
||||
let actual :: IO Value
|
||||
actual =
|
||||
@ -654,24 +654,24 @@ tests = do
|
||||
schemaName :: Schema.SchemaName
|
||||
schemaName = Schema.getSchemaName testEnvironment
|
||||
|
||||
mkArticleWithExcerptLogicalModel :: Text -> Schema.LogicalModel
|
||||
mkArticleWithExcerptLogicalModel name =
|
||||
(Schema.logicalModel name (articleQuery schemaName) "article_with_excerpt")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "length" Schema.TInt
|
||||
mkArticleWithExcerptNativeQuery :: Text -> Schema.NativeQuery
|
||||
mkArticleWithExcerptNativeQuery name =
|
||||
(Schema.nativeQuery name (articleQuery schemaName) "article_with_excerpt")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "length" Schema.TInt
|
||||
]
|
||||
}
|
||||
|
||||
Schema.trackCustomType source articleWithExcerptReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel
|
||||
Schema.trackNativeQuery
|
||||
source
|
||||
(mkArticleWithExcerptLogicalModel "article_with_excerpt_1")
|
||||
(mkArticleWithExcerptNativeQuery "article_with_excerpt_1")
|
||||
testEnvironment
|
||||
|
||||
Schema.trackLogicalModel
|
||||
Schema.trackNativeQuery
|
||||
source
|
||||
(mkArticleWithExcerptLogicalModel "article_with_excerpt_2")
|
||||
(mkArticleWithExcerptNativeQuery "article_with_excerpt_2")
|
||||
testEnvironment
|
||||
|
||||
let actual :: IO Value
|
||||
@ -707,17 +707,17 @@ tests = do
|
||||
schemaName :: Schema.SchemaName
|
||||
schemaName = Schema.getSchemaName testEnvironment
|
||||
|
||||
articleWithExcerptLogicalModel :: Schema.LogicalModel
|
||||
articleWithExcerptLogicalModel =
|
||||
(Schema.logicalModel "article_with_excerpt" (articleQuery schemaName) "article_with_excerpt")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "length" Schema.TInt
|
||||
articleWithExcerptNativeQuery :: Schema.NativeQuery
|
||||
articleWithExcerptNativeQuery =
|
||||
(Schema.nativeQuery "article_with_excerpt" (articleQuery schemaName) "article_with_excerpt")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "length" Schema.TInt
|
||||
]
|
||||
}
|
||||
|
||||
Schema.trackCustomType source articleWithExcerptReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source articleWithExcerptLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery source articleWithExcerptNativeQuery testEnvironment
|
||||
|
||||
let actual :: IO Value
|
||||
actual =
|
||||
@ -752,17 +752,17 @@ tests = do
|
||||
schemaName :: Schema.SchemaName
|
||||
schemaName = Schema.getSchemaName testEnvironment
|
||||
|
||||
articleWithExcerptLogicalModel :: Schema.LogicalModel
|
||||
articleWithExcerptLogicalModel =
|
||||
(Schema.logicalModel "article_with_excerpt" (articleQuery schemaName) "article_with_excerpt")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "length" Schema.TInt
|
||||
articleWithExcerptNativeQuery :: Schema.NativeQuery
|
||||
articleWithExcerptNativeQuery =
|
||||
(Schema.nativeQuery "article_with_excerpt" (articleQuery schemaName) "article_with_excerpt")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "length" Schema.TInt
|
||||
]
|
||||
}
|
||||
|
||||
Schema.trackCustomType source articleWithExcerptReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source articleWithExcerptLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery source articleWithExcerptNativeQuery testEnvironment
|
||||
|
||||
let variables =
|
||||
[yaml|
|
@ -1,7 +1,7 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
-- | Access to the SQL
|
||||
module Test.Databases.Postgres.LogicalModelsSpec (spec) where
|
||||
module Test.Databases.Postgres.NativeQueriesSpec (spec) where
|
||||
|
||||
import Data.Aeson (Value)
|
||||
import Data.List.NonEmpty qualified as NE
|
||||
@ -25,12 +25,12 @@ import Test.Hspec (SpecWith, describe, it)
|
||||
|
||||
-- ** Preamble
|
||||
|
||||
featureFlagForLogicalModels :: String
|
||||
featureFlagForLogicalModels = "HASURA_FF_LOGICAL_MODEL_INTERFACE"
|
||||
featureFlagForNativeQueries :: String
|
||||
featureFlagForNativeQueries = "HASURA_FF_NATIVE_QUERY_INTERFACE"
|
||||
|
||||
spec :: SpecWith GlobalTestEnvironment
|
||||
spec =
|
||||
Fixture.hgeWithEnv [(featureFlagForLogicalModels, "True")] $
|
||||
Fixture.hgeWithEnv [(featureFlagForNativeQueries, "True")] $
|
||||
Fixture.runClean -- re-run fixture setup on every test
|
||||
( NE.fromList
|
||||
[ (Fixture.fixture $ Fixture.Backend Postgres.backendTypeMetadata)
|
||||
@ -87,23 +87,23 @@ tests = do
|
||||
from article
|
||||
|]
|
||||
|
||||
describe "Testing Logical Models" $ do
|
||||
describe "Testing Native Queries" $ do
|
||||
let articleWithExcerptReturnType :: Schema.CustomType
|
||||
articleWithExcerptReturnType =
|
||||
(Schema.customType "article_with_excerpt")
|
||||
{ Schema.customTypeColumns =
|
||||
[ Schema.logicalModelColumn "id" Schema.TInt,
|
||||
Schema.logicalModelColumn "title" Schema.TStr,
|
||||
Schema.logicalModelColumn "excerpt" Schema.TStr,
|
||||
Schema.logicalModelColumn "date" Schema.TUTCTime
|
||||
[ Schema.nativeQueryColumn "id" Schema.TInt,
|
||||
Schema.nativeQueryColumn "title" Schema.TStr,
|
||||
Schema.nativeQueryColumn "excerpt" Schema.TStr,
|
||||
Schema.nativeQueryColumn "date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
mkArticleWithExcerptLogicalModel :: Text -> Schema.LogicalModel
|
||||
mkArticleWithExcerptLogicalModel name =
|
||||
(Schema.logicalModel name articleQuery "article_with_excerpt")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "length" Schema.TInt
|
||||
mkArticleWithExcerptNativeQuery :: Text -> Schema.NativeQuery
|
||||
mkArticleWithExcerptNativeQuery name =
|
||||
(Schema.nativeQuery name articleQuery "article_with_excerpt")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "length" Schema.TInt
|
||||
]
|
||||
}
|
||||
|
||||
@ -113,9 +113,9 @@ tests = do
|
||||
|
||||
Schema.trackCustomType source articleWithExcerptReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel
|
||||
Schema.trackNativeQuery
|
||||
source
|
||||
(mkArticleWithExcerptLogicalModel "article_with_excerpt")
|
||||
(mkArticleWithExcerptNativeQuery "article_with_excerpt")
|
||||
testEnvironment
|
||||
|
||||
let actual :: IO Value
|
||||
@ -151,14 +151,14 @@ tests = do
|
||||
|
||||
Schema.trackCustomType source articleWithExcerptReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel
|
||||
Schema.trackNativeQuery
|
||||
source
|
||||
(mkArticleWithExcerptLogicalModel "article_with_excerpt_1")
|
||||
(mkArticleWithExcerptNativeQuery "article_with_excerpt_1")
|
||||
testEnvironment
|
||||
|
||||
Schema.trackLogicalModel
|
||||
Schema.trackNativeQuery
|
||||
source
|
||||
(mkArticleWithExcerptLogicalModel "article_with_excerpt_2")
|
||||
(mkArticleWithExcerptNativeQuery "article_with_excerpt_2")
|
||||
testEnvironment
|
||||
|
||||
let actual :: IO Value
|
||||
@ -193,9 +193,9 @@ tests = do
|
||||
|
||||
Schema.trackCustomType source articleWithExcerptReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel
|
||||
Schema.trackNativeQuery
|
||||
source
|
||||
(mkArticleWithExcerptLogicalModel "article_with_excerpt")
|
||||
(mkArticleWithExcerptNativeQuery "article_with_excerpt")
|
||||
testEnvironment
|
||||
|
||||
let actual :: IO Value
|
||||
@ -230,9 +230,9 @@ tests = do
|
||||
|
||||
Schema.trackCustomType source articleWithExcerptReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel
|
||||
Schema.trackNativeQuery
|
||||
source
|
||||
(mkArticleWithExcerptLogicalModel "article_with_excerpt")
|
||||
(mkArticleWithExcerptNativeQuery "article_with_excerpt")
|
||||
testEnvironment
|
||||
|
||||
let variables =
|
||||
@ -273,18 +273,18 @@ tests = do
|
||||
helloWorldReturnType =
|
||||
(Schema.customType "hello_world_function")
|
||||
{ Schema.customTypeColumns =
|
||||
[ Schema.logicalModelColumn "one" Schema.TStr,
|
||||
Schema.logicalModelColumn "two" Schema.TStr
|
||||
[ Schema.nativeQueryColumn "one" Schema.TStr,
|
||||
Schema.nativeQueryColumn "two" Schema.TStr
|
||||
]
|
||||
}
|
||||
|
||||
helloWorldLogicalModelWithDuplicates :: Schema.LogicalModel
|
||||
helloWorldLogicalModelWithDuplicates =
|
||||
(Schema.logicalModel "hello_world_function" queryWithDuplicates "hello_world_function")
|
||||
helloWorldNativeQueryWithDuplicates :: Schema.NativeQuery
|
||||
helloWorldNativeQueryWithDuplicates =
|
||||
(Schema.nativeQuery "hello_world_function" queryWithDuplicates "hello_world_function")
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source helloWorldLogicalModelWithDuplicates testEnvironment
|
||||
Schema.trackNativeQuery source helloWorldNativeQueryWithDuplicates testEnvironment
|
||||
|
||||
let expected =
|
||||
[yaml|
|
@ -1,7 +1,7 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
-- | Access to the SQL
|
||||
module Test.Databases.SQLServer.LogicalModelsSpec (spec) where
|
||||
module Test.Databases.SQLServer.NativeQueriesSpec (spec) where
|
||||
|
||||
import Data.Aeson (Value)
|
||||
import Data.List.NonEmpty qualified as NE
|
||||
@ -22,12 +22,12 @@ import Test.Hspec (SpecWith, describe, it)
|
||||
|
||||
-- ** Preamble
|
||||
|
||||
featureFlagForLogicalModels :: String
|
||||
featureFlagForLogicalModels = "HASURA_FF_LOGICAL_MODEL_INTERFACE"
|
||||
featureFlagForNativeQueries :: String
|
||||
featureFlagForNativeQueries = "HASURA_FF_NATIVE_QUERY_INTERFACE"
|
||||
|
||||
spec :: SpecWith GlobalTestEnvironment
|
||||
spec =
|
||||
Fixture.hgeWithEnv [(featureFlagForLogicalModels, "True")] $
|
||||
Fixture.hgeWithEnv [(featureFlagForNativeQueries, "True")] $
|
||||
Fixture.runClean -- re-run fixture setup on every test
|
||||
( NE.fromList
|
||||
[ (Fixture.fixture $ Fixture.Backend Sqlserver.backendTypeMetadata)
|
||||
@ -70,22 +70,22 @@ tests = do
|
||||
articleWithExcerptReturnType =
|
||||
(Schema.customType "article_with_excerpt")
|
||||
{ Schema.customTypeColumns =
|
||||
[ Schema.logicalModelColumn "id" Schema.TInt,
|
||||
Schema.logicalModelColumn "title" Schema.TStr,
|
||||
Schema.logicalModelColumn "excerpt" Schema.TStr,
|
||||
Schema.logicalModelColumn "date" Schema.TUTCTime
|
||||
[ Schema.nativeQueryColumn "id" Schema.TInt,
|
||||
Schema.nativeQueryColumn "title" Schema.TStr,
|
||||
Schema.nativeQueryColumn "excerpt" Schema.TStr,
|
||||
Schema.nativeQueryColumn "date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
articleWithExcerptLogicalModel :: Text -> Schema.SchemaName -> Schema.LogicalModel
|
||||
articleWithExcerptLogicalModel name schemaName =
|
||||
(Schema.logicalModel name (articleQuery schemaName) "article_with_excerpt")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "length" Schema.TInt
|
||||
articleWithExcerptNativeQuery :: Text -> Schema.SchemaName -> Schema.NativeQuery
|
||||
articleWithExcerptNativeQuery name schemaName =
|
||||
(Schema.nativeQuery name (articleQuery schemaName) "article_with_excerpt")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "length" Schema.TInt
|
||||
]
|
||||
}
|
||||
|
||||
describe "Testing Logical Models" $ do
|
||||
describe "Testing Native Queries" $ do
|
||||
it "Runs a simple query that takes one parameter and uses it multiple times" $ \testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
source = BackendType.backendSourceName backendTypeMetadata
|
||||
@ -93,7 +93,7 @@ tests = do
|
||||
|
||||
Schema.trackCustomType source articleWithExcerptReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source (articleWithExcerptLogicalModel "article_with_excerpt" schemaName) testEnvironment
|
||||
Schema.trackNativeQuery source (articleWithExcerptNativeQuery "article_with_excerpt" schemaName) testEnvironment
|
||||
|
||||
let actual :: IO Value
|
||||
actual =
|
||||
@ -129,14 +129,14 @@ tests = do
|
||||
|
||||
Schema.trackCustomType source articleWithExcerptReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel
|
||||
Schema.trackNativeQuery
|
||||
source
|
||||
(articleWithExcerptLogicalModel "article_with_excerpt_1" schemaName)
|
||||
(articleWithExcerptNativeQuery "article_with_excerpt_1" schemaName)
|
||||
testEnvironment
|
||||
|
||||
Schema.trackLogicalModel
|
||||
Schema.trackNativeQuery
|
||||
source
|
||||
(articleWithExcerptLogicalModel "article_with_excerpt_2" schemaName)
|
||||
(articleWithExcerptNativeQuery "article_with_excerpt_2" schemaName)
|
||||
testEnvironment
|
||||
|
||||
let actual :: IO Value
|
||||
@ -172,7 +172,7 @@ tests = do
|
||||
|
||||
Schema.trackCustomType source articleWithExcerptReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source (articleWithExcerptLogicalModel "article_with_excerpt" schemaName) testEnvironment
|
||||
Schema.trackNativeQuery source (articleWithExcerptNativeQuery "article_with_excerpt" schemaName) testEnvironment
|
||||
|
||||
let actual :: IO Value
|
||||
actual =
|
||||
@ -207,7 +207,7 @@ tests = do
|
||||
|
||||
Schema.trackCustomType source articleWithExcerptReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source (articleWithExcerptLogicalModel "article_with_excerpt" schemaName) testEnvironment
|
||||
Schema.trackNativeQuery source (articleWithExcerptNativeQuery "article_with_excerpt" schemaName) testEnvironment
|
||||
|
||||
let variables =
|
||||
[yaml|
|
||||
@ -246,19 +246,19 @@ tests = do
|
||||
storedProcedureReturnType =
|
||||
(Schema.customType "stored_procedure")
|
||||
{ Schema.customTypeColumns =
|
||||
[ Schema.logicalModelColumn "database_name" Schema.TStr,
|
||||
Schema.logicalModelColumn "database_size" Schema.TInt,
|
||||
Schema.logicalModelColumn "remarks" Schema.TStr
|
||||
[ Schema.nativeQueryColumn "database_name" Schema.TStr,
|
||||
Schema.nativeQueryColumn "database_size" Schema.TInt,
|
||||
Schema.nativeQueryColumn "remarks" Schema.TStr
|
||||
]
|
||||
}
|
||||
|
||||
useStoredProcedure :: Schema.LogicalModel
|
||||
useStoredProcedure :: Schema.NativeQuery
|
||||
useStoredProcedure =
|
||||
(Schema.logicalModel "use_stored_procedure" goodQuery "stored_procedure")
|
||||
(Schema.nativeQuery "use_stored_procedure" goodQuery "stored_procedure")
|
||||
|
||||
Schema.trackCustomType source storedProcedureReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source useStoredProcedure testEnvironment
|
||||
Schema.trackNativeQuery source useStoredProcedure testEnvironment
|
||||
|
||||
-- making an assumption here that an SQLServer instance will always have
|
||||
-- a `master` database
|
@ -1,7 +1,7 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
-- | Access to the SQL
|
||||
module Test.Queries.LogicalModels.LogicalModelsQueriesSpec (spec) where
|
||||
module Test.Queries.NativeQueries.NativeQueriesSpec (spec) where
|
||||
|
||||
import Data.Aeson (Value)
|
||||
import Data.List.NonEmpty qualified as NE
|
||||
@ -23,12 +23,12 @@ import Test.Hspec (SpecWith, describe, it)
|
||||
|
||||
-- ** Preamble
|
||||
|
||||
featureFlagForLogicalModels :: String
|
||||
featureFlagForLogicalModels = "HASURA_FF_LOGICAL_MODEL_INTERFACE"
|
||||
featureFlagForNativeQueries :: String
|
||||
featureFlagForNativeQueries = "HASURA_FF_NATIVE_QUERY_INTERFACE"
|
||||
|
||||
spec :: SpecWith GlobalTestEnvironment
|
||||
spec =
|
||||
Fixture.hgeWithEnv [(featureFlagForLogicalModels, "True")] $
|
||||
Fixture.hgeWithEnv [(featureFlagForNativeQueries, "True")] $
|
||||
Fixture.runClean -- re-run fixture setup on every test
|
||||
( NE.fromList
|
||||
[ (Fixture.fixture $ Fixture.Backend Postgres.backendTypeMetadata)
|
||||
@ -78,23 +78,23 @@ tests = do
|
||||
helloWorldReturnType =
|
||||
(Schema.customType "hello_world_return_type")
|
||||
{ Schema.customTypeColumns =
|
||||
[ Schema.logicalModelColumn "one" Schema.TStr,
|
||||
Schema.logicalModelColumn "two" Schema.TStr
|
||||
[ Schema.nativeQueryColumn "one" Schema.TStr,
|
||||
Schema.nativeQueryColumn "two" Schema.TStr
|
||||
]
|
||||
}
|
||||
|
||||
helloWorldLogicalModel :: Schema.LogicalModel
|
||||
helloWorldLogicalModel =
|
||||
(Schema.logicalModel "hello_world_function" query "hello_world_return_type")
|
||||
helloWorldNativeQuery :: Schema.NativeQuery
|
||||
helloWorldNativeQuery =
|
||||
(Schema.nativeQuery "hello_world_function" query "hello_world_return_type")
|
||||
|
||||
describe "Testing Logical Models" $ do
|
||||
describe "Testing Native Queries" $ do
|
||||
it "Explain works" $ \testEnvironment -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
Schema.trackCustomType sourceName helloWorldReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel sourceName helloWorldLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery sourceName helloWorldNativeQuery testEnvironment
|
||||
|
||||
let explain :: Value
|
||||
explain =
|
||||
@ -128,28 +128,28 @@ tests = do
|
||||
descriptionsAndNullableReturnType =
|
||||
(Schema.customType "divided_stuff")
|
||||
{ Schema.customTypeColumns =
|
||||
[ (Schema.logicalModelColumn "divided" Schema.TInt)
|
||||
{ Schema.logicalModelColumnDescription = Just "A divided thing"
|
||||
[ (Schema.nativeQueryColumn "divided" Schema.TInt)
|
||||
{ Schema.nativeQueryColumnDescription = Just "A divided thing"
|
||||
},
|
||||
(Schema.logicalModelColumn "something_nullable" Schema.TStr)
|
||||
{ Schema.logicalModelColumnDescription = Just "Something nullable",
|
||||
Schema.logicalModelColumnNullable = True
|
||||
(Schema.nativeQueryColumn "something_nullable" Schema.TStr)
|
||||
{ Schema.nativeQueryColumnDescription = Just "Something nullable",
|
||||
Schema.nativeQueryColumnNullable = True
|
||||
}
|
||||
],
|
||||
Schema.customTypeDescription = Just "Return type description"
|
||||
}
|
||||
|
||||
descriptionsAndNullableLogicalModel :: Schema.LogicalModel
|
||||
descriptionsAndNullableLogicalModel =
|
||||
(Schema.logicalModel "divided_stuff" nullableQuery "divided_stuff")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "unused" Schema.TInt
|
||||
descriptionsAndNullableNativeQuery :: Schema.NativeQuery
|
||||
descriptionsAndNullableNativeQuery =
|
||||
(Schema.nativeQuery "divided_stuff" nullableQuery "divided_stuff")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "unused" Schema.TInt
|
||||
]
|
||||
}
|
||||
|
||||
Schema.trackCustomType sourceName descriptionsAndNullableReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel sourceName descriptionsAndNullableLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery sourceName descriptionsAndNullableNativeQuery testEnvironment
|
||||
|
||||
let queryTypesIntrospection :: Value
|
||||
queryTypesIntrospection =
|
||||
@ -216,7 +216,7 @@ tests = do
|
||||
source = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
Schema.trackLogicalModel source helloWorldLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery source helloWorldNativeQuery testEnvironment
|
||||
|
||||
let expected =
|
||||
[yaml|
|
||||
@ -248,7 +248,7 @@ tests = do
|
||||
source = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
Schema.trackLogicalModel source helloWorldLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery source helloWorldNativeQuery testEnvironment
|
||||
|
||||
let expected =
|
||||
[yaml|
|
||||
@ -278,7 +278,7 @@ tests = do
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
Schema.trackCustomType sourceName helloWorldReturnType testEnvironment
|
||||
Schema.trackLogicalModel sourceName helloWorldLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery sourceName helloWorldNativeQuery testEnvironment
|
||||
|
||||
let expected =
|
||||
[yaml|
|
||||
@ -307,17 +307,17 @@ tests = do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
source = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
helloWorldLogicalModelWithDummyArgument :: Schema.LogicalModel
|
||||
helloWorldLogicalModelWithDummyArgument =
|
||||
(Schema.logicalModel "hello_world_function_with_dummy" query "hello_world_return_type")
|
||||
{ Schema.logicalModelArguments =
|
||||
[ Schema.logicalModelColumn "dummy" Schema.TStr
|
||||
helloWorldNativeQueryWithDummyArgument :: Schema.NativeQuery
|
||||
helloWorldNativeQueryWithDummyArgument =
|
||||
(Schema.nativeQuery "hello_world_function_with_dummy" query "hello_world_return_type")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[ Schema.nativeQueryColumn "dummy" Schema.TStr
|
||||
]
|
||||
}
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source helloWorldLogicalModelWithDummyArgument testEnvironment
|
||||
Schema.trackNativeQuery source helloWorldNativeQueryWithDummyArgument testEnvironment
|
||||
|
||||
let expected =
|
||||
[yaml|
|
||||
@ -348,13 +348,13 @@ tests = do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
source = BackendType.backendSourceName backendTypeMetadata
|
||||
|
||||
helloCommentLogicalModel :: Schema.LogicalModel
|
||||
helloCommentLogicalModel =
|
||||
(Schema.logicalModel "hello_comment_function" spicyQuery "hello_world_return_type")
|
||||
helloCommentNativeQuery :: Schema.NativeQuery
|
||||
helloCommentNativeQuery =
|
||||
(Schema.nativeQuery "hello_comment_function" spicyQuery "hello_world_return_type")
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source helloCommentLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery source helloCommentNativeQuery testEnvironment
|
||||
|
||||
let expected =
|
||||
[yaml|
|
||||
@ -387,13 +387,13 @@ tests = do
|
||||
backendType = BackendType.backendTypeString backendTypeMetadata
|
||||
createPermRequestType = backendType <> "_create_custom_return_type_select_permission"
|
||||
|
||||
helloWorldPermLogicalModel :: Schema.LogicalModel
|
||||
helloWorldPermLogicalModel =
|
||||
(Schema.logicalModel "hello_world_with_permissions" query "hello_world_return_type")
|
||||
helloWorldPermNativeQuery :: Schema.NativeQuery
|
||||
helloWorldPermNativeQuery =
|
||||
(Schema.nativeQuery "hello_world_with_permissions" query "hello_world_return_type")
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source helloWorldPermLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery source helloWorldPermNativeQuery testEnvironment
|
||||
|
||||
shouldReturnYaml
|
||||
testEnvironment
|
||||
@ -446,13 +446,13 @@ tests = do
|
||||
backendType = BackendType.backendTypeString backendTypeMetadata
|
||||
createPermRequestType = backendType <> "_create_custom_return_type_select_permission"
|
||||
|
||||
helloWorldPermLogicalModel :: Schema.LogicalModel
|
||||
helloWorldPermLogicalModel =
|
||||
(Schema.logicalModel "hello_world_with_permissions" query "hello_world_return_type")
|
||||
helloWorldPermNativeQuery :: Schema.NativeQuery
|
||||
helloWorldPermNativeQuery =
|
||||
(Schema.nativeQuery "hello_world_with_permissions" query "hello_world_return_type")
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source helloWorldPermLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery source helloWorldPermNativeQuery testEnvironment
|
||||
|
||||
shouldReturnYaml
|
||||
testEnvironment
|
||||
@ -506,13 +506,13 @@ tests = do
|
||||
backendType = BackendType.backendTypeString backendTypeMetadata
|
||||
createPermRequestType = backendType <> "_create_custom_return_type_select_permission"
|
||||
|
||||
helloWorldPermLogicalModel :: Schema.LogicalModel
|
||||
helloWorldPermLogicalModel =
|
||||
(Schema.logicalModel "hello_world_with_permissions" query "hello_world_return_type")
|
||||
helloWorldPermNativeQuery :: Schema.NativeQuery
|
||||
helloWorldPermNativeQuery =
|
||||
(Schema.nativeQuery "hello_world_with_permissions" query "hello_world_return_type")
|
||||
|
||||
Schema.trackCustomType source helloWorldReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel source helloWorldPermLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery source helloWorldPermNativeQuery testEnvironment
|
||||
|
||||
shouldReturnYaml
|
||||
testEnvironment
|
@ -1,7 +1,7 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
-- | Test subscriptions over logical models
|
||||
module Test.Queries.LogicalModels.SubscriptionsSpec (spec) where
|
||||
-- | Test subscriptions over native queries
|
||||
module Test.Queries.NativeQueries.SubscriptionsSpec (spec) where
|
||||
|
||||
import Data.Aeson (Value)
|
||||
import Data.List.NonEmpty qualified as NE
|
||||
@ -26,12 +26,12 @@ import Test.Hspec (SpecWith, describe, it, shouldContain)
|
||||
|
||||
-- ** Preamble
|
||||
|
||||
featureFlagForLogicalModels :: String
|
||||
featureFlagForLogicalModels = "HASURA_FF_LOGICAL_MODEL_INTERFACE"
|
||||
featureFlagForNativeQueries :: String
|
||||
featureFlagForNativeQueries = "HASURA_FF_NATIVE_QUERY_INTERFACE"
|
||||
|
||||
spec :: SpecWith GlobalTestEnvironment
|
||||
spec =
|
||||
Fixture.hgeWithEnv [(featureFlagForLogicalModels, "True")] $
|
||||
Fixture.hgeWithEnv [(featureFlagForNativeQueries, "True")] $
|
||||
Fixture.run
|
||||
( NE.fromList
|
||||
[ (Fixture.fixture $ Fixture.Backend Postgres.backendTypeMetadata)
|
||||
@ -79,7 +79,7 @@ schema =
|
||||
tests :: SpecWith TestEnvironment
|
||||
tests = do
|
||||
withSubscriptions do
|
||||
describe "A subscription on a logical model" do
|
||||
describe "A subscription on a native query" do
|
||||
it "is updated on database changes" $ \(mkSubscription, testEnvironment) -> do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
sourceName = BackendType.backendSourceName backendTypeMetadata
|
||||
@ -99,23 +99,23 @@ tests = do
|
||||
articleWithExcerptReturnType =
|
||||
(Schema.customType "article_with_excerpt")
|
||||
{ Schema.customTypeColumns =
|
||||
[ Schema.logicalModelColumn "id" Schema.TInt,
|
||||
Schema.logicalModelColumn "title" Schema.TStr,
|
||||
Schema.logicalModelColumn "excerpt" Schema.TStr,
|
||||
Schema.logicalModelColumn "date" Schema.TUTCTime
|
||||
[ Schema.nativeQueryColumn "id" Schema.TInt,
|
||||
Schema.nativeQueryColumn "title" Schema.TStr,
|
||||
Schema.nativeQueryColumn "excerpt" Schema.TStr,
|
||||
Schema.nativeQueryColumn "date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
articleWithExcerptLogicalModel :: Schema.LogicalModel
|
||||
articleWithExcerptLogicalModel =
|
||||
(Schema.logicalModel "article_with_excerpt" spicyQuery "article_with_excerpt")
|
||||
{ Schema.logicalModelArguments =
|
||||
[Schema.logicalModelColumn "length" Schema.TInt]
|
||||
articleWithExcerptNativeQuery :: Schema.NativeQuery
|
||||
articleWithExcerptNativeQuery =
|
||||
(Schema.nativeQuery "article_with_excerpt" spicyQuery "article_with_excerpt")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[Schema.nativeQueryColumn "length" Schema.TInt]
|
||||
}
|
||||
|
||||
Schema.trackCustomType sourceName articleWithExcerptReturnType testEnvironment
|
||||
|
||||
Schema.trackLogicalModel sourceName articleWithExcerptLogicalModel testEnvironment
|
||||
Schema.trackNativeQuery sourceName articleWithExcerptNativeQuery testEnvironment
|
||||
|
||||
query <-
|
||||
mkSubscription
|
||||
@ -237,27 +237,27 @@ tests = do
|
||||
customReturnType =
|
||||
(Schema.customType "crt")
|
||||
{ Schema.customTypeColumns =
|
||||
[ Schema.logicalModelColumn "id" Schema.TInt,
|
||||
Schema.logicalModelColumn "title" Schema.TStr,
|
||||
Schema.logicalModelColumn "content" Schema.TStr,
|
||||
Schema.logicalModelColumn "date" Schema.TUTCTime
|
||||
[ Schema.nativeQueryColumn "id" Schema.TInt,
|
||||
Schema.nativeQueryColumn "title" Schema.TStr,
|
||||
Schema.nativeQueryColumn "content" Schema.TStr,
|
||||
Schema.nativeQueryColumn "date" Schema.TUTCTime
|
||||
]
|
||||
}
|
||||
|
||||
query :: Text
|
||||
query = [PG.sql| select * from article where title like {{pattern}} |]
|
||||
|
||||
logicalModel :: Schema.LogicalModel
|
||||
logicalModel =
|
||||
(Schema.logicalModel "filtered_article" query "crt")
|
||||
{ Schema.logicalModelArguments =
|
||||
[Schema.logicalModelColumn "pattern" Schema.TStr]
|
||||
nativeQuery :: Schema.NativeQuery
|
||||
nativeQuery =
|
||||
(Schema.nativeQuery "filtered_article" query "crt")
|
||||
{ Schema.nativeQueryArguments =
|
||||
[Schema.nativeQueryColumn "pattern" Schema.TStr]
|
||||
}
|
||||
|
||||
Schema.trackCustomType sourceName customReturnType testEnvironment
|
||||
Schema.trackLogicalModel sourceName logicalModel testEnvironment
|
||||
Schema.trackNativeQuery sourceName nativeQuery testEnvironment
|
||||
|
||||
one <- mkSubscription [graphql| subscription { filtered_article(args: { pattern: "%logical%" }) { id, title } } |] []
|
||||
one <- mkSubscription [graphql| subscription { filtered_article(args: { pattern: "%native%" }) { id, title } } |] []
|
||||
two <- mkSubscription [graphql| subscription { filtered_article(args: { pattern: "%model%" }) { id, title } } |] []
|
||||
|
||||
getNextResponse one
|
||||
@ -284,9 +284,9 @@ tests = do
|
||||
source: #{sourceName}
|
||||
sql: |
|
||||
insert into article (id, title, content, date) values
|
||||
(1, 'I like the logical song', '', now()),
|
||||
(1, 'I like the native song', '', now()),
|
||||
(2, 'I like model trains', '', now()),
|
||||
(3, 'I love me some logical models', '', now())
|
||||
(3, 'I love me some native queries', '', now())
|
||||
|]
|
||||
|
||||
getNextResponse one
|
||||
@ -294,9 +294,9 @@ tests = do
|
||||
data:
|
||||
filtered_article:
|
||||
- id: 1
|
||||
title: I like the logical song
|
||||
title: I like the native song
|
||||
- id: 3
|
||||
title: I love me some logical models
|
||||
title: I love me some native queries
|
||||
|]
|
||||
|
||||
getNextResponse two
|
||||
@ -305,6 +305,4 @@ tests = do
|
||||
filtered_article:
|
||||
- id: 2
|
||||
title: I like model trains
|
||||
- id: 3
|
||||
title: I love me some logical models
|
||||
|]
|
@ -13,10 +13,10 @@ module Harness.Schema
|
||||
BackendScalarValueType (..),
|
||||
ManualRelationship (..),
|
||||
SchemaName (..),
|
||||
LogicalModel (..),
|
||||
LogicalModelColumn (..),
|
||||
trackLogicalModelCommand,
|
||||
untrackLogicalModelCommand,
|
||||
NativeQuery (..),
|
||||
NativeQueryColumn (..),
|
||||
trackNativeQueryCommand,
|
||||
untrackNativeQueryCommand,
|
||||
CustomType (..),
|
||||
trackCustomType,
|
||||
trackCustomTypeCommand,
|
||||
@ -37,8 +37,8 @@ module Harness.Schema
|
||||
untrackComputedField,
|
||||
runSQL,
|
||||
addSource,
|
||||
trackLogicalModel,
|
||||
untrackLogicalModel,
|
||||
trackNativeQuery,
|
||||
untrackNativeQuery,
|
||||
module Harness.Schema.Table,
|
||||
module Harness.Schema.Name,
|
||||
getSchemaName,
|
||||
@ -422,67 +422,67 @@ addSource sourceName sourceConfig testEnvironment = do
|
||||
configuration: #{ sourceConfig }
|
||||
|]
|
||||
|
||||
trackLogicalModelCommand :: String -> BackendTypeConfig -> LogicalModel -> Value
|
||||
trackLogicalModelCommand sourceName backendTypeConfig (LogicalModel {logicalModelName, logicalModelArguments, logicalModelQuery, logicalModelReturnType}) =
|
||||
trackNativeQueryCommand :: String -> BackendTypeConfig -> NativeQuery -> Value
|
||||
trackNativeQueryCommand sourceName backendTypeConfig (NativeQuery {nativeQueryName, nativeQueryArguments, nativeQueryQuery, nativeQueryReturnType}) =
|
||||
-- arguments are a map from name to type details
|
||||
let argsToJson =
|
||||
Aeson.object
|
||||
. fmap
|
||||
( \LogicalModelColumn {..} ->
|
||||
let key = K.fromText logicalModelColumnName
|
||||
descriptionPair = case logicalModelColumnDescription of
|
||||
( \NativeQueryColumn {..} ->
|
||||
let key = K.fromText nativeQueryColumnName
|
||||
descriptionPair = case nativeQueryColumnDescription of
|
||||
Just desc -> [(K.fromText "description", Aeson.String desc)]
|
||||
Nothing -> []
|
||||
|
||||
value =
|
||||
Aeson.object $
|
||||
[ (K.fromText "type", Aeson.String ((BackendType.backendScalarType backendTypeConfig) logicalModelColumnType)),
|
||||
(K.fromText "nullable", Aeson.Bool logicalModelColumnNullable)
|
||||
[ (K.fromText "type", Aeson.String ((BackendType.backendScalarType backendTypeConfig) nativeQueryColumnType)),
|
||||
(K.fromText "nullable", Aeson.Bool nativeQueryColumnNullable)
|
||||
]
|
||||
<> descriptionPair
|
||||
in (key, value)
|
||||
)
|
||||
|
||||
arguments = argsToJson logicalModelArguments
|
||||
arguments = argsToJson nativeQueryArguments
|
||||
|
||||
backendType = BackendType.backendTypeString backendTypeConfig
|
||||
|
||||
requestType = backendType <> "_track_logical_model"
|
||||
requestType = backendType <> "_track_native_query"
|
||||
in [yaml|
|
||||
type: *requestType
|
||||
args:
|
||||
type: query
|
||||
source: *sourceName
|
||||
root_field_name: *logicalModelName
|
||||
code: *logicalModelQuery
|
||||
root_field_name: *nativeQueryName
|
||||
code: *nativeQueryQuery
|
||||
arguments: *arguments
|
||||
returns: *logicalModelReturnType
|
||||
returns: *nativeQueryReturnType
|
||||
|]
|
||||
|
||||
trackLogicalModel :: HasCallStack => String -> LogicalModel -> TestEnvironment -> IO ()
|
||||
trackLogicalModel sourceName logMod testEnvironment = do
|
||||
trackNativeQuery :: HasCallStack => String -> NativeQuery -> TestEnvironment -> IO ()
|
||||
trackNativeQuery sourceName logMod testEnvironment = do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
|
||||
let command = trackLogicalModelCommand sourceName backendTypeMetadata logMod
|
||||
let command = trackNativeQueryCommand sourceName backendTypeMetadata logMod
|
||||
|
||||
GraphqlEngine.postMetadata_ testEnvironment command
|
||||
|
||||
untrackLogicalModelCommand :: String -> BackendTypeConfig -> LogicalModel -> Value
|
||||
untrackLogicalModelCommand source backendTypeMetadata LogicalModel {logicalModelName} =
|
||||
untrackNativeQueryCommand :: String -> BackendTypeConfig -> NativeQuery -> Value
|
||||
untrackNativeQueryCommand source backendTypeMetadata NativeQuery {nativeQueryName} =
|
||||
let backendType = BackendType.backendTypeString backendTypeMetadata
|
||||
requestType = backendType <> "_untrack_logical_model"
|
||||
requestType = backendType <> "_untrack_native_query"
|
||||
in [yaml|
|
||||
type: *requestType
|
||||
args:
|
||||
source: *source
|
||||
root_field_name: *logicalModelName
|
||||
root_field_name: *nativeQueryName
|
||||
|]
|
||||
|
||||
untrackLogicalModel :: HasCallStack => String -> LogicalModel -> TestEnvironment -> IO ()
|
||||
untrackLogicalModel source logMod testEnvironment = do
|
||||
untrackNativeQuery :: HasCallStack => String -> NativeQuery -> TestEnvironment -> IO ()
|
||||
untrackNativeQuery source logMod testEnvironment = do
|
||||
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
|
||||
|
||||
let command = untrackLogicalModelCommand source backendTypeMetadata logMod
|
||||
let command = untrackNativeQueryCommand source backendTypeMetadata logMod
|
||||
|
||||
GraphqlEngine.postMetadata_
|
||||
testEnvironment
|
||||
@ -495,14 +495,14 @@ trackCustomTypeCommand sourceName backendTypeConfig (CustomType {customTypeDescr
|
||||
Aeson.Array
|
||||
. V.fromList
|
||||
. fmap
|
||||
( \LogicalModelColumn {..} ->
|
||||
let descriptionPair = case logicalModelColumnDescription of
|
||||
( \NativeQueryColumn {..} ->
|
||||
let descriptionPair = case nativeQueryColumnDescription of
|
||||
Just desc -> [(K.fromText "description", Aeson.String desc)]
|
||||
Nothing -> []
|
||||
in Aeson.object $
|
||||
[ (K.fromText "name", Aeson.String logicalModelColumnName),
|
||||
(K.fromText "type", Aeson.String ((BackendType.backendScalarType backendTypeConfig) logicalModelColumnType)),
|
||||
(K.fromText "nullable", Aeson.Bool logicalModelColumnNullable)
|
||||
[ (K.fromText "name", Aeson.String nativeQueryColumnName),
|
||||
(K.fromText "type", Aeson.String ((BackendType.backendScalarType backendTypeConfig) nativeQueryColumnType)),
|
||||
(K.fromText "nullable", Aeson.Bool nativeQueryColumnNullable)
|
||||
]
|
||||
<> descriptionPair
|
||||
)
|
||||
|
@ -17,10 +17,10 @@ module Harness.Schema.Table
|
||||
BackendScalarValue (..),
|
||||
BackendScalarValueType (..),
|
||||
ManualRelationship (..),
|
||||
LogicalModel (..),
|
||||
logicalModel,
|
||||
LogicalModelColumn (..),
|
||||
logicalModelColumn,
|
||||
NativeQuery (..),
|
||||
nativeQuery,
|
||||
NativeQueryColumn (..),
|
||||
nativeQueryColumn,
|
||||
CustomType (..),
|
||||
customType,
|
||||
quotedValue,
|
||||
@ -94,38 +94,38 @@ table tableName =
|
||||
tableQualifiers = []
|
||||
}
|
||||
|
||||
data LogicalModelColumn = LogicalModelColumn
|
||||
{ logicalModelColumnName :: Text,
|
||||
logicalModelColumnType :: ScalarType,
|
||||
logicalModelColumnNullable :: Bool,
|
||||
logicalModelColumnDescription :: Maybe Text
|
||||
data NativeQueryColumn = NativeQueryColumn
|
||||
{ nativeQueryColumnName :: Text,
|
||||
nativeQueryColumnType :: ScalarType,
|
||||
nativeQueryColumnNullable :: Bool,
|
||||
nativeQueryColumnDescription :: Maybe Text
|
||||
}
|
||||
deriving (Show, Eq)
|
||||
|
||||
logicalModelColumn :: Text -> ScalarType -> LogicalModelColumn
|
||||
logicalModelColumn name colType =
|
||||
LogicalModelColumn
|
||||
{ logicalModelColumnName = name,
|
||||
logicalModelColumnType = colType,
|
||||
logicalModelColumnNullable = False,
|
||||
logicalModelColumnDescription = Nothing
|
||||
nativeQueryColumn :: Text -> ScalarType -> NativeQueryColumn
|
||||
nativeQueryColumn name colType =
|
||||
NativeQueryColumn
|
||||
{ nativeQueryColumnName = name,
|
||||
nativeQueryColumnType = colType,
|
||||
nativeQueryColumnNullable = False,
|
||||
nativeQueryColumnDescription = Nothing
|
||||
}
|
||||
|
||||
data LogicalModel = LogicalModel
|
||||
{ logicalModelName :: Text,
|
||||
logicalModelReturnType :: Text,
|
||||
logicalModelQuery :: Text,
|
||||
logicalModelArguments :: [LogicalModelColumn]
|
||||
data NativeQuery = NativeQuery
|
||||
{ nativeQueryName :: Text,
|
||||
nativeQueryReturnType :: Text,
|
||||
nativeQueryQuery :: Text,
|
||||
nativeQueryArguments :: [NativeQueryColumn]
|
||||
}
|
||||
deriving (Show, Eq)
|
||||
|
||||
logicalModel :: Text -> Text -> Text -> LogicalModel
|
||||
logicalModel logicalModelName query returnType =
|
||||
LogicalModel
|
||||
{ logicalModelName,
|
||||
logicalModelReturnType = returnType,
|
||||
logicalModelQuery = query,
|
||||
logicalModelArguments = mempty
|
||||
nativeQuery :: Text -> Text -> Text -> NativeQuery
|
||||
nativeQuery nativeQueryName query returnType =
|
||||
NativeQuery
|
||||
{ nativeQueryName,
|
||||
nativeQueryReturnType = returnType,
|
||||
nativeQueryQuery = query,
|
||||
nativeQueryArguments = mempty
|
||||
}
|
||||
|
||||
-- | Foreign keys for backends that support it.
|
||||
@ -181,7 +181,7 @@ parseUTCTimeOrError = VUTCTime . parseTimeOrError True defaultTimeLocale "%F %T"
|
||||
|
||||
data CustomType = CustomType
|
||||
{ customTypeName :: Text,
|
||||
customTypeColumns :: [LogicalModelColumn],
|
||||
customTypeColumns :: [NativeQueryColumn],
|
||||
customTypeDescription :: Maybe Text
|
||||
}
|
||||
deriving (Show, Eq)
|
||||
|
@ -494,7 +494,7 @@ initialiseAppContext ::
|
||||
initialiseAppContext env serveOptions@ServeOptions {..} AppInit {..} = do
|
||||
appEnv@AppEnv {..} <- askAppEnv
|
||||
let CheckFeatureFlag runCheckFlag = appEnvCheckFeatureFlag
|
||||
logicalModelsEnabled <- liftIO $ runCheckFlag logicalModelInterface
|
||||
nativeQueriesEnabled <- liftIO $ runCheckFlag nativeQueryInterface
|
||||
let Loggers _ logger pgLogger = appEnvLoggers
|
||||
sqlGenCtx = initSQLGenCtx soExperimentalFeatures soStringifyNum soDangerousBooleanCollapse
|
||||
cacheStaticConfig = buildCacheStaticConfig appEnv
|
||||
@ -507,7 +507,7 @@ initialiseAppContext env serveOptions@ServeOptions {..} AppInit {..} = do
|
||||
soDefaultNamingConvention
|
||||
soMetadataDefaults
|
||||
soApolloFederationStatus
|
||||
logicalModelsEnabled
|
||||
nativeQueriesEnabled
|
||||
|
||||
-- Create the schema cache
|
||||
rebuildableSchemaCache <-
|
||||
|
@ -330,7 +330,7 @@ buildCacheStaticConfig AppEnv {..} =
|
||||
buildCacheDynamicConfig :: MonadIO m => AppEnv -> AppContext -> m CacheDynamicConfig
|
||||
buildCacheDynamicConfig AppEnv {..} AppContext {..} = do
|
||||
let CheckFeatureFlag runCheckFlag = appEnvCheckFeatureFlag
|
||||
logicalModelsEnabled <- liftIO $ runCheckFlag logicalModelInterface
|
||||
nativeQueriesEnabled <- liftIO $ runCheckFlag nativeQueryInterface
|
||||
pure
|
||||
CacheDynamicConfig
|
||||
{ _cdcFunctionPermsCtx = acFunctionPermsCtx,
|
||||
@ -340,5 +340,5 @@ buildCacheDynamicConfig AppEnv {..} AppContext {..} = do
|
||||
_cdcDefaultNamingConvention = acDefaultNamingConvention,
|
||||
_cdcMetadataDefaults = acMetadataDefaults,
|
||||
_cdcApolloFederationStatus = acApolloFederationStatus,
|
||||
_cdcAreLogicalModelsEnabled = logicalModelsEnabled
|
||||
_cdcAreNativeQueriesEnabled = nativeQueriesEnabled
|
||||
}
|
||||
|
@ -27,9 +27,9 @@ import Hasura.Backends.BigQuery.Instances.Types ()
|
||||
import Hasura.Backends.BigQuery.Source (BigQuerySourceConfig (..))
|
||||
import Hasura.Backends.BigQuery.Types as BigQuery
|
||||
import Hasura.Function.Cache qualified as Functions
|
||||
import Hasura.LogicalModel.IR (LogicalModel (..))
|
||||
import Hasura.LogicalModel.Metadata (InterpolatedQuery)
|
||||
import Hasura.LogicalModel.Types (LogicalModelName (..))
|
||||
import Hasura.NativeQuery.IR (NativeQuery (..))
|
||||
import Hasura.NativeQuery.Metadata (InterpolatedQuery)
|
||||
import Hasura.NativeQuery.Types (NativeQueryName (..))
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR qualified as Ir
|
||||
import Hasura.RQL.Types.Column qualified as Rql
|
||||
@ -120,10 +120,10 @@ newtype FromIr a = FromIr
|
||||
}
|
||||
deriving (Functor, Applicative, Monad, MonadValidate (NonEmpty Error))
|
||||
|
||||
-- | Collected from using a logical model in a query.
|
||||
-- | Collected from using a native query in a query.
|
||||
-- Each entry here because a CTE to be prepended to the query.
|
||||
newtype FromIrWriter = FromIrWriter
|
||||
{ fromIrWriterLogicalModels :: Map LogicalModelName (InterpolatedQuery Expression)
|
||||
{ fromIrWriterNativeQueries :: Map NativeQueryName (InterpolatedQuery Expression)
|
||||
}
|
||||
deriving newtype (Semigroup, Monoid)
|
||||
|
||||
@ -261,7 +261,7 @@ fromSelectRows parentSelectFromEntity annSelectG = do
|
||||
| functionName nm == "unnest" -> fromUnnestedJSON json columns (map fst fields)
|
||||
Ir.FromFunction functionName (Functions.FunctionArgsExp positionalArgs namedArgs) Nothing ->
|
||||
fromFunction parentSelectFromEntity functionName positionalArgs namedArgs
|
||||
Ir.FromLogicalModel logicalModel -> fromLogicalModel logicalModel
|
||||
Ir.FromNativeQuery nativeQuery -> fromNativeQuery nativeQuery
|
||||
_ -> refute (pure (FromTypeUnsupported from))
|
||||
Args
|
||||
{ argsOrderBy,
|
||||
@ -801,10 +801,10 @@ fromAnnBoolExp ::
|
||||
ReaderT EntityAlias FromIr Expression
|
||||
fromAnnBoolExp = traverse fromAnnBoolExpFld >=> fromGBoolExp
|
||||
|
||||
fromLogicalModel :: LogicalModel 'BigQuery Expression -> FromIr From
|
||||
fromLogicalModel LogicalModel {..} = FromIr do
|
||||
tell (FromIrWriter (M.singleton lmRootFieldName lmInterpolatedQuery))
|
||||
pure (FromLogicalModel lmRootFieldName)
|
||||
fromNativeQuery :: NativeQuery 'BigQuery Expression -> FromIr From
|
||||
fromNativeQuery NativeQuery {..} = FromIr do
|
||||
tell (FromIrWriter (M.singleton nqRootFieldName nqInterpolatedQuery))
|
||||
pure (FromNativeQuery nqRootFieldName)
|
||||
|
||||
fromAnnBoolExpFld ::
|
||||
Ir.AnnBoolExpFld 'BigQuery Expression -> ReaderT EntityAlias FromIr Expression
|
||||
@ -1886,7 +1886,7 @@ fromAlias (FromQualifiedTable Aliased {aliasedAlias}) = EntityAlias aliasedAlias
|
||||
fromAlias (FromSelect Aliased {aliasedAlias}) = EntityAlias aliasedAlias
|
||||
fromAlias (FromSelectJson Aliased {aliasedAlias}) = EntityAlias aliasedAlias
|
||||
fromAlias (FromFunction Aliased {aliasedAlias}) = EntityAlias aliasedAlias
|
||||
fromAlias (FromLogicalModel (LogicalModelName logicalModelName)) = EntityAlias (T.toTxt logicalModelName)
|
||||
fromAlias (FromNativeQuery (NativeQueryName nativeQueryName)) = EntityAlias (T.toTxt nativeQueryName)
|
||||
|
||||
fieldTextNames :: Ir.AnnFieldsG 'BigQuery Void Expression -> [Text]
|
||||
fieldTextNames = fmap (\(Rql.FieldName name, _) -> name)
|
||||
|
@ -15,6 +15,6 @@ instance BackendAPI 'BigQuery where
|
||||
relationshipCommands @'BigQuery,
|
||||
remoteRelationshipCommands @'BigQuery,
|
||||
computedFieldCommands @'BigQuery,
|
||||
logicalModelsCommands @'BigQuery,
|
||||
nativeQueriesCommands @'BigQuery,
|
||||
customReturnTypesCommands @'BigQuery
|
||||
]
|
||||
|
@ -26,4 +26,4 @@ instance BackendMetadata 'BigQuery where
|
||||
throw400 UnexpectedPayload "Computed fields are not supported in boolean expressions"
|
||||
supportsBeingRemoteRelationshipTarget _ = True
|
||||
listAllTables = BigQuery.listAllTables
|
||||
validateLogicalModel _ _ _ _ = pure ()
|
||||
validateNativeQuery _ _ _ _ = pure ()
|
||||
|
@ -34,8 +34,8 @@ import Hasura.GraphQL.Schema.Parser qualified as P
|
||||
import Hasura.GraphQL.Schema.Select
|
||||
import Hasura.GraphQL.Schema.Table
|
||||
import Hasura.GraphQL.Schema.Typename
|
||||
import Hasura.LogicalModel.Schema (defaultBuildLogicalModelRootFields)
|
||||
import Hasura.Name qualified as Name
|
||||
import Hasura.NativeQuery.Schema (defaultBuildNativeQueryRootFields)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.BoolExp
|
||||
import Hasura.RQL.IR.Select qualified as IR
|
||||
@ -64,7 +64,7 @@ instance BackendSchema 'BigQuery where
|
||||
buildFunctionQueryFields _ _ _ _ = pure []
|
||||
buildFunctionRelayQueryFields _ _ _ _ _ = pure []
|
||||
buildFunctionMutationFields _ _ _ _ = pure []
|
||||
buildLogicalModelRootFields = defaultBuildLogicalModelRootFields
|
||||
buildNativeQueryRootFields = defaultBuildNativeQueryRootFields
|
||||
|
||||
-- backend extensions
|
||||
relayExtension = Nothing
|
||||
|
@ -34,19 +34,19 @@ planNoPlan ::
|
||||
planNoPlan fromIrConfig userInfo queryDB = do
|
||||
rootField <- traverse (prepareValueNoPlan (_uiSession userInfo)) queryDB
|
||||
|
||||
(select, FromIrWriter {fromIrWriterLogicalModels}) <-
|
||||
(select, FromIrWriter {fromIrWriterNativeQueries}) <-
|
||||
runValidate (BigQuery.runFromIr fromIrConfig (BigQuery.fromRootField rootField))
|
||||
`onLeft` (E.throw400 E.NotSupported . (tshow :: NonEmpty Error -> Text))
|
||||
|
||||
-- Logical models used within this query need to be converted into CTEs.
|
||||
-- Native queries used within this query need to be converted into CTEs.
|
||||
-- These need to come before any other CTEs in case those CTEs also depend on
|
||||
-- the logical models.
|
||||
let logicalModels :: Maybe With
|
||||
logicalModels = do
|
||||
ctes <- NE.nonEmpty (Map.toList fromIrWriterLogicalModels)
|
||||
-- the native queries.
|
||||
let nativeQueries :: Maybe With
|
||||
nativeQueries = do
|
||||
ctes <- NE.nonEmpty (Map.toList fromIrWriterNativeQueries)
|
||||
pure (With [Aliased query (toTxt name) | (name, query) <- ctes])
|
||||
|
||||
pure select {selectWith = logicalModels <> selectWith select}
|
||||
pure select {selectWith = nativeQueries <> selectWith select}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Resolving values
|
||||
|
@ -32,8 +32,8 @@ import Data.Text.Lazy.Builder qualified as LT
|
||||
import Data.Tuple
|
||||
import Data.Vector qualified as V
|
||||
import Hasura.Backends.BigQuery.Types
|
||||
import Hasura.LogicalModel.Metadata (InterpolatedItem (..), InterpolatedQuery (..))
|
||||
import Hasura.LogicalModel.Types (LogicalModelName (..))
|
||||
import Hasura.NativeQuery.Metadata (InterpolatedItem (..), InterpolatedQuery (..))
|
||||
import Hasura.NativeQuery.Types (NativeQueryName (..))
|
||||
import Hasura.Prelude hiding (second)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@ -559,8 +559,8 @@ fromFrom =
|
||||
)
|
||||
selectFromFunction
|
||||
)
|
||||
FromLogicalModel (LogicalModelName logicalModelName) ->
|
||||
fromNameText (T.toTxt logicalModelName)
|
||||
FromNativeQuery (NativeQueryName nativeQueryName) ->
|
||||
fromNameText (T.toTxt nativeQueryName)
|
||||
|
||||
fromTableName :: TableName -> Printer
|
||||
fromTableName TableName {tableName, tableNameSchema} =
|
||||
|
@ -98,8 +98,8 @@ import Hasura.Base.Error
|
||||
import Hasura.Base.ErrorValue qualified as ErrorValue
|
||||
import Hasura.Base.ToErrorValue
|
||||
import Hasura.Function.Cache (FunctionArgName)
|
||||
import Hasura.LogicalModel.Metadata (InterpolatedQuery, LogicalModelName)
|
||||
import Hasura.Metadata.DTO.Utils (boundedEnumCodec)
|
||||
import Hasura.NativeQuery.Metadata (InterpolatedQuery, NativeQueryName)
|
||||
import Hasura.Prelude hiding (state)
|
||||
import Hasura.RQL.IR.BoolExp
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
@ -344,7 +344,7 @@ data From
|
||||
| FromSelect (Aliased Select)
|
||||
| FromSelectJson (Aliased SelectJson)
|
||||
| FromFunction (Aliased SelectFromFunction)
|
||||
| FromLogicalModel LogicalModelName
|
||||
| FromNativeQuery NativeQueryName
|
||||
deriving stock (Eq, Show, Generic, Data, Lift, Ord)
|
||||
deriving anyclass (Hashable, NFData)
|
||||
|
||||
|
@ -122,7 +122,7 @@ extractTableName selectG =
|
||||
FromTable tn -> pure $ Witch.from tn
|
||||
FromIdentifier _ -> throw400 NotSupported "AnnSelectG: FromIdentifier not supported"
|
||||
FromFunction {} -> throw400 NotSupported "AnnSelectG: FromFunction not supported"
|
||||
FromLogicalModel {} -> throw400 NotSupported "AnnSelectG: FromLogicalModel not supported"
|
||||
FromNativeQuery {} -> throw400 NotSupported "AnnSelectG: FromNativeQuery not supported"
|
||||
|
||||
translateAnnSelect ::
|
||||
( Has TableRelationships writerOutput,
|
||||
|
@ -35,8 +35,8 @@ import Hasura.Backends.MSSQL.FromIr.Expression
|
||||
import Hasura.Backends.MSSQL.Instances.Types ()
|
||||
import Hasura.Backends.MSSQL.Types.Internal as TSQL
|
||||
import Hasura.CustomReturnType.IR (CustomReturnType (..))
|
||||
import Hasura.LogicalModel.IR qualified as IR
|
||||
import Hasura.LogicalModel.Types (LogicalModelName (..), NullableScalarType (..))
|
||||
import Hasura.NativeQuery.IR qualified as IR
|
||||
import Hasura.NativeQuery.Types (NativeQueryName (..), NullableScalarType (..))
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR qualified as IR
|
||||
import Hasura.RQL.Types.Column qualified as IR
|
||||
@ -209,7 +209,7 @@ fromSelectRows annSelectG = do
|
||||
IR.FromTable qualifiedObject -> fromQualifiedTable qualifiedObject
|
||||
IR.FromIdentifier identifier -> pure $ FromIdentifier $ IR.unFIIdentifier identifier
|
||||
IR.FromFunction {} -> refute $ pure FunctionNotSupported
|
||||
IR.FromLogicalModel logicalModel -> fromLogicalModel logicalModel
|
||||
IR.FromNativeQuery nativeQuery -> fromNativeQuery nativeQuery
|
||||
Args
|
||||
{ argsOrderBy,
|
||||
argsWhere,
|
||||
@ -331,13 +331,13 @@ mkAggregateSelect Args {..} foreignKeyConditions filterExpression selectFrom agg
|
||||
| (index, (fieldName, projections)) <- aggregates
|
||||
]
|
||||
|
||||
fromLogicalModel :: IR.LogicalModel 'MSSQL Expression -> FromIr TSQL.From
|
||||
fromLogicalModel logicalModel = do
|
||||
let logicalModelName = IR.lmRootFieldName logicalModel
|
||||
logicalModelSql = IR.lmInterpolatedQuery logicalModel
|
||||
logicalModelReturnType = IR.lmReturnType logicalModel
|
||||
fromNativeQuery :: IR.NativeQuery 'MSSQL Expression -> FromIr TSQL.From
|
||||
fromNativeQuery nativeQuery = do
|
||||
let nativeQueryName = IR.nqRootFieldName nativeQuery
|
||||
nativeQuerySql = IR.nqInterpolatedQuery nativeQuery
|
||||
nativeQueryReturnType = IR.nqReturnType nativeQuery
|
||||
|
||||
rawTempTableName = T.toTxt (getLogicalModelName logicalModelName)
|
||||
rawTempTableName = T.toTxt (getNativeQueryName nativeQueryName)
|
||||
aliasedTempTableName = Aliased (TempTableName rawTempTableName) rawTempTableName
|
||||
|
||||
let columns =
|
||||
@ -347,13 +347,13 @@ fromLogicalModel logicalModel = do
|
||||
type' = (nstType ty)
|
||||
}
|
||||
)
|
||||
<$> InsOrd.toList (crtFields logicalModelReturnType)
|
||||
<$> InsOrd.toList (crtFields nativeQueryReturnType)
|
||||
|
||||
-- \| add create temp table to "the environment"
|
||||
tellBefore (CreateTemp (TempTableName rawTempTableName) columns)
|
||||
|
||||
-- \| add insert into temp table
|
||||
tellBefore (InsertTemp (TempTableName rawTempTableName) logicalModelSql)
|
||||
tellBefore (InsertTemp (TempTableName rawTempTableName) nativeQuerySql)
|
||||
|
||||
-- \| when we're done, drop the temp table
|
||||
tellAfter (DropTemp (TempTableName rawTempTableName))
|
||||
@ -378,7 +378,7 @@ fromSelectAggregate
|
||||
IR.FromTable qualifiedObject -> fromQualifiedTable qualifiedObject
|
||||
IR.FromIdentifier identifier -> pure $ FromIdentifier $ IR.unFIIdentifier identifier
|
||||
IR.FromFunction {} -> refute $ pure FunctionNotSupported
|
||||
IR.FromLogicalModel logicalModel -> fromLogicalModel logicalModel
|
||||
IR.FromNativeQuery nativeQuery -> fromNativeQuery nativeQuery
|
||||
-- Below: When we're actually a RHS of a query (of CROSS APPLY),
|
||||
-- then we'll have a LHS table that we're joining on. So we get the
|
||||
-- conditions expressions from the field mappings. The LHS table is
|
||||
|
@ -18,6 +18,6 @@ instance BackendAPI 'MSSQL where
|
||||
relationshipCommands @'MSSQL,
|
||||
remoteRelationshipCommands @'MSSQL,
|
||||
eventTriggerCommands @'MSSQL,
|
||||
logicalModelsCommands @'MSSQL,
|
||||
nativeQueriesCommands @'MSSQL,
|
||||
customReturnTypesCommands @'MSSQL
|
||||
]
|
||||
|
@ -28,4 +28,4 @@ instance BackendMetadata 'MSSQL where
|
||||
throw500 "Computed fields are not yet defined for MSSQL backends"
|
||||
supportsBeingRemoteRelationshipTarget _ = True
|
||||
listAllTables = MSSQL.listAllTables
|
||||
validateLogicalModel _ _ _ _ = pure () -- for now, all queries are valid
|
||||
validateNativeQuery _ _ _ _ = pure () -- for now, all queries are valid
|
||||
|
@ -35,8 +35,8 @@ import Hasura.GraphQL.Schema.Parser
|
||||
import Hasura.GraphQL.Schema.Parser qualified as P
|
||||
import Hasura.GraphQL.Schema.Select
|
||||
import Hasura.GraphQL.Schema.Update qualified as SU
|
||||
import Hasura.LogicalModel.Schema qualified as LogicalModels
|
||||
import Hasura.Name qualified as Name
|
||||
import Hasura.NativeQuery.Schema qualified as NativeQueries
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR
|
||||
import Hasura.RQL.IR.Select qualified as IR
|
||||
@ -60,7 +60,7 @@ instance BackendSchema 'MSSQL where
|
||||
buildTableInsertMutationFields = GSB.buildTableInsertMutationFields backendInsertParser
|
||||
buildTableDeleteMutationFields = GSB.buildTableDeleteMutationFields
|
||||
buildTableUpdateMutationFields = GSB.buildSingleBatchTableUpdateMutationFields id
|
||||
buildLogicalModelRootFields = LogicalModels.defaultBuildLogicalModelRootFields
|
||||
buildNativeQueryRootFields = NativeQueries.defaultBuildNativeQueryRootFields
|
||||
|
||||
buildFunctionQueryFields _ _ _ _ = pure []
|
||||
buildFunctionRelayQueryFields _ _ _ _ _ = pure []
|
||||
|
@ -41,7 +41,7 @@ import Data.Text.Lazy.Builder qualified as L
|
||||
import Database.ODBC.SQLServer
|
||||
import Hasura.Backends.MSSQL.Types
|
||||
import Hasura.Backends.MSSQL.Types qualified as MSSQL
|
||||
import Hasura.LogicalModel.Metadata (InterpolatedItem (..), InterpolatedQuery (..))
|
||||
import Hasura.NativeQuery.Metadata (InterpolatedItem (..), InterpolatedQuery (..))
|
||||
import Hasura.Prelude hiding (GT, LT)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
@ -112,7 +112,7 @@ import Data.Text.Casing qualified as C
|
||||
import Database.ODBC.SQLServer qualified as ODBC
|
||||
import Hasura.Base.Error
|
||||
import Hasura.GraphQL.Parser.Name qualified as GName
|
||||
import Hasura.LogicalModel.Metadata (InterpolatedQuery)
|
||||
import Hasura.NativeQuery.Metadata (InterpolatedQuery)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend (SupportedNamingCase (..))
|
||||
import Hasura.SQL.Backend
|
||||
|
@ -37,7 +37,7 @@ data Error
|
||||
= UnsupportedOpExpG (IR.OpExpG 'MySQL Expression)
|
||||
| IdentifierNotSupported
|
||||
| FunctionNotSupported
|
||||
| LogicalModelNotSupported
|
||||
| NativeQueryNotSupported
|
||||
| NodesUnsupportedForNow
|
||||
| ConnectionsNotSupported
|
||||
deriving (Show, Eq)
|
||||
@ -507,7 +507,7 @@ fromSelectAggregate mparentRelationship annSelectG = do
|
||||
IR.FromTable qualifiedObject -> fromQualifiedTable qualifiedObject
|
||||
IR.FromIdentifier {} -> refute $ pure IdentifierNotSupported
|
||||
IR.FromFunction {} -> refute $ pure FunctionNotSupported
|
||||
IR.FromLogicalModel {} -> refute $ pure LogicalModelNotSupported
|
||||
IR.FromNativeQuery {} -> refute $ pure NativeQueryNotSupported
|
||||
_mforeignKeyConditions <- fmap (Where . fromMaybe []) $
|
||||
for mparentRelationship $
|
||||
\(entityAlias, mapping) ->
|
||||
@ -698,7 +698,7 @@ fromSelectRows annSelectG = do
|
||||
IR.FromTable qualifiedObject -> fromQualifiedTable qualifiedObject
|
||||
IR.FromIdentifier {} -> refute $ pure IdentifierNotSupported
|
||||
IR.FromFunction {} -> refute $ pure FunctionNotSupported
|
||||
IR.FromLogicalModel {} -> refute $ pure LogicalModelNotSupported
|
||||
IR.FromNativeQuery {} -> refute $ pure NativeQueryNotSupported
|
||||
Args
|
||||
{ argsOrderBy,
|
||||
argsWhere,
|
||||
|
@ -261,7 +261,7 @@ withMetadataCheck ::
|
||||
PG.TxET QErr m a ->
|
||||
m a
|
||||
withMetadataCheck sqlGen source cascade txAccess runSQLQuery = do
|
||||
SourceInfo _ tableCache functionCache _logicalModels _customReturnTypes sourceConfig _ _ <- askSourceInfo @('Postgres pgKind) source
|
||||
SourceInfo _ tableCache functionCache _nativeQueries _customReturnTypes sourceConfig _ _ <- askSourceInfo @('Postgres pgKind) source
|
||||
|
||||
-- Run SQL query and metadata checker in a transaction
|
||||
(queryResult, metadataUpdater) <- runTxWithMetadataCheck source sourceConfig txAccess tableCache functionCache cascade runSQLQuery
|
||||
|
@ -23,7 +23,7 @@ instance BackendAPI ('Postgres 'Vanilla) where
|
||||
remoteRelationshipCommands @('Postgres 'Vanilla),
|
||||
eventTriggerCommands @('Postgres 'Vanilla),
|
||||
computedFieldCommands @('Postgres 'Vanilla),
|
||||
logicalModelsCommands @('Postgres 'Vanilla),
|
||||
nativeQueriesCommands @('Postgres 'Vanilla),
|
||||
customReturnTypesCommands @('Postgres 'Vanilla),
|
||||
[ commandParser
|
||||
"set_table_is_enum"
|
||||
@ -45,7 +45,7 @@ instance BackendAPI ('Postgres 'Citus) where
|
||||
relationshipCommands @('Postgres 'Citus),
|
||||
remoteRelationshipCommands @('Postgres 'Citus),
|
||||
connectionTemplateCommands @('Postgres 'Citus),
|
||||
logicalModelsCommands @('Postgres 'Citus),
|
||||
nativeQueriesCommands @('Postgres 'Citus),
|
||||
customReturnTypesCommands @('Postgres 'Citus)
|
||||
]
|
||||
|
||||
@ -64,6 +64,6 @@ instance BackendAPI ('Postgres 'Cockroach) where
|
||||
)
|
||||
],
|
||||
connectionTemplateCommands @('Postgres 'Cockroach),
|
||||
logicalModelsCommands @('Postgres 'Cockroach),
|
||||
nativeQueriesCommands @('Postgres 'Cockroach),
|
||||
customReturnTypesCommands @('Postgres 'Cockroach)
|
||||
]
|
||||
|
@ -18,7 +18,7 @@ import Database.PG.Query.Transaction qualified as Query
|
||||
import Database.PostgreSQL.LibPQ qualified as PQ
|
||||
import Hasura.Backends.Postgres.DDL qualified as Postgres
|
||||
import Hasura.Backends.Postgres.Execute.Types (runPgSourceReadTx)
|
||||
import Hasura.Backends.Postgres.Instances.LogicalModels as Postgres (validateLogicalModel)
|
||||
import Hasura.Backends.Postgres.Instances.NativeQueries as Postgres (validateNativeQuery)
|
||||
import Hasura.Backends.Postgres.SQL.Types (QualifiedObject (..), QualifiedTable)
|
||||
import Hasura.Backends.Postgres.SQL.Types qualified as Postgres
|
||||
import Hasura.Backends.Postgres.Types.CitusExtraTableMetadata
|
||||
@ -267,7 +267,7 @@ instance
|
||||
postDropSourceHook = Postgres.postDropSourceHook
|
||||
validateRelationship = validateRel @pgKind
|
||||
buildComputedFieldBooleanExp = Postgres.buildComputedFieldBooleanExp
|
||||
validateLogicalModel = Postgres.validateLogicalModel (pgTypeOidMapping @pgKind)
|
||||
validateNativeQuery = Postgres.validateNativeQuery (pgTypeOidMapping @pgKind)
|
||||
supportsBeingRemoteRelationshipTarget _ = True
|
||||
|
||||
listAllTables sourceName = do
|
||||
|
@ -1,7 +1,7 @@
|
||||
-- | Validate logical models against postgres-like flavors.
|
||||
module Hasura.Backends.Postgres.Instances.LogicalModels
|
||||
( validateLogicalModel,
|
||||
logicalModelToPreparedStatement,
|
||||
-- | Validate native queries against postgres-like flavors.
|
||||
module Hasura.Backends.Postgres.Instances.NativeQueries
|
||||
( validateNativeQuery,
|
||||
nativeQueryToPreparedStatement,
|
||||
)
|
||||
where
|
||||
|
||||
@ -27,28 +27,28 @@ import Hasura.Backends.Postgres.Instances.Types ()
|
||||
import Hasura.Backends.Postgres.SQL.Types (PGScalarType (..), pgScalarTypeToText)
|
||||
import Hasura.Base.Error
|
||||
import Hasura.CustomReturnType.Metadata (CustomReturnTypeMetadata (..))
|
||||
import Hasura.LogicalModel.Metadata
|
||||
import Hasura.NativeQuery.Metadata
|
||||
( InterpolatedItem (..),
|
||||
InterpolatedQuery (..),
|
||||
LogicalModelArgumentName,
|
||||
LogicalModelMetadata (..),
|
||||
NativeQueryArgumentName,
|
||||
NativeQueryMetadata (..),
|
||||
)
|
||||
import Hasura.LogicalModel.Types (NullableScalarType (nstType), getLogicalModelName)
|
||||
import Hasura.NativeQuery.Types (NullableScalarType (nstType), getNativeQueryName)
|
||||
import Hasura.Prelude
|
||||
import Hasura.SQL.Backend
|
||||
|
||||
-- | Prepare a logical model query against a postgres-like database to validate it.
|
||||
validateLogicalModel ::
|
||||
-- | Prepare a native query query against a postgres-like database to validate it.
|
||||
validateNativeQuery ::
|
||||
forall m pgKind.
|
||||
(MonadIO m, MonadError QErr m) =>
|
||||
InsOrd.InsOrdHashMap PGScalarType PQ.Oid ->
|
||||
Env.Environment ->
|
||||
PG.PostgresConnConfiguration ->
|
||||
CustomReturnTypeMetadata ('Postgres pgKind) ->
|
||||
LogicalModelMetadata ('Postgres pgKind) ->
|
||||
NativeQueryMetadata ('Postgres pgKind) ->
|
||||
m ()
|
||||
validateLogicalModel pgTypeOidMapping env connConf customReturnType model = do
|
||||
(prepname, preparedQuery) <- logicalModelToPreparedStatement customReturnType model
|
||||
validateNativeQuery pgTypeOidMapping env connConf customReturnType model = do
|
||||
(prepname, preparedQuery) <- nativeQueryToPreparedStatement customReturnType model
|
||||
description <- runCheck prepname (PG.fromText preparedQuery)
|
||||
let returnColumns = bimap toTxt nstType <$> InsOrd.toList (_crtmFields customReturnType)
|
||||
for_ (toList returnColumns) (matchTypes description)
|
||||
@ -135,20 +135,20 @@ invertPgTypeOidMap = Map.fromList . map swap . InsOrd.toList
|
||||
-- | The environment and fresh-name generator used by 'renameIQ'.
|
||||
data RenamingState = RenamingState
|
||||
{ rsNextFree :: Int,
|
||||
rsBoundVars :: Map LogicalModelArgumentName Int
|
||||
rsBoundVars :: Map NativeQueryArgumentName Int
|
||||
}
|
||||
|
||||
-- | 'Rename' an 'InterpolatedQuery' expression with 'LogicalModelArgumentName' variables
|
||||
-- | 'Rename' an 'InterpolatedQuery' expression with 'NativeQueryArgumentName' variables
|
||||
-- into one which uses ordinal arguments instead of named arguments, suitable
|
||||
-- for a prepared query.
|
||||
renameIQ ::
|
||||
InterpolatedQuery LogicalModelArgumentName ->
|
||||
InterpolatedQuery NativeQueryArgumentName ->
|
||||
( InterpolatedQuery Int,
|
||||
Map Int LogicalModelArgumentName
|
||||
Map Int NativeQueryArgumentName
|
||||
)
|
||||
renameIQ = runRenaming . fmap InterpolatedQuery . mapM renameII . getInterpolatedQuery
|
||||
where
|
||||
runRenaming :: forall a. State RenamingState a -> (a, Map Int LogicalModelArgumentName)
|
||||
runRenaming :: forall a. State RenamingState a -> (a, Map Int NativeQueryArgumentName)
|
||||
runRenaming action =
|
||||
let (res, st) = runState action (RenamingState 1 mempty)
|
||||
in (res, inverseMap $ rsBoundVars st)
|
||||
@ -163,7 +163,7 @@ renameIQ = runRenaming . fmap InterpolatedQuery . mapM renameII . getInterpolate
|
||||
-- variables and reusing the previously assigned indices when encountering a
|
||||
-- previously treated variable accordingly.
|
||||
renameII ::
|
||||
InterpolatedItem LogicalModelArgumentName ->
|
||||
InterpolatedItem NativeQueryArgumentName ->
|
||||
State RenamingState (InterpolatedItem Int)
|
||||
renameII = traverse \v -> do
|
||||
env <- gets rsBoundVars
|
||||
@ -193,29 +193,29 @@ renderIQ (InterpolatedQuery items) = foldMap printItem items
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
-- | Convert a logical model to a prepared statement to be validate.
|
||||
-- | Convert a native query to a prepared statement to be validate.
|
||||
--
|
||||
-- Used by 'validateLogicalModel'. Exported for testing.
|
||||
logicalModelToPreparedStatement ::
|
||||
-- Used by 'validateNativeQuery'. Exported for testing.
|
||||
nativeQueryToPreparedStatement ::
|
||||
forall m pgKind.
|
||||
MonadError QErr m =>
|
||||
CustomReturnTypeMetadata ('Postgres pgKind) ->
|
||||
LogicalModelMetadata ('Postgres pgKind) ->
|
||||
NativeQueryMetadata ('Postgres pgKind) ->
|
||||
m (BS.ByteString, Text)
|
||||
logicalModelToPreparedStatement customReturnType model = do
|
||||
let name = getLogicalModelName $ _lmmRootFieldName model
|
||||
let (preparedIQ, argumentMapping) = renameIQ $ _lmmCode model
|
||||
nativeQueryToPreparedStatement customReturnType model = do
|
||||
let name = getNativeQueryName $ _nqmRootFieldName model
|
||||
let (preparedIQ, argumentMapping) = renameIQ $ _nqmCode model
|
||||
logimoCode :: Text
|
||||
logimoCode = renderIQ preparedIQ
|
||||
prepname = "_logimo_vali_" <> toTxt name
|
||||
|
||||
occurringArguments, declaredArguments, undeclaredArguments :: Set LogicalModelArgumentName
|
||||
occurringArguments, declaredArguments, undeclaredArguments :: Set NativeQueryArgumentName
|
||||
occurringArguments = Set.fromList (Map.elems argumentMapping)
|
||||
declaredArguments = Set.fromList $ HashMap.keys (_lmmArguments model)
|
||||
declaredArguments = Set.fromList $ HashMap.keys (_nqmArguments model)
|
||||
undeclaredArguments = occurringArguments `Set.difference` declaredArguments
|
||||
|
||||
argumentTypes :: Map Int PGScalarType
|
||||
argumentTypes = nstType <$> Map.fromList (HashMap.toList $ _lmmArguments model) `Map.compose` argumentMapping
|
||||
argumentTypes = nstType <$> Map.fromList (HashMap.toList $ _nqmArguments model) `Map.compose` argumentMapping
|
||||
|
||||
argumentSignature
|
||||
| argumentTypes /= mempty = "(" <> commaSeparated (pgScalarTypeToText <$> Map.elems argumentTypes) <> ")"
|
@ -66,8 +66,8 @@ import Hasura.GraphQL.Schema.Parser qualified as P
|
||||
import Hasura.GraphQL.Schema.Select
|
||||
import Hasura.GraphQL.Schema.Update qualified as SU
|
||||
import Hasura.GraphQL.Schema.Update.Batch qualified as SUB
|
||||
import Hasura.LogicalModel.Schema qualified as LogicalModels
|
||||
import Hasura.Name qualified as Name
|
||||
import Hasura.NativeQuery.Schema qualified as NativeQueries
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.BoolExp
|
||||
import Hasura.RQL.IR.Root (RemoteRelationshipField)
|
||||
@ -307,7 +307,7 @@ instance
|
||||
buildFunctionQueryFields = buildFunctionQueryFieldsPG
|
||||
buildFunctionRelayQueryFields = pgkBuildFunctionRelayQueryFields
|
||||
buildFunctionMutationFields = buildFunctionMutationFieldsPG
|
||||
buildLogicalModelRootFields = LogicalModels.defaultBuildLogicalModelRootFields
|
||||
buildNativeQueryRootFields = NativeQueries.defaultBuildNativeQueryRootFields
|
||||
|
||||
mkRelationshipParser = GSB.mkDefaultRelationshipParser backendInsertParser ()
|
||||
|
||||
|
@ -114,7 +114,7 @@ import Data.String (fromString)
|
||||
import Data.Text (pack)
|
||||
import Data.Text.Extended
|
||||
import Hasura.Backends.Postgres.SQL.Types
|
||||
import Hasura.LogicalModel.Metadata
|
||||
import Hasura.NativeQuery.Metadata
|
||||
import Hasura.Prelude
|
||||
import Hasura.SQL.Types
|
||||
import Text.Builder qualified as TB
|
||||
|
@ -20,7 +20,7 @@ module Hasura.Backends.Postgres.Translate.Select.Internal.Helpers
|
||||
selectToSelectWith,
|
||||
customSQLToTopLevelCTEs,
|
||||
customSQLToInnerCTEs,
|
||||
logicalModelNameToAlias,
|
||||
nativeQueryNameToAlias,
|
||||
toQuery,
|
||||
)
|
||||
where
|
||||
@ -43,8 +43,8 @@ import Hasura.Backends.Postgres.Translate.Select.Internal.Aliases
|
||||
import Hasura.Backends.Postgres.Translate.Types (CustomSQLCTEs (..))
|
||||
import Hasura.Backends.Postgres.Types.Function
|
||||
import Hasura.Function.Cache
|
||||
import Hasura.LogicalModel.IR (LogicalModel (..))
|
||||
import Hasura.LogicalModel.Metadata (LogicalModelName (..))
|
||||
import Hasura.NativeQuery.IR (NativeQuery (..))
|
||||
import Hasura.NativeQuery.Metadata (NativeQueryName (..))
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR
|
||||
import Hasura.RQL.Types.Common (FieldName)
|
||||
@ -129,12 +129,12 @@ selectFromToFromItem prefix = \case
|
||||
S.mkFunctionAlias
|
||||
qf
|
||||
(fmap (fmap (first S.toColumnAlias)) defListM)
|
||||
FromLogicalModel lm ->
|
||||
S.FIIdentifier (S.tableAliasToIdentifier $ logicalModelNameToAlias (lmRootFieldName lm))
|
||||
FromNativeQuery lm ->
|
||||
S.FIIdentifier (S.tableAliasToIdentifier $ nativeQueryNameToAlias (nqRootFieldName lm))
|
||||
|
||||
-- | Given a @LogicalModelName@, what should we call the CTE generated for it?
|
||||
logicalModelNameToAlias :: LogicalModelName -> S.TableAlias
|
||||
logicalModelNameToAlias lmName = S.mkTableAlias ("cte_" <> toTxt (getLogicalModelName lmName))
|
||||
-- | Given a @NativeQueryName@, what should we call the CTE generated for it?
|
||||
nativeQueryNameToAlias :: NativeQueryName -> S.TableAlias
|
||||
nativeQueryNameToAlias nqName = S.mkTableAlias ("cte_" <> toTxt (getNativeQueryName nqName))
|
||||
|
||||
-- | Converts a function name to an 'Identifier'.
|
||||
--
|
||||
|
@ -64,7 +64,7 @@ import Hasura.Backends.Postgres.Translate.Select.Internal.Helpers
|
||||
fromTableRowArgs,
|
||||
hasNextPageIdentifier,
|
||||
hasPreviousPageIdentifier,
|
||||
logicalModelNameToAlias,
|
||||
nativeQueryNameToAlias,
|
||||
pageInfoSelectAliasIdentifier,
|
||||
selectFromToFromItem,
|
||||
startCursorIdentifier,
|
||||
@ -81,7 +81,7 @@ import Hasura.Backends.Postgres.Translate.Types
|
||||
import Hasura.GraphQL.Schema.NamingCase (NamingCase)
|
||||
import Hasura.GraphQL.Schema.Node (currentNodeIdVersion, nodeIdVersionInt)
|
||||
import Hasura.GraphQL.Schema.Options qualified as Options
|
||||
import Hasura.LogicalModel.IR (LogicalModel (..))
|
||||
import Hasura.NativeQuery.IR (NativeQuery (..))
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.BoolExp
|
||||
import Hasura.RQL.IR.OrderBy (OrderByItemG (OrderByItemG, obiColumn))
|
||||
@ -168,15 +168,15 @@ processSelectParams
|
||||
FromTable table -> pure $ S.QualTable table
|
||||
FromIdentifier i -> pure $ S.QualifiedIdentifier (TableIdentifier $ unFIIdentifier i) Nothing
|
||||
FromFunction qf _ _ -> pure $ S.QualifiedIdentifier (TableIdentifier $ qualifiedObjectToText qf) Nothing
|
||||
FromLogicalModel lm -> do
|
||||
FromNativeQuery lm -> do
|
||||
-- we are going to cram our SQL in a CTE, and this is what we will call it
|
||||
let cteName = logicalModelNameToAlias (lmRootFieldName lm)
|
||||
let cteName = nativeQueryNameToAlias (nqRootFieldName lm)
|
||||
|
||||
-- emit the query itself to the Writer
|
||||
tell $
|
||||
mempty
|
||||
{ _swCustomSQLCTEs =
|
||||
CustomSQLCTEs (HM.singleton cteName (lmInterpolatedQuery lm))
|
||||
CustomSQLCTEs (HM.singleton cteName (nqInterpolatedQuery lm))
|
||||
}
|
||||
|
||||
pure $ S.QualifiedIdentifier (S.tableAliasToIdentifier cteName) Nothing
|
||||
|
@ -34,7 +34,7 @@ import Data.HashMap.Strict qualified as HM
|
||||
import Data.Int (Int64)
|
||||
import Hasura.Backends.Postgres.SQL.DML qualified as Postgres
|
||||
import Hasura.Backends.Postgres.SQL.Types qualified as Postgres
|
||||
import Hasura.LogicalModel.Metadata (InterpolatedQuery)
|
||||
import Hasura.NativeQuery.Metadata (InterpolatedQuery)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.Select
|
||||
import Hasura.RQL.Types.Common
|
||||
|
@ -29,9 +29,9 @@ import Hasura.Base.Error
|
||||
import Hasura.CustomReturnType.Metadata (CustomReturnTypeMetadata (..), crtmSelectPermissions)
|
||||
import Hasura.CustomReturnType.Types (CustomReturnTypeName)
|
||||
import Hasura.EncJSON
|
||||
import Hasura.LogicalModel.Metadata (LogicalModelMetadata (..))
|
||||
import Hasura.LogicalModel.Types (NullableScalarType, nullableScalarTypeMapCodec)
|
||||
import Hasura.Metadata.DTO.Utils (codecNamePrefix)
|
||||
import Hasura.NativeQuery.Metadata (NativeQueryMetadata (..))
|
||||
import Hasura.NativeQuery.Types (NullableScalarType, nullableScalarTypeMapCodec)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend (Backend (..))
|
||||
import Hasura.RQL.Types.Common (SourceName, defaultSource, sourceNameToText, successMsg)
|
||||
@ -228,16 +228,16 @@ runUntrackCustomReturnType q = do
|
||||
|
||||
metadata <- getMetadata
|
||||
|
||||
let logicalModels :: [LogicalModelMetadata b]
|
||||
logicalModels = metadata ^.. metaSources . ix source . toSourceMetadata @b . smLogicalModels . traversed
|
||||
let nativeQueries :: [NativeQueryMetadata b]
|
||||
nativeQueries = metadata ^.. metaSources . ix source . toSourceMetadata @b . smNativeQueries . traversed
|
||||
|
||||
case find ((== fieldName) . _lmmReturns) logicalModels of
|
||||
Just LogicalModelMetadata {_lmmRootFieldName} ->
|
||||
case find ((== fieldName) . _nqmReturns) nativeQueries of
|
||||
Just NativeQueryMetadata {_nqmRootFieldName} ->
|
||||
throw400 ConstraintViolation $
|
||||
"Custom type "
|
||||
<> fieldName
|
||||
<<> " still being used by logical model "
|
||||
<> _lmmRootFieldName <<> "."
|
||||
<<> " still being used by native query "
|
||||
<> _nqmRootFieldName <<> "."
|
||||
Nothing -> pure ()
|
||||
|
||||
buildSchemaCacheFor metadataObj $
|
||||
@ -340,7 +340,7 @@ dropCustomReturnTypeInMetadata source name = do
|
||||
-- | check feature flag is enabled before carrying out any actions
|
||||
throwIfFeatureDisabled :: (HasFeatureFlagChecker m, MonadError QErr m) => m ()
|
||||
throwIfFeatureDisabled = do
|
||||
enableCustomReturnTypes <- checkFlag FF.logicalModelInterface
|
||||
enableCustomReturnTypes <- checkFlag FF.nativeQueryInterface
|
||||
unless enableCustomReturnTypes $ throw500 "CustomReturnTypes is disabled!"
|
||||
|
||||
-- | Check whether a custom return type with the given root field name exists for
|
||||
|
@ -15,7 +15,7 @@ import Control.Lens (makeLenses)
|
||||
import Data.Aeson (ToJSON (..), genericToJSON)
|
||||
import Data.HashMap.Strict.InsOrd qualified as InsOrd
|
||||
import Hasura.CustomReturnType.Types (CustomReturnTypeName)
|
||||
import Hasura.LogicalModel.Types (NullableScalarType (..))
|
||||
import Hasura.NativeQuery.Types (NullableScalarType (..))
|
||||
import Hasura.Prelude hiding (first)
|
||||
import Hasura.RQL.Types.Backend (Backend (..))
|
||||
import Hasura.RQL.Types.Table (RolePermInfoMap)
|
||||
|
@ -5,7 +5,7 @@ where
|
||||
|
||||
import Data.HashMap.Strict.InsOrd qualified as InsOrd
|
||||
import Data.Text.Extended (ToTxt (toTxt))
|
||||
import Hasura.LogicalModel.Types (NullableScalarType (..))
|
||||
import Hasura.NativeQuery.Types (NullableScalarType (..))
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend (Backend (..))
|
||||
import Hasura.RQL.Types.Column (ColumnInfo (..), ColumnMutability (..), ColumnType (..))
|
||||
|
@ -7,7 +7,7 @@ where
|
||||
|
||||
import Data.HashMap.Strict.InsOrd qualified as InsOrd
|
||||
import Hasura.CustomReturnType.Types (CustomReturnTypeName)
|
||||
import Hasura.LogicalModel.Types (NullableScalarType (..))
|
||||
import Hasura.NativeQuery.Types (NullableScalarType (..))
|
||||
import Hasura.Prelude hiding (first)
|
||||
import Hasura.RQL.Types.Backend (Backend (..))
|
||||
import Hasura.SQL.Backend (BackendType)
|
||||
|
@ -20,8 +20,8 @@ import Data.Aeson qualified as Aeson
|
||||
import Data.HashMap.Strict.InsOrd qualified as InsOrd
|
||||
import Data.HashMap.Strict.InsOrd.Autodocodec (sortedElemsCodec)
|
||||
import Hasura.CustomReturnType.Types
|
||||
import Hasura.LogicalModel.Types (NullableScalarType (..), nullableScalarTypeMapCodec)
|
||||
import Hasura.Metadata.DTO.Utils (codecNamePrefix)
|
||||
import Hasura.NativeQuery.Types (NullableScalarType (..), nullableScalarTypeMapCodec)
|
||||
import Hasura.Prelude hiding (first)
|
||||
import Hasura.RQL.Types.Backend (Backend (..))
|
||||
import Hasura.RQL.Types.Common (SourceName, ToAesonPairs (toAesonPairs), defaultSource)
|
||||
@ -76,7 +76,7 @@ deriving stock instance (Backend b) => Eq (CustomReturnTypeMetadata b)
|
||||
|
||||
deriving stock instance (Backend b) => Show (CustomReturnTypeMetadata b)
|
||||
|
||||
-- | A wrapper to tie something to a particular logical model. Specifically, it
|
||||
-- | A wrapper to tie something to a particular native query. Specifically, it
|
||||
-- assumes the underlying '_wlmInfo' is represented as an object, and adds two
|
||||
-- keys to that object: @source@ and @root_field_name@.
|
||||
data WithCustomReturnType a = WithCustomReturnType
|
||||
|
@ -319,7 +319,7 @@ processEventQueue logger statsLogger httpMgr getSchemaCache getEventEngineCtx ac
|
||||
events <- liftIO . fmap concat $
|
||||
-- fetch pending events across all the sources asynchronously
|
||||
LA.forConcurrently (M.toList allSources) \(sourceName, sourceCache) ->
|
||||
AB.dispatchAnyBackend @BackendEventTrigger sourceCache \(SourceInfo _sourceName tableCache _functionCache _logicalModelCache _customReturnTypeCache sourceConfig _queryTagsConfig _sourceCustomization :: SourceInfo b) -> do
|
||||
AB.dispatchAnyBackend @BackendEventTrigger sourceCache \(SourceInfo _sourceName tableCache _functionCache _nativeQueryCache _customReturnTypeCache sourceConfig _queryTagsConfig _sourceCustomization :: SourceInfo b) -> do
|
||||
let tables = M.elems tableCache
|
||||
triggerMap = _tiEventTriggerInfoMap <$> tables
|
||||
eventTriggerCount = sum (M.size <$> triggerMap)
|
||||
|
@ -46,8 +46,8 @@ import Hasura.GraphQL.Schema.Remote (buildRemoteParser)
|
||||
import Hasura.GraphQL.Schema.RemoteRelationship
|
||||
import Hasura.GraphQL.Schema.Table
|
||||
import Hasura.GraphQL.Schema.Typename (MkTypename (..))
|
||||
import Hasura.LogicalModel.Cache (LogicalModelCache, _lmiReturns)
|
||||
import Hasura.Name qualified as Name
|
||||
import Hasura.NativeQuery.Cache (NativeQueryCache, _nqiReturns)
|
||||
import Hasura.Prelude
|
||||
import Hasura.QueryTags.Types
|
||||
import Hasura.RQL.IR
|
||||
@ -348,15 +348,15 @@ buildRoleContext options sources remotes actions customTypes role remoteSchemaPe
|
||||
[FieldParser P.Parse (NamespacedField (QueryRootField UnpreparedValue))], -- subscription fields
|
||||
[(G.Name, Parser 'Output P.Parse (ApolloFederationParserFunction P.Parse))] -- apollo federation tables
|
||||
)
|
||||
buildSource schemaContext schemaOptions sourceInfo@(SourceInfo _ tables functions logicalModels _customReturnTypes _ _ sourceCustomization) =
|
||||
buildSource schemaContext schemaOptions sourceInfo@(SourceInfo _ tables functions nativeQueries _customReturnTypes _ _ sourceCustomization) =
|
||||
runSourceSchema schemaContext schemaOptions sourceInfo do
|
||||
let validFunctions = takeValidFunctions functions
|
||||
validLogicalModels = takeValidLogicalModels logicalModels
|
||||
validNativeQueries = takeValidNativeQueries nativeQueries
|
||||
validTables = takeValidTables tables
|
||||
mkRootFieldName = _rscRootFields sourceCustomization
|
||||
makeTypename = SC._rscTypeNames sourceCustomization
|
||||
(uncustomizedQueryRootFields, uncustomizedSubscriptionRootFields, apolloFedTableParsers) <-
|
||||
buildQueryAndSubscriptionFields mkRootFieldName sourceInfo validTables validFunctions validLogicalModels
|
||||
buildQueryAndSubscriptionFields mkRootFieldName sourceInfo validTables validFunctions validNativeQueries
|
||||
(,,,,apolloFedTableParsers)
|
||||
<$> customizeFields
|
||||
sourceCustomization
|
||||
@ -470,7 +470,7 @@ buildRelayRoleContext options sources actions customTypes role expFeatures = do
|
||||
[FieldParser P.Parse (NamespacedField (MutationRootField UnpreparedValue))],
|
||||
[FieldParser P.Parse (NamespacedField (QueryRootField UnpreparedValue))]
|
||||
)
|
||||
buildSource schemaContext schemaOptions sourceInfo@(SourceInfo _ tables functions _logicalModels _customReturnTypes _ _ sourceCustomization) = do
|
||||
buildSource schemaContext schemaOptions sourceInfo@(SourceInfo _ tables functions _nativeQueries _customReturnTypes _ _ sourceCustomization) = do
|
||||
runSourceSchema schemaContext schemaOptions sourceInfo do
|
||||
let validFunctions = takeValidFunctions functions
|
||||
validTables = takeValidTables tables
|
||||
@ -667,7 +667,7 @@ buildQueryAndSubscriptionFields ::
|
||||
SourceInfo b ->
|
||||
TableCache b ->
|
||||
FunctionCache b ->
|
||||
LogicalModelCache b ->
|
||||
NativeQueryCache b ->
|
||||
SchemaT
|
||||
r
|
||||
m
|
||||
@ -675,7 +675,7 @@ buildQueryAndSubscriptionFields ::
|
||||
[P.FieldParser n (SubscriptionRootField UnpreparedValue)],
|
||||
[(G.Name, Parser 'Output n (ApolloFederationParserFunction n))]
|
||||
)
|
||||
buildQueryAndSubscriptionFields mkRootFieldName sourceInfo tables (takeExposedAs FEAQuery -> functions) logicalModels = do
|
||||
buildQueryAndSubscriptionFields mkRootFieldName sourceInfo tables (takeExposedAs FEAQuery -> functions) nativeQueries = do
|
||||
roleName <- retrieve scRole
|
||||
functionPermsCtx <- retrieve Options.soInferFunctionPermissions
|
||||
functionSelectExpParsers <-
|
||||
@ -687,8 +687,8 @@ buildQueryAndSubscriptionFields mkRootFieldName sourceInfo tables (takeExposedAs
|
||||
|| functionPermsCtx == Options.InferFunctionPermissions
|
||||
let targetTableName = _fiReturnType functionInfo
|
||||
lift $ mkRFs $ buildFunctionQueryFields mkRootFieldName functionName functionInfo targetTableName
|
||||
logicalModelRootFields <-
|
||||
buildLogicalModelFields sourceInfo logicalModels
|
||||
nativeQueryRootFields <-
|
||||
buildNativeQueryFields sourceInfo nativeQueries
|
||||
|
||||
(tableQueryFields, tableSubscriptionFields, apolloFedTableParsers) <-
|
||||
unzip3 . catMaybes
|
||||
@ -700,8 +700,8 @@ buildQueryAndSubscriptionFields mkRootFieldName sourceInfo tables (takeExposedAs
|
||||
tableSubscriptionRootFields = fmap mkRF $ concat tableSubscriptionFields
|
||||
|
||||
pure
|
||||
( tableQueryRootFields <> functionSelectExpParsers <> logicalModelRootFields,
|
||||
tableSubscriptionRootFields <> functionSelectExpParsers <> logicalModelRootFields,
|
||||
( tableQueryRootFields <> functionSelectExpParsers <> nativeQueryRootFields,
|
||||
tableSubscriptionRootFields <> functionSelectExpParsers <> nativeQueryRootFields,
|
||||
catMaybes apolloFedTableParsers
|
||||
)
|
||||
where
|
||||
@ -714,25 +714,25 @@ buildQueryAndSubscriptionFields mkRootFieldName sourceInfo tables (takeExposedAs
|
||||
runMaybeTmempty :: (Monad m, Monoid a) => MaybeT m a -> m a
|
||||
runMaybeTmempty = (`onNothingM` (pure mempty)) . runMaybeT
|
||||
|
||||
buildLogicalModelFields ::
|
||||
buildNativeQueryFields ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceInfo b ->
|
||||
LogicalModelCache b ->
|
||||
NativeQueryCache b ->
|
||||
SchemaT r m [P.FieldParser n (QueryRootField UnpreparedValue)]
|
||||
buildLogicalModelFields sourceInfo logicalModels = runMaybeTmempty $ do
|
||||
buildNativeQueryFields sourceInfo nativeQueries = runMaybeTmempty $ do
|
||||
roleName <- retrieve scRole
|
||||
|
||||
map mkRF . catMaybes <$> for (Map.elems logicalModels) \logicalModel -> do
|
||||
-- only include this logical model in the schema
|
||||
map mkRF . catMaybes <$> for (Map.elems nativeQueries) \nativeQuery -> do
|
||||
-- only include this native query in the schema
|
||||
-- if the current role is admin, or we have a select permission
|
||||
-- for this role (this is the broad strokes check. later, we'll filter
|
||||
-- more granularly on columns and then rows)
|
||||
guard $
|
||||
roleName == adminRoleName
|
||||
|| roleName `Map.member` _crtiPermissions (_lmiReturns logicalModel)
|
||||
|| roleName `Map.member` _crtiPermissions (_nqiReturns nativeQuery)
|
||||
|
||||
lift (buildLogicalModelRootFields logicalModel)
|
||||
lift (buildNativeQueryRootFields nativeQuery)
|
||||
where
|
||||
mkRF ::
|
||||
FieldParser n (QueryDB b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b)) ->
|
||||
|
@ -46,7 +46,7 @@ import Hasura.GraphQL.ApolloFederation (ApolloFederationParserFunction)
|
||||
import Hasura.GraphQL.Schema.Common
|
||||
import Hasura.GraphQL.Schema.NamingCase
|
||||
import Hasura.GraphQL.Schema.Parser hiding (Type)
|
||||
import Hasura.LogicalModel.Cache (LogicalModelInfo)
|
||||
import Hasura.NativeQuery.Cache (NativeQueryInfo)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR
|
||||
import Hasura.RQL.IR.Insert qualified as IR
|
||||
@ -183,14 +183,14 @@ class
|
||||
TableName b ->
|
||||
SchemaT r m [FieldParser n (MutationDB b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))]
|
||||
|
||||
buildLogicalModelRootFields ::
|
||||
buildNativeQueryRootFields ::
|
||||
MonadBuildSchema b r m n =>
|
||||
LogicalModelInfo b ->
|
||||
NativeQueryInfo b ->
|
||||
SchemaT
|
||||
r
|
||||
m
|
||||
(Maybe (FieldParser n (QueryDB b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))))
|
||||
buildLogicalModelRootFields _ = pure Nothing
|
||||
buildNativeQueryRootFields _ = pure Nothing
|
||||
|
||||
-- | Make a parser for relationships. Default implementaton elides
|
||||
-- relationships altogether.
|
||||
|
@ -42,7 +42,7 @@ module Hasura.GraphQL.Schema.Common
|
||||
parsedSelectionsToFields,
|
||||
partialSQLExpToUnpreparedValue,
|
||||
requiredFieldParser,
|
||||
takeValidLogicalModels,
|
||||
takeValidNativeQueries,
|
||||
takeValidFunctions,
|
||||
takeValidTables,
|
||||
textToName,
|
||||
@ -75,7 +75,7 @@ import Hasura.GraphQL.Schema.Options (SchemaOptions)
|
||||
import Hasura.GraphQL.Schema.Options qualified as Options
|
||||
import Hasura.GraphQL.Schema.Parser qualified as P
|
||||
import Hasura.GraphQL.Schema.Typename
|
||||
import Hasura.LogicalModel.Cache (LogicalModelCache)
|
||||
import Hasura.NativeQuery.Cache (NativeQueryCache)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR qualified as IR
|
||||
import Hasura.RQL.IR.BoolExp
|
||||
@ -440,9 +440,9 @@ takeValidFunctions = Map.filter functionFilter
|
||||
where
|
||||
functionFilter = not . isSystemDefined . _fiSystemDefined
|
||||
|
||||
-- | Currently we do no validation on logical models in schema. Should we?
|
||||
takeValidLogicalModels :: forall b. LogicalModelCache b -> LogicalModelCache b
|
||||
takeValidLogicalModels = id
|
||||
-- | Currently we do no validation on native queries in schema. Should we?
|
||||
takeValidNativeQueries :: forall b. NativeQueryCache b -> NativeQueryCache b
|
||||
takeValidNativeQueries = id
|
||||
|
||||
-- root field builder helpers
|
||||
|
||||
|
@ -67,8 +67,8 @@ import Hasura.GraphQL.Schema.Parser
|
||||
import Hasura.GraphQL.Schema.Parser qualified as P
|
||||
import Hasura.GraphQL.Schema.Table
|
||||
import Hasura.GraphQL.Schema.Typename
|
||||
import Hasura.LogicalModel.Types (NullableScalarType (..))
|
||||
import Hasura.Name qualified as Name
|
||||
import Hasura.NativeQuery.Types (NullableScalarType (..))
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR qualified as IR
|
||||
import Hasura.RQL.IR.BoolExp
|
||||
|
@ -1,297 +0,0 @@
|
||||
{-# LANGUAGE UndecidableInstances #-}
|
||||
|
||||
-- | Define and handle v1/metadata API operations to track, untrack, and get logical models.
|
||||
module Hasura.LogicalModel.API
|
||||
( GetLogicalModel (..),
|
||||
TrackLogicalModel (..),
|
||||
UntrackLogicalModel (..),
|
||||
runGetLogicalModel,
|
||||
runTrackLogicalModel,
|
||||
runUntrackLogicalModel,
|
||||
dropLogicalModelInMetadata,
|
||||
module Hasura.LogicalModel.Types,
|
||||
)
|
||||
where
|
||||
|
||||
import Autodocodec (HasCodec)
|
||||
import Autodocodec qualified as AC
|
||||
import Control.Lens (Traversal', has, preview, (^?))
|
||||
import Data.Aeson
|
||||
import Data.Environment qualified as Env
|
||||
import Data.HashMap.Strict.InsOrd.Extended qualified as OMap
|
||||
import Data.Text.Extended (toTxt, (<<>))
|
||||
import Hasura.Base.Error
|
||||
import Hasura.CustomReturnType.API (getCustomTypes)
|
||||
import Hasura.CustomReturnType.Metadata (CustomReturnTypeName)
|
||||
import Hasura.EncJSON
|
||||
import Hasura.LogicalModel.Metadata (LogicalModelArgumentName, LogicalModelMetadata (..), parseInterpolatedQuery)
|
||||
import Hasura.LogicalModel.Types (LogicalModelName, NullableScalarType)
|
||||
import Hasura.Metadata.DTO.Utils (codecNamePrefix)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend (Backend, SourceConnConfiguration)
|
||||
import Hasura.RQL.Types.Common (SourceName, sourceNameToText, successMsg)
|
||||
import Hasura.RQL.Types.Metadata
|
||||
import Hasura.RQL.Types.Metadata.Backend
|
||||
import Hasura.RQL.Types.Metadata.Object
|
||||
import Hasura.RQL.Types.SchemaCache.Build
|
||||
import Hasura.SQL.AnyBackend qualified as AB
|
||||
import Hasura.SQL.Backend
|
||||
import Hasura.SQL.Tag
|
||||
import Hasura.Server.Init.FeatureFlag (HasFeatureFlagChecker (..))
|
||||
import Hasura.Server.Init.FeatureFlag qualified as FF
|
||||
|
||||
-- | Default implementation of the 'track_logical_model' request payload.
|
||||
data TrackLogicalModel (b :: BackendType) = TrackLogicalModel
|
||||
{ tlmSource :: SourceName,
|
||||
tlmRootFieldName :: LogicalModelName,
|
||||
tlmCode :: Text,
|
||||
tlmArguments :: HashMap LogicalModelArgumentName (NullableScalarType b),
|
||||
tlmDescription :: Maybe Text,
|
||||
tlmReturns :: CustomReturnTypeName
|
||||
}
|
||||
|
||||
instance (Backend b) => HasCodec (TrackLogicalModel b) where
|
||||
codec =
|
||||
AC.CommentCodec
|
||||
("A request to track a logical model")
|
||||
$ AC.object (codecNamePrefix @b <> "TrackLogicalModel")
|
||||
$ TrackLogicalModel
|
||||
<$> AC.requiredField "source" sourceDoc
|
||||
AC..= tlmSource
|
||||
<*> AC.requiredField "root_field_name" rootFieldDoc
|
||||
AC..= tlmRootFieldName
|
||||
<*> AC.requiredField "code" codeDoc
|
||||
AC..= tlmCode
|
||||
<*> AC.optionalFieldWithDefault "arguments" mempty argumentsDoc
|
||||
AC..= tlmArguments
|
||||
<*> AC.optionalField "description" descriptionDoc
|
||||
AC..= tlmDescription
|
||||
<*> AC.requiredField "returns" returnsDoc
|
||||
AC..= tlmReturns
|
||||
where
|
||||
sourceDoc = "The source in which this logical model should be tracked"
|
||||
rootFieldDoc = "Root field name for the logical model"
|
||||
codeDoc = "Native code expression (SQL) to run"
|
||||
argumentsDoc = "Free variables in the expression and their types"
|
||||
returnsDoc = "Return type (table) of the expression"
|
||||
descriptionDoc = "A description of the query which appears in the graphql schema"
|
||||
|
||||
deriving via
|
||||
(AC.Autodocodec (TrackLogicalModel b))
|
||||
instance
|
||||
(Backend b) => FromJSON (TrackLogicalModel b)
|
||||
|
||||
deriving via
|
||||
(AC.Autodocodec (TrackLogicalModel b))
|
||||
instance
|
||||
(Backend b) => ToJSON (TrackLogicalModel b)
|
||||
|
||||
-- | Validate a logical model and extract the logical model info from the request.
|
||||
logicalModelTrackToMetadata ::
|
||||
forall b m.
|
||||
( BackendMetadata b,
|
||||
MonadError QErr m,
|
||||
MonadIO m,
|
||||
MetadataM m
|
||||
) =>
|
||||
Env.Environment ->
|
||||
SourceConnConfiguration b ->
|
||||
TrackLogicalModel b ->
|
||||
m (LogicalModelMetadata b)
|
||||
logicalModelTrackToMetadata env sourceConnConfig TrackLogicalModel {..} = do
|
||||
code <- parseInterpolatedQuery tlmCode `onLeft` \e -> throw400 ParseFailed e
|
||||
|
||||
let logicalModelMetadata =
|
||||
LogicalModelMetadata
|
||||
{ _lmmRootFieldName = tlmRootFieldName,
|
||||
_lmmCode = code,
|
||||
_lmmReturns = tlmReturns,
|
||||
_lmmArguments = tlmArguments,
|
||||
_lmmDescription = tlmDescription
|
||||
}
|
||||
|
||||
metadata <- getMetadata
|
||||
|
||||
-- lookup custom return type in existing metadata
|
||||
case metadata ^? getCustomTypes tlmSource . ix tlmReturns of
|
||||
Just customReturnType ->
|
||||
validateLogicalModel @b env sourceConnConfig customReturnType logicalModelMetadata
|
||||
Nothing -> throw400 NotFound ("Custom return type " <> tlmReturns <<> " not found.")
|
||||
|
||||
pure logicalModelMetadata
|
||||
|
||||
-- | API payload for the 'get_logical_model' endpoint.
|
||||
data GetLogicalModel (b :: BackendType) = GetLogicalModel
|
||||
{ glmSource :: SourceName
|
||||
}
|
||||
|
||||
deriving instance Backend b => Show (GetLogicalModel b)
|
||||
|
||||
deriving instance Backend b => Eq (GetLogicalModel b)
|
||||
|
||||
instance Backend b => FromJSON (GetLogicalModel b) where
|
||||
parseJSON = withObject "GetLogicalModel" $ \o -> do
|
||||
glmSource <- o .: "source"
|
||||
pure GetLogicalModel {..}
|
||||
|
||||
instance Backend b => ToJSON (GetLogicalModel b) where
|
||||
toJSON GetLogicalModel {..} =
|
||||
object
|
||||
[ "source" .= glmSource
|
||||
]
|
||||
|
||||
-- | Handler for the 'get_logical_model' endpoint.
|
||||
runGetLogicalModel ::
|
||||
forall b m.
|
||||
( BackendMetadata b,
|
||||
MetadataM m,
|
||||
HasFeatureFlagChecker m,
|
||||
MonadError QErr m
|
||||
) =>
|
||||
GetLogicalModel b ->
|
||||
m EncJSON
|
||||
runGetLogicalModel q = do
|
||||
throwIfFeatureDisabled
|
||||
|
||||
metadata <- getMetadata
|
||||
|
||||
let logicalModel :: Maybe (LogicalModels b)
|
||||
logicalModel = metadata ^? metaSources . ix (glmSource q) . toSourceMetadata . smLogicalModels @b
|
||||
|
||||
pure (encJFromJValue (OMap.elems <$> logicalModel))
|
||||
|
||||
-- | Handler for the 'track_logical_model' endpoint. The type 'TrackLogicalModel b'
|
||||
-- (appearing here in wrapped as 'BackendTrackLogicalModel b' for 'AnyBackend'
|
||||
-- compatibility) is defined in 'class LogicalModelMetadata'.
|
||||
runTrackLogicalModel ::
|
||||
forall b m.
|
||||
( BackendMetadata b,
|
||||
MonadError QErr m,
|
||||
MonadIO m,
|
||||
CacheRWM m,
|
||||
MetadataM m,
|
||||
HasFeatureFlagChecker m
|
||||
) =>
|
||||
Env.Environment ->
|
||||
TrackLogicalModel b ->
|
||||
m EncJSON
|
||||
runTrackLogicalModel env trackLogicalModelRequest = do
|
||||
throwIfFeatureDisabled
|
||||
|
||||
sourceMetadata <-
|
||||
maybe
|
||||
( throw400 NotFound $
|
||||
"Source '"
|
||||
<> sourceNameToText source
|
||||
<> "' of kind "
|
||||
<> toTxt (reify (backendTag @b))
|
||||
<> " not found."
|
||||
)
|
||||
pure
|
||||
. preview (metaSources . ix source . toSourceMetadata @b)
|
||||
=<< getMetadata
|
||||
let sourceConnConfig = _smConfiguration sourceMetadata
|
||||
|
||||
(metadata :: LogicalModelMetadata b) <- do
|
||||
logicalModelTrackToMetadata @b env sourceConnConfig trackLogicalModelRequest
|
||||
|
||||
let fieldName = _lmmRootFieldName metadata
|
||||
metadataObj =
|
||||
MOSourceObjId source $
|
||||
AB.mkAnyBackend $
|
||||
SMOLogicalModel @b fieldName
|
||||
existingLogicalModels = OMap.keys (_smLogicalModels sourceMetadata)
|
||||
|
||||
when (fieldName `elem` existingLogicalModels) do
|
||||
throw400 AlreadyTracked $ "Logical model '" <> toTxt fieldName <> "' is already tracked."
|
||||
|
||||
buildSchemaCacheFor metadataObj $
|
||||
MetadataModifier $
|
||||
(metaSources . ix source . toSourceMetadata @b . smLogicalModels)
|
||||
%~ OMap.insert fieldName metadata
|
||||
|
||||
pure successMsg
|
||||
where
|
||||
source = tlmSource trackLogicalModelRequest
|
||||
|
||||
-- | API payload for the 'untrack_logical_model' endpoint.
|
||||
data UntrackLogicalModel (b :: BackendType) = UntrackLogicalModel
|
||||
{ utlmSource :: SourceName,
|
||||
utlmRootFieldName :: LogicalModelName
|
||||
}
|
||||
|
||||
deriving instance Show (UntrackLogicalModel b)
|
||||
|
||||
deriving instance Eq (UntrackLogicalModel b)
|
||||
|
||||
instance FromJSON (UntrackLogicalModel b) where
|
||||
parseJSON = withObject "UntrackLogicalModel" $ \o -> do
|
||||
utlmSource <- o .: "source"
|
||||
utlmRootFieldName <- o .: "root_field_name"
|
||||
pure UntrackLogicalModel {..}
|
||||
|
||||
instance ToJSON (UntrackLogicalModel b) where
|
||||
toJSON UntrackLogicalModel {..} =
|
||||
object
|
||||
[ "source" .= utlmSource,
|
||||
"root_field_name" .= utlmRootFieldName
|
||||
]
|
||||
|
||||
-- | Handler for the 'untrack_logical_model' endpoint.
|
||||
runUntrackLogicalModel ::
|
||||
forall b m.
|
||||
( BackendMetadata b,
|
||||
MonadError QErr m,
|
||||
CacheRWM m,
|
||||
MetadataM m
|
||||
) =>
|
||||
UntrackLogicalModel b ->
|
||||
m EncJSON
|
||||
runUntrackLogicalModel q = do
|
||||
-- we do not check for feature flag here as we always want users to be able
|
||||
-- to remove logical models if they'd like
|
||||
assertLogicalModelExists @b source fieldName
|
||||
|
||||
let metadataObj =
|
||||
MOSourceObjId source $
|
||||
AB.mkAnyBackend $
|
||||
SMOLogicalModel @b fieldName
|
||||
|
||||
buildSchemaCacheFor metadataObj $
|
||||
dropLogicalModelInMetadata @b source fieldName
|
||||
|
||||
pure successMsg
|
||||
where
|
||||
source = utlmSource q
|
||||
fieldName = utlmRootFieldName q
|
||||
|
||||
dropLogicalModelInMetadata :: forall b. BackendMetadata b => SourceName -> LogicalModelName -> MetadataModifier
|
||||
dropLogicalModelInMetadata source rootFieldName = do
|
||||
MetadataModifier $
|
||||
metaSources . ix source . toSourceMetadata @b . smLogicalModels
|
||||
%~ OMap.delete rootFieldName
|
||||
|
||||
-- | check feature flag is enabled before carrying out any actions
|
||||
throwIfFeatureDisabled :: (HasFeatureFlagChecker m, MonadError QErr m) => m ()
|
||||
throwIfFeatureDisabled = do
|
||||
enableLogicalModels <- checkFlag FF.logicalModelInterface
|
||||
unless enableLogicalModels (throw500 "LogicalModels is disabled!")
|
||||
|
||||
-- | Check whether a logical model with the given root field name exists for
|
||||
-- the given source.
|
||||
assertLogicalModelExists :: forall b m. (Backend b, MetadataM m, MonadError QErr m) => SourceName -> LogicalModelName -> m ()
|
||||
assertLogicalModelExists sourceName rootFieldName = do
|
||||
metadata <- getMetadata
|
||||
|
||||
let sourceMetadataTraversal :: Traversal' Metadata (SourceMetadata b)
|
||||
sourceMetadataTraversal = metaSources . ix sourceName . toSourceMetadata @b
|
||||
|
||||
sourceMetadata <-
|
||||
preview sourceMetadataTraversal metadata
|
||||
`onNothing` throw400 NotFound ("Source " <> sourceName <<> " not found.")
|
||||
|
||||
let desiredLogicalModel :: Traversal' (SourceMetadata b) (LogicalModelMetadata b)
|
||||
desiredLogicalModel = smLogicalModels . ix rootFieldName
|
||||
|
||||
unless (has desiredLogicalModel sourceMetadata) do
|
||||
throw400 NotFound ("Logical model " <> rootFieldName <<> " not found in source " <> sourceName <<> ".")
|
@ -1,45 +0,0 @@
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE UndecidableInstances #-}
|
||||
|
||||
-- | The representation of logical models as derived from the schema cache.
|
||||
module Hasura.LogicalModel.Cache
|
||||
( LogicalModelInfo (..),
|
||||
LogicalModelCache,
|
||||
lmiRootFieldName,
|
||||
lmiCode,
|
||||
lmiReturns,
|
||||
lmiArguments,
|
||||
lmiDescription,
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Lens (makeLenses)
|
||||
import Data.Aeson (ToJSON (toJSON), genericToJSON)
|
||||
import Hasura.CustomReturnType.Cache (CustomReturnTypeInfo)
|
||||
import Hasura.LogicalModel.Metadata (InterpolatedQuery, LogicalModelArgumentName, LogicalModelName)
|
||||
import Hasura.LogicalModel.Types (NullableScalarType)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend (Backend)
|
||||
import Hasura.RQL.Types.Table (RolePermInfoMap)
|
||||
import Hasura.SQL.Backend (BackendType)
|
||||
|
||||
type LogicalModelCache b = HashMap LogicalModelName (LogicalModelInfo b)
|
||||
|
||||
-- | The type into which 'LogicalModelMetadata' is resolved in
|
||||
-- 'Hasura/RQL/DDL/Schema/Cache.buildSchemaCacheRule'.
|
||||
data LogicalModelInfo (b :: BackendType) = LogicalModelInfo
|
||||
{ _lmiRootFieldName :: LogicalModelName,
|
||||
_lmiCode :: InterpolatedQuery LogicalModelArgumentName,
|
||||
_lmiReturns :: CustomReturnTypeInfo b,
|
||||
_lmiArguments :: HashMap LogicalModelArgumentName (NullableScalarType b),
|
||||
_lmiDescription :: Maybe Text
|
||||
}
|
||||
deriving stock (Generic)
|
||||
|
||||
instance
|
||||
(Backend b, ToJSON (RolePermInfoMap b)) =>
|
||||
ToJSON (LogicalModelInfo b)
|
||||
where
|
||||
toJSON = genericToJSON hasuraJSON
|
||||
|
||||
makeLenses ''LogicalModelInfo
|
@ -1,28 +0,0 @@
|
||||
-- | The RQL IR representation of an invocation of a logical model.
|
||||
module Hasura.LogicalModel.IR
|
||||
( LogicalModel (..),
|
||||
)
|
||||
where
|
||||
|
||||
import Hasura.CustomReturnType.IR
|
||||
import Hasura.LogicalModel.Metadata
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend
|
||||
import Hasura.RQL.Types.Column (ColumnValue)
|
||||
|
||||
-- | The RQL IR representation of an invocation of a logical model.
|
||||
data LogicalModel b field = LogicalModel
|
||||
{ -- | The graphql name of the logical model.
|
||||
lmRootFieldName :: LogicalModelName,
|
||||
-- | The raw sql to use in the query
|
||||
lmInterpolatedQuery :: InterpolatedQuery field,
|
||||
-- | The arguments passed to the query, if any.
|
||||
lmArgs :: HashMap LogicalModelArgumentName (ColumnValue b),
|
||||
-- | The return type of the logical model
|
||||
lmReturnType :: CustomReturnType b
|
||||
}
|
||||
deriving (Functor, Foldable, Traversable)
|
||||
|
||||
deriving instance (Backend b, Eq field) => Eq (LogicalModel b field)
|
||||
|
||||
deriving instance (Backend b, Show field) => Show (LogicalModel b field)
|
297
server/src-lib/Hasura/NativeQuery/API.hs
Normal file
297
server/src-lib/Hasura/NativeQuery/API.hs
Normal file
@ -0,0 +1,297 @@
|
||||
{-# LANGUAGE UndecidableInstances #-}
|
||||
|
||||
-- | Define and handle v1/metadata API operations to track, untrack, and get native queries.
|
||||
module Hasura.NativeQuery.API
|
||||
( GetNativeQuery (..),
|
||||
TrackNativeQuery (..),
|
||||
UntrackNativeQuery (..),
|
||||
runGetNativeQuery,
|
||||
runTrackNativeQuery,
|
||||
runUntrackNativeQuery,
|
||||
dropNativeQueryInMetadata,
|
||||
module Hasura.NativeQuery.Types,
|
||||
)
|
||||
where
|
||||
|
||||
import Autodocodec (HasCodec)
|
||||
import Autodocodec qualified as AC
|
||||
import Control.Lens (Traversal', has, preview, (^?))
|
||||
import Data.Aeson
|
||||
import Data.Environment qualified as Env
|
||||
import Data.HashMap.Strict.InsOrd.Extended qualified as OMap
|
||||
import Data.Text.Extended (toTxt, (<<>))
|
||||
import Hasura.Base.Error
|
||||
import Hasura.CustomReturnType.API (getCustomTypes)
|
||||
import Hasura.CustomReturnType.Metadata (CustomReturnTypeName)
|
||||
import Hasura.EncJSON
|
||||
import Hasura.Metadata.DTO.Utils (codecNamePrefix)
|
||||
import Hasura.NativeQuery.Metadata (NativeQueryArgumentName, NativeQueryMetadata (..), parseInterpolatedQuery)
|
||||
import Hasura.NativeQuery.Types (NativeQueryName, NullableScalarType)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend (Backend, SourceConnConfiguration)
|
||||
import Hasura.RQL.Types.Common (SourceName, sourceNameToText, successMsg)
|
||||
import Hasura.RQL.Types.Metadata
|
||||
import Hasura.RQL.Types.Metadata.Backend
|
||||
import Hasura.RQL.Types.Metadata.Object
|
||||
import Hasura.RQL.Types.SchemaCache.Build
|
||||
import Hasura.SQL.AnyBackend qualified as AB
|
||||
import Hasura.SQL.Backend
|
||||
import Hasura.SQL.Tag
|
||||
import Hasura.Server.Init.FeatureFlag (HasFeatureFlagChecker (..))
|
||||
import Hasura.Server.Init.FeatureFlag qualified as FF
|
||||
|
||||
-- | Default implementation of the 'track_native_query' request payload.
|
||||
data TrackNativeQuery (b :: BackendType) = TrackNativeQuery
|
||||
{ tnqSource :: SourceName,
|
||||
tnqRootFieldName :: NativeQueryName,
|
||||
tnqCode :: Text,
|
||||
tnqArguments :: HashMap NativeQueryArgumentName (NullableScalarType b),
|
||||
tnqDescription :: Maybe Text,
|
||||
tnqReturns :: CustomReturnTypeName
|
||||
}
|
||||
|
||||
instance (Backend b) => HasCodec (TrackNativeQuery b) where
|
||||
codec =
|
||||
AC.CommentCodec
|
||||
("A request to track a native query")
|
||||
$ AC.object (codecNamePrefix @b <> "TrackNativeQuery")
|
||||
$ TrackNativeQuery
|
||||
<$> AC.requiredField "source" sourceDoc
|
||||
AC..= tnqSource
|
||||
<*> AC.requiredField "root_field_name" rootFieldDoc
|
||||
AC..= tnqRootFieldName
|
||||
<*> AC.requiredField "code" codeDoc
|
||||
AC..= tnqCode
|
||||
<*> AC.optionalFieldWithDefault "arguments" mempty argumentsDoc
|
||||
AC..= tnqArguments
|
||||
<*> AC.optionalField "description" descriptionDoc
|
||||
AC..= tnqDescription
|
||||
<*> AC.requiredField "returns" returnsDoc
|
||||
AC..= tnqReturns
|
||||
where
|
||||
sourceDoc = "The source in which this native query should be tracked"
|
||||
rootFieldDoc = "Root field name for the native query"
|
||||
codeDoc = "Native code expression (SQL) to run"
|
||||
argumentsDoc = "Free variables in the expression and their types"
|
||||
returnsDoc = "Return type (table) of the expression"
|
||||
descriptionDoc = "A description of the query which appears in the graphql schema"
|
||||
|
||||
deriving via
|
||||
(AC.Autodocodec (TrackNativeQuery b))
|
||||
instance
|
||||
(Backend b) => FromJSON (TrackNativeQuery b)
|
||||
|
||||
deriving via
|
||||
(AC.Autodocodec (TrackNativeQuery b))
|
||||
instance
|
||||
(Backend b) => ToJSON (TrackNativeQuery b)
|
||||
|
||||
-- | Validate a native query and extract the native query info from the request.
|
||||
nativeQueryTrackToMetadata ::
|
||||
forall b m.
|
||||
( BackendMetadata b,
|
||||
MonadError QErr m,
|
||||
MonadIO m,
|
||||
MetadataM m
|
||||
) =>
|
||||
Env.Environment ->
|
||||
SourceConnConfiguration b ->
|
||||
TrackNativeQuery b ->
|
||||
m (NativeQueryMetadata b)
|
||||
nativeQueryTrackToMetadata env sourceConnConfig TrackNativeQuery {..} = do
|
||||
code <- parseInterpolatedQuery tnqCode `onLeft` \e -> throw400 ParseFailed e
|
||||
|
||||
let nativeQueryMetadata =
|
||||
NativeQueryMetadata
|
||||
{ _nqmRootFieldName = tnqRootFieldName,
|
||||
_nqmCode = code,
|
||||
_nqmReturns = tnqReturns,
|
||||
_nqmArguments = tnqArguments,
|
||||
_nqmDescription = tnqDescription
|
||||
}
|
||||
|
||||
metadata <- getMetadata
|
||||
|
||||
-- lookup custom return type in existing metadata
|
||||
case metadata ^? getCustomTypes tnqSource . ix tnqReturns of
|
||||
Just customReturnType ->
|
||||
validateNativeQuery @b env sourceConnConfig customReturnType nativeQueryMetadata
|
||||
Nothing -> throw400 NotFound ("Custom return type " <> tnqReturns <<> " not found.")
|
||||
|
||||
pure nativeQueryMetadata
|
||||
|
||||
-- | API payload for the 'get_native_query' endpoint.
|
||||
data GetNativeQuery (b :: BackendType) = GetNativeQuery
|
||||
{ gnqSource :: SourceName
|
||||
}
|
||||
|
||||
deriving instance Backend b => Show (GetNativeQuery b)
|
||||
|
||||
deriving instance Backend b => Eq (GetNativeQuery b)
|
||||
|
||||
instance Backend b => FromJSON (GetNativeQuery b) where
|
||||
parseJSON = withObject "GetNativeQuery" $ \o -> do
|
||||
gnqSource <- o .: "source"
|
||||
pure GetNativeQuery {..}
|
||||
|
||||
instance Backend b => ToJSON (GetNativeQuery b) where
|
||||
toJSON GetNativeQuery {..} =
|
||||
object
|
||||
[ "source" .= gnqSource
|
||||
]
|
||||
|
||||
-- | Handler for the 'get_native_query' endpoint.
|
||||
runGetNativeQuery ::
|
||||
forall b m.
|
||||
( BackendMetadata b,
|
||||
MetadataM m,
|
||||
HasFeatureFlagChecker m,
|
||||
MonadError QErr m
|
||||
) =>
|
||||
GetNativeQuery b ->
|
||||
m EncJSON
|
||||
runGetNativeQuery q = do
|
||||
throwIfFeatureDisabled
|
||||
|
||||
metadata <- getMetadata
|
||||
|
||||
let nativeQuery :: Maybe (NativeQueries b)
|
||||
nativeQuery = metadata ^? metaSources . ix (gnqSource q) . toSourceMetadata . smNativeQueries @b
|
||||
|
||||
pure (encJFromJValue (OMap.elems <$> nativeQuery))
|
||||
|
||||
-- | Handler for the 'track_native_query' endpoint. The type 'TrackNativeQuery b'
|
||||
-- (appearing here in wrapped as 'BackendTrackNativeQuery b' for 'AnyBackend'
|
||||
-- compatibility) is defined in 'class NativeQueryMetadata'.
|
||||
runTrackNativeQuery ::
|
||||
forall b m.
|
||||
( BackendMetadata b,
|
||||
MonadError QErr m,
|
||||
MonadIO m,
|
||||
CacheRWM m,
|
||||
MetadataM m,
|
||||
HasFeatureFlagChecker m
|
||||
) =>
|
||||
Env.Environment ->
|
||||
TrackNativeQuery b ->
|
||||
m EncJSON
|
||||
runTrackNativeQuery env trackNativeQueryRequest = do
|
||||
throwIfFeatureDisabled
|
||||
|
||||
sourceMetadata <-
|
||||
maybe
|
||||
( throw400 NotFound $
|
||||
"Source '"
|
||||
<> sourceNameToText source
|
||||
<> "' of kind "
|
||||
<> toTxt (reify (backendTag @b))
|
||||
<> " not found."
|
||||
)
|
||||
pure
|
||||
. preview (metaSources . ix source . toSourceMetadata @b)
|
||||
=<< getMetadata
|
||||
let sourceConnConfig = _smConfiguration sourceMetadata
|
||||
|
||||
(metadata :: NativeQueryMetadata b) <- do
|
||||
nativeQueryTrackToMetadata @b env sourceConnConfig trackNativeQueryRequest
|
||||
|
||||
let fieldName = _nqmRootFieldName metadata
|
||||
metadataObj =
|
||||
MOSourceObjId source $
|
||||
AB.mkAnyBackend $
|
||||
SMONativeQuery @b fieldName
|
||||
existingNativeQueries = OMap.keys (_smNativeQueries sourceMetadata)
|
||||
|
||||
when (fieldName `elem` existingNativeQueries) do
|
||||
throw400 AlreadyTracked $ "Native query '" <> toTxt fieldName <> "' is already tracked."
|
||||
|
||||
buildSchemaCacheFor metadataObj $
|
||||
MetadataModifier $
|
||||
(metaSources . ix source . toSourceMetadata @b . smNativeQueries)
|
||||
%~ OMap.insert fieldName metadata
|
||||
|
||||
pure successMsg
|
||||
where
|
||||
source = tnqSource trackNativeQueryRequest
|
||||
|
||||
-- | API payload for the 'untrack_native_query' endpoint.
|
||||
data UntrackNativeQuery (b :: BackendType) = UntrackNativeQuery
|
||||
{ utnqSource :: SourceName,
|
||||
utnqRootFieldName :: NativeQueryName
|
||||
}
|
||||
|
||||
deriving instance Show (UntrackNativeQuery b)
|
||||
|
||||
deriving instance Eq (UntrackNativeQuery b)
|
||||
|
||||
instance FromJSON (UntrackNativeQuery b) where
|
||||
parseJSON = withObject "UntrackNativeQuery" $ \o -> do
|
||||
utnqSource <- o .: "source"
|
||||
utnqRootFieldName <- o .: "root_field_name"
|
||||
pure UntrackNativeQuery {..}
|
||||
|
||||
instance ToJSON (UntrackNativeQuery b) where
|
||||
toJSON UntrackNativeQuery {..} =
|
||||
object
|
||||
[ "source" .= utnqSource,
|
||||
"root_field_name" .= utnqRootFieldName
|
||||
]
|
||||
|
||||
-- | Handler for the 'untrack_native_query' endpoint.
|
||||
runUntrackNativeQuery ::
|
||||
forall b m.
|
||||
( BackendMetadata b,
|
||||
MonadError QErr m,
|
||||
CacheRWM m,
|
||||
MetadataM m
|
||||
) =>
|
||||
UntrackNativeQuery b ->
|
||||
m EncJSON
|
||||
runUntrackNativeQuery q = do
|
||||
-- we do not check for feature flag here as we always want users to be able
|
||||
-- to remove native queries if they'd like
|
||||
assertNativeQueryExists @b source fieldName
|
||||
|
||||
let metadataObj =
|
||||
MOSourceObjId source $
|
||||
AB.mkAnyBackend $
|
||||
SMONativeQuery @b fieldName
|
||||
|
||||
buildSchemaCacheFor metadataObj $
|
||||
dropNativeQueryInMetadata @b source fieldName
|
||||
|
||||
pure successMsg
|
||||
where
|
||||
source = utnqSource q
|
||||
fieldName = utnqRootFieldName q
|
||||
|
||||
dropNativeQueryInMetadata :: forall b. BackendMetadata b => SourceName -> NativeQueryName -> MetadataModifier
|
||||
dropNativeQueryInMetadata source rootFieldName = do
|
||||
MetadataModifier $
|
||||
metaSources . ix source . toSourceMetadata @b . smNativeQueries
|
||||
%~ OMap.delete rootFieldName
|
||||
|
||||
-- | check feature flag is enabled before carrying out any actions
|
||||
throwIfFeatureDisabled :: (HasFeatureFlagChecker m, MonadError QErr m) => m ()
|
||||
throwIfFeatureDisabled = do
|
||||
enableNativeQueries <- checkFlag FF.nativeQueryInterface
|
||||
unless enableNativeQueries (throw500 "NativeQueries is disabled!")
|
||||
|
||||
-- | Check whether a native query with the given root field name exists for
|
||||
-- the given source.
|
||||
assertNativeQueryExists :: forall b m. (Backend b, MetadataM m, MonadError QErr m) => SourceName -> NativeQueryName -> m ()
|
||||
assertNativeQueryExists sourceName rootFieldName = do
|
||||
metadata <- getMetadata
|
||||
|
||||
let sourceMetadataTraversal :: Traversal' Metadata (SourceMetadata b)
|
||||
sourceMetadataTraversal = metaSources . ix sourceName . toSourceMetadata @b
|
||||
|
||||
sourceMetadata <-
|
||||
preview sourceMetadataTraversal metadata
|
||||
`onNothing` throw400 NotFound ("Source " <> sourceName <<> " not found.")
|
||||
|
||||
let desiredNativeQuery :: Traversal' (SourceMetadata b) (NativeQueryMetadata b)
|
||||
desiredNativeQuery = smNativeQueries . ix rootFieldName
|
||||
|
||||
unless (has desiredNativeQuery sourceMetadata) do
|
||||
throw400 NotFound ("Native query " <> rootFieldName <<> " not found in source " <> sourceName <<> ".")
|
45
server/src-lib/Hasura/NativeQuery/Cache.hs
Normal file
45
server/src-lib/Hasura/NativeQuery/Cache.hs
Normal file
@ -0,0 +1,45 @@
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE UndecidableInstances #-}
|
||||
|
||||
-- | The representation of native queries as derived from the schema cache.
|
||||
module Hasura.NativeQuery.Cache
|
||||
( NativeQueryInfo (..),
|
||||
NativeQueryCache,
|
||||
nqiRootFieldName,
|
||||
nqiCode,
|
||||
nqiReturns,
|
||||
nqiArguments,
|
||||
nqiDescription,
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Lens (makeLenses)
|
||||
import Data.Aeson (ToJSON (toJSON), genericToJSON)
|
||||
import Hasura.CustomReturnType.Cache (CustomReturnTypeInfo)
|
||||
import Hasura.NativeQuery.Metadata (InterpolatedQuery, NativeQueryArgumentName, NativeQueryName)
|
||||
import Hasura.NativeQuery.Types (NullableScalarType)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend (Backend)
|
||||
import Hasura.RQL.Types.Table (RolePermInfoMap)
|
||||
import Hasura.SQL.Backend (BackendType)
|
||||
|
||||
type NativeQueryCache b = HashMap NativeQueryName (NativeQueryInfo b)
|
||||
|
||||
-- | The type into which 'NativeQueryMetadata' is resolved in
|
||||
-- 'Hasura/RQL/DDL/Schema/Cache.buildSchemaCacheRule'.
|
||||
data NativeQueryInfo (b :: BackendType) = NativeQueryInfo
|
||||
{ _nqiRootFieldName :: NativeQueryName,
|
||||
_nqiCode :: InterpolatedQuery NativeQueryArgumentName,
|
||||
_nqiReturns :: CustomReturnTypeInfo b,
|
||||
_nqiArguments :: HashMap NativeQueryArgumentName (NullableScalarType b),
|
||||
_nqiDescription :: Maybe Text
|
||||
}
|
||||
deriving stock (Generic)
|
||||
|
||||
instance
|
||||
(Backend b, ToJSON (RolePermInfoMap b)) =>
|
||||
ToJSON (NativeQueryInfo b)
|
||||
where
|
||||
toJSON = genericToJSON hasuraJSON
|
||||
|
||||
makeLenses ''NativeQueryInfo
|
28
server/src-lib/Hasura/NativeQuery/IR.hs
Normal file
28
server/src-lib/Hasura/NativeQuery/IR.hs
Normal file
@ -0,0 +1,28 @@
|
||||
-- | The RQL IR representation of an invocation of a native query.
|
||||
module Hasura.NativeQuery.IR
|
||||
( NativeQuery (..),
|
||||
)
|
||||
where
|
||||
|
||||
import Hasura.CustomReturnType.IR
|
||||
import Hasura.NativeQuery.Metadata
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend
|
||||
import Hasura.RQL.Types.Column (ColumnValue)
|
||||
|
||||
-- | The RQL IR representation of an invocation of a native query.
|
||||
data NativeQuery b field = NativeQuery
|
||||
{ -- | The graphql name of the native query.
|
||||
nqRootFieldName :: NativeQueryName,
|
||||
-- | The raw sql to use in the query
|
||||
nqInterpolatedQuery :: InterpolatedQuery field,
|
||||
-- | The arguments passed to the query, if any.
|
||||
nqArgs :: HashMap NativeQueryArgumentName (ColumnValue b),
|
||||
-- | The return type of the native query
|
||||
nqReturnType :: CustomReturnType b
|
||||
}
|
||||
deriving (Functor, Foldable, Traversable)
|
||||
|
||||
deriving instance (Backend b, Eq field) => Eq (NativeQuery b field)
|
||||
|
||||
deriving instance (Backend b, Show field) => Show (NativeQuery b field)
|
@ -2,21 +2,21 @@
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE UndecidableInstances #-}
|
||||
|
||||
-- | Metadata representation of a logical model in the metadata,
|
||||
-- | Metadata representation of a native query in the metadata,
|
||||
-- as well as a parser and prettyprinter for the query code.
|
||||
module Hasura.LogicalModel.Metadata
|
||||
( LogicalModelName (..),
|
||||
LogicalModelMetadata (..),
|
||||
lmmArguments,
|
||||
lmmCode,
|
||||
lmmDescription,
|
||||
lmmReturns,
|
||||
lmmRootFieldName,
|
||||
LogicalModelArgumentName (..),
|
||||
module Hasura.NativeQuery.Metadata
|
||||
( NativeQueryName (..),
|
||||
NativeQueryMetadata (..),
|
||||
nqmArguments,
|
||||
nqmCode,
|
||||
nqmDescription,
|
||||
nqmReturns,
|
||||
nqmRootFieldName,
|
||||
NativeQueryArgumentName (..),
|
||||
InterpolatedItem (..),
|
||||
InterpolatedQuery (..),
|
||||
parseInterpolatedQuery,
|
||||
module Hasura.LogicalModel.Types,
|
||||
module Hasura.NativeQuery.Types,
|
||||
)
|
||||
where
|
||||
|
||||
@ -27,8 +27,8 @@ import Data.Aeson (FromJSON, FromJSONKey, ToJSON, ToJSONKey)
|
||||
import Data.Bifunctor (first)
|
||||
import Data.Text qualified as T
|
||||
import Hasura.CustomReturnType.Metadata (CustomReturnTypeName)
|
||||
import Hasura.LogicalModel.Types (LogicalModelName (..), NullableScalarType)
|
||||
import Hasura.Metadata.DTO.Utils (codecNamePrefix)
|
||||
import Hasura.NativeQuery.Types (NativeQueryName (..), NullableScalarType)
|
||||
import Hasura.Prelude hiding (first)
|
||||
import Hasura.RQL.Types.Backend
|
||||
import Hasura.SQL.Backend
|
||||
@ -52,9 +52,9 @@ data InterpolatedItem variable
|
||||
|
||||
-- | Converting an interpolated query back to text.
|
||||
-- Should roundtrip with the 'parseInterpolatedQuery'.
|
||||
ppInterpolatedItem :: InterpolatedItem LogicalModelArgumentName -> Text
|
||||
ppInterpolatedItem :: InterpolatedItem NativeQueryArgumentName -> Text
|
||||
ppInterpolatedItem (IIText t) = t
|
||||
ppInterpolatedItem (IIVariable v) = "{{" <> getLogicalModelArgumentName v <> "}}"
|
||||
ppInterpolatedItem (IIVariable v) = "{{" <> getNativeQueryArgumentName v <> "}}"
|
||||
|
||||
deriving instance (Hashable variable) => Hashable (InterpolatedItem variable)
|
||||
|
||||
@ -62,7 +62,7 @@ deriving instance (NFData variable) => NFData (InterpolatedItem variable)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
-- | A list of logical model components representing a single logical model,
|
||||
-- | A list of native query components representing a single native query,
|
||||
-- separating the variables from the text.
|
||||
newtype InterpolatedQuery variable = InterpolatedQuery
|
||||
{ getInterpolatedQuery :: [InterpolatedItem variable]
|
||||
@ -74,12 +74,12 @@ deriving newtype instance (Hashable variable) => Hashable (InterpolatedQuery var
|
||||
|
||||
deriving newtype instance (NFData variable) => NFData (InterpolatedQuery variable)
|
||||
|
||||
ppInterpolatedQuery :: InterpolatedQuery LogicalModelArgumentName -> Text
|
||||
ppInterpolatedQuery :: InterpolatedQuery NativeQueryArgumentName -> Text
|
||||
ppInterpolatedQuery (InterpolatedQuery parts) = foldMap ppInterpolatedItem parts
|
||||
|
||||
-- | We store the interpolated query as the user text and parse it back
|
||||
-- when converting back to Haskell code.
|
||||
instance v ~ LogicalModelArgumentName => HasCodec (InterpolatedQuery v) where
|
||||
instance v ~ NativeQueryArgumentName => HasCodec (InterpolatedQuery v) where
|
||||
codec =
|
||||
CommentCodec
|
||||
("An interpolated query expressed in native code (SQL)")
|
||||
@ -89,85 +89,85 @@ instance v ~ LogicalModelArgumentName => HasCodec (InterpolatedQuery v) where
|
||||
textCodec
|
||||
|
||||
deriving via
|
||||
(Autodocodec (InterpolatedQuery LogicalModelArgumentName))
|
||||
(Autodocodec (InterpolatedQuery NativeQueryArgumentName))
|
||||
instance
|
||||
v ~ LogicalModelArgumentName =>
|
||||
v ~ NativeQueryArgumentName =>
|
||||
ToJSON (InterpolatedQuery v)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
newtype LogicalModelArgumentName = LogicalModelArgumentName
|
||||
{ getLogicalModelArgumentName :: Text
|
||||
newtype NativeQueryArgumentName = NativeQueryArgumentName
|
||||
{ getNativeQueryArgumentName :: Text
|
||||
}
|
||||
deriving newtype (Eq, Ord, Show, Hashable)
|
||||
deriving stock (Generic)
|
||||
|
||||
instance HasCodec LogicalModelArgumentName where
|
||||
codec = dimapCodec LogicalModelArgumentName getLogicalModelArgumentName codec
|
||||
instance HasCodec NativeQueryArgumentName where
|
||||
codec = dimapCodec NativeQueryArgumentName getNativeQueryArgumentName codec
|
||||
|
||||
deriving newtype instance ToJSON LogicalModelArgumentName
|
||||
deriving newtype instance ToJSON NativeQueryArgumentName
|
||||
|
||||
deriving newtype instance FromJSON LogicalModelArgumentName
|
||||
deriving newtype instance FromJSON NativeQueryArgumentName
|
||||
|
||||
deriving newtype instance ToJSONKey LogicalModelArgumentName
|
||||
deriving newtype instance ToJSONKey NativeQueryArgumentName
|
||||
|
||||
deriving newtype instance FromJSONKey LogicalModelArgumentName
|
||||
deriving newtype instance FromJSONKey NativeQueryArgumentName
|
||||
|
||||
instance NFData LogicalModelArgumentName
|
||||
instance NFData NativeQueryArgumentName
|
||||
|
||||
---------------------------------------
|
||||
|
||||
-- | The representation of logical models within the metadata structure.
|
||||
data LogicalModelMetadata (b :: BackendType) = LogicalModelMetadata
|
||||
{ _lmmRootFieldName :: LogicalModelName,
|
||||
_lmmCode :: InterpolatedQuery LogicalModelArgumentName,
|
||||
_lmmReturns :: CustomReturnTypeName,
|
||||
_lmmArguments :: HashMap LogicalModelArgumentName (NullableScalarType b),
|
||||
_lmmDescription :: Maybe Text
|
||||
-- | The representation of native queries within the metadata structure.
|
||||
data NativeQueryMetadata (b :: BackendType) = NativeQueryMetadata
|
||||
{ _nqmRootFieldName :: NativeQueryName,
|
||||
_nqmCode :: InterpolatedQuery NativeQueryArgumentName,
|
||||
_nqmReturns :: CustomReturnTypeName,
|
||||
_nqmArguments :: HashMap NativeQueryArgumentName (NullableScalarType b),
|
||||
_nqmDescription :: Maybe Text
|
||||
}
|
||||
deriving (Generic)
|
||||
|
||||
deriving instance Backend b => Eq (LogicalModelMetadata b)
|
||||
deriving instance Backend b => Eq (NativeQueryMetadata b)
|
||||
|
||||
deriving instance Backend b => Show (LogicalModelMetadata b)
|
||||
deriving instance Backend b => Show (NativeQueryMetadata b)
|
||||
|
||||
instance (Backend b) => HasCodec (LogicalModelMetadata b) where
|
||||
instance (Backend b) => HasCodec (NativeQueryMetadata b) where
|
||||
codec =
|
||||
CommentCodec
|
||||
("A logical model as represented in metadata.")
|
||||
$ AC.object (codecNamePrefix @b <> "LogicalModelMetadata")
|
||||
$ LogicalModelMetadata
|
||||
("A native query as represented in metadata.")
|
||||
$ AC.object (codecNamePrefix @b <> "NativeQueryMetadata")
|
||||
$ NativeQueryMetadata
|
||||
<$> requiredField "root_field_name" fieldNameDoc
|
||||
AC..= _lmmRootFieldName
|
||||
AC..= _nqmRootFieldName
|
||||
<*> requiredField "code" sqlDoc
|
||||
AC..= _lmmCode
|
||||
AC..= _nqmCode
|
||||
<*> requiredField "returns" returnsDoc
|
||||
AC..= _lmmReturns
|
||||
AC..= _nqmReturns
|
||||
<*> optionalFieldWithDefault "arguments" mempty argumentDoc
|
||||
AC..= _lmmArguments
|
||||
AC..= _nqmArguments
|
||||
<*> optionalField "description" descriptionDoc
|
||||
AC..= _lmmDescription
|
||||
AC..= _nqmDescription
|
||||
where
|
||||
fieldNameDoc = "Root field name for the logical model"
|
||||
fieldNameDoc = "Root field name for the native query"
|
||||
sqlDoc = "Native code expression (SQL) to run"
|
||||
argumentDoc = "Free variables in the expression and their types"
|
||||
returnsDoc = "Return type (table) of the expression"
|
||||
descriptionDoc = "A description of the logical model which appears in the graphql schema"
|
||||
descriptionDoc = "A description of the native query which appears in the graphql schema"
|
||||
|
||||
deriving via
|
||||
(Autodocodec (LogicalModelMetadata b))
|
||||
(Autodocodec (NativeQueryMetadata b))
|
||||
instance
|
||||
(Backend b) => (FromJSON (LogicalModelMetadata b))
|
||||
(Backend b) => (FromJSON (NativeQueryMetadata b))
|
||||
|
||||
deriving via
|
||||
(Autodocodec (LogicalModelMetadata b))
|
||||
(Autodocodec (NativeQueryMetadata b))
|
||||
instance
|
||||
(Backend b) => (ToJSON (LogicalModelMetadata b))
|
||||
(Backend b) => (ToJSON (NativeQueryMetadata b))
|
||||
|
||||
-- | extract all of the `{{ variable }}` inside our query string
|
||||
parseInterpolatedQuery ::
|
||||
Text ->
|
||||
Either Text (InterpolatedQuery LogicalModelArgumentName)
|
||||
Either Text (InterpolatedQuery NativeQueryArgumentName)
|
||||
parseInterpolatedQuery =
|
||||
fmap
|
||||
( InterpolatedQuery
|
||||
@ -185,7 +185,7 @@ parseInterpolatedQuery =
|
||||
(a : rest) -> a : mergeAdjacent rest
|
||||
[] -> []
|
||||
|
||||
consumeString :: String -> Either Text [InterpolatedItem LogicalModelArgumentName]
|
||||
consumeString :: String -> Either Text [InterpolatedItem NativeQueryArgumentName]
|
||||
consumeString str =
|
||||
let (beforeCurly, fromCurly) = break (== '{') str
|
||||
in case fromCurly of
|
||||
@ -195,12 +195,12 @@ parseInterpolatedQuery =
|
||||
(IIText (T.pack (beforeCurly <> "{")) :) <$> consumeString other
|
||||
_other -> pure [IIText (T.pack beforeCurly)]
|
||||
|
||||
consumeVar :: String -> Either Text [InterpolatedItem LogicalModelArgumentName]
|
||||
consumeVar :: String -> Either Text [InterpolatedItem NativeQueryArgumentName]
|
||||
consumeVar str =
|
||||
let (beforeCloseCurly, fromClosedCurly) = break (== '}') str
|
||||
in case fromClosedCurly of
|
||||
('}' : '}' : rest) ->
|
||||
(IIVariable (LogicalModelArgumentName $ T.pack beforeCloseCurly) :) <$> consumeString rest
|
||||
(IIVariable (NativeQueryArgumentName $ T.pack beforeCloseCurly) :) <$> consumeString rest
|
||||
_ -> Left "Found '{{' without a matching closing '}}'"
|
||||
|
||||
makeLenses ''LogicalModelMetadata
|
||||
makeLenses ''NativeQueryMetadata
|
@ -1,7 +1,7 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
-- | Schema parsers for logical models.
|
||||
module Hasura.LogicalModel.Schema (defaultBuildLogicalModelRootFields) where
|
||||
-- | Schema parsers for native queries.
|
||||
module Hasura.NativeQuery.Schema (defaultBuildNativeQueryRootFields) where
|
||||
|
||||
import Data.Has (Has (getter))
|
||||
import Data.HashMap.Strict qualified as HM
|
||||
@ -18,10 +18,10 @@ import Hasura.GraphQL.Schema.Common
|
||||
)
|
||||
import Hasura.GraphQL.Schema.Options qualified as Options
|
||||
import Hasura.GraphQL.Schema.Parser qualified as P
|
||||
import Hasura.LogicalModel.Cache (LogicalModelInfo (..))
|
||||
import Hasura.LogicalModel.IR (LogicalModel (..))
|
||||
import Hasura.LogicalModel.Metadata (InterpolatedQuery (..), LogicalModelArgumentName (..))
|
||||
import Hasura.LogicalModel.Types (NullableScalarType (..), getLogicalModelName)
|
||||
import Hasura.NativeQuery.Cache (NativeQueryInfo (..))
|
||||
import Hasura.NativeQuery.IR (NativeQuery (..))
|
||||
import Hasura.NativeQuery.Metadata (InterpolatedQuery (..), NativeQueryArgumentName (..))
|
||||
import Hasura.NativeQuery.Types (NullableScalarType (..), getNativeQueryName)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.Root (RemoteRelationshipField)
|
||||
import Hasura.RQL.IR.Select (QueryDB (QDBMultipleRows))
|
||||
@ -39,54 +39,54 @@ import Hasura.SQL.AnyBackend (mkAnyBackend)
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
import Language.GraphQL.Draft.Syntax.QQ qualified as G
|
||||
|
||||
defaultBuildLogicalModelRootFields ::
|
||||
defaultBuildNativeQueryRootFields ::
|
||||
forall b r m n.
|
||||
( MonadBuildSchema b r m n,
|
||||
BackendCustomReturnTypeSelectSchema b
|
||||
) =>
|
||||
LogicalModelInfo b ->
|
||||
NativeQueryInfo b ->
|
||||
SchemaT
|
||||
r
|
||||
m
|
||||
(Maybe (P.FieldParser n (QueryDB b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))))
|
||||
defaultBuildLogicalModelRootFields LogicalModelInfo {..} = runMaybeT $ do
|
||||
let fieldName = getLogicalModelName _lmiRootFieldName
|
||||
defaultBuildNativeQueryRootFields NativeQueryInfo {..} = runMaybeT $ do
|
||||
let fieldName = getNativeQueryName _nqiRootFieldName
|
||||
|
||||
logicalModelArgsParser <-
|
||||
logicalModelArgumentsSchema @b @r @m @n fieldName _lmiArguments
|
||||
nativeQueryArgsParser <-
|
||||
nativeQueryArgumentsSchema @b @r @m @n fieldName _nqiArguments
|
||||
|
||||
sourceInfo :: SourceInfo b <- asks getter
|
||||
|
||||
let sourceName = _siName sourceInfo
|
||||
tCase = _rscNamingConvention $ _siCustomization sourceInfo
|
||||
description = G.Description <$> _lmiDescription
|
||||
description = G.Description <$> _nqiDescription
|
||||
|
||||
stringifyNumbers <- retrieve Options.soStringifyNumbers
|
||||
|
||||
customReturnTypePermissions <-
|
||||
MaybeT . fmap Just $
|
||||
buildCustomReturnTypePermissions @b @r @m @n _lmiReturns
|
||||
buildCustomReturnTypePermissions @b @r @m @n _nqiReturns
|
||||
|
||||
(selectionSetParser, customTypesArgsParser) <-
|
||||
MaybeT $ buildCustomReturnTypeFields _lmiReturns
|
||||
MaybeT $ buildCustomReturnTypeFields _nqiReturns
|
||||
|
||||
let interpolatedQuery lmArgs =
|
||||
let interpolatedQuery nqArgs =
|
||||
InterpolatedQuery $
|
||||
(fmap . fmap)
|
||||
( \var@(LogicalModelArgumentName name) -> case HM.lookup var lmArgs of
|
||||
( \var@(NativeQueryArgumentName name) -> case HM.lookup var nqArgs of
|
||||
Just arg -> UVParameter (FromInternal name) arg
|
||||
Nothing ->
|
||||
-- the `logicalModelArgsParser` will already have checked
|
||||
-- the `nativeQueryArgsParser` will already have checked
|
||||
-- we have all the args the query needs so this _should
|
||||
-- not_ happen
|
||||
error $ "No logical model arg passed for " <> show var
|
||||
error $ "No native query arg passed for " <> show var
|
||||
)
|
||||
(getInterpolatedQuery _lmiCode)
|
||||
(getInterpolatedQuery _nqiCode)
|
||||
|
||||
let sourceObj =
|
||||
MO.MOSourceObjId
|
||||
sourceName
|
||||
(mkAnyBackend $ MO.SMOLogicalModel @b _lmiRootFieldName)
|
||||
(mkAnyBackend $ MO.SMONativeQuery @b _nqiRootFieldName)
|
||||
|
||||
pure $
|
||||
P.setFieldParserOrigin sourceObj $
|
||||
@ -95,20 +95,20 @@ defaultBuildLogicalModelRootFields LogicalModelInfo {..} = runMaybeT $ do
|
||||
description
|
||||
( (,)
|
||||
<$> customTypesArgsParser
|
||||
<*> logicalModelArgsParser
|
||||
<*> nativeQueryArgsParser
|
||||
)
|
||||
selectionSetParser
|
||||
<&> \((crtArgs, lmArgs), fields) ->
|
||||
<&> \((crtArgs, nqArgs), fields) ->
|
||||
QDBMultipleRows $
|
||||
IR.AnnSelectG
|
||||
{ IR._asnFields = fields,
|
||||
IR._asnFrom =
|
||||
IR.FromLogicalModel
|
||||
LogicalModel
|
||||
{ lmRootFieldName = _lmiRootFieldName,
|
||||
lmArgs,
|
||||
lmInterpolatedQuery = interpolatedQuery lmArgs,
|
||||
lmReturnType = buildCustomReturnTypeIR _lmiReturns
|
||||
IR.FromNativeQuery
|
||||
NativeQuery
|
||||
{ nqRootFieldName = _nqiRootFieldName,
|
||||
nqArgs,
|
||||
nqInterpolatedQuery = interpolatedQuery nqArgs,
|
||||
nqReturnType = buildCustomReturnTypeIR _nqiReturns
|
||||
},
|
||||
IR._asnPerm = customReturnTypePermissions,
|
||||
IR._asnArgs = crtArgs,
|
||||
@ -116,13 +116,13 @@ defaultBuildLogicalModelRootFields LogicalModelInfo {..} = runMaybeT $ do
|
||||
IR._asnNamingConvention = Just tCase
|
||||
}
|
||||
|
||||
logicalModelArgumentsSchema ::
|
||||
nativeQueryArgumentsSchema ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
G.Name ->
|
||||
HashMap LogicalModelArgumentName (NullableScalarType b) ->
|
||||
MaybeT (SchemaT r m) (P.InputFieldsParser n (HashMap LogicalModelArgumentName (Column.ColumnValue b)))
|
||||
logicalModelArgumentsSchema logicalModelName argsSignature = do
|
||||
HashMap NativeQueryArgumentName (NullableScalarType b) ->
|
||||
MaybeT (SchemaT r m) (P.InputFieldsParser n (HashMap NativeQueryArgumentName (Column.ColumnValue b)))
|
||||
nativeQueryArgumentsSchema nativeQueryName argsSignature = do
|
||||
-- Lift 'SchemaT r m (InputFieldsParser ..)' into a monoid using Applicative.
|
||||
-- This lets us use 'foldMap' + monoid structure of hashmaps to avoid awkwardly
|
||||
-- traversing the arguments and building the resulting parser.
|
||||
@ -135,10 +135,10 @@ logicalModelArgumentsSchema logicalModelName argsSignature = do
|
||||
<$> lift (columnParser (Column.ColumnScalar nstType) (G.Nullability nstNullable))
|
||||
-- TODO: Naming conventions?
|
||||
-- TODO: Custom fields? (Probably not)
|
||||
argName <- hoistMaybe (G.mkName (getLogicalModelArgumentName name))
|
||||
argName <- hoistMaybe (G.mkName (getNativeQueryArgumentName name))
|
||||
let description = case nstDescription of
|
||||
Just desc -> G.Description desc
|
||||
Nothing -> G.Description ("Logical model argument " <> getLogicalModelArgumentName name)
|
||||
Nothing -> G.Description ("Native query argument " <> getNativeQueryArgumentName name)
|
||||
pure $
|
||||
P.field
|
||||
argName
|
||||
@ -147,7 +147,7 @@ logicalModelArgumentsSchema logicalModelName argsSignature = do
|
||||
)
|
||||
(HM.toList argsSignature)
|
||||
|
||||
let desc = Just $ G.Description $ G.unName logicalModelName <> " Logical Model Arguments"
|
||||
let desc = Just $ G.Description $ G.unName nativeQueryName <> " Native Query Arguments"
|
||||
|
||||
pure $
|
||||
if null argsSignature
|
||||
@ -156,4 +156,4 @@ logicalModelArgumentsSchema logicalModelName argsSignature = do
|
||||
P.field
|
||||
[G.name|args|]
|
||||
desc
|
||||
(P.object (logicalModelName <> [G.name|_arguments|]) desc argsParser)
|
||||
(P.object (nativeQueryName <> [G.name|_arguments|]) desc argsParser)
|
@ -1,6 +1,6 @@
|
||||
-- | A name for a logical model as it is recognized by the graphql schema.
|
||||
module Hasura.LogicalModel.Types
|
||||
( LogicalModelName (..),
|
||||
-- | A name for a native query as it is recognized by the graphql schema.
|
||||
module Hasura.NativeQuery.Types
|
||||
( NativeQueryName (..),
|
||||
NullableScalarType (..),
|
||||
nullableScalarTypeMapCodec,
|
||||
)
|
||||
@ -17,17 +17,17 @@ import Hasura.RQL.Types.Backend (Backend (..))
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
import Language.Haskell.TH.Syntax (Lift)
|
||||
|
||||
-- The name of a logical model. This appears as a root field name in the graphql schema.
|
||||
newtype LogicalModelName = LogicalModelName {getLogicalModelName :: G.Name}
|
||||
-- The name of a native query. This appears as a root field name in the graphql schema.
|
||||
newtype NativeQueryName = NativeQueryName {getNativeQueryName :: G.Name}
|
||||
deriving newtype (Eq, Ord, Show, Hashable, NFData, ToJSON, FromJSON, ToTxt)
|
||||
deriving stock (Data, Generic, Lift)
|
||||
|
||||
instance HasCodec LogicalModelName where
|
||||
codec = dimapCodec LogicalModelName getLogicalModelName codec
|
||||
instance HasCodec NativeQueryName where
|
||||
codec = dimapCodec NativeQueryName getNativeQueryName codec
|
||||
|
||||
instance FromJSONKey LogicalModelName
|
||||
instance FromJSONKey NativeQueryName
|
||||
|
||||
instance ToJSONKey LogicalModelName
|
||||
instance ToJSONKey NativeQueryName
|
||||
|
||||
-- | A ScalarType that can be nullable with an optional description
|
||||
data NullableScalarType b = NullableScalarType
|
@ -674,7 +674,7 @@ toggleEventTriggerCleanupAction conf cleanupSwitch = do
|
||||
case tlcs of
|
||||
TriggerAllSource -> do
|
||||
ifor_ (scSources schemaCache) $ \sourceName backendSourceInfo -> do
|
||||
AB.dispatchAnyBackend @BackendEventTrigger backendSourceInfo \(SourceInfo _ tableCache _ _logicalModelCache _customReturnTypeCache _ _ _ :: SourceInfo b) -> do
|
||||
AB.dispatchAnyBackend @BackendEventTrigger backendSourceInfo \(SourceInfo _ tableCache _ _nativeQueryCache _customReturnTypeCache _ _ _ :: SourceInfo b) -> do
|
||||
traverseTableHelper tableCache cleanupSwitch sourceName
|
||||
TriggerSource sourceNameLst -> do
|
||||
forM_ sourceNameLst $ \sourceName -> do
|
||||
@ -682,7 +682,7 @@ toggleEventTriggerCleanupAction conf cleanupSwitch = do
|
||||
HM.lookup sourceName (scSources schemaCache)
|
||||
`onNothing` throw400 NotExists ("source with name " <> sourceNameToText sourceName <> " does not exists")
|
||||
|
||||
AB.dispatchAnyBackend @BackendEventTrigger backendSourceInfo \(SourceInfo _ tableCache _ _logicalModelCache _customReturnTypeCache _ _ _ :: SourceInfo b) -> do
|
||||
AB.dispatchAnyBackend @BackendEventTrigger backendSourceInfo \(SourceInfo _ tableCache _ _nativeQueryCache _customReturnTypeCache _ _ _ :: SourceInfo b) -> do
|
||||
traverseTableHelper tableCache cleanupSwitch sourceName
|
||||
TriggerQualifier qualifierLst -> do
|
||||
forM_ qualifierLst $ \qualifier -> do
|
||||
|
@ -43,8 +43,8 @@ import Hasura.CustomReturnType.API
|
||||
import Hasura.EncJSON
|
||||
import Hasura.Function.API
|
||||
import Hasura.Logging qualified as HL
|
||||
import Hasura.LogicalModel.API
|
||||
import Hasura.Metadata.Class
|
||||
import Hasura.NativeQuery.API
|
||||
import Hasura.Prelude hiding (first)
|
||||
import Hasura.RQL.DDL.Action
|
||||
import Hasura.RQL.DDL.ApiLimit
|
||||
@ -704,7 +704,7 @@ purgeMetadataObj = \case
|
||||
SMOFunction qf -> dropFunctionInMetadata @b source qf
|
||||
SMOFunctionPermission qf rn -> dropFunctionPermissionInMetadata @b source qf rn
|
||||
SMOCustomReturnType crt -> dropCustomReturnTypeInMetadata @b source crt
|
||||
SMOLogicalModel lm -> dropLogicalModelInMetadata @b source lm
|
||||
SMONativeQuery lm -> dropNativeQueryInMetadata @b source lm
|
||||
SMOCustomReturnTypeObj customReturnTypeName customReturnTypeMetadataObjId ->
|
||||
MetadataModifier $
|
||||
customReturnTypeMetadataSetter @b source customReturnTypeName
|
||||
|
@ -418,8 +418,8 @@ validateAllowedRootFields sourceName tableName roleName SelPerm {..} = do
|
||||
"The \"select_aggregate\" root field can only be enabled in the query_root_fields or "
|
||||
<> " the subscription_root_fields when \"allow_aggregations\" is set to true"
|
||||
|
||||
-- | Given the logical model's definition and the permissions as defined in the
|
||||
-- logical model's metadata, try to construct the @SELECT@ permission
|
||||
-- | Given the native query's definition and the permissions as defined in the
|
||||
-- native query's metadata, try to construct the @SELECT@ permission
|
||||
-- definition.
|
||||
buildCustomReturnTypeSelPermInfo ::
|
||||
forall b m.
|
||||
@ -473,7 +473,7 @@ buildCustomReturnTypeSelPermInfo source customReturnTypeName fieldInfoMap sp = w
|
||||
spiCols :: HashMap (Column b) (Maybe (AnnColumnCaseBoolExpPartialSQL b))
|
||||
spiCols = HM.fromList (map (,Nothing) columns)
|
||||
|
||||
-- Logical models don't have computed fields.
|
||||
-- Native queries don't have computed fields.
|
||||
spiComputedFields :: HashMap ComputedFieldName (Maybe (AnnColumnCaseBoolExpPartialSQL b))
|
||||
spiComputedFields = mempty
|
||||
|
||||
@ -485,7 +485,7 @@ buildCustomReturnTypeSelPermInfo source customReturnTypeName fieldInfoMap sp = w
|
||||
spiAllowedSubscriptionRootFields :: AllowedRootFields SubscriptionRootFieldType
|
||||
spiAllowedSubscriptionRootFields = spAllowedSubscriptionRootFields sp
|
||||
|
||||
-- We don't currently allow for aggregations over logical models.
|
||||
-- We don't currently allow for aggregations over native queries.
|
||||
spiAllowAgg :: Bool
|
||||
spiAllowAgg = spAllowAggregations sp
|
||||
|
||||
|
@ -127,12 +127,12 @@ procCustomReturnTypeBoolExp source lmn fieldInfoMap be = do
|
||||
let -- The parser for the "right hand side" of operations. We use @rhsParser@
|
||||
-- as the name here for ease of grepping, though it's maybe a bit vague.
|
||||
-- More specifically, if we think of an operation that combines a field
|
||||
-- (such as those in tables or logical models) on the /left/ with a value
|
||||
-- (such as those in tables or native queries) on the /left/ with a value
|
||||
-- or session variable on the /right/, this is a parser for the latter.
|
||||
rhsParser :: BoolExpRHSParser b m (PartialSQLExp b)
|
||||
rhsParser = BoolExpRHSParser parseCollectableType PSESession
|
||||
|
||||
-- In Logical Models, there are no relationships (unlike tables, where one
|
||||
-- In Native Queries, there are no relationships (unlike tables, where one
|
||||
-- table can reference another). This means that our root fieldInfoMap is
|
||||
-- always going to be the same as our current fieldInfoMap, so we just pass
|
||||
-- the same one in twice.
|
||||
|
@ -48,9 +48,9 @@ import Hasura.GraphQL.Schema (buildGQLContext)
|
||||
import Hasura.GraphQL.Schema.NamingCase
|
||||
import Hasura.Incremental qualified as Inc
|
||||
import Hasura.Logging
|
||||
import Hasura.LogicalModel.Cache (LogicalModelCache, LogicalModelInfo (..))
|
||||
import Hasura.LogicalModel.Metadata (LogicalModelMetadata (..))
|
||||
import Hasura.Metadata.Class
|
||||
import Hasura.NativeQuery.Cache (NativeQueryCache, NativeQueryInfo (..))
|
||||
import Hasura.NativeQuery.Metadata (NativeQueryMetadata (..))
|
||||
import Hasura.Prelude
|
||||
import Hasura.QueryTags
|
||||
import Hasura.RQL.DDL.Action
|
||||
@ -654,7 +654,7 @@ buildSchemaCacheRule logger env = proc (MetadataWithResourceVersion metadataNoDe
|
||||
)
|
||||
`arr` (SourceInfo b)
|
||||
buildSource = proc (dynamicConfig, allSources, sourceMetadata, sourceConfig, tablesRawInfo, eventTriggerInfoMaps, _dbTables, dbFunctions, remoteSchemaMap, orderedRoles) -> do
|
||||
let SourceMetadata sourceName _backendKind tables functions logicalModels customReturnTypes _ queryTagsConfig sourceCustomization _healthCheckConfig = sourceMetadata
|
||||
let SourceMetadata sourceName _backendKind tables functions nativeQueries customReturnTypes _ queryTagsConfig sourceCustomization _healthCheckConfig = sourceMetadata
|
||||
tablesMetadata = OMap.elems tables
|
||||
(_, nonColumnInputs, permissions) = unzip3 $ map mkTableInputs tablesMetadata
|
||||
alignTableMap :: HashMap (TableName b) a -> HashMap (TableName b) c -> HashMap (TableName b) (a, c)
|
||||
@ -753,7 +753,7 @@ buildSchemaCacheRule logger env = proc (MetadataWithResourceVersion metadataNoDe
|
||||
(OMap.elems customReturnTypes)
|
||||
\crtm@CustomReturnTypeMetadata {..} ->
|
||||
withRecordInconsistencyM (mkCustomReturnTypeMetadataObject crtm) $ do
|
||||
unless (_cdcAreLogicalModelsEnabled dynamicConfig) $
|
||||
unless (_cdcAreNativeQueriesEnabled dynamicConfig) $
|
||||
throw400 InvalidConfiguration "The Custom Return Type feature is disabled"
|
||||
|
||||
fieldInfoMap <- case toFieldInfo _crtmFields of
|
||||
@ -774,25 +774,25 @@ buildSchemaCacheRule logger env = proc (MetadataWithResourceVersion metadataNoDe
|
||||
let customReturnTypesCache :: CustomReturnTypeCache b
|
||||
customReturnTypesCache = mapFromL _crtiName (catMaybes customReturnTypeCacheMaybes)
|
||||
|
||||
logicalModelCacheMaybes <-
|
||||
nativeQueryCacheMaybes <-
|
||||
interpretWriter
|
||||
-< for
|
||||
(OMap.elems logicalModels)
|
||||
\lmm@LogicalModelMetadata {..} -> do
|
||||
(OMap.elems nativeQueries)
|
||||
\nqm@NativeQueryMetadata {..} -> do
|
||||
let metadataObject :: MetadataObject
|
||||
metadataObject =
|
||||
MetadataObject
|
||||
( MOSourceObjId sourceName $
|
||||
AB.mkAnyBackend $
|
||||
SMOLogicalModel @b _lmmRootFieldName
|
||||
SMONativeQuery @b _nqmRootFieldName
|
||||
)
|
||||
(toJSON lmm)
|
||||
(toJSON nqm)
|
||||
|
||||
schemaObjId :: SchemaObjId
|
||||
schemaObjId =
|
||||
SOSourceObj sourceName $
|
||||
AB.mkAnyBackend $
|
||||
SOILogicalModel @b _lmmRootFieldName
|
||||
SOINativeQuery @b _nqmRootFieldName
|
||||
|
||||
dependency :: SchemaDependency
|
||||
dependency =
|
||||
@ -800,35 +800,35 @@ buildSchemaCacheRule logger env = proc (MetadataWithResourceVersion metadataNoDe
|
||||
{ sdObjId =
|
||||
SOSourceObj sourceName $
|
||||
AB.mkAnyBackend $
|
||||
SOICustomReturnType @b _lmmReturns,
|
||||
SOICustomReturnType @b _nqmReturns,
|
||||
sdReason = DRCustomReturnType
|
||||
}
|
||||
|
||||
withRecordInconsistencyM metadataObject $ do
|
||||
unless (_cdcAreLogicalModelsEnabled dynamicConfig) $
|
||||
throw400 InvalidConfiguration "The Logical Models feature is disabled"
|
||||
unless (_cdcAreNativeQueriesEnabled dynamicConfig) $
|
||||
throw400 InvalidConfiguration "The Native Queries feature is disabled"
|
||||
|
||||
customReturnType <-
|
||||
onNothing
|
||||
(M.lookup _lmmReturns customReturnTypesCache)
|
||||
(throw400 InvalidConfiguration ("The custom return type " <> toTxt _lmmReturns <> " could not be found"))
|
||||
(M.lookup _nqmReturns customReturnTypesCache)
|
||||
(throw400 InvalidConfiguration ("The custom return type " <> toTxt _nqmReturns <> " could not be found"))
|
||||
|
||||
recordDependenciesM metadataObject schemaObjId $
|
||||
Seq.singleton dependency
|
||||
|
||||
pure
|
||||
LogicalModelInfo
|
||||
{ _lmiRootFieldName = _lmmRootFieldName,
|
||||
_lmiCode = _lmmCode,
|
||||
_lmiReturns = customReturnType,
|
||||
_lmiArguments = _lmmArguments,
|
||||
_lmiDescription = _lmmDescription
|
||||
NativeQueryInfo
|
||||
{ _nqiRootFieldName = _nqmRootFieldName,
|
||||
_nqiCode = _nqmCode,
|
||||
_nqiReturns = customReturnType,
|
||||
_nqiArguments = _nqmArguments,
|
||||
_nqiDescription = _nqmDescription
|
||||
}
|
||||
|
||||
let logicalModelCache :: LogicalModelCache b
|
||||
logicalModelCache = mapFromL _lmiRootFieldName (catMaybes logicalModelCacheMaybes)
|
||||
let nativeQueryCache :: NativeQueryCache b
|
||||
nativeQueryCache = mapFromL _nqiRootFieldName (catMaybes nativeQueryCacheMaybes)
|
||||
|
||||
returnA -< SourceInfo sourceName tableCache functionCache logicalModelCache customReturnTypesCache sourceConfig queryTagsConfig resolvedCustomization
|
||||
returnA -< SourceInfo sourceName tableCache functionCache nativeQueryCache customReturnTypesCache sourceConfig queryTagsConfig resolvedCustomization
|
||||
|
||||
buildAndCollectInfo ::
|
||||
forall arr m.
|
||||
@ -858,7 +858,7 @@ buildSchemaCacheRule logger env = proc (MetadataWithResourceVersion metadataNoDe
|
||||
HS.fromList $
|
||||
concat $
|
||||
OMap.elems sources >>= \(BackendSourceMetadata e) ->
|
||||
AB.dispatchAnyBackend @Backend e \(SourceMetadata _ _ tables _functions _logicalModels _customReturnTypes _ _ _ _) -> do
|
||||
AB.dispatchAnyBackend @Backend e \(SourceMetadata _ _ tables _functions _nativeQueries _customReturnTypes _ _ _ _) -> do
|
||||
table <- OMap.elems tables
|
||||
pure $
|
||||
OMap.keys (_tmInsertPermissions table)
|
||||
|
@ -65,10 +65,10 @@ data CacheDynamicConfig = CacheDynamicConfig
|
||||
_cdcDefaultNamingConvention :: NamingCase,
|
||||
_cdcMetadataDefaults :: MetadataDefaults,
|
||||
_cdcApolloFederationStatus :: ApolloFederationStatus,
|
||||
-- | Logical models can be enabled or disabled on the fly via a feature
|
||||
-- | Native queries can be enabled or disabled on the fly via a feature
|
||||
-- flag: we want to be able to properly rebuild the relevant parts of the
|
||||
-- schema cache when this value changes, hence the need for it to be part of
|
||||
-- the dynamic config.
|
||||
_cdcAreLogicalModelsEnabled :: Bool
|
||||
_cdcAreNativeQueriesEnabled :: Bool
|
||||
}
|
||||
deriving (Eq)
|
||||
|
@ -180,8 +180,8 @@ pruneDanglingDependents cache =
|
||||
CRTOCol column ->
|
||||
unless (InsOrd.member column (_crtiFields customReturnType)) do
|
||||
Left ("Could not find column " <> column <<> " in custom return type " <>> customReturnTypeName)
|
||||
SOILogicalModel logicalModelName -> do
|
||||
void $ resolveLogicalModel sourceInfo logicalModelName
|
||||
SOINativeQuery nativeQueryName -> do
|
||||
void $ resolveNativeQuery sourceInfo nativeQueryName
|
||||
SOITableObj tableName tableObjectId -> do
|
||||
tableInfo <- resolveTable sourceInfo tableName
|
||||
case tableObjectId of
|
||||
@ -228,9 +228,9 @@ pruneDanglingDependents cache =
|
||||
M.lookup tableName (_siTables sourceInfo)
|
||||
`onNothing` Left ("table " <> tableName <<> " is not tracked")
|
||||
|
||||
resolveLogicalModel sourceInfo logicalModelName =
|
||||
M.lookup logicalModelName (_siLogicalModels sourceInfo)
|
||||
`onNothing` Left ("logical model " <> logicalModelName <<> " is not tracked")
|
||||
resolveNativeQuery sourceInfo nativeQueryName =
|
||||
M.lookup nativeQueryName (_siNativeQueries sourceInfo)
|
||||
`onNothing` Left ("native query " <> nativeQueryName <<> " is not tracked")
|
||||
|
||||
resolveCustomReturnType sourceInfo customReturnTypeName =
|
||||
M.lookup customReturnTypeName (_siCustomReturnTypes sourceInfo)
|
||||
@ -303,7 +303,7 @@ deleteMetadataObject = \case
|
||||
SMOFunction name -> siFunctions %~ M.delete name
|
||||
SMOFunctionPermission functionName role ->
|
||||
siFunctions . ix functionName . fiPermissions %~ M.delete role
|
||||
SMOLogicalModel name -> siLogicalModels %~ M.delete name
|
||||
SMONativeQuery name -> siNativeQueries %~ M.delete name
|
||||
SMOCustomReturnType name -> siCustomReturnTypes %~ M.delete name
|
||||
SMOCustomReturnTypeObj customReturnTypeName customReturnTypeObjectId ->
|
||||
siCustomReturnTypes . ix customReturnTypeName %~ case customReturnTypeObjectId of
|
||||
|
@ -281,7 +281,7 @@ buildTablePermissions source tableCache tableFields tablePermissions orderedRole
|
||||
definition = toJSON $ WithTable @b source table permDef
|
||||
in MetadataObject objectId definition
|
||||
|
||||
-- | Create the permission map for a logical model based on the select
|
||||
-- | Create the permission map for a native query based on the select
|
||||
-- permissions given in metadata. Compare with 'buildTablePermissions'.
|
||||
buildCustomReturnTypePermissions ::
|
||||
forall b m.
|
||||
|
@ -161,7 +161,7 @@ import Hasura.Backends.Postgres.SQL.Types qualified as Postgres
|
||||
import Hasura.Function.Cache
|
||||
import Hasura.GraphQL.Schema.NamingCase (NamingCase)
|
||||
import Hasura.GraphQL.Schema.Options (StringifyNumbers)
|
||||
import Hasura.LogicalModel.IR (LogicalModel)
|
||||
import Hasura.NativeQuery.IR (NativeQuery)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.BoolExp
|
||||
import Hasura.RQL.IR.OrderBy
|
||||
@ -387,7 +387,7 @@ data SelectFromG (b :: BackendType) v
|
||||
(FunctionArgsExp b v)
|
||||
-- a definition list
|
||||
(Maybe [(Column b, ScalarType b)])
|
||||
| FromLogicalModel (LogicalModel b v)
|
||||
| FromNativeQuery (NativeQuery b v)
|
||||
deriving stock (Generic)
|
||||
|
||||
deriving stock instance (Backend b) => Functor (SelectFromG b)
|
||||
@ -400,7 +400,7 @@ deriving stock instance
|
||||
( Backend b,
|
||||
Eq v,
|
||||
Eq (FunctionArgumentExp b v),
|
||||
Eq (LogicalModel b v)
|
||||
Eq (NativeQuery b v)
|
||||
) =>
|
||||
Eq (SelectFromG b v)
|
||||
|
||||
@ -408,7 +408,7 @@ deriving stock instance
|
||||
( Backend b,
|
||||
Show v,
|
||||
Show (FunctionArgumentExp b v),
|
||||
Show (LogicalModel b v)
|
||||
Show (NativeQuery b v)
|
||||
) =>
|
||||
Show (SelectFromG b v)
|
||||
|
||||
@ -416,7 +416,7 @@ instance
|
||||
( Backend b,
|
||||
Hashable v,
|
||||
Hashable (FunctionArgumentExp b v),
|
||||
Hashable (LogicalModel b v)
|
||||
Hashable (NativeQuery b v)
|
||||
) =>
|
||||
Hashable (SelectFromG b v)
|
||||
|
||||
|
@ -22,7 +22,7 @@ data Provenance
|
||||
Unknown
|
||||
| -- | A GraphQL variable (e.g. a query parameter)
|
||||
FromGraphQL VariableInfo
|
||||
| -- | An internal source (e.g. a logical model argument)
|
||||
| -- | An internal source (e.g. a native query argument)
|
||||
FromInternal Text
|
||||
deriving stock (Eq, Show)
|
||||
|
||||
|
@ -23,7 +23,7 @@ module Hasura.RQL.Types.Metadata
|
||||
emptyMetadataDefaults,
|
||||
functionMetadataSetter,
|
||||
customReturnTypeMetadataSetter,
|
||||
logicalModelMetadataSetter,
|
||||
nativeQueryMetadataSetter,
|
||||
metaActions,
|
||||
metaAllowlist,
|
||||
metaApiLimits,
|
||||
@ -59,8 +59,8 @@ import Hasura.CustomReturnType.Metadata (CustomReturnTypeMetadata, CustomReturnT
|
||||
import Hasura.Function.Cache
|
||||
import Hasura.Function.Metadata (FunctionMetadata (..))
|
||||
import Hasura.Incremental qualified as Inc
|
||||
import Hasura.LogicalModel.Metadata (LogicalModelMetadata, LogicalModelName)
|
||||
import Hasura.Metadata.DTO.MetadataV3 (MetadataV3 (..))
|
||||
import Hasura.NativeQuery.Metadata (NativeQueryMetadata, NativeQueryName)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Allowlist
|
||||
import Hasura.RQL.Types.ApiLimit
|
||||
@ -289,15 +289,15 @@ customReturnTypeMetadataSetter ::
|
||||
customReturnTypeMetadataSetter source name =
|
||||
metaSources . ix source . toSourceMetadata . smCustomReturnTypes . ix name
|
||||
|
||||
-- | A lens setter for the metadata of a logical model as identified by the
|
||||
-- | A lens setter for the metadata of a native query as identified by the
|
||||
-- source name and root field name.
|
||||
logicalModelMetadataSetter ::
|
||||
nativeQueryMetadataSetter ::
|
||||
(Backend b) =>
|
||||
SourceName ->
|
||||
LogicalModelName ->
|
||||
ASetter' Metadata (LogicalModelMetadata b)
|
||||
logicalModelMetadataSetter source logicalModelName =
|
||||
metaSources . ix source . toSourceMetadata . smLogicalModels . ix logicalModelName
|
||||
NativeQueryName ->
|
||||
ASetter' Metadata (NativeQueryMetadata b)
|
||||
nativeQueryMetadataSetter source nativeQueryName =
|
||||
metaSources . ix source . toSourceMetadata . smNativeQueries . ix nativeQueryName
|
||||
|
||||
-- | A simple monad class which enables fetching and setting @'Metadata'
|
||||
-- in the state.
|
||||
|
@ -14,7 +14,7 @@ import Hasura.Function.Cache
|
||||
import Hasura.GraphQL.Schema.NamingCase
|
||||
import Hasura.Incremental qualified as Inc
|
||||
import Hasura.Logging (Hasura, Logger)
|
||||
import Hasura.LogicalModel.Metadata (LogicalModelMetadata)
|
||||
import Hasura.NativeQuery.Metadata (NativeQueryMetadata)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.BoolExp
|
||||
import Hasura.RQL.Types.Backend
|
||||
@ -198,15 +198,15 @@ class
|
||||
SourceName ->
|
||||
m [TableName b]
|
||||
|
||||
validateLogicalModel ::
|
||||
validateNativeQuery ::
|
||||
(MonadIO m, MonadError QErr m) =>
|
||||
Env.Environment ->
|
||||
SourceConnConfiguration b ->
|
||||
CustomReturnTypeMetadata b ->
|
||||
LogicalModelMetadata b ->
|
||||
NativeQueryMetadata b ->
|
||||
m ()
|
||||
validateLogicalModel _ _ _ _ =
|
||||
throw500 "validateLogicalModel: not implemented for this backend."
|
||||
validateNativeQuery _ _ _ _ =
|
||||
throw500 "validateNativeQuery: not implemented for this backend."
|
||||
|
||||
-- | How to convert a column to a field.
|
||||
-- For backends that don't support nested objects or arrays the default implementation
|
||||
|
@ -16,7 +16,7 @@ module Hasura.RQL.Types.Metadata.Common
|
||||
CronTriggers,
|
||||
CustomReturnTypes,
|
||||
Endpoints,
|
||||
LogicalModels,
|
||||
NativeQueries,
|
||||
EventTriggers,
|
||||
Functions,
|
||||
GetCatalogState (..),
|
||||
@ -43,7 +43,7 @@ module Hasura.RQL.Types.Metadata.Common
|
||||
smQueryTags,
|
||||
smTables,
|
||||
smCustomization,
|
||||
smLogicalModels,
|
||||
smNativeQueries,
|
||||
smCustomReturnTypes,
|
||||
smHealthCheckConfig,
|
||||
sourcesCodec,
|
||||
@ -80,8 +80,8 @@ import Data.Text qualified as T
|
||||
import Data.Text.Extended qualified as T
|
||||
import Hasura.CustomReturnType.Metadata (CustomReturnTypeMetadata (..), CustomReturnTypeName)
|
||||
import Hasura.Function.Metadata (FunctionMetadata (..))
|
||||
import Hasura.LogicalModel.Metadata (LogicalModelMetadata (..), LogicalModelName)
|
||||
import Hasura.Metadata.DTO.Utils (codecNamePrefix)
|
||||
import Hasura.NativeQuery.Metadata (NativeQueryMetadata (..), NativeQueryName)
|
||||
import Hasura.Prelude
|
||||
import Hasura.QueryTags.Types
|
||||
import Hasura.RQL.Types.Action
|
||||
@ -345,7 +345,7 @@ type Tables b = InsOrdHashMap (TableName b) (TableMetadata b)
|
||||
|
||||
type Functions b = InsOrdHashMap (FunctionName b) (FunctionMetadata b)
|
||||
|
||||
type LogicalModels b = InsOrdHashMap LogicalModelName (LogicalModelMetadata b)
|
||||
type NativeQueries b = InsOrdHashMap NativeQueryName (NativeQueryMetadata b)
|
||||
|
||||
type CustomReturnTypes b = InsOrdHashMap CustomReturnTypeName (CustomReturnTypeMetadata b)
|
||||
|
||||
@ -363,7 +363,7 @@ data SourceMetadata b = SourceMetadata
|
||||
_smKind :: BackendSourceKind b,
|
||||
_smTables :: Tables b,
|
||||
_smFunctions :: Functions b,
|
||||
_smLogicalModels :: LogicalModels b,
|
||||
_smNativeQueries :: NativeQueries b,
|
||||
_smCustomReturnTypes :: CustomReturnTypes b,
|
||||
_smConfiguration :: SourceConnConfiguration b,
|
||||
_smQueryTags :: Maybe QueryTagsConfig,
|
||||
@ -383,7 +383,7 @@ instance (Backend b) => FromJSONWithContext (BackendSourceKind b) (SourceMetadat
|
||||
_smName <- o .: "name"
|
||||
_smTables <- oMapFromL _tmTable <$> o .: "tables"
|
||||
_smFunctions <- oMapFromL _fmFunction <$> o .:? "functions" .!= []
|
||||
_smLogicalModels <- oMapFromL _lmmRootFieldName <$> o .:? "logical_models" .!= []
|
||||
_smNativeQueries <- oMapFromL _nqmRootFieldName <$> o .:? "native_queries" .!= []
|
||||
_smCustomReturnTypes <- oMapFromL _crtmName <$> o .:? "custom_return_types" .!= []
|
||||
_smConfiguration <- o .: "configuration"
|
||||
_smQueryTags <- o .:? "query_tags"
|
||||
@ -443,8 +443,8 @@ instance Backend b => HasCodec (SourceMetadata b) where
|
||||
.== _smTables
|
||||
<*> optionalFieldOrNullWithOmittedDefaultWith' "functions" (sortedElemsCodec _fmFunction) mempty
|
||||
.== _smFunctions
|
||||
<*> optionalFieldOrNullWithOmittedDefaultWith' "logical_models" (sortedElemsCodec _lmmRootFieldName) mempty
|
||||
.== _smLogicalModels
|
||||
<*> optionalFieldOrNullWithOmittedDefaultWith' "native_queries" (sortedElemsCodec _nqmRootFieldName) mempty
|
||||
.== _smNativeQueries
|
||||
<*> optionalFieldOrNullWithOmittedDefaultWith' "custom_return_types" (sortedElemsCodec _crtmName) mempty
|
||||
.== _smCustomReturnTypes
|
||||
<*> requiredField' "configuration"
|
||||
|
@ -45,7 +45,7 @@ import Hasura.Backends.DataConnector.Adapter.Types (DataConnectorName)
|
||||
import Hasura.Base.ErrorMessage
|
||||
import Hasura.Base.ToErrorValue
|
||||
import Hasura.CustomReturnType.Types
|
||||
import Hasura.LogicalModel.Types
|
||||
import Hasura.NativeQuery.Types
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Action
|
||||
import Hasura.RQL.Types.Backend
|
||||
@ -84,7 +84,7 @@ data SourceMetadataObjId b
|
||||
| SMOFunction (FunctionName b)
|
||||
| SMOFunctionPermission (FunctionName b) RoleName
|
||||
| SMOTableObj (TableName b) TableMetadataObjId
|
||||
| SMOLogicalModel LogicalModelName
|
||||
| SMONativeQuery NativeQueryName
|
||||
| SMOCustomReturnType CustomReturnTypeName
|
||||
| SMOCustomReturnTypeObj CustomReturnTypeName CustomReturnTypeMetadataObjId
|
||||
deriving (Generic)
|
||||
@ -147,7 +147,7 @@ moiTypeName = \case
|
||||
handleSourceObj = \case
|
||||
SMOTable _ -> "table"
|
||||
SMOFunction _ -> "function"
|
||||
SMOLogicalModel _ -> "logical_model"
|
||||
SMONativeQuery _ -> "native_query"
|
||||
SMOCustomReturnType _ -> "custom_type"
|
||||
SMOCustomReturnTypeObj _ customReturnTypeObjectId -> case customReturnTypeObjectId of
|
||||
CRTMOPerm _ permType -> permTypeToCode permType <> "_permission"
|
||||
@ -202,7 +202,7 @@ moiName objectId =
|
||||
<> toTxt functionName
|
||||
<> " in source "
|
||||
<> toTxt source
|
||||
SMOLogicalModel name -> toTxt name <> " in source " <> toTxt source
|
||||
SMONativeQuery name -> toTxt name <> " in source " <> toTxt source
|
||||
SMOCustomReturnType name -> toTxt name <> " in source " <> toTxt source
|
||||
SMOCustomReturnTypeObj customReturnTypeName customReturnTypeObjectId -> do
|
||||
let objectName :: Text
|
||||
|
@ -28,7 +28,7 @@ import Data.Vector qualified as Vector
|
||||
import Hasura.CustomReturnType.Metadata (CustomReturnTypeMetadata (..))
|
||||
import Hasura.Function.Cache (emptyFunctionConfig)
|
||||
import Hasura.Function.Metadata (FunctionMetadata (..))
|
||||
import Hasura.LogicalModel.Metadata (LogicalModelMetadata (..))
|
||||
import Hasura.NativeQuery.Metadata (NativeQueryMetadata (..))
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Action
|
||||
( ActionDefinition (..),
|
||||
@ -116,12 +116,12 @@ sourcesToOrdJSONList sources =
|
||||
where
|
||||
sourceMetaToOrdJSON :: BackendSourceMetadata -> AO.Value
|
||||
sourceMetaToOrdJSON (BackendSourceMetadata exists) =
|
||||
AB.dispatchAnyBackend @Backend exists $ \(SourceMetadata _smName _smKind _smTables _smFunctions _smLogicalModels _smCustomReturnTypes _smConfiguration _smQueryTags _smCustomization _smHealthCheckConfig :: SourceMetadata b) ->
|
||||
AB.dispatchAnyBackend @Backend exists $ \(SourceMetadata _smName _smKind _smTables _smFunctions _smNativeQueries _smCustomReturnTypes _smConfiguration _smQueryTags _smCustomization _smHealthCheckConfig :: SourceMetadata b) ->
|
||||
let sourceNamePair = ("name", AO.toOrdered _smName)
|
||||
sourceKindPair = ("kind", AO.toOrdered _smKind)
|
||||
tablesPair = ("tables", AO.array $ map tableMetaToOrdJSON $ sortOn _tmTable $ OM.elems _smTables)
|
||||
functionsPair = listToMaybeOrdPairSort "functions" functionMetadataToOrdJSON _fmFunction _smFunctions
|
||||
logicalModelsPair = listToMaybeOrdPairSort "logical_models" AO.toOrdered _lmmRootFieldName (OM.elems _smLogicalModels)
|
||||
nativeQueriesPair = listToMaybeOrdPairSort "native_queries" AO.toOrdered _nqmRootFieldName (OM.elems _smNativeQueries)
|
||||
customReturnTypesPair = listToMaybeOrdPairSort "custom_return_types" AO.toOrdered _crtmName (OM.elems _smCustomReturnTypes)
|
||||
configurationPair = [("configuration", AO.toOrdered _smConfiguration)]
|
||||
queryTagsConfigPair = maybe [] (\queryTagsConfig -> [("query_tags", AO.toOrdered queryTagsConfig)]) _smQueryTags
|
||||
@ -133,7 +133,7 @@ sourcesToOrdJSONList sources =
|
||||
in AO.object $
|
||||
[sourceNamePair, sourceKindPair, tablesPair]
|
||||
<> maybeToList functionsPair
|
||||
<> maybeToList logicalModelsPair
|
||||
<> maybeToList nativeQueriesPair
|
||||
<> maybeToList customReturnTypesPair
|
||||
<> configurationPair
|
||||
<> queryTagsConfigPair
|
||||
|
@ -341,7 +341,7 @@ getInconsistentQueryCollections rs qcs lqToMetadataObj restEndpoints allowLst =
|
||||
lqs = _cdQueries . _ccDefinition $ cc
|
||||
|
||||
inAllowList :: [NormalizedQuery] -> (ListedQuery) -> Bool
|
||||
inAllowList logicalModelList (ListedQuery {..}) = any (\lmCode -> unNormalizedQuery lmCode == (unGQLQuery . getGQLQuery) _lqQuery) logicalModelList
|
||||
inAllowList nativeQueryList (ListedQuery {..}) = any (\nqCode -> unNormalizedQuery nqCode == (unGQLQuery . getGQLQuery) _lqQuery) nativeQueryList
|
||||
|
||||
inRESTEndpoints :: EndpointTrie GQLQueryWithText -> (ListedQuery) -> [Text]
|
||||
inRESTEndpoints edTrie lq = map fst $ filter (queryIsFaulty) allQueries
|
||||
|
@ -30,7 +30,7 @@ import Data.Text.Extended
|
||||
import Data.Text.NonEmpty
|
||||
import Hasura.Base.Error
|
||||
import Hasura.CustomReturnType.Types (CustomReturnTypeName)
|
||||
import Hasura.LogicalModel.Types (LogicalModelName)
|
||||
import Hasura.NativeQuery.Types (NativeQueryName)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.BoolExp (PartialSQLExp)
|
||||
import Hasura.RQL.Types.Backend
|
||||
@ -76,7 +76,7 @@ data SourceObjId (b :: BackendType)
|
||||
= SOITable (TableName b)
|
||||
| SOITableObj (TableName b) (TableObjId b)
|
||||
| SOIFunction (FunctionName b)
|
||||
| SOILogicalModel LogicalModelName
|
||||
| SOINativeQuery NativeQueryName
|
||||
| SOICustomReturnType CustomReturnTypeName
|
||||
| SOICustomReturnTypeObj CustomReturnTypeName (CustomReturnTypeObjId b)
|
||||
deriving (Eq, Generic)
|
||||
@ -107,7 +107,7 @@ reportSchemaObj = \case
|
||||
\case
|
||||
SOITable tn -> "table " <> toTxt tn
|
||||
SOIFunction fn -> "function " <> toTxt fn
|
||||
SOILogicalModel lmn -> "logical model " <> toTxt lmn
|
||||
SOINativeQuery lmn -> "native query " <> toTxt lmn
|
||||
SOICustomReturnType crt -> "custom return type " <> toTxt crt
|
||||
SOICustomReturnTypeObj crt (CRTOCol cn) ->
|
||||
"custom return type column " <> toTxt crt <> "." <> toTxt cn
|
||||
|
@ -13,7 +13,7 @@ module Hasura.RQL.Types.Source
|
||||
unsafeSourceName,
|
||||
unsafeSourceTables,
|
||||
siConfiguration,
|
||||
siLogicalModels,
|
||||
siNativeQueries,
|
||||
siCustomReturnTypes,
|
||||
siFunctions,
|
||||
siName,
|
||||
@ -51,7 +51,7 @@ import Hasura.Base.Error
|
||||
import Hasura.CustomReturnType.Cache (CustomReturnTypeCache)
|
||||
import Hasura.Function.Cache
|
||||
import Hasura.Logging qualified as L
|
||||
import Hasura.LogicalModel.Cache (LogicalModelCache)
|
||||
import Hasura.NativeQuery.Cache (NativeQueryCache)
|
||||
import Hasura.Prelude
|
||||
import Hasura.QueryTags.Types
|
||||
import Hasura.RQL.Types.Backend
|
||||
@ -73,7 +73,7 @@ data SourceInfo b = SourceInfo
|
||||
{ _siName :: SourceName,
|
||||
_siTables :: TableCache b,
|
||||
_siFunctions :: FunctionCache b,
|
||||
_siLogicalModels :: LogicalModelCache b,
|
||||
_siNativeQueries :: NativeQueryCache b,
|
||||
_siCustomReturnTypes :: CustomReturnTypeCache b,
|
||||
_siConfiguration :: ~(SourceConfig b),
|
||||
_siQueryTagsConfig :: Maybe QueryTagsConfig,
|
||||
@ -86,7 +86,7 @@ instance
|
||||
( Backend b,
|
||||
ToJSON (TableCache b),
|
||||
ToJSON (FunctionCache b),
|
||||
ToJSON (LogicalModelCache b),
|
||||
ToJSON (NativeQueryCache b),
|
||||
ToJSON (QueryTagsConfig),
|
||||
ToJSON (SourceCustomization)
|
||||
) =>
|
||||
@ -97,7 +97,7 @@ instance
|
||||
[ "name" .= _siName,
|
||||
"tables" .= _siTables,
|
||||
"functions" .= _siFunctions,
|
||||
"logical_models" .= _siLogicalModels,
|
||||
"native_queries" .= _siNativeQueries,
|
||||
"configuration" .= _siConfiguration,
|
||||
"query_tags_config" .= _siQueryTagsConfig
|
||||
]
|
||||
|
@ -22,7 +22,7 @@ module Hasura.Server.API.Backend
|
||||
tablePermissionsCommands,
|
||||
computedFieldCommands,
|
||||
connectionTemplateCommands,
|
||||
logicalModelsCommands,
|
||||
nativeQueriesCommands,
|
||||
customReturnTypesCommands,
|
||||
)
|
||||
where
|
||||
@ -169,11 +169,11 @@ connectionTemplateCommands =
|
||||
[ commandParser "test_connection_template" $ RMTestConnectionTemplate . mkAnyBackend @b
|
||||
]
|
||||
|
||||
logicalModelsCommands :: forall (b :: BackendType). Backend b => [CommandParser b]
|
||||
logicalModelsCommands =
|
||||
[ commandParser "get_logical_model" $ RMGetLogicalModel . mkAnyBackend @b,
|
||||
commandParser "track_logical_model" $ RMTrackLogicalModel . mkAnyBackend @b,
|
||||
commandParser "untrack_logical_model" $ RMUntrackLogicalModel . mkAnyBackend @b
|
||||
nativeQueriesCommands :: forall (b :: BackendType). Backend b => [CommandParser b]
|
||||
nativeQueriesCommands =
|
||||
[ commandParser "get_native_query" $ RMGetNativeQuery . mkAnyBackend @b,
|
||||
commandParser "track_native_query" $ RMTrackNativeQuery . mkAnyBackend @b,
|
||||
commandParser "untrack_native_query" $ RMUntrackNativeQuery . mkAnyBackend @b
|
||||
]
|
||||
|
||||
customReturnTypesCommands :: forall (b :: BackendType). Backend b => [CommandParser b]
|
||||
|
@ -25,8 +25,8 @@ import Hasura.EncJSON
|
||||
import Hasura.Function.API qualified as Functions
|
||||
import Hasura.GraphQL.Schema.Options qualified as Options
|
||||
import Hasura.Logging qualified as L
|
||||
import Hasura.LogicalModel.API qualified as LogicalModels
|
||||
import Hasura.Metadata.Class
|
||||
import Hasura.NativeQuery.API qualified as NativeQueries
|
||||
import Hasura.Prelude hiding (first)
|
||||
import Hasura.RQL.DDL.Action
|
||||
import Hasura.RQL.DDL.ApiLimit
|
||||
@ -137,10 +137,10 @@ data RQLMetadataV1
|
||||
| RMDropComputedField !(AnyBackend DropComputedField)
|
||||
| -- Connection template
|
||||
RMTestConnectionTemplate !(AnyBackend TestConnectionTemplate)
|
||||
| -- Logical Models
|
||||
RMGetLogicalModel !(AnyBackend LogicalModels.GetLogicalModel)
|
||||
| RMTrackLogicalModel !(AnyBackend LogicalModels.TrackLogicalModel)
|
||||
| RMUntrackLogicalModel !(AnyBackend LogicalModels.UntrackLogicalModel)
|
||||
| -- Native Queries
|
||||
RMGetNativeQuery !(AnyBackend NativeQueries.GetNativeQuery)
|
||||
| RMTrackNativeQuery !(AnyBackend NativeQueries.TrackNativeQuery)
|
||||
| RMUntrackNativeQuery !(AnyBackend NativeQueries.UntrackNativeQuery)
|
||||
| -- Custom types
|
||||
RMGetCustomReturnType !(AnyBackend CustomReturnType.GetCustomReturnType)
|
||||
| RMTrackCustomReturnType !(AnyBackend CustomReturnType.TrackCustomReturnType)
|
||||
@ -508,9 +508,9 @@ queryModifiesMetadata = \case
|
||||
RMGetTableInfo _ -> False
|
||||
RMTestConnectionTemplate _ -> False
|
||||
RMSuggestRelationships _ -> False
|
||||
RMGetLogicalModel _ -> False
|
||||
RMTrackLogicalModel _ -> True
|
||||
RMUntrackLogicalModel _ -> True
|
||||
RMGetNativeQuery _ -> False
|
||||
RMTrackNativeQuery _ -> True
|
||||
RMUntrackNativeQuery _ -> True
|
||||
RMGetCustomReturnType _ -> False
|
||||
RMTrackCustomReturnType _ -> True
|
||||
RMUntrackCustomReturnType _ -> True
|
||||
@ -704,9 +704,9 @@ runMetadataQueryV1M env checkFeatureFlag remoteSchemaPerms currentResourceVersio
|
||||
RMAddComputedField q -> dispatchMetadata runAddComputedField q
|
||||
RMDropComputedField q -> dispatchMetadata runDropComputedField q
|
||||
RMTestConnectionTemplate q -> dispatchMetadata runTestConnectionTemplate q
|
||||
RMGetLogicalModel q -> dispatchMetadata LogicalModels.runGetLogicalModel q
|
||||
RMTrackLogicalModel q -> dispatchMetadata (LogicalModels.runTrackLogicalModel env) q
|
||||
RMUntrackLogicalModel q -> dispatchMetadata LogicalModels.runUntrackLogicalModel q
|
||||
RMGetNativeQuery q -> dispatchMetadata NativeQueries.runGetNativeQuery q
|
||||
RMTrackNativeQuery q -> dispatchMetadata (NativeQueries.runTrackNativeQuery env) q
|
||||
RMUntrackNativeQuery q -> dispatchMetadata NativeQueries.runUntrackNativeQuery q
|
||||
RMGetCustomReturnType q -> dispatchMetadata CustomReturnType.runGetCustomReturnType q
|
||||
RMTrackCustomReturnType q -> dispatchMetadata CustomReturnType.runTrackCustomReturnType q
|
||||
RMUntrackCustomReturnType q -> dispatchMetadata CustomReturnType.runUntrackCustomReturnType q
|
||||
|
@ -5,7 +5,7 @@ where
|
||||
|
||||
import Hasura.CustomReturnType.API qualified as CustomReturnType
|
||||
import Hasura.Function.API qualified as Functions
|
||||
import Hasura.LogicalModel.API qualified as LogicalModels
|
||||
import Hasura.NativeQuery.API qualified as NativeQueries
|
||||
import Hasura.RQL.DDL.Action
|
||||
import Hasura.RQL.DDL.ComputedField
|
||||
import Hasura.RQL.DDL.ConnectionTemplate
|
||||
@ -89,10 +89,10 @@ data RQLMetadataV1
|
||||
| RMDropComputedField !(AnyBackend DropComputedField)
|
||||
| -- Connection template
|
||||
RMTestConnectionTemplate !(AnyBackend TestConnectionTemplate)
|
||||
| -- Logical Models
|
||||
RMGetLogicalModel !(AnyBackend LogicalModels.GetLogicalModel)
|
||||
| RMTrackLogicalModel !(AnyBackend LogicalModels.TrackLogicalModel)
|
||||
| RMUntrackLogicalModel !(AnyBackend LogicalModels.UntrackLogicalModel)
|
||||
| -- Native Queries
|
||||
RMGetNativeQuery !(AnyBackend NativeQueries.GetNativeQuery)
|
||||
| RMTrackNativeQuery !(AnyBackend NativeQueries.TrackNativeQuery)
|
||||
| RMUntrackNativeQuery !(AnyBackend NativeQueries.UntrackNativeQuery)
|
||||
| -- Custom types
|
||||
RMGetCustomReturnType !(AnyBackend CustomReturnType.GetCustomReturnType)
|
||||
| RMTrackCustomReturnType !(AnyBackend CustomReturnType.TrackCustomReturnType)
|
||||
|
@ -9,7 +9,7 @@ module Hasura.Server.Init.FeatureFlag
|
||||
FeatureFlags (..),
|
||||
HasFeatureFlagChecker (..),
|
||||
featureFlags,
|
||||
logicalModelInterface,
|
||||
nativeQueryInterface,
|
||||
)
|
||||
where
|
||||
|
||||
@ -55,7 +55,7 @@ featureFlags =
|
||||
FeatureFlags $
|
||||
HashMap.fromList
|
||||
[ ("test-flag", testFlag),
|
||||
("native-query-interface", logicalModelInterface)
|
||||
("native-query-interface", nativeQueryInterface)
|
||||
]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@ -83,11 +83,11 @@ testFlag =
|
||||
ffEnvVar = "HASURA_FF_TEST_FLAG"
|
||||
}
|
||||
|
||||
logicalModelInterface :: FeatureFlag
|
||||
logicalModelInterface =
|
||||
nativeQueryInterface :: FeatureFlag
|
||||
nativeQueryInterface =
|
||||
FeatureFlag
|
||||
{ ffIdentifier = Identifier "native-query-interface",
|
||||
ffDefaultValue = False,
|
||||
ffDescription = "Expose custom views, permissions and advanced SQL functionality via custom queries",
|
||||
ffEnvVar = "HASURA_FF_LOGICAL_MODEL_INTERFACE"
|
||||
ffEnvVar = "HASURA_FF_NATIVE_QUERY_INTERFACE"
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ import Data.Text.Conversions (UTF8 (..), decodeText)
|
||||
import Hasura.App.State qualified as State
|
||||
import Hasura.HTTP
|
||||
import Hasura.Logging
|
||||
import Hasura.LogicalModel.Cache (LogicalModelInfo (_lmiArguments))
|
||||
import Hasura.NativeQuery.Cache (NativeQueryInfo (_nqiArguments))
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Action
|
||||
import Hasura.RQL.Types.Common
|
||||
@ -267,7 +267,7 @@ computeMetrics sourceInfo _mtServiceTimings remoteSchemaMap actionCache =
|
||||
_mtRemoteSchemas = Map.size <$> remoteSchemaMap
|
||||
_mtFunctions = Map.size $ Map.filter (not . isSystemDefined . _fiSystemDefined) sourceFunctionCache
|
||||
_mtActions = computeActionsMetrics <$> actionCache
|
||||
_mtLogicalModels = countLogicalModels (HM.elems $ _siLogicalModels sourceInfo)
|
||||
_mtNativeQueries = countNativeQueries (HM.elems $ _siNativeQueries sourceInfo)
|
||||
in Metrics {..}
|
||||
where
|
||||
sourceTableCache = _siTables sourceInfo
|
||||
@ -280,13 +280,13 @@ computeMetrics sourceInfo _mtServiceTimings remoteSchemaMap actionCache =
|
||||
permsOfTbl :: TableInfo b -> [(RoleName, RolePermInfo b)]
|
||||
permsOfTbl = Map.toList . _tiRolePermInfoMap
|
||||
|
||||
countLogicalModels :: [LogicalModelInfo b] -> LogicalModelsMetrics
|
||||
countLogicalModels =
|
||||
countNativeQueries :: [NativeQueryInfo b] -> NativeQueriesMetrics
|
||||
countNativeQueries =
|
||||
foldMap
|
||||
( \logimo ->
|
||||
if null (_lmiArguments logimo)
|
||||
then mempty {_lmmWithoutParameters = 1}
|
||||
else mempty {_lmmWithParameters = 1}
|
||||
if null (_nqiArguments logimo)
|
||||
then mempty {_nqmWithoutParameters = 1}
|
||||
else mempty {_nqmWithParameters = 1}
|
||||
)
|
||||
|
||||
-- | Compute the relevant metrics for actions from the action cache.
|
||||
|
@ -8,7 +8,7 @@ module Hasura.Server.Telemetry.Types
|
||||
RelationshipMetric (..),
|
||||
PermissionMetric (..),
|
||||
ActionMetric (..),
|
||||
LogicalModelsMetrics (..),
|
||||
NativeQueriesMetrics (..),
|
||||
Metrics (..),
|
||||
SourceMetadata (..),
|
||||
HasuraTelemetry (..),
|
||||
@ -74,22 +74,22 @@ data ActionMetric = ActionMetric
|
||||
|
||||
$(A.deriveToJSON hasuraJSON ''ActionMetric)
|
||||
|
||||
data LogicalModelsMetrics = LogicalModelsMetrics
|
||||
{ _lmmWithParameters :: Int,
|
||||
_lmmWithoutParameters :: Int
|
||||
data NativeQueriesMetrics = NativeQueriesMetrics
|
||||
{ _nqmWithParameters :: Int,
|
||||
_nqmWithoutParameters :: Int
|
||||
}
|
||||
deriving (Show, Eq)
|
||||
|
||||
instance Semigroup LogicalModelsMetrics where
|
||||
instance Semigroup NativeQueriesMetrics where
|
||||
a <> b =
|
||||
LogicalModelsMetrics
|
||||
(_lmmWithParameters a + _lmmWithParameters b)
|
||||
(_lmmWithoutParameters a + _lmmWithoutParameters b)
|
||||
NativeQueriesMetrics
|
||||
(_nqmWithParameters a + _nqmWithParameters b)
|
||||
(_nqmWithoutParameters a + _nqmWithoutParameters b)
|
||||
|
||||
instance Monoid LogicalModelsMetrics where
|
||||
mempty = LogicalModelsMetrics 0 0
|
||||
instance Monoid NativeQueriesMetrics where
|
||||
mempty = NativeQueriesMetrics 0 0
|
||||
|
||||
$(A.deriveToJSON hasuraJSON ''LogicalModelsMetrics)
|
||||
$(A.deriveToJSON hasuraJSON ''NativeQueriesMetrics)
|
||||
|
||||
data Metrics = Metrics
|
||||
{ _mtTables :: Int,
|
||||
@ -102,7 +102,7 @@ data Metrics = Metrics
|
||||
_mtRemoteSchemas :: Maybe Int,
|
||||
_mtServiceTimings :: Maybe ServiceTimingMetrics,
|
||||
_mtActions :: Maybe ActionMetric,
|
||||
_mtLogicalModels :: LogicalModelsMetrics
|
||||
_mtNativeQueries :: NativeQueriesMetrics
|
||||
}
|
||||
deriving (Show, Eq)
|
||||
|
||||
|
@ -4,17 +4,17 @@
|
||||
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
|
||||
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
|
||||
|
||||
module Hasura.Backends.Postgres.LogicalModels.LogicalModelsSpec (spec) where
|
||||
module Hasura.Backends.Postgres.NativeQueries.NativeQueriesSpec (spec) where
|
||||
|
||||
import Data.Bifunctor
|
||||
import Data.Either
|
||||
import Data.HashMap.Strict qualified as HM
|
||||
import Hasura.Backends.Postgres.Instances.LogicalModels
|
||||
import Hasura.Backends.Postgres.Instances.NativeQueries
|
||||
import Hasura.Backends.Postgres.SQL.Types
|
||||
import Hasura.Base.Error
|
||||
import Hasura.CustomReturnType.Metadata
|
||||
import Hasura.LogicalModel.Metadata
|
||||
import Hasura.LogicalModel.Types
|
||||
import Hasura.NativeQuery.Metadata
|
||||
import Hasura.NativeQuery.Types
|
||||
import Hasura.Prelude hiding (first)
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
import Test.Hspec (Spec, describe, it, shouldBe, shouldSatisfy)
|
||||
@ -28,7 +28,7 @@ spec = do
|
||||
|
||||
it "Parses only a variable" $ do
|
||||
let rawSQL = "{{dogs}}"
|
||||
parseInterpolatedQuery rawSQL `shouldBe` Right (InterpolatedQuery [IIVariable (LogicalModelArgumentName "dogs")])
|
||||
parseInterpolatedQuery rawSQL `shouldBe` Right (InterpolatedQuery [IIVariable (NativeQueryArgumentName "dogs")])
|
||||
|
||||
it "Parses SQL with one parameter in it" $ do
|
||||
let rawSQL = "SELECT * FROM dogs WHERE name = {{name}}"
|
||||
@ -36,7 +36,7 @@ spec = do
|
||||
`shouldBe` Right
|
||||
( InterpolatedQuery
|
||||
[ IIText "SELECT * FROM dogs WHERE name = ",
|
||||
IIVariable (LogicalModelArgumentName "name")
|
||||
IIVariable (NativeQueryArgumentName "name")
|
||||
]
|
||||
)
|
||||
|
||||
@ -46,7 +46,7 @@ spec = do
|
||||
`shouldBe` Right
|
||||
( InterpolatedQuery
|
||||
[ IIText "SELECT * FROM dogs WHERE ",
|
||||
IIVariable (LogicalModelArgumentName "name"),
|
||||
IIVariable (NativeQueryArgumentName "name"),
|
||||
IIText " = name"
|
||||
]
|
||||
)
|
||||
@ -57,7 +57,7 @@ spec = do
|
||||
`shouldBe` Right
|
||||
( InterpolatedQuery
|
||||
[ IIText "SELECT * FROM dogs WHERE ",
|
||||
IIVariable (LogicalModelArgumentName "name"),
|
||||
IIVariable (NativeQueryArgumentName "name"),
|
||||
IIText " = '{doggy friend}'"
|
||||
]
|
||||
)
|
||||
@ -75,18 +75,18 @@ spec = do
|
||||
_crtmSelectPermissions = mempty
|
||||
}
|
||||
|
||||
lmm =
|
||||
LogicalModelMetadata
|
||||
{ _lmmRootFieldName = LogicalModelName (G.unsafeMkName "root_field_name"),
|
||||
_lmmCode = InterpolatedQuery mempty,
|
||||
_lmmReturns = CustomReturnTypeName (G.unsafeMkName "custom_return_type_name"),
|
||||
_lmmArguments = mempty,
|
||||
_lmmDescription = mempty
|
||||
nqm =
|
||||
NativeQueryMetadata
|
||||
{ _nqmRootFieldName = NativeQueryName (G.unsafeMkName "root_field_name"),
|
||||
_nqmCode = InterpolatedQuery mempty,
|
||||
_nqmReturns = CustomReturnTypeName (G.unsafeMkName "custom_return_type_name"),
|
||||
_nqmArguments = mempty,
|
||||
_nqmDescription = mempty
|
||||
}
|
||||
|
||||
it "Rejects undeclared variables" do
|
||||
let Right code = parseInterpolatedQuery "SELECT {{hey}}"
|
||||
let actual :: Either QErr Text = fmap snd $ runExcept $ logicalModelToPreparedStatement crtm lmm {_lmmCode = code}
|
||||
let actual :: Either QErr Text = fmap snd $ runExcept $ nativeQueryToPreparedStatement crtm nqm {_nqmCode = code}
|
||||
|
||||
(first showQErr actual) `shouldSatisfy` isLeft
|
||||
let Left err = actual
|
||||
@ -97,13 +97,13 @@ spec = do
|
||||
let actual :: Either QErr Text =
|
||||
fmap snd $
|
||||
runExcept $
|
||||
logicalModelToPreparedStatement
|
||||
nativeQueryToPreparedStatement
|
||||
crtm
|
||||
lmm
|
||||
{ _lmmCode = code,
|
||||
_lmmArguments =
|
||||
nqm
|
||||
{ _nqmCode = code,
|
||||
_nqmArguments =
|
||||
HM.fromList
|
||||
[ (LogicalModelArgumentName "hey", NullableScalarType PGVarchar False Nothing)
|
||||
[ (NativeQueryArgumentName "hey", NullableScalarType PGVarchar False Nothing)
|
||||
]
|
||||
}
|
||||
|
||||
@ -117,14 +117,14 @@ spec = do
|
||||
let actual :: Either QErr Text =
|
||||
fmap snd $
|
||||
runExcept $
|
||||
logicalModelToPreparedStatement
|
||||
nativeQueryToPreparedStatement
|
||||
crtm
|
||||
lmm
|
||||
{ _lmmCode = code,
|
||||
_lmmArguments =
|
||||
nqm
|
||||
{ _nqmCode = code,
|
||||
_nqmArguments =
|
||||
HM.fromList
|
||||
[ (LogicalModelArgumentName "hey", NullableScalarType PGVarchar False Nothing),
|
||||
(LogicalModelArgumentName "ho", NullableScalarType PGInteger False Nothing)
|
||||
[ (NativeQueryArgumentName "hey", NullableScalarType PGVarchar False Nothing),
|
||||
(NativeQueryArgumentName "ho", NullableScalarType PGInteger False Nothing)
|
||||
]
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ spec = do
|
||||
{ _siName = SNDefault,
|
||||
_siTables = makeTableCache [albumTableInfo, trackTableInfo],
|
||||
_siFunctions = mempty,
|
||||
_siLogicalModels = mempty,
|
||||
_siNativeQueries = mempty,
|
||||
_siCustomReturnTypes = mempty,
|
||||
_siConfiguration = notImplementedYet "SourceConfig",
|
||||
_siQueryTagsConfig = Nothing,
|
||||
|
@ -98,7 +98,7 @@ runUpdateFieldTest UpdateTestSetup {..} =
|
||||
{ _siName = SNDefault,
|
||||
_siTables = HM.singleton table tableInfo,
|
||||
_siFunctions = mempty,
|
||||
_siLogicalModels = mempty,
|
||||
_siNativeQueries = mempty,
|
||||
_siCustomReturnTypes = mempty,
|
||||
_siConfiguration = notImplementedYet "SourceConfig",
|
||||
_siQueryTagsConfig = Nothing,
|
||||
|
Loading…
Reference in New Issue
Block a user