Break down Data Connector agent schema tests into finer grained, more accurate, tests [GDC-479]

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/6225
GitOrigin-RevId: 8eaadcc14cf4bc90a22450e924daf8cc340ed2ea
This commit is contained in:
Daniel Chambers 2022-10-10 13:23:43 +11:00 committed by hasura-bot
parent 4a321e2459
commit c862c64b33
17 changed files with 139 additions and 98 deletions

View File

@ -1,6 +1,6 @@
{
"name": "@hasura/dc-api-types",
"version": "0.8.0",
"version": "0.9.0",
"description": "Hasura GraphQL Engine Data Connector Agent API types",
"author": "Hasura (https://github.com/hasura/graphql-engine)",
"license": "Apache-2.0",

View File

@ -768,19 +768,19 @@
"additionalProperties": {
"$ref": "#/components/schemas/Constraint"
},
"default": {},
"description": "Foreign key constraints",
"nullable": true,
"type": "object"
},
"name": {
"$ref": "#/components/schemas/TableName"
},
"primary_key": {
"default": [],
"description": "The primary key of the table",
"items": {
"type": "string"
},
"nullable": true,
"type": "array"
}
},

View File

@ -18,11 +18,11 @@ export type TableInfo = {
/**
* Foreign key constraints
*/
foreign_keys?: Record<string, Constraint> | null;
foreign_keys?: Record<string, Constraint>;
name: TableName;
/**
* The primary key of the table
*/
primary_key?: Array<string> | null;
primary_key?: Array<string>;
};

View File

@ -24,7 +24,7 @@
},
"dc-api-types": {
"name": "@hasura/dc-api-types",
"version": "0.8.0",
"version": "0.9.0",
"license": "Apache-2.0",
"devDependencies": {
"@tsconfig/node16": "^1.0.3",
@ -631,7 +631,7 @@
"license": "Apache-2.0",
"dependencies": {
"@fastify/cors": "^7.0.0",
"@hasura/dc-api-types": "0.8.0",
"@hasura/dc-api-types": "0.9.0",
"fastify": "^3.29.0",
"mathjs": "^11.0.0",
"pino-pretty": "^8.0.0",
@ -1389,7 +1389,7 @@
"license": "Apache-2.0",
"dependencies": {
"@fastify/cors": "^8.1.0",
"@hasura/dc-api-types": "0.8.0",
"@hasura/dc-api-types": "0.9.0",
"fastify": "^4.4.0",
"fastify-metrics": "^9.2.1",
"nanoid": "^3.3.4",
@ -3122,7 +3122,7 @@
"version": "file:reference",
"requires": {
"@fastify/cors": "^7.0.0",
"@hasura/dc-api-types": "0.8.0",
"@hasura/dc-api-types": "0.9.0",
"@tsconfig/node16": "^1.0.3",
"@types/node": "^16.11.49",
"@types/xml2js": "^0.4.11",
@ -3613,7 +3613,7 @@
"version": "file:sqlite",
"requires": {
"@fastify/cors": "^8.1.0",
"@hasura/dc-api-types": "0.8.0",
"@hasura/dc-api-types": "0.9.0",
"@tsconfig/node16": "^1.0.3",
"@types/node": "^16.11.49",
"@types/sqlite3": "^3.1.8",

View File

@ -10,7 +10,7 @@
"license": "Apache-2.0",
"dependencies": {
"@fastify/cors": "^7.0.0",
"@hasura/dc-api-types": "0.8.0",
"@hasura/dc-api-types": "0.9.0",
"fastify": "^3.29.0",
"mathjs": "^11.0.0",
"pino-pretty": "^8.0.0",
@ -44,7 +44,7 @@
}
},
"node_modules/@hasura/dc-api-types": {
"version": "0.8.0",
"version": "0.9.0",
"license": "Apache-2.0",
"devDependencies": {
"@tsconfig/node16": "^1.0.3",

View File

@ -22,7 +22,7 @@
},
"dependencies": {
"@fastify/cors": "^7.0.0",
"@hasura/dc-api-types": "0.8.0",
"@hasura/dc-api-types": "0.9.0",
"fastify": "^3.29.0",
"mathjs": "^11.0.0",
"pino-pretty": "^8.0.0",

View File

@ -18,6 +18,9 @@ const scalarTypes: ScalarTypesCapabilities = {
}
const capabilities: Capabilities = {
queries: {
supports_primary_keys: true,
},
relationships: {},
comparisons: {
subquery: {

View File

@ -10,7 +10,7 @@
"license": "Apache-2.0",
"dependencies": {
"@fastify/cors": "^8.1.0",
"@hasura/dc-api-types": "0.8.0",
"@hasura/dc-api-types": "0.9.0",
"fastify": "^4.4.0",
"fastify-metrics": "^9.2.1",
"nanoid": "^3.3.4",
@ -54,7 +54,7 @@
"license": "MIT"
},
"node_modules/@hasura/dc-api-types": {
"version": "0.8.0",
"version": "0.9.0",
"license": "Apache-2.0",
"devDependencies": {
"@tsconfig/node16": "^1.0.3",

View File

@ -22,7 +22,7 @@
},
"dependencies": {
"@fastify/cors": "^8.1.0",
"@hasura/dc-api-types": "0.8.0",
"@hasura/dc-api-types": "0.9.0",
"fastify-metrics": "^9.2.1",
"fastify": "^4.4.0",
"nanoid": "^3.3.4",

View File

@ -57,8 +57,8 @@ instance HasCodec TableName where
data TableInfo = TableInfo
{ _tiName :: TableName,
_tiColumns :: [API.V0.ColumnInfo],
_tiPrimaryKey :: Maybe [API.V0.ColumnName],
_tiForeignKeys :: Maybe ForeignKeys,
_tiPrimaryKey :: [API.V0.ColumnName],
_tiForeignKeys :: ForeignKeys,
_tiDescription :: Maybe Text
}
deriving stock (Eq, Ord, Show, Generic, Data)
@ -71,19 +71,19 @@ instance HasCodec TableInfo where
TableInfo
<$> requiredField "name" "The name of the table" .= _tiName
<*> requiredField "columns" "The columns of the table" .= _tiColumns
<*> optionalFieldOrNull "primary_key" "The primary key of the table" .= _tiPrimaryKey
<*> optionalFieldOrNull "foreign_keys" "Foreign key constraints" .= _tiForeignKeys
<*> optionalFieldWithOmittedDefault "primary_key" [] "The primary key of the table" .= _tiPrimaryKey
<*> optionalFieldWithOmittedDefault "foreign_keys" (ForeignKeys mempty) "Foreign key constraints" .= _tiForeignKeys
<*> optionalFieldOrNull "description" "Description of the table" .= _tiDescription
--------------------------------------------------------------------------------
newtype ForeignKeys = ForeignKeys {unConstraints :: HashMap ConstraintName Constraint}
newtype ForeignKeys = ForeignKeys {unForeignKeys :: HashMap ConstraintName Constraint}
deriving stock (Eq, Ord, Show, Generic, Data)
deriving anyclass (NFData, Hashable)
deriving (FromJSON, ToJSON) via Autodocodec ForeignKeys
instance HasCodec ForeignKeys where
codec = dimapCodec ForeignKeys unConstraints $ codec @(HashMap ConstraintName Constraint)
codec = dimapCodec ForeignKeys unForeignKeys $ codec @(HashMap ConstraintName Constraint)
newtype ConstraintName = ConstraintName {unConstraintName :: Text}
deriving stock (Eq, Ord, Show, Generic, Data)

View File

@ -39,7 +39,7 @@ tests :: TestData -> Client IO (NamedRoutes Routes) -> API.SourceName -> API.Con
tests testData api sourceName agentConfig capabilities = do
Test.HealthSpec.spec api sourceName agentConfig
Test.CapabilitiesSpec.spec api agentConfig capabilities
Test.SchemaSpec.spec testData api sourceName agentConfig
Test.SchemaSpec.spec testData api sourceName agentConfig capabilities
Test.QuerySpec.spec testData api sourceName agentConfig capabilities
for_ (API._cMetrics capabilities) \m -> Test.MetricsSpec.spec api m
for_ (API._cExplain capabilities) \_ -> Test.ExplainSpec.spec testData api sourceName agentConfig capabilities

View File

@ -30,7 +30,7 @@ where
import Codec.Compression.GZip qualified as GZip
import Command (NameCasing (..), TestConfig (..))
import Control.Arrow (first, (>>>))
import Control.Lens (Index, IxValue, Ixed, Traversal', ix, lens, (%~), (&), (^.), (^..), (^?), _Just)
import Control.Lens (Index, IxValue, Ixed, Traversal', ix, lens, (%~), (&), (^.), (^..), (^?))
import Data.Aeson (eitherDecodeStrict)
import Data.Aeson qualified as J
import Data.Aeson.Lens (_Bool, _Number, _String)
@ -387,8 +387,8 @@ mkTestData TestConfig {..} =
formatTableInfo =
API.tiName %~ formatTableName
>>> API.tiColumns . traverse . API.ciName %~ formatColumnName
>>> API.tiPrimaryKey . _Just . traverse %~ formatColumnName
>>> API.tiForeignKeys . _Just . lens API.unConstraints (const API.ForeignKeys) . traverse
>>> API.tiPrimaryKey . traverse %~ formatColumnName
>>> API.tiForeignKeys . lens API.unForeignKeys (const API.ForeignKeys) . traverse
%~ ( API.cForeignTable %~ formatTableName
>>> API.cColumnMapping %~ (HashMap.toList >>> fmap (bimap formatColumnName formatColumnName) >>> HashMap.fromList)
)

View File

@ -2,39 +2,82 @@ module Test.SchemaSpec (spec) where
--------------------------------------------------------------------------------
import Control.Lens ((%~), (.~))
import Control.Lens.At (at)
import Control.Lens.Lens ((&))
import Control.Monad (forM_)
import Data.Aeson (toJSON)
import Data.Aeson.Lens (_Object)
import Data.Foldable (find)
import Data.HashMap.Strict qualified as HashMap
import Data.List (sort, sortOn)
import Data.List.NonEmpty qualified as NonEmpty
import Data.Text qualified as Text
import Hasura.Backends.DataConnector.API qualified as API
import Servant.API (NamedRoutes)
import Servant.Client (Client, (//))
import Test.Data (TestData (..))
import Test.Expectations (jsonShouldBe)
import Test.Hspec (Spec, describe, it)
import Test.Hspec (Expectation, Spec, SpecWith, describe, it)
import Prelude
--------------------------------------------------------------------------------
removeDescriptionFromColumn :: API.ColumnInfo -> API.ColumnInfo
removeDescriptionFromColumn c = c {API._ciDescription = Nothing}
spec :: TestData -> Client IO (NamedRoutes API.Routes) -> API.SourceName -> API.Config -> API.Capabilities -> Spec
spec TestData {..} api sourceName config API.Capabilities {..} = describe "schema API" $ do
it "returns the Chinook tables" $ do
let extractTableNames = sort . fmap API._tiName
tableNames <- (extractTableNames . API._srTables) <$> (api // API._schema) sourceName config
removeDescription :: API.TableInfo -> API.TableInfo
removeDescription t@API.TableInfo {API._tiColumns} = t {API._tiDescription = Nothing, API._tiColumns = newColumns}
let expectedTableNames = extractTableNames _tdSchemaTables
tableNames `jsonShouldBe` expectedTableNames
testPerTable "returns the correct columns in the Chinook tables" $ \expectedTable@API.TableInfo {..} -> do
tables <- find (\t -> API._tiName t == _tiName) . API._srTables <$> (api // API._schema) sourceName config
-- We remove some properties here so that we don't compare them since they vary between agent implementations
let extractJsonForComparison table =
let columns = fmap toJSON . sortOn API._ciName $ API._tiColumns table
in columns & traverse %~ \column ->
column
& _Object . at "type" .~ Nothing -- Types can vary between agents since underlying datatypes can change
& _Object . at "description" .~ Nothing -- Descriptions are not supported by all agents
let actualJsonColumns = extractJsonForComparison <$> tables
let expectedJsonColumns = Just $ extractJsonForComparison expectedTable
actualJsonColumns `jsonShouldBe` expectedJsonColumns
if (API._qcSupportsPrimaryKeys <$> _cQueries) == Just True
then testPerTable "returns the correct primary keys for the Chinook tables" $ \API.TableInfo {..} -> do
tables <- find (\t -> API._tiName t == _tiName) . API._srTables <$> (api // API._schema) sourceName config
let actualPrimaryKey = API._tiPrimaryKey <$> tables
actualPrimaryKey `jsonShouldBe` Just _tiPrimaryKey
else testPerTable "returns no primary keys for the Chinook tables" $ \API.TableInfo {..} -> do
tables <- find (\t -> API._tiName t == _tiName) . API._srTables <$> (api // API._schema) sourceName config
let actualPrimaryKey = API._tiPrimaryKey <$> tables
actualPrimaryKey `jsonShouldBe` Just []
if (API._qcSupportsPrimaryKeys <$> _cQueries) == Just True
then testPerTable "returns the correct foreign keys for the Chinook tables" $ \expectedTable@API.TableInfo {..} -> do
tables <- find (\t -> API._tiName t == _tiName) . API._srTables <$> (api // API._schema) sourceName config
-- We compare only the constraints and ignore the constraint names since some agents will have
-- different constraint names
let extractConstraintsForComparison table =
sort . HashMap.elems . API.unForeignKeys $ API._tiForeignKeys table
let actualConstraints = extractConstraintsForComparison <$> tables
let expectedConstraints = Just $ extractConstraintsForComparison expectedTable
actualConstraints `jsonShouldBe` expectedConstraints
else testPerTable "returns no foreign keys for the Chinook tables" $ \API.TableInfo {..} -> do
tables <- find (\t -> API._tiName t == _tiName) . API._srTables <$> (api // API._schema) sourceName config
let actualJsonConstraints = API._tiForeignKeys <$> tables
actualJsonConstraints `jsonShouldBe` Just (API.ForeignKeys mempty)
where
newColumns = map removeDescriptionFromColumn _tiColumns
removeForeignKeys :: API.TableInfo -> API.TableInfo
removeForeignKeys t = t {API._tiForeignKeys = Nothing}
extractForeignKeys :: API.TableInfo -> [API.Constraint]
extractForeignKeys = foldMap (HashMap.elems . API.unConstraints) . API._tiForeignKeys
spec :: TestData -> Client IO (NamedRoutes API.Routes) -> API.SourceName -> API.Config -> Spec
spec TestData {..} api sourceName config = describe "schema API" $ do
it "returns Chinook schema" $ do
tables <- (map removeDescription . sortOn API._tiName . API._srTables) <$> (api // API._schema) sourceName config
-- NOTE: Constraint names arent guaranteed to be the same across
-- Chinook backends so we compare Constraints without their names
-- independently from the rest of the schema.
(map removeForeignKeys tables) `jsonShouldBe` map (removeForeignKeys . removeDescription) _tdSchemaTables
(map (sort . extractForeignKeys) tables) `jsonShouldBe` map (sort . extractForeignKeys) _tdSchemaTables
testPerTable :: String -> (API.TableInfo -> Expectation) -> SpecWith ()
testPerTable description test =
describe description $ do
forM_ _tdSchemaTables $ \expectedTable@API.TableInfo {..} -> do
it (Text.unpack . NonEmpty.last $ API.unTableName _tiName) $
test expectedTable

View File

@ -90,9 +90,9 @@ schema =
API._ciDescription = Just "The name of the artist"
}
],
API._tiPrimaryKey = Just [API.ColumnName "ArtistId"],
API._tiPrimaryKey = [API.ColumnName "ArtistId"],
API._tiDescription = Just "Collection of artists of music",
API._tiForeignKeys = Nothing
API._tiForeignKeys = API.ForeignKeys mempty
},
API.TableInfo
{ API._tiName = mkTableName "Album",
@ -116,12 +116,11 @@ schema =
API._ciDescription = Just "The ID of the artist that created the album"
}
],
API._tiPrimaryKey = Just [API.ColumnName "AlbumId"],
API._tiPrimaryKey = [API.ColumnName "AlbumId"],
API._tiDescription = Just "Collection of music albums created by artists",
API._tiForeignKeys =
Just $
API.ForeignKeys $
HashMap.singleton (API.ConstraintName "Artist") (API.Constraint (mkTableName "Artist") (HashMap.singleton (API.ColumnName "ArtistId") (API.ColumnName "ArtistId")))
API.ForeignKeys $
HashMap.singleton (API.ConstraintName "Artist") (API.Constraint (mkTableName "Artist") (HashMap.singleton (API.ColumnName "ArtistId") (API.ColumnName "ArtistId")))
},
API.TableInfo
{ API._tiName = mkTableName "Customer",
@ -205,12 +204,11 @@ schema =
API._ciDescription = Just "The ID of the Employee who is this customer's support representative"
}
],
API._tiPrimaryKey = Just [API.ColumnName "CustomerId"],
API._tiPrimaryKey = [API.ColumnName "CustomerId"],
API._tiDescription = Just "Collection of customers who can buy tracks",
API._tiForeignKeys =
Just $
API.ForeignKeys $
HashMap.singleton (API.ConstraintName "CustomerSupportRep") (API.Constraint (mkTableName "Employee") (HashMap.singleton (API.ColumnName "SupportRepId") (API.ColumnName "EmployeeId")))
API.ForeignKeys $
HashMap.singleton (API.ConstraintName "CustomerSupportRep") (API.Constraint (mkTableName "Employee") (HashMap.singleton (API.ColumnName "SupportRepId") (API.ColumnName "EmployeeId")))
},
API.TableInfo
{ API._tiName = mkTableName "Employee",
@ -306,12 +304,11 @@ schema =
API._ciDescription = Just "The employee's email address"
}
],
API._tiPrimaryKey = Just [API.ColumnName "EmployeeId"],
API._tiPrimaryKey = [API.ColumnName "EmployeeId"],
API._tiDescription = Just "Collection of employees who work for the business",
API._tiForeignKeys =
Just $
API.ForeignKeys $
HashMap.singleton (API.ConstraintName "EmployeeReportsTo") (API.Constraint (mkTableName "Employee") (HashMap.singleton (API.ColumnName "ReportsTo") (API.ColumnName "EmployeeId")))
API.ForeignKeys $
HashMap.singleton (API.ConstraintName "EmployeeReportsTo") (API.Constraint (mkTableName "Employee") (HashMap.singleton (API.ColumnName "ReportsTo") (API.ColumnName "EmployeeId")))
},
API.TableInfo
{ API._tiName = mkTableName "Genre",
@ -329,9 +326,9 @@ schema =
API._ciDescription = Just "The name of the genre"
}
],
API._tiPrimaryKey = Just [API.ColumnName "GenreId"],
API._tiPrimaryKey = [API.ColumnName "GenreId"],
API._tiDescription = Just "Genres of music",
API._tiForeignKeys = Nothing
API._tiForeignKeys = API.ForeignKeys mempty
},
API.TableInfo
{ API._tiName = mkTableName "Invoice",
@ -391,13 +388,12 @@ schema =
API._ciDescription = Just "The total amount due on the invoice"
}
],
API._tiPrimaryKey = Just [API.ColumnName "InvoiceId"],
API._tiPrimaryKey = [API.ColumnName "InvoiceId"],
API._tiDescription = Just "Collection of invoices of music purchases by a customer",
API._tiForeignKeys =
Just $
API.ForeignKeys $
HashMap.singleton (API.ConstraintName "InvoiceCustomer") $
API.Constraint (mkTableName "Customer") (HashMap.singleton (API.ColumnName "CustomerId") (API.ColumnName "CustomerId"))
API.ForeignKeys $
HashMap.singleton (API.ConstraintName "InvoiceCustomer") $
API.Constraint (mkTableName "Customer") (HashMap.singleton (API.ColumnName "CustomerId") (API.ColumnName "CustomerId"))
},
API.TableInfo
{ API._tiName = mkTableName "InvoiceLine",
@ -433,15 +429,14 @@ schema =
API._ciDescription = Just "Quantity of the track purchased"
}
],
API._tiPrimaryKey = Just [API.ColumnName "InvoiceLineId"],
API._tiPrimaryKey = [API.ColumnName "InvoiceLineId"],
API._tiDescription = Just "Collection of track purchasing line items of invoices",
API._tiForeignKeys =
Just $
API.ForeignKeys $
HashMap.fromList
[ (API.ConstraintName "Invoice", API.Constraint (mkTableName "Invoice") (HashMap.singleton (API.ColumnName "InvoiceId") (API.ColumnName "InvoiceId"))),
(API.ConstraintName "Track", API.Constraint (mkTableName "Track") (HashMap.singleton (API.ColumnName "TrackId") (API.ColumnName "TrackId")))
]
API.ForeignKeys $
HashMap.fromList
[ (API.ConstraintName "Invoice", API.Constraint (mkTableName "Invoice") (HashMap.singleton (API.ColumnName "InvoiceId") (API.ColumnName "InvoiceId"))),
(API.ConstraintName "Track", API.Constraint (mkTableName "Track") (HashMap.singleton (API.ColumnName "TrackId") (API.ColumnName "TrackId")))
]
},
API.TableInfo
{ API._tiName = mkTableName "MediaType",
@ -459,9 +454,9 @@ schema =
API._ciDescription = Just "The name of the media type format"
}
],
API._tiPrimaryKey = Just [API.ColumnName "MediaTypeId"],
API._tiPrimaryKey = [API.ColumnName "MediaTypeId"],
API._tiDescription = Just "Collection of media types that tracks can be encoded in",
API._tiForeignKeys = Nothing
API._tiForeignKeys = API.ForeignKeys mempty
},
API.TableInfo
{ API._tiName = mkTableName "Track",
@ -521,16 +516,15 @@ schema =
API._ciDescription = Just "The price of the track"
}
],
API._tiPrimaryKey = Just [API.ColumnName "TrackId"],
API._tiPrimaryKey = [API.ColumnName "TrackId"],
API._tiDescription = Just "Collection of music tracks",
API._tiForeignKeys =
Just $
API.ForeignKeys $
HashMap.fromList
[ (API.ConstraintName "Album", API.Constraint (mkTableName "Album") (HashMap.singleton (API.ColumnName "AlbumId") (API.ColumnName "AlbumId"))),
(API.ConstraintName "Genre", API.Constraint (mkTableName "Genre") (HashMap.singleton (API.ColumnName "GenreId") (API.ColumnName "GenreId"))),
(API.ConstraintName "MediaType", API.Constraint (mkTableName "MediaType") (HashMap.singleton (API.ColumnName "MediaTypeId") (API.ColumnName "MediaTypeId")))
]
API.ForeignKeys $
HashMap.fromList
[ (API.ConstraintName "Album", API.Constraint (mkTableName "Album") (HashMap.singleton (API.ColumnName "AlbumId") (API.ColumnName "AlbumId"))),
(API.ConstraintName "Genre", API.Constraint (mkTableName "Genre") (HashMap.singleton (API.ColumnName "GenreId") (API.ColumnName "GenreId"))),
(API.ConstraintName "MediaType", API.Constraint (mkTableName "MediaType") (HashMap.singleton (API.ColumnName "MediaTypeId") (API.ColumnName "MediaTypeId")))
]
}
]
}

View File

@ -64,6 +64,8 @@ defaultBackendCapabilities = \case
DataConnectorReference ->
Just
[yaml|
queries:
supports_primary_keys: true
graphql_schema: |-
scalar DateTime

View File

@ -1,5 +1,4 @@
{-# LANGUAGE Arrows #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Hasura.Backends.DataConnector.Adapter.Metadata () where
@ -188,7 +187,7 @@ resolveDatabaseMetadata' _ sc@(DC.SourceConfig {_scSchema = API.SchemaResponse {
let foreignKeys = fmap API._tiForeignKeys _srTables
tables = Map.fromList $ do
API.TableInfo {..} <- _srTables
let primaryKeyColumns = Seq.fromList $ coerce <$> fromMaybe [] _tiPrimaryKey
let primaryKeyColumns = Seq.fromList $ coerce <$> _tiPrimaryKey
let meta =
RQL.T.T.DBTableMetadata
{ _ptmiOid = OID 0,
@ -225,8 +224,8 @@ resolveDatabaseMetadata' _ sc@(DC.SourceConfig {_scSchema = API.SchemaResponse {
-- | Construct a 'HashSet' 'RQL.T.T.ForeignKeyMetadata'
-- 'DataConnector' to build the foreign key constraints in the table
-- metadata.
buildForeignKeySet :: [Maybe API.ForeignKeys] -> HashSet (RQL.T.T.ForeignKeyMetadata 'DataConnector)
buildForeignKeySet (catMaybes -> foreignKeys) =
buildForeignKeySet :: [API.ForeignKeys] -> HashSet (RQL.T.T.ForeignKeyMetadata 'DataConnector)
buildForeignKeySet foreignKeys =
HashSet.fromList $
join $
foreignKeys <&> \(API.ForeignKeys constraints) ->

View File

@ -23,7 +23,7 @@ spec = do
describe "TableInfo" $ do
describe "minimal" $
testToFromJSONToSchema
(TableInfo (TableName ["my_table_name"]) [] Nothing Nothing Nothing)
(TableInfo (TableName ["my_table_name"]) [] [] (ForeignKeys mempty) Nothing)
[aesonQQ|
{ "name": ["my_table_name"],
"columns": []
@ -34,8 +34,8 @@ spec = do
( TableInfo
(TableName ["my_table_name"])
[ColumnInfo (ColumnName "id") StringTy False Nothing]
(Just [ColumnName "id"])
Nothing
[ColumnName "id"]
(ForeignKeys mempty)
(Just "my description")
)
[aesonQQ|
@ -50,8 +50,8 @@ spec = do
( TableInfo
(TableName ["my_table_name"])
[ColumnInfo (ColumnName "id") StringTy False Nothing]
(Just [ColumnName "id"])
(Just $ ForeignKeys $ HashMap.singleton (ConstraintName "Artist") (Constraint (TableName ["artist_table"]) (HashMap.singleton (ColumnName "ArtistId") (ColumnName "ArtistId"))))
[ColumnName "id"]
(ForeignKeys $ HashMap.singleton (ConstraintName "Artist") (Constraint (TableName ["artist_table"]) (HashMap.singleton (ColumnName "ArtistId") (ColumnName "ArtistId"))))
(Just "my description")
)
[aesonQQ|
@ -91,6 +91,6 @@ genTableInfo =
TableInfo
<$> genTableName
<*> Gen.list defaultRange genColumnInfo
<*> Gen.maybe (Gen.list defaultRange genColumnName)
<*> Gen.maybe genForeignKeys
<*> Gen.list defaultRange genColumnName
<*> genForeignKeys
<*> Gen.maybe (genArbitraryAlphaNumText defaultRange)