Rename "Logical Models" → "Native Queries"

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8769
GitOrigin-RevId: 66f2cbfb620d641e672a4074554d9d324a18c591
This commit is contained in:
Philip Lykke Carlsen 2023-04-13 18:10:38 +02:00 committed by hasura-bot
parent ef5377a09e
commit 0346224444
95 changed files with 1369 additions and 1371 deletions

View File

@ -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"`

View File

@ -51,7 +51,7 @@
- question
filter: {}
role: user
logical_models:
native_queries:
- arguments:
unused:
description: An integer argument that we completely ignore

View File

@ -81,7 +81,7 @@
]
}
],
"logical_models": [
"native_queries": [
{
"arguments": {
"unused": {

View File

@ -81,7 +81,7 @@
}
}
],
"logical_models": [
"native_queries": [
{
"arguments": {
"unused": {

View File

@ -51,7 +51,7 @@
- question
filter: {}
role: user
logical_models:
native_queries:
- arguments:
unused:
description: An integer argument that we completely ignore

View File

@ -25012,7 +25012,7 @@
]
}
],
"logical_models": null,
"native_queries": null,
"custom_return_types": null,
"functions": [
{

View File

@ -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:

View File

@ -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
}

View File

@ -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"
},

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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 =

View File

@ -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|

View File

@ -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|

View File

@ -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

View File

@ -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

View File

@ -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
|]

View File

@ -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
)

View File

@ -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)

View File

@ -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 <-

View File

@ -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
}

View File

@ -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)

View File

@ -15,6 +15,6 @@ instance BackendAPI 'BigQuery where
relationshipCommands @'BigQuery,
remoteRelationshipCommands @'BigQuery,
computedFieldCommands @'BigQuery,
logicalModelsCommands @'BigQuery,
nativeQueriesCommands @'BigQuery,
customReturnTypesCommands @'BigQuery
]

View File

@ -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 ()

View File

@ -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

View File

@ -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

View File

@ -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} =

View File

@ -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)

View File

@ -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,

View File

@ -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

View File

@ -18,6 +18,6 @@ instance BackendAPI 'MSSQL where
relationshipCommands @'MSSQL,
remoteRelationshipCommands @'MSSQL,
eventTriggerCommands @'MSSQL,
logicalModelsCommands @'MSSQL,
nativeQueriesCommands @'MSSQL,
customReturnTypesCommands @'MSSQL
]

View File

@ -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

View File

@ -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 []

View File

@ -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)
--------------------------------------------------------------------------------

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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)
]

View File

@ -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

View File

@ -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) <> ")"

View File

@ -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 ()

View File

@ -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

View File

@ -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'.
--

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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 (..))

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)) ->

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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 <<> ".")

View File

@ -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

View File

@ -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)

View 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 <<> ".")

View 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

View 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)

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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)

View File

@ -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)

View File

@ -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.

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
]

View File

@ -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]

View File

@ -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

View File

@ -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)

View File

@ -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"
}

View File

@ -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.

View File

@ -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)

View File

@ -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)
]
}

View File

@ -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,

View File

@ -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,