mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-09-11 10:46:25 +03:00
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:
parent
4a321e2459
commit
c862c64b33
@ -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",
|
||||
|
@ -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"
|
||||
}
|
||||
},
|
||||
|
@ -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>;
|
||||
};
|
||||
|
||||
|
10
dc-agents/package-lock.json
generated
10
dc-agents/package-lock.json
generated
@ -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",
|
||||
|
4
dc-agents/reference/package-lock.json
generated
4
dc-agents/reference/package-lock.json
generated
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -18,6 +18,9 @@ const scalarTypes: ScalarTypesCapabilities = {
|
||||
}
|
||||
|
||||
const capabilities: Capabilities = {
|
||||
queries: {
|
||||
supports_primary_keys: true,
|
||||
},
|
||||
relationships: {},
|
||||
comparisons: {
|
||||
subquery: {
|
||||
|
4
dc-agents/sqlite/package-lock.json
generated
4
dc-agents/sqlite/package-lock.json
generated
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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")))
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -64,6 +64,8 @@ defaultBackendCapabilities = \case
|
||||
DataConnectorReference ->
|
||||
Just
|
||||
[yaml|
|
||||
queries:
|
||||
supports_primary_keys: true
|
||||
graphql_schema: |-
|
||||
scalar DateTime
|
||||
|
||||
|
@ -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) ->
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user