server/tests: Table Computed Fields > Postgres

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7122
GitOrigin-RevId: e8c191a87465c1810908e8851bcc4b6919873bd8
This commit is contained in:
Abby Sassel 2022-12-01 16:42:11 +00:00 committed by hasura-bot
parent e008e113d3
commit 13eb1122ed
8 changed files with 652 additions and 440 deletions

View File

@ -74,6 +74,7 @@ library
Test.Auth.Authorization.DisableRootFields.SelectPermission.RelationshipSpec
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
@ -92,17 +93,17 @@ library
Test.DataConnector.MockAgent.TransformedConfigurationSpec
Test.DataConnector.QuerySpec
Test.DataConnector.SelectPermissionsSpec
Test.EventTriggers.MSSQL.EventTriggersUniqueNameSpec
Test.EventTriggers.MSSQL.EventTriggerDropSourceCleanupSpec
Test.EventTriggers.MSSQL.EventTriggersUntrackTableCleanupSpec
Test.EventTriggers.MSSQL.EventTriggersForReplicationSpec
Test.EventTriggers.MSSQL.EventTriggersUniqueNameSpec
Test.EventTriggers.MSSQL.EventTriggersUntrackTableCleanupSpec
Test.EventTriggers.PG.EventTriggersExtensionSchemaSpec
Test.EventTriggers.PG.EventTriggersForReplicationSpec
Test.EventTriggers.PG.EventTriggersRecreationSpec
Test.EventTriggers.PG.EventTriggersReplaceMetadataCleanupSpec
Test.EventTriggers.PG.EventTriggersRunSQLSpec
Test.EventTriggers.PG.EventTriggersUniqueNameSpec
Test.EventTriggers.PG.EventTriggersUntrackTableCleanupSpec
Test.EventTriggers.PG.EventTriggersForReplicationSpec
Test.Harness.Quoter.YamlSpec
Test.HelloWorldSpec
Test.Mutations.Delete.AllSpec
@ -147,8 +148,8 @@ library
Test.Regression.ObjectRelationshipsLimit7936Spec
Test.Regression.StreamConflictSpec
Test.Regression.UsingTheSameFunctionForRootFieldAndComputedField8643Spec
Test.Schema.ComputedFields.TableSpec
Test.Schema.ComputedFields.ScalarSpec
Test.Schema.ComputedFields.TableSpec
Test.Schema.ConflictsSpec
Test.Schema.CustomFieldNames.MutationSpec
Test.Schema.CustomFieldNames.QuerySpec
@ -158,7 +159,6 @@ library
Test.Schema.DefaultValues.DefaultValuesSpec
Test.Schema.DefaultValues.OnConflictSpec
Test.Schema.EnumsSpec
Test.Schema.RemoteSchemaCustomizationSpec
Test.Schema.RemoteRelationships.FromRemoteSchemaSpec
Test.Schema.RemoteRelationships.MetadataAPI.ClearMetadataSpec
Test.Schema.RemoteRelationships.MetadataAPI.Common
@ -167,6 +167,7 @@ library
Test.Schema.RemoteRelationships.XToDBArrayRelationshipSpec
Test.Schema.RemoteRelationships.XToDBObjectRelationshipSpec
Test.Schema.RemoteRelationships.XToRemoteSchemaRelationshipSpec
Test.Schema.RemoteSchemaCustomizationSpec
Test.Schema.TableRelationships.ArrayRelationshipsSpec
Test.Schema.TableRelationships.ObjectRelationshipsSpec
Test.Schema.TableRelationships.PortedSpec

View File

@ -82,10 +82,7 @@ setupFunctions testEnv =
"AS t WHERE t.author_id = a_id and (t.title LIKE `search` OR t.content LIKE `search`)",
");"
],
Fixture.teardownAction = \_ ->
BigQuery.run_ $
T.unpack $
"DROP TABLE FUNCTION " <> fetch_articles_returns_table schemaName <> ";"
Fixture.teardownAction = \_ -> pure ()
},
Fixture.SetupAction
{ Fixture.setupAction =
@ -101,10 +98,7 @@ setupFunctions testEnv =
"AS t WHERE t.author_id = a_id and (t.title LIKE `search` OR t.content LIKE `search`)",
");"
],
Fixture.teardownAction = \_ ->
BigQuery.run_ $
T.unpack $
"DROP TABLE FUNCTION " <> fetch_articles schemaName <> ";"
Fixture.teardownAction = \_ -> pure ()
},
Fixture.SetupAction
{ Fixture.setupAction =
@ -118,10 +112,7 @@ setupFunctions testEnv =
articleTableSQL,
"AS t);"
],
Fixture.teardownAction = \_ ->
BigQuery.run_ $
T.unpack $
"DROP TABLE FUNCTION " <> function_no_args schemaName <> ";"
Fixture.teardownAction = \_ -> pure ()
},
Fixture.SetupAction
{ Fixture.setupAction =
@ -132,10 +123,7 @@ setupFunctions testEnv =
add_int schemaName <> "(a INT64, b INT64)",
"RETURNS INT64 AS (a + b);"
],
Fixture.teardownAction = \_ ->
BigQuery.run_ $
T.unpack $
"DROP FUNCTION " <> add_int schemaName <> ";"
Fixture.teardownAction = \_ -> pure ()
}
]

View File

@ -0,0 +1,324 @@
{-# LANGUAGE QuasiQuotes #-}
-- | Test BigQuery-specific function definitions related to computed fields.
-- For generic tests of computed fields, see `Test.Schema.ComputedFields`
--
-- https://hasura.io/docs/latest/schema/bigquery/computed-fields/#bigquery-create-table-function
module Test.Databases.BigQuery.Schema.ComputedFields.TableSpec (spec) where
import Data.Aeson as Aeson
import Data.List.NonEmpty qualified as NE
import Data.String.Interpolate (i)
import Data.Text qualified as T
import Harness.Backend.BigQuery qualified as BigQuery
import Harness.GraphqlEngine qualified as GraphqlEngine
import Harness.Quoter.Graphql (graphql)
import Harness.Quoter.Yaml (interpolateYaml, yaml)
import Harness.Test.BackendType (BackendType (..))
import Harness.Test.BackendType qualified as BackendType
import Harness.Test.Fixture qualified as Fixture
import Harness.Test.Schema (SchemaName (..), Table (..), table)
import Harness.Test.Schema qualified as Schema
import Harness.Test.SchemaName (SchemaName (..))
import Harness.TestEnvironment (TestEnvironment)
import Harness.Yaml (shouldReturnYaml)
import Hasura.Prelude
import Test.Hspec (SpecWith, it)
-- ** Preamble
spec :: SpecWith TestEnvironment
spec =
Fixture.run
( NE.fromList
[ (Fixture.fixture $ Fixture.Backend Fixture.BigQuery)
{ Fixture.setupTeardown = \(testEnv, _) ->
[ BigQuery.setupTablesAction schema testEnv
]
<> setupFunction testEnv
<> setupMetadata testEnv BackendType.BigQuery
}
]
)
tests
-- ** Schema
schema :: [Table]
schema = [authorTable, articleTable]
authorTable :: Table
authorTable =
(table "author")
{ tableColumns =
[ Schema.column "id" Schema.TInt,
Schema.column "name" Schema.TStr
],
tablePrimaryKey = ["id"],
tableData =
[ [ Schema.VInt 1,
Schema.VStr "Author 1"
],
[ Schema.VInt 2,
Schema.VStr "Author 2"
]
]
}
articleTable :: Table
articleTable =
(table "article")
{ tableColumns =
[ Schema.column "id" Schema.TInt,
Schema.column "title" Schema.TStr,
Schema.column "content" Schema.TStr,
Schema.column "author_id" Schema.TInt
],
tablePrimaryKey = ["id"],
tableData =
[ [ Schema.VInt 1,
Schema.VStr "Article 1 Title",
Schema.VStr "Article 1 by Author 1",
Schema.VInt 1
],
[ Schema.VInt 2,
Schema.VStr "Article 2 Title",
Schema.VStr "Article 2 by Author 2",
Schema.VInt 2
],
[ Schema.VInt 3,
Schema.VStr "Article 3 Title",
Schema.VStr "Article 3 by Author 2, has search keyword",
Schema.VInt 2
]
]
}
-- ** Setup and teardown
setupFunction :: TestEnvironment -> [Fixture.SetupAction]
setupFunction testEnv =
let schemaName = Schema.getSchemaName testEnv
in [ Fixture.SetupAction
{ Fixture.setupAction =
BigQuery.run_ $
[i|
CREATE TABLE FUNCTION #{ unSchemaName schemaName }.fetch_articles_implicit_return(a_id INT64, search STRING)
AS
SELECT article_alias.*
FROM #{ unSchemaName schemaName }.article AS article_alias
WHERE article_alias.author_id = a_id
AND (article_alias.title LIKE `search` OR article_alias.content LIKE `search`)
|],
Fixture.teardownAction = \_ -> pure ()
},
Fixture.SetupAction
{ Fixture.setupAction =
BigQuery.run_ $
[i|
CREATE TABLE FUNCTION #{ unSchemaName schemaName }.fetch_articles_explicit_return(a_id INT64, search STRING)
RETURNS TABLE<id INT64, title STRING, content STRING, author_id INT64> AS
SELECT article_alias.id, article_alias.title, article_alias.content, article_alias.author_id
FROM #{ unSchemaName schemaName }.article AS article_alias
WHERE article_alias.author_id = a_id
AND (article_alias.title LIKE `search` OR article_alias.content LIKE `search`)
|],
Fixture.teardownAction = \_ -> pure ()
}
]
setupMetadata :: TestEnvironment -> BackendType -> [Fixture.SetupAction]
setupMetadata testEnv backend =
let schemaName :: Schema.SchemaName
schemaName = Schema.getSchemaName testEnv
source :: String
source = Fixture.defaultSource backend
backendPrefix :: String
backendPrefix = BackendType.defaultBackendTypeString backend
in -- Add computed fields
[ Fixture.SetupAction
{ Fixture.setupAction =
Schema.trackComputedField
backend
source
authorTable
"fetch_articles_implicit_return"
"search_articles_implicit_return"
[yaml| a_id: id |]
[yaml|
name: article
dataset: *schemaName
|]
testEnv,
Fixture.teardownAction = \_ -> pure ()
},
Fixture.SetupAction
{ Fixture.setupAction =
Schema.trackComputedField
backend
source
authorTable
"fetch_articles_explicit_return"
"search_articles_explicit_return"
[yaml| a_id: id |]
Aeson.Null
testEnv,
Fixture.teardownAction = \_ -> pure ()
}
]
-- * Tests
tests :: Fixture.Options -> SpecWith TestEnvironment
tests opts = do
-- This is a duplicate of `Test.Schema.ComputedFields.TableSpec/"Query with computed fields"
-- but I thought it was clearer next to the counterexample that follows
it "respects the `return_table` value in metadata, if it is not provided in the SQL statement" $ \testEnv -> do
let schemaName = Schema.getSchemaName testEnv
shouldReturnYaml
opts
( GraphqlEngine.postGraphql
testEnv
[graphql|
query {
#{schemaName}_author(order_by: {id: asc}){
id
name
search_articles_implicit_return(args: {search: "%keyword%"}){
id
title
content
author_id
}
}
}
|]
)
[interpolateYaml|
data:
#{schemaName}_author:
- id: '1'
name: Author 1
search_articles_implicit_return: []
- id: '2'
name: Author 2
search_articles_implicit_return:
- id: '3'
title: Article 3 Title
content: Article 3 by Author 2, has search keyword
author_id: '2'
|]
it "respects the return table based on the RETURNS TABLE<..> syntax in the SQL statement" $ \testEnv -> do
let schemaName = Schema.getSchemaName testEnv
shouldReturnYaml
opts
( GraphqlEngine.postGraphql
testEnv
[graphql|
query {
#{schemaName}_author(order_by: {id: asc}){
id
name
search_articles_explicit_return(args: {search: "%keyword%"}){
id
title
content
author_id
}
}
}
|]
)
[interpolateYaml|
data:
#{schemaName}_author:
- id: '1'
name: Author 1
search_articles_explicit_return: []
- id: '2'
name: Author 2
search_articles_explicit_return:
- id: '3'
title: Article 3 Title
content: Article 3 by Author 2, has search keyword
author_id: '2'
|]
-- This is a duplicate of `Test.Schema.ComputedFields.TableSpec/"Query respects limit and order_by"
-- but I thought it was clearer next to the counterexample that follows
it "respects limit and order_by when `returning_table` is specified in metadata" $ \testEnv -> do
let schemaName = Schema.getSchemaName testEnv
shouldReturnYaml
opts
( GraphqlEngine.postGraphql
testEnv
[graphql|
query {
#{schemaName}_author(order_by: {id: asc}){
id
name
search_articles_implicit_return(args: {search: "%by%"} limit: 1 order_by: {id: asc}){
id
title
content
author_id
}
}
}
|]
)
[interpolateYaml|
data:
#{schemaName}_author:
- id: '1'
name: Author 1
search_articles_implicit_return:
- author_id: '1'
content: Article 1 by Author 1
id: '1'
title: Article 1 Title
- id: '2'
name: Author 2
search_articles_implicit_return:
- author_id: '2'
content: Article 2 by Author 2
id: '2'
title: Article 2 Title
|]
it "throws an `order_by` error when `returning_table` is not specified in metadata" $ \testEnv -> do
let schemaName = Schema.getSchemaName testEnv
shouldReturnYaml
opts
( GraphqlEngine.postGraphql
testEnv
[graphql|
query {
#{schemaName}_author(order_by: {id: asc}){
id
name
search_articles_explicit_return(args: {search: "%by%"} limit: 1 order_by: {id: asc}){
id
title
content
author_id
}
}
}
|]
)
[interpolateYaml|
errors:
- extensions:
path: $.selectionSet.#{schemaName}_author.selectionSet.search_articles_explicit_return
code: validation-failed
message: |-
'search_articles_explicit_return' has no argument named 'order_by'
|]

View File

@ -69,7 +69,8 @@ authorTable =
-- ** Setup and teardown
-- | SQL
-- * SQL
authorFullNameSQL :: SchemaName -> String
authorFullNameSQL schemaName =
[i|
@ -79,6 +80,8 @@ authorFullNameSQL schemaName =
$$ LANGUAGE sql STABLE;
|]
-- * Setup
setupFunction :: TestEnvironment -> [Fixture.SetupAction]
setupFunction testEnv =
let schemaName = Schema.getSchemaName testEnv

View File

@ -1,17 +1,27 @@
{-# LANGUAGE QuasiQuotes #-}
-- | All tests related to computed fields
-- | Tests table computed fields whose associated SQL function returns a table
--
-- https://hasura.io/docs/latest/schema/postgres/computed-fields/#2-table-computed-fields
-- https://hasura.io/docs/latest/schema/bigquery/computed-fields/
module Test.Schema.ComputedFields.TableSpec (spec) where
import Data.List.NonEmpty qualified as NE
import Data.String.Interpolate (i)
import Data.Text qualified as T
import Harness.Backend.BigQuery qualified as BigQuery
import Harness.Backend.Postgres qualified as Postgres
import Harness.GraphqlEngine qualified as GraphqlEngine
import Harness.Quoter.Graphql (graphql)
import Harness.Quoter.Yaml (interpolateYaml, yaml)
import Harness.Test.BackendType (BackendType (..))
import Harness.Test.BackendType qualified as BackendType
import Harness.Test.Fixture qualified as Fixture
import Harness.Test.Permissions (Permission (..), selectPermission)
import Harness.Test.Permissions qualified as Permission
import Harness.Test.Schema (SchemaName (..), Table (..), table)
import Harness.Test.Schema qualified as Schema
import Harness.Test.SchemaName (SchemaName (..))
import Harness.TestEnvironment (TestEnvironment)
import Harness.Yaml (shouldReturnYaml)
import Hasura.Prelude
@ -23,12 +33,24 @@ spec :: SpecWith TestEnvironment
spec =
Fixture.run
( NE.fromList
[ (Fixture.fixture $ Fixture.Backend Fixture.BigQuery)
[ (Fixture.fixture $ Fixture.Backend Fixture.Postgres)
{ Fixture.setupTeardown = \(testEnv, _) ->
[ Postgres.setupTablesAction schema testEnv
]
<> postgresSetupFunctions testEnv
<> setupMetadata testEnv BackendType.Postgres
},
(Fixture.fixture $ Fixture.Backend Fixture.BigQuery)
{ Fixture.setupTeardown = \(testEnv, _) ->
[ BigQuery.setupTablesAction schema testEnv
]
<> setupFunctions testEnv
<> setupMetadata testEnv
<> bigquerySetupFunctions testEnv
<> setupMetadata testEnv BackendType.BigQuery,
Fixture.customOptions =
Just $
Fixture.defaultOptions
{ Fixture.stringifyNumbers = True
}
}
]
)
@ -88,280 +110,167 @@ articleTable =
-- ** Setup and teardown
setupFunctions :: TestEnvironment -> [Fixture.SetupAction]
setupFunctions testEnv =
postgresSetupFunctions :: TestEnvironment -> [Fixture.SetupAction]
postgresSetupFunctions testEnv =
let schemaName = Schema.getSchemaName testEnv
articleTableSQL = unSchemaName schemaName <> ".article"
in [ Fixture.SetupAction
{ Fixture.setupAction =
Postgres.run_ testEnv $
[i|
CREATE FUNCTION #{ fetch_articles schemaName }(author_row author, search TEXT)
RETURNS SETOF article AS $$
SELECT *
FROM #{ articleTableSQL }
WHERE
( title ilike ('%' || search || '%')
OR content ilike ('%' || search || '%')
) AND author_id = author_row.id
$$ LANGUAGE sql STABLE;
|],
Fixture.teardownAction = \_ -> pure ()
},
Fixture.SetupAction
{ Fixture.setupAction =
Postgres.run_ testEnv $
[i|
CREATE FUNCTION #{ fetch_articles_no_user_args schemaName }(author_row author)
RETURNS SETOF article AS $$
SELECT *
FROM #{ articleTableSQL }
WHERE author_id = author_row.id
$$ LANGUAGE sql STABLE;
|],
Fixture.teardownAction = \_ -> pure ()
}
]
bigquerySetupFunctions :: TestEnvironment -> [Fixture.SetupAction]
bigquerySetupFunctions testEnv =
let schemaName = Schema.getSchemaName testEnv
articleTableSQL = unSchemaName schemaName <> ".article"
in [ Fixture.SetupAction
{ Fixture.setupAction =
BigQuery.run_ $
T.unpack $
T.unwords $
[ "CREATE TABLE FUNCTION ",
fetch_articles_returns_table schemaName,
"(a_id INT64, search STRING)",
"RETURNS TABLE<id INT64, title STRING, content STRING>",
"AS (",
"SELECT t.id, t.title, t.content FROM",
articleTableSQL,
"AS t WHERE t.author_id = a_id and (t.title LIKE `search` OR t.content LIKE `search`)",
");"
],
Fixture.teardownAction = \_ ->
BigQuery.run_ $
T.unpack $
"DROP TABLE FUNCTION " <> fetch_articles_returns_table schemaName <> ";"
[i|
CREATE TABLE FUNCTION
#{ fetch_articles schemaName }(a_id INT64, search STRING)
AS
(
SELECT t.* FROM #{ articleTableSQL } AS t
WHERE t.author_id = a_id and (t.title LIKE `search` OR t.content LIKE `search`)
)
|],
Fixture.teardownAction = \_ -> pure ()
},
Fixture.SetupAction
{ Fixture.setupAction =
BigQuery.run_ $
T.unpack $
T.unwords $
[ "CREATE TABLE FUNCTION ",
fetch_articles schemaName,
"(a_id INT64, search STRING)",
"AS (",
"SELECT t.* FROM",
articleTableSQL,
"AS t WHERE t.author_id = a_id and (t.title LIKE `search` OR t.content LIKE `search`)",
");"
],
Fixture.teardownAction = \_ ->
BigQuery.run_ $
T.unpack $
"DROP TABLE FUNCTION " <> fetch_articles schemaName <> ";"
},
Fixture.SetupAction
{ Fixture.setupAction =
BigQuery.run_ $
T.unpack $
T.unwords $
[ "CREATE TABLE FUNCTION ",
fetch_articles_no_user_args_returns_table schemaName,
"(a_id INT64)",
"AS (",
"SELECT t.* FROM",
articleTableSQL,
"AS t WHERE t.author_id = a_id",
");"
],
Fixture.teardownAction = \_ ->
BigQuery.run_ $
T.unpack $
"DROP TABLE FUNCTION " <> fetch_articles_no_user_args_returns_table schemaName <> ";"
[i|
CREATE TABLE FUNCTION
#{ fetch_articles_no_user_args schemaName }(a_id INT64)
AS
(
SELECT t.* FROM #{ articleTableSQL } AS t
WHERE t.author_id = a_id
)
|],
Fixture.teardownAction = \_ -> pure ()
}
]
fetch_articles_returns_table :: SchemaName -> T.Text
fetch_articles_returns_table schemaName =
unSchemaName schemaName <> ".fetch_articles_returns_table"
fetch_articles_no_user_args_returns_table :: SchemaName -> T.Text
fetch_articles_no_user_args_returns_table schemaName =
unSchemaName schemaName <> ".fetch_articles_no_user_args_returns_table"
fetch_articles :: SchemaName -> T.Text
fetch_articles schemaName =
unSchemaName schemaName <> ".fetch_articles"
setupMetadata :: TestEnvironment -> [Fixture.SetupAction]
setupMetadata testEnv =
let schemaName = Schema.getSchemaName testEnv
fetch_articles_no_user_args :: SchemaName -> T.Text
fetch_articles_no_user_args schemaName =
unSchemaName schemaName <> ".fetch_articles_no_user_args"
setupMetadata :: TestEnvironment -> BackendType -> [Fixture.SetupAction]
setupMetadata testEnv backend =
let schemaName :: Schema.SchemaName
schemaName = Schema.getSchemaName testEnv
source :: String
source = Fixture.defaultSource backend
backendPrefix :: String
backendPrefix = BackendType.defaultBackendTypeString backend
in -- Add computed fields and define select permissions
[ Fixture.SetupAction
{ Fixture.setupAction =
GraphqlEngine.postMetadata_
testEnv
Schema.trackComputedField
backend
source
authorTable
"fetch_articles"
"search_articles"
[yaml| a_id: id |]
[yaml|
type: bigquery_add_computed_field
args:
source: bigquery
name: search_articles_1
table:
dataset: *schemaName
name: author
definition:
function:
dataset: *schemaName
name: fetch_articles_returns_table
argument_mapping:
a_id: id
|],
Fixture.teardownAction = \_ ->
GraphqlEngine.postMetadata_
testEnv
[yaml|
type: bigquery_drop_computed_field
args:
source: bigquery
name: search_articles_1
table:
dataset: *schemaName
name: author
|]
name: article
dataset: *schemaName
|]
testEnv,
Fixture.teardownAction = \_ -> pure ()
},
Fixture.SetupAction
{ Fixture.setupAction =
GraphqlEngine.postMetadata_
testEnv
Schema.trackComputedField
backend
source
authorTable
"fetch_articles_no_user_args"
"articles_no_search"
[yaml| a_id: id |]
[yaml|
type: bigquery_add_computed_field
args:
source: bigquery
name: search_articles_2
table:
dataset: *schemaName
name: author
definition:
function:
dataset: *schemaName
name: fetch_articles
argument_mapping:
a_id: id
return_table:
name: article
dataset: *schemaName
|],
Fixture.teardownAction = \_ ->
GraphqlEngine.postMetadata_
testEnv
[yaml|
type: bigquery_drop_computed_field
args:
source: bigquery
name: search_articles_2
table:
dataset: *schemaName
name: author
name: article
dataset: *schemaName
|]
testEnv,
Fixture.teardownAction = \_ -> pure ()
},
Fixture.SetupAction
{ Fixture.setupAction =
GraphqlEngine.postMetadata_
-- Role user_1 has select permissions on author and article tables.
-- user_1 can query search_articles computed field.
Permission.createPermission
backend
testEnv
[yaml|
type: bigquery_add_computed_field
args:
source: bigquery
name: articles_no_search
table:
dataset: *schemaName
name: author
definition:
function:
dataset: *schemaName
name: fetch_articles_no_user_args_returns_table
argument_mapping:
a_id: id
return_table:
name: article
dataset: *schemaName
|],
Fixture.teardownAction = \_ ->
GraphqlEngine.postMetadata_
testEnv
[yaml|
type: bigquery_drop_computed_field
args:
source: bigquery
name: articles_no_search
table:
dataset: *schemaName
name: author
|]
selectPermission
{ permissionSource = T.pack source,
permissionTable = "author",
permissionRole = "user_1",
permissionColumns = (["id", "name"] :: [Text])
},
Fixture.teardownAction = \_ -> pure ()
},
Fixture.SetupAction
{ Fixture.setupAction =
GraphqlEngine.postMetadata_
Permission.createPermission
backend
testEnv
[yaml|
# Role user_1 has select permissions on author and article tables.
# user_1 can query search_articles_1 computed field.
type: bigquery_create_select_permission
args:
source: bigquery
table:
dataset: *schemaName
name: author
role: user_1
permission:
columns: '*'
filter: {}
computed_fields:
- search_articles_1
|],
Fixture.teardownAction = \_ ->
GraphqlEngine.postMetadata_
testEnv
[yaml|
args:
type: bigquery_drop_select_permission
args:
source: bigquery
table:
dataset: *schemaName
name: author
role: user_1
|]
selectPermission
{ permissionSource = T.pack source,
permissionTable = "article",
permissionRole = "user_1",
permissionColumns = (["id", "title", "content", "author_id"] :: [Text])
},
Fixture.teardownAction = \_ -> pure ()
},
Fixture.SetupAction
{ Fixture.setupAction =
GraphqlEngine.postMetadata_
-- Role user_2 has select permissions only on author table.
Permission.createPermission
backend
testEnv
[yaml|
type: bigquery_create_select_permission
args:
source: bigquery
table:
dataset: *schemaName
name: article
role: user_1
permission:
columns: '*'
filter: {}
|],
Fixture.teardownAction = \_ ->
GraphqlEngine.postMetadata_
testEnv
[yaml|
type: bigquery_drop_select_permission
args:
source: bigquery
table:
dataset: *schemaName
name: article
role: user_1
|]
},
Fixture.SetupAction
{ Fixture.setupAction =
GraphqlEngine.postMetadata_
testEnv
[yaml|
# Role user_2 has select permissions only on author table.
type: bigquery_create_select_permission
args:
source: bigquery
table:
dataset: *schemaName
name: author
role: user_2
permission:
columns: '*'
filter: {}
|],
Fixture.teardownAction = \_ ->
GraphqlEngine.postMetadata_
testEnv
[yaml|
type: bigquery_drop_select_permission
args:
source: bigquery
table:
dataset: *schemaName
name: author
role: user_2
|]
selectPermission
{ permissionSource = T.pack source,
permissionTable = "author",
permissionRole = "user_2",
permissionColumns = (["id", "name"] :: [Text])
},
Fixture.teardownAction = \_ -> pure ()
}
]
@ -377,85 +286,32 @@ tests opts = do
( GraphqlEngine.postGraphql
testEnv
[graphql|
query {
#{schemaName}_author(order_by: {id: asc}){
id
name
search_articles_1(args: {search: "%1%"}){
id
title
content
}
search_articles_2(args: {search: "%keyword%"}){
id
title
content
author_id
}
}
}
|]
query {
#{schemaName}_author(order_by: {id: asc}){
id
name
search_articles(args: {search: "%1%"}){
id
title
content
}
}
}
|]
)
[interpolateYaml|
data:
#{schemaName}_author:
- id: '1'
name: Author 1
search_articles_1:
- id: '1'
title: Article 1 Title
content: Article 1 by Author 1
search_articles_2: []
- id: '2'
name: Author 2
search_articles_1: []
search_articles_2:
- id: '3'
title: Article 3 Title
content: Article 3 by Author 2, has search keyword
author_id: '2'
|]
it "Query with computed fields using limit and order_by" $ \testEnv -> do
let schemaName = Schema.getSchemaName testEnv
shouldReturnYaml
opts
( GraphqlEngine.postGraphql
testEnv
[graphql|
query {
#{schemaName}_author(order_by: {id: asc}){
id
name
search_articles_2(args: {search: "%by%"} limit: 1 order_by: {id: asc}){
id
title
content
author_id
}
}
}
|]
)
[interpolateYaml|
data:
#{schemaName}_author:
- id: '1'
name: Author 1
search_articles_2:
- author_id: '1'
content: Article 1 by Author 1
id: '1'
title: Article 1 Title
- id: '2'
name: Author 2
search_articles_2:
- author_id: '2'
content: Article 2 by Author 2
id: '2'
title: Article 2 Title
|]
data:
#{schemaName}_author:
- id: 1
name: Author 1
search_articles:
- id: 1
title: Article 1 Title
content: Article 1 by Author 1
- id: 2
name: Author 2
search_articles: []
|]
it "Query with computed fields as user_1 role" $ \testEnv -> do
let schemaName = Schema.getSchemaName testEnv
@ -466,46 +322,34 @@ data:
testEnv
[("X-Hasura-Role", "user_1")]
[graphql|
query {
#{schemaName}_author(order_by: {id: asc}){
id
name
search_articles_1(args: {search: "%1%"}){
id
title
content
}
search_articles_2(args: {search: "%keyword%"}){
id
title
content
author_id
}
}
}
|]
query {
#{schemaName}_author(order_by: {id: asc}){
id
name
search_articles(args: {search: "%1%"}){
id
title
content
}
}
}
|]
)
[interpolateYaml|
data:
#{schemaName}_author:
- id: '1'
name: Author 1
search_articles_1:
- id: '1'
title: Article 1 Title
content: Article 1 by Author 1
search_articles_2: []
- id: '2'
name: Author 2
search_articles_1: []
search_articles_2:
- id: '3'
title: Article 3 Title
content: Article 3 by Author 2, has search keyword
author_id: '2'
|]
data:
#{schemaName}_author:
- id: 1
name: Author 1
search_articles:
- id: 1
title: Article 1 Title
content: Article 1 by Author 1
- id: 2
name: Author 2
search_articles: []
|]
it "Query with computed field search_articles_1 as user_2 role" $ \testEnv -> do
it "Query with computed field search_articles as user_2 role" $ \testEnv -> do
let schemaName = Schema.getSchemaName testEnv
shouldReturnYaml
@ -514,29 +358,29 @@ data:
testEnv
[("X-Hasura-Role", "user_2")]
[graphql|
query {
#{schemaName}_author(order_by: {id: asc}){
id
name
search_articles_1(args: {search: "%1%"}){
id
title
content
}
}
}
|]
query {
#{schemaName}_author(order_by: {id: asc}){
id
name
search_articles(args: {search: "%1%"}){
id
title
content
}
}
}
|]
)
[interpolateYaml|
errors:
- extensions:
path: "$.selectionSet.#{schemaName}_author.selectionSet.search_articles_1"
code: validation-failed
message: |-
field 'search_articles_1' not found in type: '#{schemaName}_author'
|]
errors:
- extensions:
path: "$.selectionSet.#{schemaName}_author.selectionSet.search_articles"
code: validation-failed
message: |-
field 'search_articles' not found in type: '#{schemaName}_author'
|]
it "Query with computed field search_articles_2 as user_2 role" $ \testEnv -> do
it "Query with computed field search_articles as user_2 role" $ \testEnv -> do
let schemaName = Schema.getSchemaName testEnv
shouldReturnYaml
@ -545,28 +389,28 @@ errors:
testEnv
[("X-Hasura-Role", "user_2")]
[graphql|
query {
#{schemaName}_author(order_by: {id: asc}){
id
name
search_articles_2(args: {search: "%keyword%"}){
id
title
content
author_id
}
}
}
|]
query {
#{schemaName}_author(order_by: {id: asc}){
id
name
search_articles(args: {search: "%keyword%"}){
id
title
content
author_id
}
}
}
|]
)
[interpolateYaml|
errors:
- extensions:
path: "$.selectionSet.#{schemaName}_author.selectionSet.search_articles_2"
code: validation-failed
message: |-
field 'search_articles_2' not found in type: '#{schemaName}_author'
|]
errors:
- extensions:
path: "$.selectionSet.#{schemaName}_author.selectionSet.search_articles"
code: validation-failed
message: |-
field 'search_articles' not found in type: '#{schemaName}_author'
|]
it "Query articles_no_search without user arguments" $ \testEnv -> do
let schemaName = Schema.getSchemaName testEnv
@ -576,24 +420,65 @@ errors:
( GraphqlEngine.postGraphql
testEnv
[graphql|
query {
#{schemaName}_author(order_by: {id: asc}){
id
articles_no_search(order_by: {id: asc}){
id
}
}
}
|]
query {
#{schemaName}_author(order_by: {id: asc}){
id
articles_no_search(order_by: {id: asc}){
id
}
}
}
|]
)
[interpolateYaml|
data:
#{schemaName}_author:
- id: '1'
articles_no_search:
- id: '1'
- id: '2'
articles_no_search:
- id: '2'
- id: '3'
|]
data:
#{schemaName}_author:
- id: 1
articles_no_search:
- id: 1
- id: 2
articles_no_search:
- id: 2
- id: 3
|]
it "Query respects limit and order_by" $ \testEnv -> do
let schemaName = Schema.getSchemaName testEnv
shouldReturnYaml
opts
( GraphqlEngine.postGraphql
testEnv
[graphql|
query {
#{schemaName}_author(order_by: {id: asc}){
id
name
search_articles(args: {search: "%by%"} limit: 1 order_by: {id: asc}){
id
title
content
author_id
}
}
}
|]
)
[interpolateYaml|
data:
#{schemaName}_author:
- id: 1
name: Author 1
search_articles:
- author_id: 1
content: Article 1 by Author 1
id: 1
title: Article 1 Title
- id: 2
name: Author 2
search_articles:
- author_id: 2
content: Article 2 by Author 2
id: 2
title: Article 2 Title
|]

View File

@ -35,6 +35,7 @@ where
import Control.Concurrent.Extended (sleep)
import Control.Monad.Reader
import Data.Aeson (Value)
import Data.Aeson qualified as Aeson
import Data.ByteString qualified as BS
import Data.ByteString.Char8 qualified as S8
import Data.Monoid (Last, getLast)
@ -485,6 +486,8 @@ setupComputedFieldAction table functionName asFieldName env =
table
functionName
asFieldName
Aeson.Null
Aeson.Null
env
)
( \_ ->

View File

@ -132,6 +132,8 @@ defaultBackendServerUrl = \case
DataConnectorSqlite -> Just "http://localhost:65007"
DataConnector _ -> Nothing
-- workaround until we support schema/dataset keys generically
-- https://hasurahq.atlassian.net/browse/NDAT-332
schemaKeyword :: BackendType -> Key
schemaKeyword = \case
Postgres -> "schema"

View File

@ -375,11 +375,14 @@ trackComputedField ::
Table ->
String ->
String ->
Aeson.Value ->
Aeson.Value ->
TestEnvironment ->
IO ()
trackComputedField backend source Table {tableName} functionName asFieldName testEnvironment = do
trackComputedField backend source Table {tableName} functionName asFieldName argumentMapping returnTable testEnvironment = do
let backendType = defaultBackendTypeString backend
schema = getSchemaName testEnvironment
schemaKey = schemaKeyword backend
requestType = backendType <> "_add_computed_field"
GraphqlEngine.postMetadata_
testEnvironment
@ -389,15 +392,17 @@ args:
source: *source
comment: null
table:
schema: *schema
*schemaKey: *schema
name: *tableName
name: *asFieldName
definition:
function:
schema: *schema
*schemaKey: *schema
name: *functionName
table_argument: null
session_argument: null
argument_mapping: *argumentMapping
return_table: *returnTable
|]
-- | Unified untrack computed field
@ -405,6 +410,7 @@ untrackComputedField :: HasCallStack => BackendType -> String -> Table -> String
untrackComputedField backend source Table {tableName} fieldName testEnvironment = do
let backendType = defaultBackendTypeString backend
schema = getSchemaName testEnvironment
schemaKey = schemaKeyword backend
let requestType = backendType <> "_drop_computed_field"
GraphqlEngine.postMetadata_
testEnvironment
@ -413,7 +419,7 @@ type: *requestType
args:
source: *source
table:
schema: *schema
*schemaKey: *schema
name: *tableName
name: *fieldName
|]