mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-09-11 10:46:25 +03:00
Support composite primary keys for Data Connector [GDW-127]
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4926 GitOrigin-RevId: 2b6e5052f56a765e0b9a19345fcc4688d7e4700f
This commit is contained in:
parent
40617719ef
commit
b9fb7d8720
@ -165,39 +165,46 @@ The `GET /schema` endpoint is called whenever the metadata is (re)loaded by `gra
|
||||
{
|
||||
"tables": [
|
||||
{
|
||||
"name": "artists",
|
||||
"primary_key": "id",
|
||||
"name": "Artist",
|
||||
"primary_key": ["ArtistId"],
|
||||
"description": "Collection of artists of music",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
"name": "ArtistId",
|
||||
"type": "number",
|
||||
"nullable": false,
|
||||
"description": "Artist primary key identifier"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"name": "Name",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
"nullable": true,
|
||||
"description": "The name of the artist"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "albums",
|
||||
"primary_key": "id",
|
||||
"name": "Album",
|
||||
"primary_key": ["AlbumId"],
|
||||
"description": "Collection of music albums created by artists",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
"name": "AlbumId",
|
||||
"type": "number",
|
||||
"nullable": false,
|
||||
"description": "Album primary key identifier"
|
||||
},
|
||||
{
|
||||
"name": "title",
|
||||
"name": "Title",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
"nullable": false,
|
||||
"description": "The title of the album"
|
||||
},
|
||||
{
|
||||
"name": "artist_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
"name": "ArtistId",
|
||||
"type": "number",
|
||||
"nullable": false,
|
||||
"description": "The ID of the artist that created this album"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ const schema: SchemaResponse = {
|
||||
tables: [
|
||||
{
|
||||
name: "Artist",
|
||||
primary_key: "ArtistId",
|
||||
primary_key: ["ArtistId"],
|
||||
description: "Collection of artists of music",
|
||||
columns: [
|
||||
{
|
||||
@ -57,7 +57,7 @@ const schema: SchemaResponse = {
|
||||
},
|
||||
{
|
||||
name: "Album",
|
||||
primary_key: "AlbumId",
|
||||
primary_key: ["AlbumId"],
|
||||
description: "Collection of music albums created by artists",
|
||||
columns: [
|
||||
{
|
||||
@ -82,7 +82,7 @@ const schema: SchemaResponse = {
|
||||
},
|
||||
{
|
||||
name: "Customer",
|
||||
primary_key: "CustomerId",
|
||||
primary_key: ["CustomerId"],
|
||||
description: "Collection of customers who can buy tracks",
|
||||
columns: [
|
||||
{
|
||||
@ -167,7 +167,7 @@ const schema: SchemaResponse = {
|
||||
},
|
||||
{
|
||||
name: "Employee",
|
||||
primary_key: "EmployeeId",
|
||||
primary_key: ["EmployeeId"],
|
||||
description: "Collection of employees who work for the business",
|
||||
columns: [
|
||||
{
|
||||
@ -258,7 +258,7 @@ const schema: SchemaResponse = {
|
||||
},
|
||||
{
|
||||
name: "Genre",
|
||||
primary_key: "GenreId",
|
||||
primary_key: ["GenreId"],
|
||||
description: "Genres of music",
|
||||
columns: [
|
||||
{
|
||||
@ -277,7 +277,7 @@ const schema: SchemaResponse = {
|
||||
},
|
||||
{
|
||||
name: "Invoice",
|
||||
primary_key: "InvoiceId",
|
||||
primary_key: ["InvoiceId"],
|
||||
description: "Collection of invoices of music purchases by a customer",
|
||||
columns: [
|
||||
{
|
||||
@ -338,7 +338,7 @@ const schema: SchemaResponse = {
|
||||
},
|
||||
{
|
||||
name: "InvoiceLine",
|
||||
primary_key: "InvoiceLineId",
|
||||
primary_key: ["InvoiceLineId"],
|
||||
description: "Collection of track purchasing line items of invoices",
|
||||
columns: [
|
||||
{
|
||||
@ -375,7 +375,7 @@ const schema: SchemaResponse = {
|
||||
},
|
||||
{
|
||||
name: "MediaType",
|
||||
primary_key: "MediaTypeId",
|
||||
primary_key: ["MediaTypeId"],
|
||||
description: "Collection of media types that tracks can be encoded in",
|
||||
columns: [
|
||||
{
|
||||
@ -394,7 +394,7 @@ const schema: SchemaResponse = {
|
||||
},
|
||||
{
|
||||
name: "Playlist",
|
||||
primary_key: "PlaylistId",
|
||||
primary_key: ["PlaylistId"],
|
||||
description: "Collection of playlists",
|
||||
columns: [
|
||||
{
|
||||
@ -411,29 +411,28 @@ const schema: SchemaResponse = {
|
||||
},
|
||||
]
|
||||
},
|
||||
// We don't support composite primary keys yet :(
|
||||
// {
|
||||
// name: "PlaylistTrack",
|
||||
// primary_key: ["PlaylistId", "TrackId"],
|
||||
// description: "Associations between playlists and tracks",
|
||||
// columns: [
|
||||
// {
|
||||
// name: "PlaylistId",
|
||||
// type: "number",
|
||||
// nullable: false,
|
||||
// description: "The ID of the playlist"
|
||||
// },
|
||||
// {
|
||||
// name: "TrackId",
|
||||
// type: "number",
|
||||
// nullable: true,
|
||||
// description: "The ID of the track"
|
||||
// },
|
||||
// ]
|
||||
// },
|
||||
{
|
||||
name: "PlaylistTrack",
|
||||
primary_key: ["PlaylistId", "TrackId"],
|
||||
description: "Associations between playlists and tracks",
|
||||
columns: [
|
||||
{
|
||||
name: "PlaylistId",
|
||||
type: "number",
|
||||
nullable: false,
|
||||
description: "The ID of the playlist"
|
||||
},
|
||||
{
|
||||
name: "TrackId",
|
||||
type: "number",
|
||||
nullable: true,
|
||||
description: "The ID of the track"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Track",
|
||||
primary_key: "TrackId",
|
||||
primary_key: ["TrackId"],
|
||||
description: "Collection of music tracks",
|
||||
columns: [
|
||||
{
|
||||
|
@ -578,8 +578,11 @@
|
||||
},
|
||||
"primary_key": {
|
||||
"description": "The primary key of the table",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"nullable": true,
|
||||
"type": "string"
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
@ -20,6 +20,6 @@ export type TableInfo = {
|
||||
/**
|
||||
* The primary key of the table
|
||||
*/
|
||||
primary_key?: string | null;
|
||||
primary_key?: Array<string> | null;
|
||||
};
|
||||
|
||||
|
@ -187,7 +187,47 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"table": "Playlist"
|
||||
"table": "Playlist",
|
||||
"array_relationships": [
|
||||
{
|
||||
"name": "PlaylistTracks",
|
||||
"using": {
|
||||
"manual_configuration": {
|
||||
"remote_table": "PlaylistTrack",
|
||||
"column_mapping": {
|
||||
"PlaylistId": "PlaylistId"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"table": "PlaylistTrack",
|
||||
"object_relationships": [
|
||||
{
|
||||
"name": "Playlist",
|
||||
"using": {
|
||||
"manual_configuration": {
|
||||
"remote_table": "Playlist",
|
||||
"column_mapping": {
|
||||
"PlaylistId": "PlaylistId"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Track",
|
||||
"using": {
|
||||
"manual_configuration": {
|
||||
"remote_table": "Track",
|
||||
"column_mapping": {
|
||||
"TrackId": "TrackId"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"table": "Track",
|
||||
@ -237,6 +277,17 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "PlaylistTracks",
|
||||
"using": {
|
||||
"manual_configuration": {
|
||||
"remote_table": "PlaylistTrack",
|
||||
"column_mapping": {
|
||||
"TrackId": "TrackId"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -253,4 +304,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ instance HasCodec TableName where
|
||||
data TableInfo = TableInfo
|
||||
{ dtiName :: TableName,
|
||||
dtiColumns :: [API.V0.ColumnInfo],
|
||||
dtiPrimaryKey :: Maybe Text,
|
||||
dtiPrimaryKey :: Maybe [API.V0.ColumnName],
|
||||
dtiDescription :: Maybe Text
|
||||
}
|
||||
deriving stock (Eq, Ord, Show, Generic, Data)
|
||||
|
@ -12,6 +12,7 @@ module Data.Sequence.NonEmpty
|
||||
head,
|
||||
tail,
|
||||
toSeq,
|
||||
fromSeq,
|
||||
toNonEmpty,
|
||||
)
|
||||
where
|
||||
|
@ -8,6 +8,7 @@ import Data.Aeson.KeyMap qualified as KM
|
||||
import Data.Environment (Environment)
|
||||
import Data.HashMap.Strict qualified as Map
|
||||
import Data.HashMap.Strict.InsOrd qualified as OMap
|
||||
import Data.Sequence qualified as Seq
|
||||
import Data.Sequence.NonEmpty qualified as NESeq
|
||||
import Data.Text qualified as Text
|
||||
import Data.Text.Extended (toTxt, (<<>), (<>>))
|
||||
@ -114,6 +115,7 @@ resolveDatabaseMetadata' ::
|
||||
resolveDatabaseMetadata' _ sc@(DC.SourceConfig {_scSchema = API.SchemaResponse {..}}) customization =
|
||||
let tables = Map.fromList $ do
|
||||
API.TableInfo {..} <- srTables
|
||||
let primaryKeyColumns = Seq.fromList $ coerce <$> fromMaybe [] dtiPrimaryKey
|
||||
let meta =
|
||||
RQL.T.T.DBTableMetadata
|
||||
{ _ptmiOid = OID 0,
|
||||
@ -129,7 +131,7 @@ resolveDatabaseMetadata' _ sc@(DC.SourceConfig {_scSchema = API.SchemaResponse {
|
||||
-- TODO: Add Column Mutability to the 'TableInfo'
|
||||
rciMutability = RQL.T.C.ColumnMutability False False
|
||||
},
|
||||
_ptmiPrimaryKey = dtiPrimaryKey <&> \key -> RQL.T.T.PrimaryKey (RQL.T.T.Constraint () (OID 0)) (NESeq.singleton (coerce key)),
|
||||
_ptmiPrimaryKey = RQL.T.T.PrimaryKey (RQL.T.T.Constraint () (OID 0)) <$> NESeq.fromSeq primaryKeyColumns,
|
||||
_ptmiUniqueConstraints = mempty,
|
||||
_ptmiForeignKeys = mempty,
|
||||
_ptmiViewInfo = Just $ RQL.T.T.ViewInfo False False False,
|
||||
|
@ -5,7 +5,7 @@ module Hasura.Backends.DataConnector.API.V0.TableSpec (spec, genTableName, genTa
|
||||
|
||||
import Data.Aeson.QQ.Simple (aesonQQ)
|
||||
import Hasura.Backends.DataConnector.API.V0
|
||||
import Hasura.Backends.DataConnector.API.V0.ColumnSpec (genColumnInfo)
|
||||
import Hasura.Backends.DataConnector.API.V0.ColumnSpec (genColumnInfo, genColumnName)
|
||||
import Hasura.Prelude
|
||||
import Hedgehog
|
||||
import Hedgehog.Gen
|
||||
@ -33,13 +33,13 @@ spec = do
|
||||
( TableInfo
|
||||
(TableName "my_table_name")
|
||||
[ColumnInfo (ColumnName "id") StringTy False Nothing]
|
||||
(Just "id")
|
||||
(Just [ColumnName "id"])
|
||||
(Just "my description")
|
||||
)
|
||||
[aesonQQ|
|
||||
{ "name": "my_table_name",
|
||||
"columns": [{"name": "id", "type": "string", "nullable": false}],
|
||||
"primary_key": "id",
|
||||
"primary_key": ["id"],
|
||||
"description": "my description"
|
||||
}
|
||||
|]
|
||||
@ -53,5 +53,5 @@ genTableInfo =
|
||||
TableInfo
|
||||
<$> genTableName
|
||||
<*> Gen.list (linear 0 5) genColumnInfo
|
||||
<*> Gen.maybe (text (linear 0 10) unicode)
|
||||
<*> Gen.maybe (Gen.list (linear 0 5) genColumnName)
|
||||
<*> Gen.maybe (text (linear 0 20) unicode)
|
||||
|
@ -1,7 +1,7 @@
|
||||
[
|
||||
{
|
||||
"name": "Artist",
|
||||
"primary_key": "ArtistId",
|
||||
"primary_key": ["ArtistId"],
|
||||
"description": "Collection of artists of music",
|
||||
"columns": [
|
||||
{
|
||||
@ -20,7 +20,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Album",
|
||||
"primary_key": "AlbumId",
|
||||
"primary_key": ["AlbumId"],
|
||||
"description": "Collection of music albums created by artists",
|
||||
"columns": [
|
||||
{
|
||||
@ -45,7 +45,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Customer",
|
||||
"primary_key": "CustomerId",
|
||||
"primary_key": ["CustomerId"],
|
||||
"description": "Collection of customers who can buy tracks",
|
||||
"columns": [
|
||||
{
|
||||
@ -130,7 +130,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Employee",
|
||||
"primary_key": "EmployeeId",
|
||||
"primary_key": ["EmployeeId"],
|
||||
"description": "Collection of employees who work for the business",
|
||||
"columns": [
|
||||
{
|
||||
@ -221,7 +221,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Genre",
|
||||
"primary_key": "GenreId",
|
||||
"primary_key": ["GenreId"],
|
||||
"description": "Genres of music",
|
||||
"columns": [
|
||||
{
|
||||
@ -240,7 +240,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Invoice",
|
||||
"primary_key": "InvoiceId",
|
||||
"primary_key": ["InvoiceId"],
|
||||
"description": "Collection of invoices of music purchases by a customer",
|
||||
"columns": [
|
||||
{
|
||||
@ -301,7 +301,7 @@
|
||||
},
|
||||
{
|
||||
"name": "InvoiceLine",
|
||||
"primary_key": "InvoiceLineId",
|
||||
"primary_key": ["InvoiceLineId"],
|
||||
"description": "Collection of track purchasing line items of invoices",
|
||||
"columns": [
|
||||
{
|
||||
@ -338,7 +338,7 @@
|
||||
},
|
||||
{
|
||||
"name": "MediaType",
|
||||
"primary_key": "MediaTypeId",
|
||||
"primary_key": ["MediaTypeId"],
|
||||
"description": "Collection of media types that tracks can be encoded in",
|
||||
"columns": [
|
||||
{
|
||||
@ -357,7 +357,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Playlist",
|
||||
"primary_key": "PlaylistId",
|
||||
"primary_key": ["PlaylistId"],
|
||||
"description": "Collection of playlists",
|
||||
"columns": [
|
||||
{
|
||||
@ -374,9 +374,28 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "PlaylistTrack",
|
||||
"primary_key": ["PlaylistId", "TrackId"],
|
||||
"description": "Associations between playlists and tracks",
|
||||
"columns": [
|
||||
{
|
||||
"name": "PlaylistId",
|
||||
"type": "number",
|
||||
"nullable": false,
|
||||
"description": "The ID of the playlist"
|
||||
},
|
||||
{
|
||||
"name": "TrackId",
|
||||
"type": "number",
|
||||
"nullable": true,
|
||||
"description": "The ID of the track"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Track",
|
||||
"primary_key": "TrackId",
|
||||
"primary_key": ["TrackId"],
|
||||
"description": "Collection of music tracks",
|
||||
"columns": [
|
||||
{
|
||||
|
@ -66,7 +66,7 @@ schema =
|
||||
API.dciDescription = Just "The name of the artist"
|
||||
}
|
||||
],
|
||||
API.dtiPrimaryKey = Just "ArtistId",
|
||||
API.dtiPrimaryKey = Just [API.ColumnName "ArtistId"],
|
||||
API.dtiDescription = Just "Collection of artists of music"
|
||||
},
|
||||
API.TableInfo
|
||||
@ -91,7 +91,7 @@ schema =
|
||||
API.dciDescription = Just "The ID of the artist that created the album"
|
||||
}
|
||||
],
|
||||
API.dtiPrimaryKey = Just "AlbumId",
|
||||
API.dtiPrimaryKey = Just [API.ColumnName "AlbumId"],
|
||||
API.dtiDescription = Just "Collection of music albums created by artists"
|
||||
},
|
||||
API.TableInfo
|
||||
@ -110,7 +110,7 @@ schema =
|
||||
API.dciDescription = Just "The name of the genre"
|
||||
}
|
||||
],
|
||||
API.dtiPrimaryKey = Just "GenreId",
|
||||
API.dtiPrimaryKey = Just [API.ColumnName "GenreId"],
|
||||
API.dtiDescription = Just "Genres of music"
|
||||
},
|
||||
API.TableInfo
|
||||
@ -129,7 +129,7 @@ schema =
|
||||
API.dciDescription = Just "The name of the media type format"
|
||||
}
|
||||
],
|
||||
API.dtiPrimaryKey = Just "MediaTypeId",
|
||||
API.dtiPrimaryKey = Just [API.ColumnName "MediaTypeId"],
|
||||
API.dtiDescription = Just "Collection of media types that tracks can be encoded in"
|
||||
},
|
||||
API.TableInfo
|
||||
@ -190,7 +190,7 @@ schema =
|
||||
API.dciDescription = Just "The price of the track"
|
||||
}
|
||||
],
|
||||
API.dtiPrimaryKey = Just "TrackId",
|
||||
API.dtiPrimaryKey = Just [API.ColumnName "TrackId"],
|
||||
API.dtiDescription = Just "Collection of music tracks"
|
||||
}
|
||||
]
|
||||
|
@ -79,6 +79,22 @@ tables:
|
||||
remote_table: Album
|
||||
column_mapping:
|
||||
ArtistId: ArtistId
|
||||
- table: Playlist
|
||||
- table: PlaylistTrack
|
||||
object_relationships:
|
||||
- name: Playlist
|
||||
using:
|
||||
manual_configuration:
|
||||
remote_table: Playlist
|
||||
column_mapping:
|
||||
PlaylistId: PlaylistId
|
||||
- name: Track
|
||||
using:
|
||||
manual_configuration:
|
||||
remote_table: Track
|
||||
column_mapping:
|
||||
TrackId: TrackId
|
||||
- table: Track
|
||||
configuration: {}
|
||||
|]
|
||||
|
||||
@ -114,24 +130,24 @@ tests opts = describe "Queries" $ do
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
query getAlbum {
|
||||
albums(limit: 3, order_by: {id: asc}) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
query getAlbum {
|
||||
albums(limit: 3, order_by: {id: asc}) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
albums:
|
||||
- id: 1
|
||||
title: For Those About To Rock We Salute You
|
||||
- id: 2
|
||||
title: Balls to the Wall
|
||||
- id: 3
|
||||
title: Restless and Wild
|
||||
|]
|
||||
data:
|
||||
albums:
|
||||
- id: 1
|
||||
title: For Those About To Rock We Salute You
|
||||
- id: 2
|
||||
title: Balls to the Wall
|
||||
- id: 3
|
||||
title: Restless and Wild
|
||||
|]
|
||||
|
||||
it "works with a primary key" $ \(testEnvironment, _) ->
|
||||
shouldReturnYaml
|
||||
@ -139,20 +155,20 @@ data:
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
query getAlbum {
|
||||
albums_by_pk(id: 1) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
query getAlbum {
|
||||
albums_by_pk(id: 1) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
albums_by_pk:
|
||||
- id: 1
|
||||
title: "For Those About To Rock We Salute You"
|
||||
|]
|
||||
data:
|
||||
albums_by_pk:
|
||||
- id: 1
|
||||
title: "For Those About To Rock We Salute You"
|
||||
|]
|
||||
|
||||
it "works with non existent primary key" $ \(testEnvironment, _) ->
|
||||
shouldReturnYaml
|
||||
@ -160,18 +176,45 @@ data:
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
query getAlbum {
|
||||
albums_by_pk(id: 999999) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
query getAlbum {
|
||||
albums_by_pk(id: 999999) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
albums_by_pk: []
|
||||
|]
|
||||
data:
|
||||
albums_by_pk: []
|
||||
|]
|
||||
|
||||
it "works with a composite primary key" $ \(testEnvironment, _) ->
|
||||
shouldReturnYaml
|
||||
opts
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
query getAlbum {
|
||||
PlaylistTrack_by_pk(PlaylistId: 1, TrackId: 2) {
|
||||
Playlist {
|
||||
Name
|
||||
}
|
||||
Track {
|
||||
Name
|
||||
}
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
PlaylistTrack_by_pk:
|
||||
- Playlist:
|
||||
Name: "Music"
|
||||
Track:
|
||||
Name: "Balls to the Wall"
|
||||
|]
|
||||
|
||||
it "works with pagination" $ \(testEnvironment, _) ->
|
||||
shouldReturnYaml
|
||||
@ -179,20 +222,20 @@ data:
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
query getAlbum {
|
||||
albums (limit: 3, offset: 2) {
|
||||
id
|
||||
}
|
||||
}
|
||||
|]
|
||||
query getAlbum {
|
||||
albums (limit: 3, offset: 2) {
|
||||
id
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
albums:
|
||||
- id: 3
|
||||
- id: 4
|
||||
- id: 5
|
||||
|]
|
||||
data:
|
||||
albums:
|
||||
- id: 3
|
||||
- id: 4
|
||||
- id: 5
|
||||
|]
|
||||
|
||||
describe "Array Relationships" $ do
|
||||
it "joins on album id" $ \(testEnvironment, _) ->
|
||||
@ -201,26 +244,26 @@ data:
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
query getArtist {
|
||||
artists_by_pk(id: 1) {
|
||||
id
|
||||
name
|
||||
albums {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
|]
|
||||
query getArtist {
|
||||
artists_by_pk(id: 1) {
|
||||
id
|
||||
name
|
||||
albums {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
artists_by_pk:
|
||||
- name: AC/DC
|
||||
id: 1
|
||||
albums:
|
||||
- title: For Those About To Rock We Salute You
|
||||
- title: Let There Be Rock
|
||||
|]
|
||||
data:
|
||||
artists_by_pk:
|
||||
- name: AC/DC
|
||||
id: 1
|
||||
albums:
|
||||
- title: For Those About To Rock We Salute You
|
||||
- title: Let There Be Rock
|
||||
|]
|
||||
|
||||
describe "Object Relationships" $ do
|
||||
it "joins on artist id" $ \(testEnvironment, _) ->
|
||||
@ -229,25 +272,25 @@ data:
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
query getAlbum {
|
||||
albums_by_pk(id: 1) {
|
||||
id
|
||||
title
|
||||
artist {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
|]
|
||||
query getAlbum {
|
||||
albums_by_pk(id: 1) {
|
||||
id
|
||||
title
|
||||
artist {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
albums_by_pk:
|
||||
- id: 1
|
||||
title: "For Those About To Rock We Salute You"
|
||||
artist:
|
||||
name: "AC/DC"
|
||||
|]
|
||||
data:
|
||||
albums_by_pk:
|
||||
- id: 1
|
||||
title: "For Those About To Rock We Salute You"
|
||||
artist:
|
||||
name: "AC/DC"
|
||||
|]
|
||||
|
||||
describe "Where Clause Tests" $ do
|
||||
it "works with '_in' predicate" $ \(testEnvironment, _) ->
|
||||
@ -256,24 +299,24 @@ data:
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
query getAlbum {
|
||||
albums(where: {id: {_in: [1, 3, 5]}}) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
query getAlbum {
|
||||
albums(where: {id: {_in: [1, 3, 5]}}) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
albums:
|
||||
- id: 1
|
||||
title: For Those About To Rock We Salute You
|
||||
- id: 3
|
||||
title: Restless and Wild
|
||||
- id: 5
|
||||
title: Big Ones
|
||||
|]
|
||||
data:
|
||||
albums:
|
||||
- id: 1
|
||||
title: For Those About To Rock We Salute You
|
||||
- id: 3
|
||||
title: Restless and Wild
|
||||
- id: 5
|
||||
title: Big Ones
|
||||
|]
|
||||
|
||||
it "works with '_nin' predicate" $ \(testEnvironment, _) ->
|
||||
shouldReturnYaml
|
||||
@ -281,22 +324,22 @@ data:
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
query getAlbum {
|
||||
albums(where: {id: {_in: [1, 3, 5]}, title: {_nin: ["Big Ones"]}}) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
query getAlbum {
|
||||
albums(where: {id: {_in: [1, 3, 5]}, title: {_nin: ["Big Ones"]}}) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
albums:
|
||||
- id: 1
|
||||
title: For Those About To Rock We Salute You
|
||||
- id: 3
|
||||
title: Restless and Wild
|
||||
|]
|
||||
data:
|
||||
albums:
|
||||
- id: 1
|
||||
title: For Those About To Rock We Salute You
|
||||
- id: 3
|
||||
title: Restless and Wild
|
||||
|]
|
||||
|
||||
it "works with '_eq' predicate" $ \(testEnvironment, _) ->
|
||||
shouldReturnYaml
|
||||
@ -304,20 +347,20 @@ data:
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
query getAlbum {
|
||||
albums(where: {id: {_eq: 1}}) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
query getAlbum {
|
||||
albums(where: {id: {_eq: 1}}) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
albums:
|
||||
- id: 1
|
||||
title: For Those About To Rock We Salute You
|
||||
|]
|
||||
data:
|
||||
albums:
|
||||
- id: 1
|
||||
title: For Those About To Rock We Salute You
|
||||
|]
|
||||
|
||||
it "works with '_neq' predicate" $ \(testEnvironment, _) ->
|
||||
shouldReturnYaml
|
||||
@ -325,22 +368,22 @@ data:
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
query getAlbum {
|
||||
albums(where: {id: {_neq: 2, _in: [1, 2, 3]}}) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
query getAlbum {
|
||||
albums(where: {id: {_neq: 2, _in: [1, 2, 3]}}) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
albums:
|
||||
- id: 1
|
||||
title: For Those About To Rock We Salute You
|
||||
- id: 3
|
||||
title: Restless and Wild
|
||||
|]
|
||||
data:
|
||||
albums:
|
||||
- id: 1
|
||||
title: For Those About To Rock We Salute You
|
||||
- id: 3
|
||||
title: Restless and Wild
|
||||
|]
|
||||
|
||||
it "works with '_lt' predicate" $ \(testEnvironment, _) ->
|
||||
shouldReturnYaml
|
||||
@ -348,20 +391,20 @@ data:
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
query getAlbum {
|
||||
albums(where: {id: {_lt: 2}}) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
query getAlbum {
|
||||
albums(where: {id: {_lt: 2}}) {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
albums:
|
||||
- id: 1
|
||||
title: For Those About To Rock We Salute You
|
||||
|]
|
||||
data:
|
||||
albums:
|
||||
- id: 1
|
||||
title: For Those About To Rock We Salute You
|
||||
|]
|
||||
|
||||
it "works with '_lte' predicate" $ \(testEnvironment, _) ->
|
||||
shouldReturnYaml
|
||||
@ -369,22 +412,22 @@ data:
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
query getArtists {
|
||||
artists(where: {id: {_lte: 2}}) {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
|]
|
||||
query getArtists {
|
||||
artists(where: {id: {_lte: 2}}) {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
artists:
|
||||
- id: 1
|
||||
name: AC/DC
|
||||
- id: 2
|
||||
name: Accept
|
||||
|]
|
||||
data:
|
||||
artists:
|
||||
- id: 1
|
||||
name: AC/DC
|
||||
- id: 2
|
||||
name: Accept
|
||||
|]
|
||||
|
||||
it "works with '_gt' predicate" $ \(testEnvironment, _) ->
|
||||
shouldReturnYaml
|
||||
@ -392,20 +435,20 @@ data:
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
query getArtists {
|
||||
artists(where: {id: {_gt: 274}}) {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
|]
|
||||
query getArtists {
|
||||
artists(where: {id: {_gt: 274}}) {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
artists:
|
||||
- id: 275
|
||||
name: Philip Glass Ensemble
|
||||
|]
|
||||
data:
|
||||
artists:
|
||||
- id: 275
|
||||
name: Philip Glass Ensemble
|
||||
|]
|
||||
|
||||
it "works with '_gte' predicate" $ \(testEnvironment, _) ->
|
||||
shouldReturnYaml
|
||||
@ -413,19 +456,19 @@ data:
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
query getArtists {
|
||||
artists(where: {id: {_gte: 274}}) {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
|]
|
||||
query getArtists {
|
||||
artists(where: {id: {_gte: 274}}) {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
artists:
|
||||
- id: 274
|
||||
name: Nash Ensemble
|
||||
- id: 275
|
||||
name: Philip Glass Ensemble
|
||||
|]
|
||||
data:
|
||||
artists:
|
||||
- id: 274
|
||||
name: Nash Ensemble
|
||||
- id: 275
|
||||
name: Philip Glass Ensemble
|
||||
|]
|
||||
|
Loading…
Reference in New Issue
Block a user