Remove builtin scalar types from Data Connector backend

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7167
Co-authored-by: Daniel Chambers <1214352+daniel-chambers@users.noreply.github.com>
GitOrigin-RevId: 926e7282b908e3a9669ac39d625aa54971e11c37
This commit is contained in:
David Overton 2023-01-11 13:36:03 +11:00 committed by hasura-bot
parent 7393c152e3
commit a9f77acb32
46 changed files with 448 additions and 429 deletions

View File

@ -165,7 +165,7 @@ The `GET /capabilities` endpoint is used by `graphql-engine` to discover the cap
The `capabilities` section describes the _capabilities_ of the service. This includes The `capabilities` section describes the _capabilities_ of the service. This includes
- `data_schema`: What sorts of features the agent supports when describing its data schema - `data_schema`: What sorts of features the agent supports when describing its data schema
- `relationships`: whether or not the agent supports relationships - `relationships`: whether or not the agent supports relationships
- `scalar_types`: custom scalar types and the operations they support. See [Scalar types capabilities](#scalar-type-capabilities). - `scalar_types`: scalar types and the operations they support. See [Scalar types capabilities](#scalar-type-capabilities).
The `config_schema` property contains an [OpenAPI 3 Schema](https://swagger.io/specification/#schema-object) object that represents the schema of the configuration object. It can use references (`$ref`) to refer to other schemas defined in the `other_schemas` object by name. The `config_schema` property contains an [OpenAPI 3 Schema](https://swagger.io/specification/#schema-object) object that represents the schema of the configuration object. It can use references (`$ref`) to refer to other schemas defined in the `other_schemas` object by name.
@ -178,23 +178,23 @@ If the agent only supports table columns that are always nullable, then it shoul
#### Scalar type capabilities #### Scalar type capabilities
The agent is expected to support a default set of scalar types (`Number`, `String`, `Bool`) and a default set of [comparison operators](#filters) on these types. Agents should declare the scalar types they support, along with the comparison operators and aggregate functions on those types.
Agents may optionally declare support for their own custom scalar types, along with custom comparison operators and aggregate functions on those types. The agent may optionally specify how to parse values of scalar type by associating it with one of the built-in GraphQL types (`Int`, `Float`, `String`, `Boolean` or `ID`)
The agent may optionally specify how to parse values of custom scalar types by associating them with one of the built-in GraphQL types (`Int`, `Float`, `String`, `Boolean` or `ID`)
Custom scalar types are declared by adding a property to the `scalar_types` section of the [capabilities](#capabilities-and-configuration-schema). Scalar types are declared by adding a property to the `scalar_types` section of the [capabilities](#capabilities-and-configuration-schema).
Custom comparison types can be defined by adding a `comparison_operators` property to the scalar type capabilities object. Comparison operators can be defined by adding a `comparison_operators` property to the scalar type capabilities object.
The `comparison_operators` property is an object where each key specifies a comparison operator name. The `comparison_operators` property is an object where each key specifies a comparison operator name.
The operator name must be a valid GraphQL name. The operator name must be a valid GraphQL name.
The value associated with each key should be a string specifying the argument type, which must be a valid scalar type. The value associated with each key should be a string specifying the argument type, which must be a valid scalar type.
All scalar types must also support the built-in comparison operators `eq`, `gt`, `gte`, `lt` and `lte`.
Custom aggregate functions can be defined by adding an `aggregate_functions` property to the scalar type capabilities object. Aggregate functions can be defined by adding an `aggregate_functions` property to the scalar type capabilities object.
The `aggregate_functions` property must be an object mapping aggregate function names to their result types. The `aggregate_functions` property must be an object mapping aggregate function names to their result types.
Aggregate function names must be must be valid GraphQL names. Aggregate function names must be must be valid GraphQL names.
Result types must be valid scalar types. Result types must be valid scalar types.
The `graphql_type` property can be used to tell Hasura GraphQL Engine to parse values of the custom scalar type as though they were one of the built-in GraphQL scalar types `Int`, `Float`, `String`, `Boolean`, or `ID`. The `graphql_type` property can be used to tell Hasura GraphQL Engine to parse values of the scalar type as though they were one of the built-in GraphQL scalar types `Int`, `Float`, `String`, `Boolean`, or `ID`.
Example: Example:
@ -210,10 +210,10 @@ capabilities:
graphql_type: String graphql_type: String
``` ```
This example declares a custom scalar type `DateTime` which should be parsed as though it were a GraphQL `String`. This example declares a scalar type `DateTime` which should be parsed as though it were a GraphQL `String`.
The type supports a comparison operator `in_year`, which takes an argument of type `Number`. The type supports a comparison operator `in_year`, which takes an argument of type `Number`.
An example GraphQL query using the custom comparison operator might look like below: An example GraphQL query using the comparison operator might look like below:
```graphql ```graphql
query MyQuery { query MyQuery {
Employee(where: {BirthDate: {in_year: 1962}}) { Employee(where: {BirthDate: {in_year: 1962}}) {
@ -223,7 +223,7 @@ query MyQuery {
} }
``` ```
In this query we have an `Employee` field with a `BirthDate` property of type `DateTime`. In this query we have an `Employee` field with a `BirthDate` property of type `DateTime`.
The `in_year` custom comparison operator is being used to request all employees with a birth date in the year 1962. The `in_year` comparison operator is being used to request all employees with a birth date in the year 1962.
The example also defines two aggregate functions `min` and `max`, both of which have a result type of `DateTime`. The example also defines two aggregate functions `min` and `max`, both of which have a result type of `DateTime`.

View File

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

View File

@ -502,20 +502,7 @@
}, },
"SubscriptionCapabilities": {}, "SubscriptionCapabilities": {},
"ScalarType": { "ScalarType": {
"additionalProperties": true, "type": "string"
"anyOf": [
{
"enum": [
"string",
"number",
"bool"
],
"type": "string"
},
{
"type": "string"
}
]
}, },
"ComparisonOperators": { "ComparisonOperators": {
"additionalProperties": { "additionalProperties": {

View File

@ -2,5 +2,4 @@
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */ /* eslint-disable */
export type ScalarType = ('string' | 'number' | 'bool' | string); export type ScalarType = string;

View File

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

View File

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

View File

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

View File

@ -16,14 +16,32 @@ const dateTimeCapabilities: ScalarTypeCapabilities = {
const stringCapabilities: ScalarTypeCapabilities = { const stringCapabilities: ScalarTypeCapabilities = {
aggregate_functions: { aggregate_functions: {
longest: 'string', longest: 'string',
shortest: 'string' shortest: 'string',
min: 'string',
max: 'string'
}, },
graphql_type: 'String' graphql_type: 'String'
} }
const numberCapabilities: ScalarTypeCapabilities = {
aggregate_functions: {
max: 'number',
min: 'number',
stddev: 'number',
stddev_pop: 'number',
stddev_samp: 'number',
sum: 'number',
var_pop: 'number',
var_samp: 'number',
variance: 'number'
},
graphql_type: 'Float'
}
const scalarTypes: ScalarTypesCapabilities = { const scalarTypes: ScalarTypesCapabilities = {
DateTime: dateTimeCapabilities, DateTime: dateTimeCapabilities,
string: stringCapabilities string: stringCapabilities,
number: numberCapabilities
} }
const capabilities: Capabilities = { const capabilities: Capabilities = {

View File

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

View File

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

View File

@ -55,19 +55,33 @@ const scalar_types: Record<ScalarTypeKey, ScalarTypeCapabilities> = {
_glob: 'string', _glob: 'string',
// _regexp: 'string', // TODO: Detect if REGEXP is supported // _regexp: 'string', // TODO: Detect if REGEXP is supported
...standardOperators('string') ...standardOperators('string')
},
aggregate_functions: {
max: 'string',
min: 'string'
} }
}, },
// TODO: Why do we need a seperate 'decimal' type? // TODO: Why do we need a seperate 'decimal' type?
decimal: { decimal: {
comparison_operators: { comparison_operators: {
_modulus_is_zero: 'number', _modulus_is_zero: 'decimal',
...standardOperators('number') ...standardOperators('decimal')
},
aggregate_functions: {
max: 'decimal',
min: 'decimal',
sum: 'decimal'
} }
}, },
number: { number: {
comparison_operators: { comparison_operators: {
_modulus_is_zero: 'number', _modulus_is_zero: 'number',
...standardOperators('number') ...standardOperators('number')
},
aggregate_functions: {
max: 'number',
min: 'number',
sum: 'number'
} }
}, },
bool: { bool: {

View File

@ -162,8 +162,8 @@ tests opts = describe "Aggregate Query Tests" $ do
{ _qFields = { _qFields =
Just $ Just $
HashMap.fromList HashMap.fromList
[ (API.FieldName "ArtistIds_Id", API.ColumnField (API.ColumnName "ArtistId") API.NumberTy), [ (API.FieldName "ArtistIds_Id", API.ColumnField (API.ColumnName "ArtistId") (API.ScalarType "number")),
(API.FieldName "ArtistNames_Name", API.ColumnField (API.ColumnName "Name") API.StringTy), (API.FieldName "ArtistNames_Name", API.ColumnField (API.ColumnName "Name") (API.ScalarType "string")),
( API.FieldName "nodes_Albums", ( API.FieldName "nodes_Albums",
API.RelField API.RelField
( API.RelationshipField ( API.RelationshipField
@ -172,7 +172,7 @@ tests opts = describe "Aggregate Query Tests" $ do
{ _qFields = { _qFields =
Just $ Just $
HashMap.fromList HashMap.fromList
[ (API.FieldName "nodes_Title", API.ColumnField (API.ColumnName "Title") API.StringTy) [ (API.FieldName "nodes_Title", API.ColumnField (API.ColumnName "Title") (API.ScalarType "string"))
], ],
_qAggregates = Nothing, _qAggregates = Nothing,
_qLimit = Nothing, _qLimit = Nothing,

View File

@ -145,8 +145,8 @@ tests opts = do
{ _qFields = { _qFields =
Just $ Just $
HashMap.fromList HashMap.fromList
[ (API.FieldName "id", API.ColumnField (API.ColumnName "AlbumId") API.NumberTy), [ (API.FieldName "id", API.ColumnField (API.ColumnName "AlbumId") (API.ScalarType "number")),
(API.FieldName "title", API.ColumnField (API.ColumnName "Title") API.StringTy) (API.FieldName "title", API.ColumnField (API.ColumnName "Title") (API.ScalarType "string"))
], ],
_qAggregates = Nothing, _qAggregates = Nothing,
_qLimit = Just 1, _qLimit = Just 1,
@ -207,8 +207,8 @@ tests opts = do
{ _qFields = { _qFields =
Just $ Just $
HashMap.fromList HashMap.fromList
[ (API.FieldName "id", API.ColumnField (API.ColumnName "AlbumId") API.NumberTy), [ (API.FieldName "id", API.ColumnField (API.ColumnName "AlbumId") $ API.ScalarType "number"),
(API.FieldName "title", API.ColumnField (API.ColumnName "Title") API.StringTy) (API.FieldName "title", API.ColumnField (API.ColumnName "Title") $ API.ScalarType "string")
], ],
_qAggregates = Nothing, _qAggregates = Nothing,
_qLimit = Just 3, _qLimit = Just 3,
@ -266,7 +266,7 @@ tests opts = do
{ _qFields = { _qFields =
Just $ Just $
HashMap.fromList HashMap.fromList
[ (API.FieldName "CustomerId", API.ColumnField (API.ColumnName "CustomerId") API.NumberTy) [ (API.FieldName "CustomerId", API.ColumnField (API.ColumnName "CustomerId") $ API.ScalarType "number")
], ],
_qAggregates = Nothing, _qAggregates = Nothing,
_qLimit = Nothing, _qLimit = Nothing,
@ -276,8 +276,8 @@ tests opts = do
API.Exists (API.UnrelatedTable $ API.TableName ("Employee" :| [])) $ API.Exists (API.UnrelatedTable $ API.TableName ("Employee" :| [])) $
API.ApplyBinaryComparisonOperator API.ApplyBinaryComparisonOperator
API.Equal API.Equal
(API.ComparisonColumn API.CurrentTable (API.ColumnName "EmployeeId") API.NumberTy) (API.ComparisonColumn API.CurrentTable (API.ColumnName "EmployeeId") $ API.ScalarType "number")
(API.ScalarValue (Aeson.Number 1) API.NumberTy), (API.ScalarValue (Aeson.Number 1) $ API.ScalarType "number"),
_qOrderBy = Nothing _qOrderBy = Nothing
} }
} }

View File

@ -94,12 +94,12 @@ tests opts = do
{ _qFields = { _qFields =
Just $ Just $
HashMap.fromList HashMap.fromList
[ (API.FieldName "MyIntColumn", API.ColumnField (API.ColumnName "MyIntColumn") $ API.CustomTy "MyInt"), [ (API.FieldName "MyIntColumn", API.ColumnField (API.ColumnName "MyIntColumn") $ API.ScalarType "MyInt"),
(API.FieldName "MyFloatColumn", API.ColumnField (API.ColumnName "MyFloatColumn") $ API.CustomTy "MyFloat"), (API.FieldName "MyFloatColumn", API.ColumnField (API.ColumnName "MyFloatColumn") $ API.ScalarType "MyFloat"),
(API.FieldName "MyStringColumn", API.ColumnField (API.ColumnName "MyStringColumn") $ API.CustomTy "MyString"), (API.FieldName "MyStringColumn", API.ColumnField (API.ColumnName "MyStringColumn") $ API.ScalarType "MyString"),
(API.FieldName "MyBooleanColumn", API.ColumnField (API.ColumnName "MyBooleanColumn") $ API.CustomTy "MyBoolean"), (API.FieldName "MyBooleanColumn", API.ColumnField (API.ColumnName "MyBooleanColumn") $ API.ScalarType "MyBoolean"),
(API.FieldName "MyIDColumn", API.ColumnField (API.ColumnName "MyIDColumn") $ API.CustomTy "MyID"), (API.FieldName "MyIDColumn", API.ColumnField (API.ColumnName "MyIDColumn") $ API.ScalarType "MyID"),
(API.FieldName "MyAnythingColumn", API.ColumnField (API.ColumnName "MyAnythingColumn") $ API.CustomTy "MyAnything") (API.FieldName "MyAnythingColumn", API.ColumnField (API.ColumnName "MyAnythingColumn") $ API.ScalarType "MyAnything")
], ],
_qAggregates = Nothing, _qAggregates = Nothing,
_qLimit = Just 1, _qLimit = Just 1,
@ -159,12 +159,12 @@ tests opts = do
{ _qFields = { _qFields =
Just $ Just $
HashMap.fromList HashMap.fromList
[ (API.FieldName "MyIntColumn", API.ColumnField (API.ColumnName "MyIntColumn") $ API.CustomTy "MyInt"), [ (API.FieldName "MyIntColumn", API.ColumnField (API.ColumnName "MyIntColumn") $ API.ScalarType "MyInt"),
(API.FieldName "MyFloatColumn", API.ColumnField (API.ColumnName "MyFloatColumn") $ API.CustomTy "MyFloat"), (API.FieldName "MyFloatColumn", API.ColumnField (API.ColumnName "MyFloatColumn") $ API.ScalarType "MyFloat"),
(API.FieldName "MyStringColumn", API.ColumnField (API.ColumnName "MyStringColumn") $ API.CustomTy "MyString"), (API.FieldName "MyStringColumn", API.ColumnField (API.ColumnName "MyStringColumn") $ API.ScalarType "MyString"),
(API.FieldName "MyBooleanColumn", API.ColumnField (API.ColumnName "MyBooleanColumn") $ API.CustomTy "MyBoolean"), (API.FieldName "MyBooleanColumn", API.ColumnField (API.ColumnName "MyBooleanColumn") $ API.ScalarType "MyBoolean"),
(API.FieldName "MyIDColumn", API.ColumnField (API.ColumnName "MyIDColumn") $ API.CustomTy "MyID"), (API.FieldName "MyIDColumn", API.ColumnField (API.ColumnName "MyIDColumn") $ API.ScalarType "MyID"),
(API.FieldName "MyAnythingColumn", API.ColumnField (API.ColumnName "MyAnythingColumn") $ API.CustomTy "MyAnything") (API.FieldName "MyAnythingColumn", API.ColumnField (API.ColumnName "MyAnythingColumn") $ API.ScalarType "MyAnything")
], ],
_qAggregates = Nothing, _qAggregates = Nothing,
_qLimit = Just 1, _qLimit = Just 1,
@ -174,28 +174,28 @@ tests opts = do
And And
[ ApplyBinaryComparisonOperator [ ApplyBinaryComparisonOperator
Equal Equal
(ComparisonColumn {_ccPath = CurrentTable, _ccName = ColumnName {unColumnName = "MyBooleanColumn"}, _ccColumnType = CustomTy {getCustomTy = "MyBoolean"}}) (ComparisonColumn {_ccPath = CurrentTable, _ccName = ColumnName {unColumnName = "MyBooleanColumn"}, _ccColumnType = ScalarType "MyBoolean"})
(ScalarValue (Aeson.Bool True) (CustomTy {getCustomTy = "MyBoolean"})), (ScalarValue (Aeson.Bool True) (ScalarType "MyBoolean")),
ApplyBinaryComparisonOperator ApplyBinaryComparisonOperator
Equal Equal
(ComparisonColumn {_ccPath = CurrentTable, _ccName = ColumnName {unColumnName = "MyFloatColumn"}, _ccColumnType = CustomTy {getCustomTy = "MyFloat"}}) (ComparisonColumn {_ccPath = CurrentTable, _ccName = ColumnName {unColumnName = "MyFloatColumn"}, _ccColumnType = ScalarType "MyFloat"})
(ScalarValue (Aeson.Number 3.14) (CustomTy {getCustomTy = "MyFloat"})), (ScalarValue (Aeson.Number 3.14) (ScalarType "MyFloat")),
ApplyBinaryComparisonOperator ApplyBinaryComparisonOperator
Equal Equal
(ComparisonColumn {_ccPath = CurrentTable, _ccName = ColumnName {unColumnName = "MyStringColumn"}, _ccColumnType = CustomTy {getCustomTy = "MyString"}}) (ComparisonColumn {_ccPath = CurrentTable, _ccName = ColumnName {unColumnName = "MyStringColumn"}, _ccColumnType = ScalarType "MyString"})
(ScalarValue (Aeson.String "foo") (CustomTy {getCustomTy = "MyString"})), (ScalarValue (Aeson.String "foo") (ScalarType "MyString")),
ApplyBinaryComparisonOperator ApplyBinaryComparisonOperator
Equal Equal
(ComparisonColumn {_ccPath = CurrentTable, _ccName = ColumnName {unColumnName = "MyIDColumn"}, _ccColumnType = CustomTy {getCustomTy = "MyID"}}) (ComparisonColumn {_ccPath = CurrentTable, _ccName = ColumnName {unColumnName = "MyIDColumn"}, _ccColumnType = ScalarType "MyID"})
(ScalarValue (Aeson.String "x") (CustomTy {getCustomTy = "MyID"})), (ScalarValue (Aeson.String "x") (ScalarType "MyID")),
ApplyBinaryComparisonOperator ApplyBinaryComparisonOperator
Equal Equal
(ComparisonColumn {_ccPath = CurrentTable, _ccName = ColumnName {unColumnName = "MyIntColumn"}, _ccColumnType = CustomTy {getCustomTy = "MyInt"}}) (ComparisonColumn {_ccPath = CurrentTable, _ccName = ColumnName {unColumnName = "MyIntColumn"}, _ccColumnType = ScalarType "MyInt"})
(ScalarValue (Aeson.Number 42.0) (CustomTy {getCustomTy = "MyInt"})), (ScalarValue (Aeson.Number 42.0) (ScalarType "MyInt")),
ApplyBinaryComparisonOperator ApplyBinaryComparisonOperator
Equal Equal
(ComparisonColumn {_ccPath = CurrentTable, _ccName = ColumnName {unColumnName = "MyAnythingColumn"}, _ccColumnType = CustomTy {getCustomTy = "MyAnything"}}) (ComparisonColumn {_ccPath = CurrentTable, _ccName = ColumnName {unColumnName = "MyAnythingColumn"}, _ccColumnType = ScalarType "MyAnything"})
(ScalarValue (Aeson.Object mempty) (CustomTy {getCustomTy = "MyAnything"})) (ScalarValue (Aeson.Object mempty) (ScalarType "MyAnything"))
], ],
_qOrderBy = Nothing _qOrderBy = Nothing
} }

View File

@ -99,8 +99,8 @@ tests opts = do
{ _qFields = { _qFields =
Just $ Just $
HashMap.fromList HashMap.fromList
[ (API.FieldName "id", API.ColumnField (API.ColumnName "AlbumId") API.NumberTy), [ (API.FieldName "id", API.ColumnField (API.ColumnName "AlbumId") $ API.ScalarType "number"),
(API.FieldName "title", API.ColumnField (API.ColumnName "Title") API.StringTy) (API.FieldName "title", API.ColumnField (API.ColumnName "Title") $ API.ScalarType "string")
], ],
_qAggregates = Nothing, _qAggregates = Nothing,
_qLimit = Just 1, _qLimit = Just 1,

View File

@ -209,7 +209,7 @@ tests opts = do
{ _qFields = { _qFields =
Just $ Just $
HashMap.fromList HashMap.fromList
[ (API.FieldName "Name", API.ColumnField (API.ColumnName "Name") API.StringTy), [ (API.FieldName "Name", API.ColumnField (API.ColumnName "Name") $ API.ScalarType "string"),
( API.FieldName "Genre", ( API.FieldName "Genre",
API.RelField API.RelField
( API.RelationshipField ( API.RelationshipField
@ -218,7 +218,7 @@ tests opts = do
{ _qFields = { _qFields =
Just $ Just $
HashMap.fromList HashMap.fromList
[ (API.FieldName "Name", API.ColumnField (API.ColumnName "Name") API.StringTy) [ (API.FieldName "Name", API.ColumnField (API.ColumnName "Name") $ API.ScalarType "string")
], ],
_qAggregates = Nothing, _qAggregates = Nothing,
_qLimit = Nothing, _qLimit = Nothing,
@ -236,7 +236,7 @@ tests opts = do
{ _qFields = { _qFields =
Just $ Just $
HashMap.fromList HashMap.fromList
[ (API.FieldName "Name", API.ColumnField (API.ColumnName "Name") API.StringTy) [ (API.FieldName "Name", API.ColumnField (API.ColumnName "Name") $ API.ScalarType "string")
], ],
_qAggregates = Nothing, _qAggregates = Nothing,
_qLimit = Nothing, _qLimit = Nothing,
@ -339,7 +339,7 @@ tests opts = do
{ _qFields = { _qFields =
Just $ Just $
HashMap.fromList HashMap.fromList
[ (API.FieldName "Name", API.ColumnField (API.ColumnName "Name") API.StringTy), [ (API.FieldName "Name", API.ColumnField (API.ColumnName "Name") $ API.ScalarType "string"),
( API.FieldName "Album", ( API.FieldName "Album",
API.RelField API.RelField
( API.RelationshipField ( API.RelationshipField
@ -356,7 +356,7 @@ tests opts = do
{ _qFields = { _qFields =
Just $ Just $
HashMap.fromList HashMap.fromList
[ (API.FieldName "Name", API.ColumnField (API.ColumnName "Name") API.StringTy) [ (API.FieldName "Name", API.ColumnField (API.ColumnName "Name") $ API.ScalarType "string")
], ],
_qAggregates = Nothing, _qAggregates = Nothing,
_qLimit = Nothing, _qLimit = Nothing,
@ -472,7 +472,7 @@ tests opts = do
{ _qFields = { _qFields =
Just $ Just $
HashMap.fromList HashMap.fromList
[ (API.FieldName "EmployeeId", API.ColumnField (API.ColumnName "EmployeeId") API.NumberTy) [ (API.FieldName "EmployeeId", API.ColumnField (API.ColumnName "EmployeeId") $ API.ScalarType "number")
], ],
_qAggregates = Nothing, _qAggregates = Nothing,
_qLimit = Just 1, _qLimit = Just 1,
@ -482,8 +482,8 @@ tests opts = do
API.Exists (API.RelatedTable $ API.RelationshipName "SupportRepForCustomers") $ API.Exists (API.RelatedTable $ API.RelationshipName "SupportRepForCustomers") $
API.ApplyBinaryComparisonOperator API.ApplyBinaryComparisonOperator
API.Equal API.Equal
(API.ComparisonColumn API.CurrentTable (API.ColumnName "Country") API.StringTy) (API.ComparisonColumn API.CurrentTable (API.ColumnName "Country") $ API.ScalarType "string")
(API.AnotherColumn (API.ComparisonColumn API.QueryTable (API.ColumnName "Country") API.StringTy)), (API.AnotherColumn (API.ComparisonColumn API.QueryTable (API.ColumnName "Country") $ API.ScalarType "string")),
_qOrderBy = _qOrderBy =
Just $ Just $
API.OrderBy API.OrderBy
@ -494,8 +494,8 @@ tests opts = do
API.Exists (API.RelatedTable $ API.RelationshipName "SupportRep") $ API.Exists (API.RelatedTable $ API.RelationshipName "SupportRep") $
API.ApplyBinaryComparisonOperator API.ApplyBinaryComparisonOperator
API.Equal API.Equal
(API.ComparisonColumn API.CurrentTable (API.ColumnName "Country") API.StringTy) (API.ComparisonColumn API.CurrentTable (API.ColumnName "Country") $ API.ScalarType "string")
(API.AnotherColumn (API.ComparisonColumn API.QueryTable (API.ColumnName "Country") API.StringTy)) (API.AnotherColumn (API.ComparisonColumn API.QueryTable (API.ColumnName "Country") $ API.ScalarType "string"))
) )
mempty mempty
) )

View File

@ -140,8 +140,8 @@ tests opts = do
{ _qFields = { _qFields =
Just $ Just $
HashMap.fromList HashMap.fromList
[ (API.FieldName "id", API.ColumnField (API.ColumnName "AlbumId") API.NumberTy), [ (API.FieldName "id", API.ColumnField (API.ColumnName "AlbumId") $ API.ScalarType "number"),
(API.FieldName "title", API.ColumnField (API.ColumnName "Title") API.StringTy) (API.FieldName "title", API.ColumnField (API.ColumnName "Title") $ API.ScalarType "string")
], ],
_qAggregates = Nothing, _qAggregates = Nothing,
_qLimit = Just 1, _qLimit = Just 1,

View File

@ -1,10 +1,8 @@
{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE OverloadedLists #-}
-- --
module Hasura.Backends.DataConnector.API.V0.Scalar module Hasura.Backends.DataConnector.API.V0.Scalar
( ScalarType (..), ( ScalarType (..),
scalarTypeToText,
) )
where where
@ -24,41 +22,13 @@ import Prelude
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
data ScalarType newtype ScalarType = ScalarType {getScalarType :: Text}
= StringTy
| NumberTy
| BoolTy
| CustomTy {getCustomTy :: Text}
deriving stock (Eq, Generic, Ord, Show) deriving stock (Eq, Generic, Ord, Show)
deriving anyclass (Hashable, NFData) deriving anyclass (Hashable, NFData)
deriving newtype (FromJSONKey, ToJSONKey)
deriving (FromJSON, ToJSON, ToSchema) via Autodocodec ScalarType deriving (FromJSON, ToJSON, ToSchema) via Autodocodec ScalarType
instance ToJSONKey ScalarType where
toJSONKey = ToJSONKeyText (Key.fromText . scalarTypeToText) (Encoding.text . scalarTypeToText)
instance FromJSONKey ScalarType where
fromJSONKey = FromJSONKeyText textToScalarType
scalarTypeToText :: ScalarType -> Text
scalarTypeToText = \case
StringTy -> "string"
NumberTy -> "number"
BoolTy -> "bool"
CustomTy t -> t
textToScalarType :: Text -> ScalarType
textToScalarType t
| t == "string" = StringTy
| t == "number" = NumberTy
| t == "bool" = BoolTy
| otherwise = CustomTy t
instance HasCodec ScalarType where instance HasCodec ScalarType where
codec = codec =
named "ScalarType" $ named "ScalarType" $
matchChoiceCodec dimapCodec ScalarType getScalarType textCodec
(stringConstCodec [(StringTy, "string"), (NumberTy, "number"), (BoolTy, "bool")])
(dimapCodec CustomTy getCustomTy textCodec)
\case
ty@CustomTy {} -> Right ty
ty -> Left ty

View File

@ -10,7 +10,7 @@ import Hasura.Backends.DataConnector.API (openApiSchema)
import Hasura.Backends.DataConnector.API qualified as API import Hasura.Backends.DataConnector.API qualified as API
import Servant.Client ((//)) import Servant.Client ((//))
import System.Environment (withArgs) import System.Environment (withArgs)
import Test.AgentClient (AgentIOClient (..), guardCapabilitiesResponse, introduceAgentClient, mkAgentClientConfig, mkAgentIOClient) import Test.AgentClient (AgentIOClient (..), guardCapabilitiesResponse, guardSchemaResponse, introduceAgentClient, mkAgentClientConfig, mkAgentIOClient)
import Test.Data (TestData, mkTestData) import Test.Data (TestData, mkTestData)
import Test.DataExport (exportData) import Test.DataExport (exportData)
import Test.Sandwich (runSandwichWithCommandLineArgs) import Test.Sandwich (runSandwichWithCommandLineArgs)
@ -49,9 +49,10 @@ main = do
Test TestOptions {..} (SandwichArguments arguments) -> withArgs arguments $ do Test TestOptions {..} (SandwichArguments arguments) -> withArgs arguments $ do
(AgentIOClient agentClient) <- mkAgentIOClient _toSensitiveOutputHandling _toAgentOptions (AgentIOClient agentClient) <- mkAgentIOClient _toSensitiveOutputHandling _toAgentOptions
agentCapabilities <- (agentClient // API._capabilities) >>= guardCapabilitiesResponse agentCapabilities <- (agentClient // API._capabilities) >>= guardCapabilitiesResponse
schemaResponse <- (agentClient // API._schema) testSourceName (_aoAgentConfig _toAgentOptions) >>= guardSchemaResponse
agentClientConfig <- mkAgentClientConfig _toSensitiveOutputHandling _toAgentOptions agentClientConfig <- mkAgentClientConfig _toSensitiveOutputHandling _toAgentOptions
let testData = mkTestData _toTestConfig let testData = mkTestData schemaResponse _toTestConfig
runSandwichWithCommandLineArgs Sandwich.defaultOptions $ runSandwichWithCommandLineArgs Sandwich.defaultOptions $
introduceAgentClient agentClientConfig $ introduceAgentClient agentClientConfig $
tests testData testSourceName (_aoAgentConfig _toAgentOptions) agentCapabilities tests testData testSourceName (_aoAgentConfig _toAgentOptions) agentCapabilities

View File

@ -15,6 +15,7 @@ module Test.AgentClient
guardCapabilitiesResponse, guardCapabilitiesResponse,
getHealth, getHealth,
getSchemaGuarded, getSchemaGuarded,
guardSchemaResponse,
queryGuarded, queryGuarded,
queryExpectError, queryExpectError,
explain, explain,

View File

@ -65,7 +65,7 @@ schemaTables :: [API.TableInfo]
schemaTables = sortOn API._tiName . either error id . eitherDecodeStrict $ schemaBS schemaTables = sortOn API._tiName . either error id . eitherDecodeStrict $ schemaBS
numericColumns :: [API.ColumnName] numericColumns :: [API.ColumnName]
numericColumns = schemaTables >>= (API._tiColumns >>> mapMaybe (\API.ColumnInfo {..} -> if _ciType == API.NumberTy then Just _ciName else Nothing)) numericColumns = schemaTables >>= (API._tiColumns >>> mapMaybe (\API.ColumnInfo {..} -> if _ciType == API.ScalarType "number" then Just _ciName else Nothing))
chinookXmlBS :: ByteString chinookXmlBS :: ByteString
chinookXmlBS = $(makeRelativeToProject "test/Test/Data/ChinookData.xml.gz" >>= embedFile) chinookXmlBS = $(makeRelativeToProject "test/Test/Data/ChinookData.xml.gz" >>= embedFile)
@ -344,19 +344,17 @@ data TestData = TestData
_tdGenresRows :: [HashMap API.FieldName API.FieldValue], _tdGenresRows :: [HashMap API.FieldName API.FieldValue],
_tdGenresTableRelationships :: API.TableRelationships, _tdGenresTableRelationships :: API.TableRelationships,
-- = Scalar Types -- = Scalar Types
_tdStringType :: API.ScalarType, _tdFindColumnScalarType :: API.TableName -> Text -> API.ScalarType,
_tdIntType :: API.ScalarType,
_tdFloatType :: API.ScalarType,
-- = Utility functions -- = Utility functions
_tdColumnName :: Text -> API.ColumnName, _tdColumnName :: Text -> API.ColumnName,
_tdColumnField :: Text -> API.ScalarType -> API.Field, _tdColumnField :: API.TableName -> Text -> API.Field,
_tdQueryComparisonColumn :: Text -> API.ScalarType -> API.ComparisonColumn, _tdQueryComparisonColumn :: Text -> API.ScalarType -> API.ComparisonColumn,
_tdCurrentComparisonColumn :: Text -> API.ScalarType -> API.ComparisonColumn, _tdCurrentComparisonColumn :: Text -> API.ScalarType -> API.ComparisonColumn,
_tdOrderByColumn :: [API.RelationshipName] -> Text -> API.OrderDirection -> API.OrderByElement _tdOrderByColumn :: [API.RelationshipName] -> Text -> API.OrderDirection -> API.OrderByElement
} }
mkTestData :: TestConfig -> TestData mkTestData :: API.SchemaResponse -> TestConfig -> TestData
mkTestData TestConfig {..} = mkTestData schemaResponse TestConfig {..} =
TestData TestData
{ _tdSchemaTables = formatTableInfo <$> schemaTables, { _tdSchemaTables = formatTableInfo <$> schemaTables,
_tdArtistsTableName = formatTableName artistsTableName, _tdArtistsTableName = formatTableName artistsTableName,
@ -395,14 +393,12 @@ mkTestData TestConfig {..} =
_tdGenresTableName = formatTableName genresTableName, _tdGenresTableName = formatTableName genresTableName,
_tdGenresRows = genresRows, _tdGenresRows = genresRows,
_tdGenresTableRelationships = formatTableRelationships genresTableRelationships, _tdGenresTableRelationships = formatTableRelationships genresTableRelationships,
_tdColumnName = API.ColumnName . applyNameCasing _tcColumnNameCasing, _tdColumnName = formatColumnName . API.ColumnName,
_tdColumnField = columnField . applyNameCasing _tcColumnNameCasing, _tdColumnField = columnField,
_tdStringType = API.StringTy, _tdFindColumnScalarType = \tableName name -> findColumnScalarType schemaResponse tableName (formatColumnName $ API.ColumnName name),
_tdIntType = API.NumberTy, _tdQueryComparisonColumn = API.ComparisonColumn API.QueryTable . formatColumnName . API.ColumnName,
_tdFloatType = API.NumberTy, _tdCurrentComparisonColumn = API.ComparisonColumn API.CurrentTable . formatColumnName . API.ColumnName,
_tdQueryComparisonColumn = queryComparisonColumn . applyNameCasing _tcColumnNameCasing, _tdOrderByColumn = \targetPath name -> orderByColumn targetPath (formatColumnName $ API.ColumnName name)
_tdCurrentComparisonColumn = currentComparisonColumn . applyNameCasing _tcColumnNameCasing,
_tdOrderByColumn = \targetPath name -> orderByColumn targetPath (applyNameCasing _tcColumnNameCasing name)
} }
where where
formatTableName :: API.TableName -> API.TableName formatTableName :: API.TableName -> API.TableName
@ -431,6 +427,13 @@ mkTestData TestConfig {..} =
>>> API.cColumnMapping %~ (HashMap.toList >>> fmap (bimap formatColumnName formatColumnName) >>> HashMap.fromList) >>> API.cColumnMapping %~ (HashMap.toList >>> fmap (bimap formatColumnName formatColumnName) >>> HashMap.fromList)
) )
columnField :: API.TableName -> Text -> API.Field
columnField tableName columnName =
API.ColumnField columnName' scalarType
where
columnName' = formatColumnName $ API.ColumnName columnName
scalarType = findColumnScalarType schemaResponse tableName columnName'
applyTableNamePrefix :: [Text] -> API.TableName -> API.TableName applyTableNamePrefix :: [Text] -> API.TableName -> API.TableName
applyTableNamePrefix prefix tableName@(API.TableName rawTableName) = applyTableNamePrefix prefix tableName@(API.TableName rawTableName) =
case NonEmpty.nonEmpty prefix of case NonEmpty.nonEmpty prefix of
@ -443,6 +446,13 @@ applyNameCasing casing text = case casing of
Lowercase -> Text.toLower text Lowercase -> Text.toLower text
Uppercase -> Text.toUpper text Uppercase -> Text.toUpper text
findColumnScalarType :: API.SchemaResponse -> API.TableName -> API.ColumnName -> API.ScalarType
findColumnScalarType API.SchemaResponse {..} tableName columnName =
maybe (error $ "Can't find the scalar type of column " <> show columnName <> " in table " <> show tableName) API._ciType columnInfo
where
tableInfo = find (\API.TableInfo {..} -> _tiName == tableName) _srTables
columnInfo = find (\API.ColumnInfo {..} -> _ciName == columnName) =<< API._tiColumns <$> tableInfo
emptyQuery :: API.Query emptyQuery :: API.Query
emptyQuery = API.Query Nothing Nothing Nothing Nothing Nothing Nothing emptyQuery = API.Query Nothing Nothing Nothing Nothing Nothing Nothing
@ -511,15 +521,6 @@ _ColumnFieldBoolean = API._ColumnFieldValue . _Bool
_RelationshipFieldRows :: Traversal' API.FieldValue [HashMap API.FieldName API.FieldValue] _RelationshipFieldRows :: Traversal' API.FieldValue [HashMap API.FieldName API.FieldValue]
_RelationshipFieldRows = API._RelationshipFieldValue . API.qrRows . _Just _RelationshipFieldRows = API._RelationshipFieldValue . API.qrRows . _Just
columnField :: Text -> API.ScalarType -> API.Field orderByColumn :: [API.RelationshipName] -> API.ColumnName -> API.OrderDirection -> API.OrderByElement
columnField name scalarType = API.ColumnField (API.ColumnName name) scalarType
queryComparisonColumn :: Text -> API.ScalarType -> API.ComparisonColumn
queryComparisonColumn columnName scalarType = API.ComparisonColumn API.QueryTable (API.ColumnName columnName) scalarType
currentComparisonColumn :: Text -> API.ScalarType -> API.ComparisonColumn
currentComparisonColumn columnName scalarType = API.ComparisonColumn API.CurrentTable (API.ColumnName columnName) scalarType
orderByColumn :: [API.RelationshipName] -> Text -> API.OrderDirection -> API.OrderByElement
orderByColumn targetPath columnName orderDirection = orderByColumn targetPath columnName orderDirection =
API.OrderByElement targetPath (API.OrderByColumn $ API.ColumnName columnName) orderDirection API.OrderByElement targetPath (API.OrderByColumn columnName) orderDirection

View File

@ -63,7 +63,7 @@ formatDateColumnsInRow dateTimeFormatString TableInfo {..} row =
) )
where where
dateFields = fmap (\ColumnInfo {..} -> FieldName $ unColumnName _ciName) $ filter (\ColumnInfo {..} -> _ciType == dateTimeScalarType) _tiColumns dateFields = fmap (\ColumnInfo {..} -> FieldName $ unColumnName _ciName) $ filter (\ColumnInfo {..} -> _ciType == dateTimeScalarType) _tiColumns
dateTimeScalarType = CustomTy "DateTime" dateTimeScalarType = ScalarType "DateTime"
tryFormatDate fieldValue = case deserializeAsColumnFieldValue fieldValue of tryFormatDate fieldValue = case deserializeAsColumnFieldValue fieldValue of
J.String value -> do J.String value -> do
(zonedTime :: ZonedTime) <- iso8601ParseM $ Text.unpack value (zonedTime :: ZonedTime) <- iso8601ParseM $ Text.unpack value

View File

@ -1,6 +1,7 @@
module Test.Specs.ErrorSpec (spec) where module Test.Specs.ErrorSpec (spec) where
import Control.Lens ((&), (?~)) import Control.Lens ((&), (?~))
import Data.Aeson (Value (..))
import Hasura.Backends.DataConnector.API import Hasura.Backends.DataConnector.API
import Test.AgentClient (queryExpectError) import Test.AgentClient (queryExpectError)
import Test.Data (TestData (..)) import Test.Data (TestData (..))
@ -16,13 +17,15 @@ spec TestData {..} sourceName config _capabilities = describe "Error Protocol" d
where where
brokenQueryRequest :: QueryRequest brokenQueryRequest :: QueryRequest
brokenQueryRequest = brokenQueryRequest =
let fields = Data.mkFieldsMap [("ArtistId", _tdColumnField "ArtistId" _tdIntType), ("Name", _tdColumnField "Name" _tdStringType)] let fields = Data.mkFieldsMap [("ArtistId", _tdColumnField _tdArtistsTableName "ArtistId"), ("Name", _tdColumnField _tdArtistsTableName "Name")]
query = query =
Data.emptyQuery Data.emptyQuery
& qFields ?~ fields & qFields ?~ fields
& qWhere & qWhere
?~ ApplyBinaryComparisonOperator ?~ ApplyBinaryComparisonOperator
(CustomBinaryComparisonOperator "FOOBAR") (CustomBinaryComparisonOperator "FOOBAR")
(ComparisonColumn CurrentTable (ColumnName "ArtistId") NumberTy) (_tdCurrentComparisonColumn "ArtistId" artistIdScalarType)
(ScalarValue "1" StringTy) (ScalarValue (Number 1) $ artistIdScalarType)
in QueryRequest _tdArtistsTableName [] query in QueryRequest _tdArtistsTableName [] query
artistIdScalarType = _tdFindColumnScalarType _tdArtistsTableName "ArtistId"

View File

@ -24,6 +24,6 @@ spec TestData {..} sourceName config _ = do
where where
artistsQueryRequest :: QueryRequest artistsQueryRequest :: QueryRequest
artistsQueryRequest = artistsQueryRequest =
let fields = Data.mkFieldsMap [("ArtistId", _tdColumnField "ArtistId" _tdIntType), ("Name", _tdColumnField "Name" _tdStringType)] let fields = Data.mkFieldsMap [("ArtistId", _tdColumnField _tdArtistsTableName "ArtistId"), ("Name", _tdColumnField _tdArtistsTableName "Name")]
query = Data.emptyQuery & qFields ?~ fields query = Data.emptyQuery & qFields ?~ fields
in QueryRequest _tdArtistsTableName [] query in QueryRequest _tdArtistsTableName [] query

View File

@ -39,7 +39,7 @@ spec TestData {..} sourceName config relationshipCapabilities = describe "Aggreg
Data.responseRows response `rowsShouldBe` [] Data.responseRows response `rowsShouldBe` []
it "counts all rows, after applying filters" $ do it "counts all rows, after applying filters" $ do
let where' = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "BillingCity" _tdStringType) (ScalarValue (String "Oslo") _tdStringType) let where' = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "BillingCity" billingCityScalarType) (ScalarValue (String "Oslo") billingCityScalarType)
let aggregates = Data.mkFieldsMap [("count_all", StarCount)] let aggregates = Data.mkFieldsMap [("count_all", StarCount)]
let queryRequest = invoicesQueryRequest aggregates & qrQuery . qWhere ?~ where' let queryRequest = invoicesQueryRequest aggregates & qrQuery . qWhere ?~ where'
response <- queryGuarded sourceName config queryRequest response <- queryGuarded sourceName config queryRequest
@ -77,7 +77,7 @@ spec TestData {..} sourceName config relationshipCapabilities = describe "Aggreg
it "can count all rows with non-null values in a column, after applying pagination and filtering" $ do it "can count all rows with non-null values in a column, after applying pagination and filtering" $ do
let limit = 50 let limit = 50
let where' = ApplyBinaryComparisonOperator GreaterThanOrEqual (_tdCurrentComparisonColumn "InvoiceId" _tdIntType) (ScalarValue (Number 380) _tdIntType) let where' = ApplyBinaryComparisonOperator GreaterThanOrEqual (_tdCurrentComparisonColumn "InvoiceId" invoiceIdScalarType) (ScalarValue (Number 380) invoiceIdScalarType)
let aggregates = Data.mkFieldsMap [("count_cols", ColumnCount $ ColumnCountAggregate (_tdColumnName "BillingState") False)] let aggregates = Data.mkFieldsMap [("count_cols", ColumnCount $ ColumnCountAggregate (_tdColumnName "BillingState") False)]
let queryRequest = invoicesQueryRequest aggregates & qrQuery %~ (qLimit ?~ limit >>> qWhere ?~ where') let queryRequest = invoicesQueryRequest aggregates & qrQuery %~ (qLimit ?~ limit >>> qWhere ?~ where')
response <- queryGuarded sourceName config queryRequest response <- queryGuarded sourceName config queryRequest
@ -107,7 +107,7 @@ spec TestData {..} sourceName config relationshipCapabilities = describe "Aggreg
it "can count all rows with distinct non-null values in a column, after applying pagination and filtering" $ do it "can count all rows with distinct non-null values in a column, after applying pagination and filtering" $ do
let limit = 20 let limit = 20
let where' = ApplyBinaryComparisonOperator GreaterThanOrEqual (_tdCurrentComparisonColumn "InvoiceId" _tdIntType) (ScalarValue (Number 380) _tdIntType) let where' = ApplyBinaryComparisonOperator GreaterThanOrEqual (_tdCurrentComparisonColumn "InvoiceId" invoiceIdScalarType) (ScalarValue (Number 380) invoiceIdScalarType)
-- It is important to add an explicit order by for this query as different database engines will order implicitly resulting in incorrect results -- It is important to add an explicit order by for this query as different database engines will order implicitly resulting in incorrect results
let orderBy = OrderBy mempty $ _tdOrderByColumn [] "InvoiceId" Ascending :| [] let orderBy = OrderBy mempty $ _tdOrderByColumn [] "InvoiceId" Ascending :| []
let aggregates = Data.mkFieldsMap [("count_cols", ColumnCount $ ColumnCountAggregate (_tdColumnName "BillingState") True)] let aggregates = Data.mkFieldsMap [("count_cols", ColumnCount $ ColumnCountAggregate (_tdColumnName "BillingState") True)]
@ -141,7 +141,7 @@ spec TestData {..} sourceName config relationshipCapabilities = describe "Aggreg
it "can get the max total from all rows, after applying pagination, filtering and ordering" $ do it "can get the max total from all rows, after applying pagination, filtering and ordering" $ do
let limit = 20 let limit = 20
let where' = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "BillingCountry" _tdStringType) (ScalarValue (String "USA") _tdStringType) let where' = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "BillingCountry" billingCountryScalarType) (ScalarValue (String "USA") billingCountryScalarType)
let orderBy = OrderBy mempty $ _tdOrderByColumn [] "BillingPostalCode" Descending :| [_tdOrderByColumn [] "InvoiceId" Ascending] let orderBy = OrderBy mempty $ _tdOrderByColumn [] "BillingPostalCode" Descending :| [_tdOrderByColumn [] "InvoiceId" Ascending]
let aggregates = Data.mkFieldsMap [("max", singleColumnAggregateMax (_tdColumnName "Total"))] let aggregates = Data.mkFieldsMap [("max", singleColumnAggregateMax (_tdColumnName "Total"))]
let queryRequest = invoicesQueryRequest aggregates & qrQuery %~ (qLimit ?~ limit >>> qWhere ?~ where' >>> qOrderBy ?~ orderBy) let queryRequest = invoicesQueryRequest aggregates & qrQuery %~ (qLimit ?~ limit >>> qWhere ?~ where' >>> qOrderBy ?~ orderBy)
@ -180,7 +180,7 @@ spec TestData {..} sourceName config relationshipCapabilities = describe "Aggreg
Data.responseRows response `rowsShouldBe` [] Data.responseRows response `rowsShouldBe` []
it "aggregates over empty row lists results in nulls" $ do it "aggregates over empty row lists results in nulls" $ do
let where' = ApplyBinaryComparisonOperator LessThan (_tdCurrentComparisonColumn "ArtistId" _tdIntType) (ScalarValue (Number 0) _tdIntType) let where' = ApplyBinaryComparisonOperator LessThan (_tdCurrentComparisonColumn "ArtistId" artistIdScalarType) (ScalarValue (Number 0) artistIdScalarType)
let aggregates = Data.mkFieldsMap [("min", singleColumnAggregateMin (_tdColumnName "Name"))] let aggregates = Data.mkFieldsMap [("min", singleColumnAggregateMin (_tdColumnName "Name"))]
let queryRequest = artistsQueryRequest aggregates & qrQuery . qWhere ?~ where' let queryRequest = artistsQueryRequest aggregates & qrQuery . qWhere ?~ where'
response <- queryGuarded sourceName config queryRequest response <- queryGuarded sourceName config queryRequest
@ -240,10 +240,10 @@ spec TestData {..} sourceName config relationshipCapabilities = describe "Aggreg
let limit = 30 let limit = 30
let fields = let fields =
Data.mkFieldsMap Data.mkFieldsMap
[ ("InvoiceId", _tdColumnField "InvoiceId" _tdIntType), [ ("InvoiceId", _tdColumnField _tdInvoicesTableName "InvoiceId"),
("BillingCountry", _tdColumnField "BillingCountry" _tdStringType) ("BillingCountry", _tdColumnField _tdInvoicesTableName "BillingCountry")
] ]
let where' = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "BillingCountry" _tdStringType) (ScalarValue (String "Canada") _tdStringType) let where' = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "BillingCountry" billingCountryScalarType) (ScalarValue (String "Canada") billingCountryScalarType)
let orderBy = OrderBy mempty $ _tdOrderByColumn [] "BillingAddress" Ascending :| [_tdOrderByColumn [] "InvoiceId" Ascending] let orderBy = OrderBy mempty $ _tdOrderByColumn [] "BillingAddress" Ascending :| [_tdOrderByColumn [] "InvoiceId" Ascending]
let aggregates = Data.mkFieldsMap [("min", singleColumnAggregateMin (_tdColumnName "Total"))] let aggregates = Data.mkFieldsMap [("min", singleColumnAggregateMin (_tdColumnName "Total"))]
let queryRequest = invoicesQueryRequest aggregates & qrQuery %~ (qFields ?~ fields >>> qLimit ?~ limit >>> qWhere ?~ where' >>> qOrderBy ?~ orderBy) let queryRequest = invoicesQueryRequest aggregates & qrQuery %~ (qFields ?~ fields >>> qLimit ?~ limit >>> qWhere ?~ where' >>> qOrderBy ?~ orderBy)
@ -293,8 +293,8 @@ spec TestData {..} sourceName config relationshipCapabilities = describe "Aggreg
let limit = 5 let limit = 5
let albumFields = let albumFields =
Data.mkFieldsMap Data.mkFieldsMap
[ ("AlbumId", _tdColumnField "AlbumId" _tdIntType), [ ("AlbumId", _tdColumnField _tdAlbumsTableName "AlbumId"),
("Title", _tdColumnField "Title" _tdStringType) ("Title", _tdColumnField _tdAlbumsTableName "Title")
] ]
let query = artistsWithAlbumsQuery (qFields ?~ albumFields) & qrQuery . qLimit ?~ limit let query = artistsWithAlbumsQuery (qFields ?~ albumFields) & qrQuery . qLimit ?~ limit
receivedArtists <- queryGuarded sourceName config query receivedArtists <- queryGuarded sourceName config query
@ -494,8 +494,8 @@ spec TestData {..} sourceName config relationshipCapabilities = describe "Aggreg
albumsSubquery = Data.emptyQuery & qAggregates ?~ albumAggregates & modifySubquery albumsSubquery = Data.emptyQuery & qAggregates ?~ albumAggregates & modifySubquery
artistFields = artistFields =
Data.mkFieldsMap Data.mkFieldsMap
[ ("ArtistId", _tdColumnField "ArtistId" _tdIntType), [ ("ArtistId", _tdColumnField _tdArtistsTableName "ArtistId"),
("Name", _tdColumnField "Name" _tdStringType), ("Name", _tdColumnField _tdArtistsTableName "Name"),
("Albums", RelField $ RelationshipField _tdAlbumsRelationshipName albumsSubquery) ("Albums", RelField $ RelationshipField _tdAlbumsRelationshipName albumsSubquery)
] ]
artistOrderBy = OrderBy mempty $ _tdOrderByColumn [] "ArtistId" Ascending :| [] artistOrderBy = OrderBy mempty $ _tdOrderByColumn [] "ArtistId" Ascending :| []
@ -538,34 +538,34 @@ spec TestData {..} sourceName config relationshipCapabilities = describe "Aggreg
deeplyNestedArtistsQuery = deeplyNestedArtistsQuery =
let invoiceLinesAggregates = Data.mkFieldsMap [("aggregate_sum_Quantity", singleColumnAggregateSum (_tdColumnName "Quantity"))] let invoiceLinesAggregates = Data.mkFieldsMap [("aggregate_sum_Quantity", singleColumnAggregateSum (_tdColumnName "Quantity"))]
invoiceLinesSubquery = Data.emptyQuery & qAggregates ?~ invoiceLinesAggregates invoiceLinesSubquery = Data.emptyQuery & qAggregates ?~ invoiceLinesAggregates
mediaTypeFields = Data.mkFieldsMap [("Name", _tdColumnField "Name" _tdStringType)] mediaTypeFields = Data.mkFieldsMap [("Name", _tdColumnField _tdMediaTypesTableName "Name")]
mediaTypeSubquery = Data.emptyQuery & qFields ?~ mediaTypeFields mediaTypeSubquery = Data.emptyQuery & qFields ?~ mediaTypeFields
tracksFields = tracksFields =
Data.mkFieldsMap Data.mkFieldsMap
[ ("nodes_Name", _tdColumnField "Name" _tdStringType), [ ("nodes_Name", _tdColumnField _tdTracksTableName "Name"),
("nodes_MediaType", RelField $ RelationshipField _tdMediaTypeRelationshipName mediaTypeSubquery), ("nodes_MediaType", RelField $ RelationshipField _tdMediaTypeRelationshipName mediaTypeSubquery),
("nodes_InvoiceLines_aggregate", RelField $ RelationshipField _tdInvoiceLinesRelationshipName invoiceLinesSubquery) ("nodes_InvoiceLines_aggregate", RelField $ RelationshipField _tdInvoiceLinesRelationshipName invoiceLinesSubquery)
] ]
tracksAggregates = Data.mkFieldsMap [("aggregate_count", StarCount)] tracksAggregates = Data.mkFieldsMap [("aggregate_count", StarCount)]
tracksWhere = ApplyBinaryComparisonOperator LessThan (_tdCurrentComparisonColumn "Milliseconds" _tdIntType) (ScalarValue (Number 300000) _tdIntType) tracksWhere = ApplyBinaryComparisonOperator LessThan (_tdCurrentComparisonColumn "Milliseconds" millisecondsScalarType) (ScalarValue (Number 300000) millisecondsScalarType)
tracksOrderBy = OrderBy mempty $ _tdOrderByColumn [] "Name" Descending :| [] tracksOrderBy = OrderBy mempty $ _tdOrderByColumn [] "Name" Descending :| []
tracksSubquery = Query (Just tracksFields) (Just tracksAggregates) Nothing Nothing (Just tracksWhere) (Just tracksOrderBy) tracksSubquery = Query (Just tracksFields) (Just tracksAggregates) Nothing Nothing (Just tracksWhere) (Just tracksOrderBy)
albumsFields = albumsFields =
Data.mkFieldsMap Data.mkFieldsMap
[ ("nodes_Title", _tdColumnField "Title" _tdStringType), [ ("nodes_Title", _tdColumnField _tdAlbumsTableName "Title"),
("nodes_Tracks_aggregate", RelField $ RelationshipField _tdTracksRelationshipName tracksSubquery) ("nodes_Tracks_aggregate", RelField $ RelationshipField _tdTracksRelationshipName tracksSubquery)
] ]
albumsOrderBy = OrderBy mempty $ _tdOrderByColumn [] "Title" Ascending :| [] albumsOrderBy = OrderBy mempty $ _tdOrderByColumn [] "Title" Ascending :| []
albumsSubquery = Data.emptyQuery & qFields ?~ albumsFields & qOrderBy ?~ albumsOrderBy albumsSubquery = Data.emptyQuery & qFields ?~ albumsFields & qOrderBy ?~ albumsOrderBy
artistFields = artistFields =
Data.mkFieldsMap Data.mkFieldsMap
[ ("Name", _tdColumnField "Name" _tdStringType), [ ("Name", _tdColumnField _tdArtistsTableName "Name"),
("Albums_aggregate", RelField $ RelationshipField _tdAlbumsRelationshipName albumsSubquery) ("Albums_aggregate", RelField $ RelationshipField _tdAlbumsRelationshipName albumsSubquery)
] ]
artistWhere = artistWhere =
And And
[ ApplyBinaryComparisonOperator GreaterThan (_tdCurrentComparisonColumn "Name" _tdStringType) (ScalarValue (String "A") _tdStringType), [ ApplyBinaryComparisonOperator GreaterThan (_tdCurrentComparisonColumn "Name" artistNameScalarType) (ScalarValue (String "A") artistNameScalarType),
ApplyBinaryComparisonOperator LessThan (_tdCurrentComparisonColumn "Name" _tdStringType) (ScalarValue (String "B") _tdStringType) ApplyBinaryComparisonOperator LessThan (_tdCurrentComparisonColumn "Name" artistNameScalarType) (ScalarValue (String "B") artistNameScalarType)
] ]
artistOrderBy = OrderBy mempty $ _tdOrderByColumn [] "Name" Descending :| [] artistOrderBy = OrderBy mempty $ _tdOrderByColumn [] "Name" Descending :| []
artistQuery = Query (Just artistFields) Nothing (Just 3) (Just 1) (Just artistWhere) (Just artistOrderBy) artistQuery = Query (Just artistFields) Nothing (Just 3) (Just 1) (Just artistWhere) (Just artistOrderBy)
@ -607,3 +607,10 @@ spec TestData {..} sourceName config relationshipCapabilities = describe "Aggreg
singleColumnAggregateSum :: ColumnName -> Aggregate singleColumnAggregateSum :: ColumnName -> Aggregate
singleColumnAggregateSum = SingleColumn . SingleColumnAggregate (SingleColumnAggregateFunction [G.name|sum|]) singleColumnAggregateSum = SingleColumn . SingleColumnAggregate (SingleColumnAggregateFunction [G.name|sum|])
billingCityScalarType = _tdFindColumnScalarType _tdInvoicesTableName "BillingCity"
billingCountryScalarType = _tdFindColumnScalarType _tdInvoicesTableName "BillingCountry"
invoiceIdScalarType = _tdFindColumnScalarType _tdInvoicesTableName "InvoiceId"
artistIdScalarType = _tdFindColumnScalarType _tdArtistsTableName "ArtistId"
artistNameScalarType = _tdFindColumnScalarType _tdArtistsTableName "Name"
millisecondsScalarType = _tdFindColumnScalarType _tdTracksTableName "Milliseconds"

View File

@ -24,7 +24,7 @@ spec TestData {..} sourceName config = describe "Basic Queries" $ do
_qrAggregates receivedArtists `jsonShouldBe` Nothing _qrAggregates receivedArtists `jsonShouldBe` Nothing
it "can query for a list of albums with a subset of columns" $ do it "can query for a list of albums with a subset of columns" $ do
let fields = Data.mkFieldsMap [("ArtistId", _tdColumnField "ArtistId" _tdIntType), ("Title", _tdColumnField "Title" _tdStringType)] let fields = Data.mkFieldsMap [("ArtistId", _tdColumnField _tdAlbumsTableName "ArtistId"), ("Title", _tdColumnField _tdAlbumsTableName "Title")]
let query = albumsQueryRequest & qrQuery . qFields ?~ fields let query = albumsQueryRequest & qrQuery . qFields ?~ fields
receivedAlbums <- Data.sortResponseRowsBy "Title" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "Title" <$> queryGuarded sourceName config query
@ -36,7 +36,7 @@ spec TestData {..} sourceName config = describe "Basic Queries" $ do
_qrAggregates receivedAlbums `jsonShouldBe` Nothing _qrAggregates receivedAlbums `jsonShouldBe` Nothing
it "can project columns into fields with different names" $ do it "can project columns into fields with different names" $ do
let fields = Data.mkFieldsMap [("Artist_Id", _tdColumnField "ArtistId" _tdIntType), ("Artist_Name", _tdColumnField "Name" _tdStringType)] let fields = Data.mkFieldsMap [("Artist_Id", _tdColumnField _tdArtistsTableName "ArtistId"), ("Artist_Name", _tdColumnField _tdArtistsTableName "Name")]
let query = artistsQueryRequest & qrQuery . qFields ?~ fields let query = artistsQueryRequest & qrQuery . qFields ?~ fields
receivedArtists <- Data.sortResponseRowsBy "ArtistId" <$> queryGuarded sourceName config query receivedArtists <- Data.sortResponseRowsBy "ArtistId" <$> queryGuarded sourceName config query
@ -67,12 +67,12 @@ spec TestData {..} sourceName config = describe "Basic Queries" $ do
where where
artistsQueryRequest :: QueryRequest artistsQueryRequest :: QueryRequest
artistsQueryRequest = artistsQueryRequest =
let fields = Data.mkFieldsMap [("ArtistId", _tdColumnField "ArtistId" _tdIntType), ("Name", _tdColumnField "Name" _tdStringType)] let fields = Data.mkFieldsMap [("ArtistId", _tdColumnField _tdArtistsTableName "ArtistId"), ("Name", _tdColumnField _tdArtistsTableName "Name")]
query = Data.emptyQuery & qFields ?~ fields query = Data.emptyQuery & qFields ?~ fields
in QueryRequest _tdArtistsTableName [] query in QueryRequest _tdArtistsTableName [] query
albumsQueryRequest :: QueryRequest albumsQueryRequest :: QueryRequest
albumsQueryRequest = albumsQueryRequest =
let fields = Data.mkFieldsMap [("AlbumId", _tdColumnField "AlbumId" _tdIntType), ("ArtistId", _tdColumnField "ArtistId" _tdIntType), ("Title", _tdColumnField "Title" _tdStringType)] let fields = Data.mkFieldsMap [("AlbumId", _tdColumnField _tdAlbumsTableName "AlbumId"), ("ArtistId", _tdColumnField _tdAlbumsTableName "ArtistId"), ("Title", _tdColumnField _tdAlbumsTableName "Title")]
query = Data.emptyQuery & qFields ?~ fields query = Data.emptyQuery & qFields ?~ fields
in QueryRequest _tdAlbumsTableName [] query in QueryRequest _tdAlbumsTableName [] query

View File

@ -34,7 +34,7 @@ spec TestData {..} sourceName config (ScalarTypesCapabilities scalarTypesCapabil
forM_ (HashMap.toList items) \((operatorName, columnType), (columnName, tableName, argColumnName, argType)) -> do forM_ (HashMap.toList items) \((operatorName, columnType), (columnName, tableName, argColumnName, argType)) -> do
-- Perform a select using the operator in a where clause -- Perform a select using the operator in a where clause
let queryRequest = let queryRequest =
let fields = Data.mkFieldsMap [(unColumnName columnName, _tdColumnField (unColumnName columnName) columnType)] let fields = Data.mkFieldsMap [(unColumnName columnName, _tdColumnField tableName (unColumnName columnName))]
query' = Data.emptyQuery & qFields ?~ fields query' = Data.emptyQuery & qFields ?~ fields
in QueryRequest tableName [] query' in QueryRequest tableName [] query'
where' = where' =
@ -46,7 +46,7 @@ spec TestData {..} sourceName config (ScalarTypesCapabilities scalarTypesCapabil
queryRequest queryRequest
& qrQuery . qWhere ?~ where' & qrQuery . qWhere ?~ where'
& qrQuery . qLimit ?~ 1 -- No need to test actual results & qrQuery . qLimit ?~ 1 -- No need to test actual results
it (Text.unpack $ "ComparisonOperator " <> unName operatorName <> ": " <> scalarTypeToText columnType <> " executes without an error") do it (Text.unpack $ "ComparisonOperator " <> unName operatorName <> ": " <> getScalarType columnType <> " executes without an error") do
result <- queryGuarded sourceName config query result <- queryGuarded sourceName config query
-- Check that you get a success response -- Check that you get a success response
Data.responseRows result `shouldBe` take 1 (Data.responseRows result) Data.responseRows result `shouldBe` take 1 (Data.responseRows result)

View File

@ -20,7 +20,7 @@ import Prelude
spec :: TestData -> SourceName -> Config -> Maybe ComparisonCapabilities -> AgentTestSpec spec :: TestData -> SourceName -> Config -> Maybe ComparisonCapabilities -> AgentTestSpec
spec TestData {..} sourceName config comparisonCapabilities = describe "Filtering in Queries" $ do spec TestData {..} sourceName config comparisonCapabilities = describe "Filtering in Queries" $ do
it "can filter using an equality expression" $ do it "can filter using an equality expression" $ do
let where' = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "AlbumId" _tdIntType) (ScalarValue (Number 2) _tdIntType) let where' = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "AlbumId" albumIdScalarType) (ScalarValue (Number 2) albumIdScalarType)
let query = albumsQueryRequest & qrQuery . qWhere ?~ where' let query = albumsQueryRequest & qrQuery . qWhere ?~ where'
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -31,7 +31,7 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
_qrAggregates receivedAlbums `jsonShouldBe` Nothing _qrAggregates receivedAlbums `jsonShouldBe` Nothing
it "can filter using an inequality expression" $ do it "can filter using an inequality expression" $ do
let where' = Not (ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "AlbumId" _tdIntType) (ScalarValue (Number 2) _tdIntType)) let where' = Not (ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "AlbumId" albumIdScalarType) (ScalarValue (Number 2) albumIdScalarType))
let query = albumsQueryRequest & qrQuery . qWhere ?~ where' let query = albumsQueryRequest & qrQuery . qWhere ?~ where'
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -42,7 +42,7 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
_qrAggregates receivedAlbums `jsonShouldBe` Nothing _qrAggregates receivedAlbums `jsonShouldBe` Nothing
it "can filter using an in expression" $ do it "can filter using an in expression" $ do
let where' = ApplyBinaryArrayComparisonOperator In (_tdCurrentComparisonColumn "AlbumId" _tdIntType) [Number 2, Number 3] _tdIntType let where' = ApplyBinaryArrayComparisonOperator In (_tdCurrentComparisonColumn "AlbumId" albumIdScalarType) [Number 2, Number 3] albumIdScalarType
let query = albumsQueryRequest & qrQuery . qWhere ?~ where' let query = albumsQueryRequest & qrQuery . qWhere ?~ where'
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -53,7 +53,7 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
_qrAggregates receivedAlbums `jsonShouldBe` Nothing _qrAggregates receivedAlbums `jsonShouldBe` Nothing
it "can negate an in expression filter using a not expression" $ do it "can negate an in expression filter using a not expression" $ do
let where' = Not (ApplyBinaryArrayComparisonOperator In (_tdCurrentComparisonColumn "AlbumId" _tdIntType) [Number 2, Number 3] _tdIntType) let where' = Not (ApplyBinaryArrayComparisonOperator In (_tdCurrentComparisonColumn "AlbumId" albumIdScalarType) [Number 2, Number 3] albumIdScalarType)
let query = albumsQueryRequest & qrQuery . qWhere ?~ where' let query = albumsQueryRequest & qrQuery . qWhere ?~ where'
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -64,8 +64,8 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
_qrAggregates receivedAlbums `jsonShouldBe` Nothing _qrAggregates receivedAlbums `jsonShouldBe` Nothing
it "can combine filters using an and expression" $ do it "can combine filters using an and expression" $ do
let where1 = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "ArtistId" _tdIntType) (ScalarValue (Number 58) _tdIntType) let where1 = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "ArtistId" artistIdScalarType) (ScalarValue (Number 58) artistIdScalarType)
let where2 = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "Title" _tdStringType) (ScalarValue (String "Stormbringer") _tdStringType) let where2 = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "Title" albumTitleScalarType) (ScalarValue (String "Stormbringer") albumTitleScalarType)
let where' = And [where1, where2] let where' = And [where1, where2]
let query = albumsQueryRequest & qrQuery . qWhere ?~ where' let query = albumsQueryRequest & qrQuery . qWhere ?~ where'
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -89,8 +89,8 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
_qrAggregates receivedAlbums `jsonShouldBe` Nothing _qrAggregates receivedAlbums `jsonShouldBe` Nothing
it "can combine filters using an or expression" $ do it "can combine filters using an or expression" $ do
let where1 = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "AlbumId" _tdIntType) (ScalarValue (Number 2) _tdIntType) let where1 = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "AlbumId" albumIdScalarType) (ScalarValue (Number 2) albumIdScalarType)
let where2 = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "AlbumId" _tdIntType) (ScalarValue (Number 3) _tdIntType) let where2 = ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "AlbumId" albumIdScalarType) (ScalarValue (Number 3) albumIdScalarType)
let where' = Or [where1, where2] let where' = Or [where1, where2]
let query = albumsQueryRequest & qrQuery . qWhere ?~ where' let query = albumsQueryRequest & qrQuery . qWhere ?~ where'
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -110,7 +110,7 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
_qrAggregates receivedAlbums `jsonShouldBe` Nothing _qrAggregates receivedAlbums `jsonShouldBe` Nothing
it "can filter by applying the greater than operator" $ do it "can filter by applying the greater than operator" $ do
let where' = ApplyBinaryComparisonOperator GreaterThan (_tdCurrentComparisonColumn "AlbumId" _tdIntType) (ScalarValue (Number 300) _tdIntType) let where' = ApplyBinaryComparisonOperator GreaterThan (_tdCurrentComparisonColumn "AlbumId" albumIdScalarType) (ScalarValue (Number 300) albumIdScalarType)
let query = albumsQueryRequest & qrQuery . qWhere ?~ where' let query = albumsQueryRequest & qrQuery . qWhere ?~ where'
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -121,7 +121,7 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
_qrAggregates receivedAlbums `jsonShouldBe` Nothing _qrAggregates receivedAlbums `jsonShouldBe` Nothing
it "can filter by applying the greater than or equal operator" $ do it "can filter by applying the greater than or equal operator" $ do
let where' = ApplyBinaryComparisonOperator GreaterThanOrEqual (_tdCurrentComparisonColumn "AlbumId" _tdIntType) (ScalarValue (Number 300) _tdIntType) let where' = ApplyBinaryComparisonOperator GreaterThanOrEqual (_tdCurrentComparisonColumn "AlbumId" albumIdScalarType) (ScalarValue (Number 300) albumIdScalarType)
let query = albumsQueryRequest & qrQuery . qWhere ?~ where' let query = albumsQueryRequest & qrQuery . qWhere ?~ where'
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -132,7 +132,7 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
_qrAggregates receivedAlbums `jsonShouldBe` Nothing _qrAggregates receivedAlbums `jsonShouldBe` Nothing
it "can filter by applying the less than operator" $ do it "can filter by applying the less than operator" $ do
let where' = ApplyBinaryComparisonOperator LessThan (_tdCurrentComparisonColumn "AlbumId" _tdIntType) (ScalarValue (Number 100) _tdIntType) let where' = ApplyBinaryComparisonOperator LessThan (_tdCurrentComparisonColumn "AlbumId" albumIdScalarType) (ScalarValue (Number 100) albumIdScalarType)
let query = albumsQueryRequest & qrQuery . qWhere ?~ where' let query = albumsQueryRequest & qrQuery . qWhere ?~ where'
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -143,7 +143,7 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
_qrAggregates receivedAlbums `jsonShouldBe` Nothing _qrAggregates receivedAlbums `jsonShouldBe` Nothing
it "can filter by applying the less than or equal operator" $ do it "can filter by applying the less than or equal operator" $ do
let where' = ApplyBinaryComparisonOperator LessThanOrEqual (_tdCurrentComparisonColumn "AlbumId" _tdIntType) (ScalarValue (Number 100) _tdIntType) let where' = ApplyBinaryComparisonOperator LessThanOrEqual (_tdCurrentComparisonColumn "AlbumId" albumIdScalarType) (ScalarValue (Number 100) albumIdScalarType)
let query = albumsQueryRequest & qrQuery . qWhere ?~ where' let query = albumsQueryRequest & qrQuery . qWhere ?~ where'
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -154,7 +154,7 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
_qrAggregates receivedAlbums `jsonShouldBe` Nothing _qrAggregates receivedAlbums `jsonShouldBe` Nothing
it "can filter using a greater than operator with a column comparison" $ do it "can filter using a greater than operator with a column comparison" $ do
let where' = ApplyBinaryComparisonOperator GreaterThan (_tdCurrentComparisonColumn "AlbumId" _tdIntType) (AnotherColumn (_tdCurrentComparisonColumn "ArtistId" _tdIntType)) let where' = ApplyBinaryComparisonOperator GreaterThan (_tdCurrentComparisonColumn "AlbumId" albumIdScalarType) (AnotherColumn (_tdCurrentComparisonColumn "ArtistId" albumIdScalarType))
let query = albumsQueryRequest & qrQuery . qWhere ?~ where' let query = albumsQueryRequest & qrQuery . qWhere ?~ where'
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -171,7 +171,7 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
it "returns all rows if matching rows exist" $ do it "returns all rows if matching rows exist" $ do
let where' = let where' =
Exists (UnrelatedTable _tdEmployeesTableName) $ Exists (UnrelatedTable _tdEmployeesTableName) $
ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "EmployeeId" _tdIntType) (ScalarValue (Number 1) _tdIntType) ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "EmployeeId" employeeIdScalarType) (ScalarValue (Number 1) employeeIdScalarType)
let query = albumsQueryRequest & qrQuery . qWhere ?~ where' let query = albumsQueryRequest & qrQuery . qWhere ?~ where'
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -183,7 +183,7 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
it "returns no rows if matching rows do not exist" $ do it "returns no rows if matching rows do not exist" $ do
let where' = let where' =
Exists (UnrelatedTable _tdEmployeesTableName) $ Exists (UnrelatedTable _tdEmployeesTableName) $
ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "EmployeeId" _tdIntType) (ScalarValue (Number 0) _tdIntType) ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "EmployeeId" employeeIdScalarType) (ScalarValue (Number 0) employeeIdScalarType)
let query = albumsQueryRequest & qrQuery . qWhere ?~ where' let query = albumsQueryRequest & qrQuery . qWhere ?~ where'
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -195,8 +195,8 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
let where' = let where' =
Exists (UnrelatedTable _tdEmployeesTableName) $ Exists (UnrelatedTable _tdEmployeesTableName) $
And And
[ ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "EmployeeId" _tdIntType) (ScalarValue (Number 1) _tdIntType), [ ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "EmployeeId" employeeIdScalarType) (ScalarValue (Number 1) employeeIdScalarType),
ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "City" _tdStringType) (ScalarValue (String "Edmonton") _tdStringType) ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "City" employeeCityScalarType) (ScalarValue (String "Edmonton") employeeCityScalarType)
] ]
let query = albumsQueryRequest & qrQuery . qWhere ?~ where' let query = albumsQueryRequest & qrQuery . qWhere ?~ where'
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -210,8 +210,8 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
let where' = let where' =
Exists (UnrelatedTable _tdEmployeesTableName) $ Exists (UnrelatedTable _tdEmployeesTableName) $
And And
[ ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "EmployeeId" _tdIntType) (ScalarValue (Number 1) _tdIntType), [ ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "EmployeeId" employeeIdScalarType) (ScalarValue (Number 1) employeeIdScalarType),
ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "City" _tdStringType) (ScalarValue (String "Calgary") _tdStringType) ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "City" employeeCityScalarType) (ScalarValue (String "Calgary") employeeCityScalarType)
] ]
let query = albumsQueryRequest & qrQuery . qWhere ?~ where' let query = albumsQueryRequest & qrQuery . qWhere ?~ where'
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -224,7 +224,7 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
it "can filter by comparing against rows in a related table" $ do it "can filter by comparing against rows in a related table" $ do
let where' = let where' =
Exists (RelatedTable _tdArtistRelationshipName) $ Exists (RelatedTable _tdArtistRelationshipName) $
ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "Name" _tdStringType) (ScalarValue (String "AC/DC") _tdStringType) ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "Name" artistNameScalarType) (ScalarValue (String "AC/DC") artistNameScalarType)
let query = let query =
albumsQueryRequest albumsQueryRequest
& qrTableRelationships .~ [Data.onlyKeepRelationships [_tdArtistRelationshipName] _tdAlbumsTableRelationships] & qrTableRelationships .~ [Data.onlyKeepRelationships [_tdArtistRelationshipName] _tdAlbumsTableRelationships]
@ -247,7 +247,7 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
it "can filter by comparing against rows in a deeply related table" $ do it "can filter by comparing against rows in a deeply related table" $ do
let where' = let where' =
Exists (RelatedTable _tdAlbumsRelationshipName) . Exists (RelatedTable _tdTracksRelationshipName) . Exists (RelatedTable _tdGenreRelationshipName) $ Exists (RelatedTable _tdAlbumsRelationshipName) . Exists (RelatedTable _tdTracksRelationshipName) . Exists (RelatedTable _tdGenreRelationshipName) $
ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "Name" _tdStringType) (ScalarValue (String "Metal") _tdStringType) ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "Name" genreNameScalarType) (ScalarValue (String "Metal") genreNameScalarType)
let query = let query =
artistsQueryRequest artistsQueryRequest
& qrTableRelationships & qrTableRelationships
@ -285,8 +285,8 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
let where' = let where' =
Exists (RelatedTable _tdAlbumsRelationshipName) $ Exists (RelatedTable _tdAlbumsRelationshipName) $
And And
[ ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "AlbumId" _tdIntType) (ScalarValue (Number 1) _tdIntType), [ ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "AlbumId" albumIdScalarType) (ScalarValue (Number 1) albumIdScalarType),
ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "Title" _tdStringType) (ScalarValue (String "Let There Be Rock") _tdStringType) ApplyBinaryComparisonOperator Equal (_tdCurrentComparisonColumn "Title" albumTitleScalarType) (ScalarValue (String "Let There Be Rock") albumTitleScalarType)
] ]
let query = let query =
artistsQueryRequest artistsQueryRequest
@ -308,12 +308,20 @@ spec TestData {..} sourceName config comparisonCapabilities = describe "Filterin
where where
artistsQueryRequest :: QueryRequest artistsQueryRequest :: QueryRequest
artistsQueryRequest = artistsQueryRequest =
let fields = Data.mkFieldsMap [("ArtistId", _tdColumnField "ArtistId" _tdIntType), ("Name", _tdColumnField "Name" _tdStringType)] let fields = Data.mkFieldsMap [("ArtistId", _tdColumnField _tdArtistsTableName "ArtistId"), ("Name", _tdColumnField _tdArtistsTableName "Name")]
query = Data.emptyQuery & qFields ?~ fields query = Data.emptyQuery & qFields ?~ fields
in QueryRequest _tdArtistsTableName [] query in QueryRequest _tdArtistsTableName [] query
albumsQueryRequest :: QueryRequest albumsQueryRequest :: QueryRequest
albumsQueryRequest = albumsQueryRequest =
let fields = Data.mkFieldsMap [("AlbumId", _tdColumnField "AlbumId" _tdIntType), ("ArtistId", _tdColumnField "ArtistId" _tdIntType), ("Title", _tdColumnField "Title" _tdStringType)] let fields = Data.mkFieldsMap [("AlbumId", _tdColumnField _tdAlbumsTableName "AlbumId"), ("ArtistId", _tdColumnField _tdAlbumsTableName "ArtistId"), ("Title", _tdColumnField _tdAlbumsTableName "Title")]
query = Data.emptyQuery & qFields ?~ fields query = Data.emptyQuery & qFields ?~ fields
in QueryRequest _tdAlbumsTableName [] query in QueryRequest _tdAlbumsTableName [] query
albumIdScalarType = _tdFindColumnScalarType _tdAlbumsTableName "AlbumId"
albumTitleScalarType = _tdFindColumnScalarType _tdAlbumsTableName "Title"
artistIdScalarType = _tdFindColumnScalarType _tdArtistsTableName "ArtistId"
artistNameScalarType = _tdFindColumnScalarType _tdArtistsTableName "Name"
employeeIdScalarType = _tdFindColumnScalarType _tdEmployeesTableName "EmployeeId"
employeeCityScalarType = _tdFindColumnScalarType _tdEmployeesTableName "City"
genreNameScalarType = _tdFindColumnScalarType _tdGenresTableName "Name"

View File

@ -115,7 +115,7 @@ spec TestData {..} sourceName config Capabilities {..} = describe "Order By in Q
_qrAggregates receivedAlbums `jsonShouldBe` Nothing _qrAggregates receivedAlbums `jsonShouldBe` Nothing
it "can order results by a column in a related table where the related table is filtered" $ do it "can order results by a column in a related table where the related table is filtered" $ do
let artistTableFilter = ApplyBinaryComparisonOperator GreaterThan (_tdCurrentComparisonColumn "Name" _tdStringType) (ScalarValue (String "N") _tdStringType) let artistTableFilter = ApplyBinaryComparisonOperator GreaterThan (_tdCurrentComparisonColumn "Name" artistNameScalarType) (ScalarValue (String "N") artistNameScalarType)
let orderByRelations = HashMap.fromList [(_tdArtistRelationshipName, OrderByRelation (Just artistTableFilter) mempty)] let orderByRelations = HashMap.fromList [(_tdArtistRelationshipName, OrderByRelation (Just artistTableFilter) mempty)]
let orderBy = let orderBy =
OrderBy orderByRelations $ OrderBy orderByRelations $
@ -285,7 +285,7 @@ spec TestData {..} sourceName config Capabilities {..} = describe "Order By in Q
_qrAggregates receivedArtists `jsonShouldBe` Nothing _qrAggregates receivedArtists `jsonShouldBe` Nothing
it "can order results by an aggregate of a related table where the related table is filtered" $ do it "can order results by an aggregate of a related table where the related table is filtered" $ do
let albumTableFilter = ApplyBinaryComparisonOperator GreaterThan (_tdCurrentComparisonColumn "Title" _tdStringType) (ScalarValue (String "N") _tdStringType) let albumTableFilter = ApplyBinaryComparisonOperator GreaterThan (_tdCurrentComparisonColumn "Title" albumTitleScalarType) (ScalarValue (String "N") albumTitleScalarType)
let orderByRelations = HashMap.fromList [(_tdAlbumsRelationshipName, OrderByRelation (Just albumTableFilter) mempty)] let orderByRelations = HashMap.fromList [(_tdAlbumsRelationshipName, OrderByRelation (Just albumTableFilter) mempty)]
let orderBy = let orderBy =
OrderBy orderByRelations $ OrderBy orderByRelations $
@ -360,7 +360,7 @@ spec TestData {..} sourceName config Capabilities {..} = describe "Order By in Q
where where
albumsQuery :: Query albumsQuery :: Query
albumsQuery = albumsQuery =
let fields = Data.mkFieldsMap [("AlbumId", _tdColumnField "AlbumId" _tdIntType), ("ArtistId", _tdColumnField "ArtistId" _tdIntType), ("Title", _tdColumnField "Title" _tdStringType)] let fields = Data.mkFieldsMap [("AlbumId", _tdColumnField _tdAlbumsTableName "AlbumId"), ("ArtistId", _tdColumnField _tdAlbumsTableName "ArtistId"), ("Title", _tdColumnField _tdAlbumsTableName "Title")]
in Data.emptyQuery & qFields ?~ fields in Data.emptyQuery & qFields ?~ fields
albumsQueryRequest :: QueryRequest albumsQueryRequest :: QueryRequest
@ -369,13 +369,13 @@ spec TestData {..} sourceName config Capabilities {..} = describe "Order By in Q
artistsQueryRequest :: QueryRequest artistsQueryRequest :: QueryRequest
artistsQueryRequest = artistsQueryRequest =
let fields = Data.mkFieldsMap [("ArtistId", _tdColumnField "ArtistId" _tdIntType), ("Name", _tdColumnField "Name" _tdStringType)] let fields = Data.mkFieldsMap [("ArtistId", _tdColumnField _tdArtistsTableName "ArtistId"), ("Name", _tdColumnField _tdArtistsTableName "Name")]
query = Data.emptyQuery & qFields ?~ fields query = Data.emptyQuery & qFields ?~ fields
in QueryRequest _tdArtistsTableName [] query in QueryRequest _tdArtistsTableName [] query
tracksQuery :: Query tracksQuery :: Query
tracksQuery = tracksQuery =
let fields = Data.mkFieldsMap [("TrackId", _tdColumnField "TrackId" _tdIntType), ("Name", _tdColumnField "Name" _tdStringType)] let fields = Data.mkFieldsMap [("TrackId", _tdColumnField _tdTracksTableName "TrackId"), ("Name", _tdColumnField _tdTracksTableName "Name")]
in Data.emptyQuery & qFields ?~ fields in Data.emptyQuery & qFields ?~ fields
tracksQueryRequest :: QueryRequest tracksQueryRequest :: QueryRequest
@ -384,10 +384,13 @@ spec TestData {..} sourceName config Capabilities {..} = describe "Order By in Q
invoicesQueryRequest :: QueryRequest invoicesQueryRequest :: QueryRequest
invoicesQueryRequest = invoicesQueryRequest =
let fields = Data.mkFieldsMap [("InvoiceId", _tdColumnField "InvoiceId" _tdIntType), ("BillingState", _tdColumnField "BillingState" _tdStringType)] let fields = Data.mkFieldsMap [("InvoiceId", _tdColumnField _tdInvoicesTableName "InvoiceId"), ("BillingState", _tdColumnField _tdInvoicesTableName "BillingState")]
query = Data.emptyQuery & qFields ?~ fields query = Data.emptyQuery & qFields ?~ fields
in QueryRequest _tdInvoicesTableName [] query in QueryRequest _tdInvoicesTableName [] query
albumTitleScalarType = _tdFindColumnScalarType _tdAlbumsTableName "Title"
artistNameScalarType = _tdFindColumnScalarType _tdArtistsTableName "Name"
data NullableOrdered a data NullableOrdered a
= NullFirst = NullFirst
| Some a | Some a

View File

@ -67,7 +67,7 @@ spec TestData {..} sourceName config subqueryComparisonCapabilities = describe "
_qrAggregates receivedArtists `jsonShouldBe` Nothing _qrAggregates receivedArtists `jsonShouldBe` Nothing
it "can filter in object relationships" $ do it "can filter in object relationships" $ do
let artistWhere = ApplyBinaryComparisonOperator GreaterThanOrEqual (_tdCurrentComparisonColumn "Name" _tdStringType) (ScalarValue (String "H") _tdStringType) let artistWhere = ApplyBinaryComparisonOperator GreaterThanOrEqual (_tdCurrentComparisonColumn "Name" artistNameScalarType) (ScalarValue (String "H") artistNameScalarType)
let query = albumsWithArtistQuery (qWhere ?~ artistWhere) let query = albumsWithArtistQuery (qWhere ?~ artistWhere)
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> queryGuarded sourceName config query
@ -85,7 +85,7 @@ spec TestData {..} sourceName config subqueryComparisonCapabilities = describe "
_qrAggregates receivedAlbums `jsonShouldBe` Nothing _qrAggregates receivedAlbums `jsonShouldBe` Nothing
it "can filter in array relationships" $ do it "can filter in array relationships" $ do
let albumsWhere = ApplyBinaryComparisonOperator GreaterThanOrEqual (_tdCurrentComparisonColumn "Title" _tdStringType) (ScalarValue (String "O") _tdStringType) let albumsWhere = ApplyBinaryComparisonOperator GreaterThanOrEqual (_tdCurrentComparisonColumn "Title" albumTitleScalarType) (ScalarValue (String "O") albumTitleScalarType)
let query = artistsWithAlbumsQuery (qWhere ?~ albumsWhere) let query = artistsWithAlbumsQuery (qWhere ?~ albumsWhere)
receivedArtists <- Data.sortResponseRowsBy "ArtistId" <$> queryGuarded sourceName config query receivedArtists <- Data.sortResponseRowsBy "ArtistId" <$> queryGuarded sourceName config query
@ -114,8 +114,8 @@ spec TestData {..} sourceName config subqueryComparisonCapabilities = describe "
Exists (RelatedTable _tdSupportRepRelationshipName) $ Exists (RelatedTable _tdSupportRepRelationshipName) $
ApplyBinaryComparisonOperator ApplyBinaryComparisonOperator
Equal Equal
(_tdCurrentComparisonColumn "Country" _tdStringType) (_tdCurrentComparisonColumn "Country" employeeCountryScalarType)
(AnotherColumn (_tdQueryComparisonColumn "Country" _tdStringType)) (AnotherColumn (_tdQueryComparisonColumn "Country" employeeCountryScalarType))
let query = customersWithSupportRepQuery id & qrQuery . qWhere ?~ where' let query = customersWithSupportRepQuery id & qrQuery . qWhere ?~ where'
receivedCustomers <- Data.sortResponseRowsBy "CustomerId" <$> queryGuarded sourceName config query receivedCustomers <- Data.sortResponseRowsBy "CustomerId" <$> queryGuarded sourceName config query
@ -142,8 +142,8 @@ spec TestData {..} sourceName config subqueryComparisonCapabilities = describe "
Exists (RelatedTable _tdSupportRepForCustomersRelationshipName) $ Exists (RelatedTable _tdSupportRepForCustomersRelationshipName) $
ApplyBinaryComparisonOperator ApplyBinaryComparisonOperator
Equal Equal
(_tdCurrentComparisonColumn "Country" _tdStringType) (_tdCurrentComparisonColumn "Country" employeeCountryScalarType)
(AnotherColumn (_tdQueryComparisonColumn "Country" _tdStringType)) (AnotherColumn (_tdQueryComparisonColumn "Country" employeeCountryScalarType))
let query = employeesWithCustomersQuery id & qrQuery . qWhere ?~ where' let query = employeesWithCustomersQuery id & qrQuery . qWhere ?~ where'
receivedEmployees <- Data.sortResponseRowsBy "EmployeeId" <$> queryGuarded sourceName config query receivedEmployees <- Data.sortResponseRowsBy "EmployeeId" <$> queryGuarded sourceName config query
@ -173,17 +173,17 @@ spec TestData {..} sourceName config subqueryComparisonCapabilities = describe "
And And
[ ( ApplyBinaryComparisonOperator [ ( ApplyBinaryComparisonOperator
GreaterThan GreaterThan
(_tdCurrentComparisonColumn "FirstName" _tdStringType) (_tdCurrentComparisonColumn "FirstName" employeeFirstNameScalarType)
(AnotherColumn (_tdCurrentComparisonColumn "LastName" _tdStringType)) (AnotherColumn (_tdCurrentComparisonColumn "LastName" employeeLastNameScalarType))
), ),
(Not (ApplyUnaryComparisonOperator IsNull (_tdCurrentComparisonColumn "EmployeeId" _tdIntType))) (Not (ApplyUnaryComparisonOperator IsNull (_tdCurrentComparisonColumn "EmployeeId" employeeIdScalarType)))
] ]
let employeesWhere = let employeesWhere =
ApplyBinaryComparisonOperator ApplyBinaryComparisonOperator
GreaterThan GreaterThan
(_tdCurrentComparisonColumn "FirstName" _tdStringType) (_tdCurrentComparisonColumn "FirstName" employeeFirstNameScalarType)
(AnotherColumn (_tdCurrentComparisonColumn "LastName" _tdStringType)) (AnotherColumn (_tdCurrentComparisonColumn "LastName" employeeLastNameScalarType))
let query = customersWithSupportRepQuery (\q -> q & qWhere ?~ employeesWhere) & qrQuery . qWhere ?~ customersWhere let query = customersWithSupportRepQuery (\q -> q & qWhere ?~ employeesWhere) & qrQuery . qWhere ?~ customersWhere
receivedCustomers <- Data.sortResponseRowsBy "CustomerId" <$> queryGuarded sourceName config query receivedCustomers <- Data.sortResponseRowsBy "CustomerId" <$> queryGuarded sourceName config query
@ -211,8 +211,8 @@ spec TestData {..} sourceName config subqueryComparisonCapabilities = describe "
let artistsSubquery = modifySubquery artistsQuery let artistsSubquery = modifySubquery artistsQuery
fields = fields =
Data.mkFieldsMap Data.mkFieldsMap
[ ("AlbumId", _tdColumnField "AlbumId" _tdIntType), [ ("AlbumId", _tdColumnField _tdAlbumsTableName "AlbumId"),
("Title", _tdColumnField "Title" _tdStringType), ("Title", _tdColumnField _tdAlbumsTableName "Title"),
("Artist", RelField $ RelationshipField _tdArtistRelationshipName artistsSubquery) ("Artist", RelField $ RelationshipField _tdArtistRelationshipName artistsSubquery)
] ]
query = albumsQuery & qFields ?~ fields query = albumsQuery & qFields ?~ fields
@ -220,13 +220,13 @@ spec TestData {..} sourceName config subqueryComparisonCapabilities = describe "
artistsWithAlbumsQuery :: (Query -> Query) -> QueryRequest artistsWithAlbumsQuery :: (Query -> Query) -> QueryRequest
artistsWithAlbumsQuery modifySubquery = artistsWithAlbumsQuery modifySubquery =
let albumFields = Data.mkFieldsMap [("AlbumId", _tdColumnField "AlbumId" _tdIntType), ("Title", _tdColumnField "Title" _tdStringType)] let albumFields = Data.mkFieldsMap [("AlbumId", _tdColumnField _tdAlbumsTableName "AlbumId"), ("Title", _tdColumnField _tdAlbumsTableName "Title")]
albumsSort = OrderBy mempty $ _tdOrderByColumn [] "AlbumId" Ascending :| [] albumsSort = OrderBy mempty $ _tdOrderByColumn [] "AlbumId" Ascending :| []
albumsSubquery = albumsQuery & qFields ?~ albumFields & qOrderBy ?~ albumsSort & modifySubquery albumsSubquery = albumsQuery & qFields ?~ albumFields & qOrderBy ?~ albumsSort & modifySubquery
fields = fields =
Data.mkFieldsMap Data.mkFieldsMap
[ ("ArtistId", _tdColumnField "ArtistId" _tdIntType), [ ("ArtistId", _tdColumnField _tdArtistsTableName "ArtistId"),
("Name", _tdColumnField "Name" _tdStringType), ("Name", _tdColumnField _tdArtistsTableName "Name"),
("Albums", RelField $ RelationshipField _tdAlbumsRelationshipName albumsSubquery) ("Albums", RelField $ RelationshipField _tdAlbumsRelationshipName albumsSubquery)
] ]
query = artistsQuery & qFields ?~ fields query = artistsQuery & qFields ?~ fields
@ -257,23 +257,23 @@ spec TestData {..} sourceName config subqueryComparisonCapabilities = describe "
artistsQuery :: Query artistsQuery :: Query
artistsQuery = artistsQuery =
let fields = Data.mkFieldsMap [("ArtistId", _tdColumnField "ArtistId" _tdIntType), ("Name", _tdColumnField "Name" _tdStringType)] let fields = Data.mkFieldsMap [("ArtistId", _tdColumnField _tdArtistsTableName "ArtistId"), ("Name", _tdColumnField _tdArtistsTableName "Name")]
in Data.emptyQuery & qFields ?~ fields in Data.emptyQuery & qFields ?~ fields
albumsQuery :: Query albumsQuery :: Query
albumsQuery = albumsQuery =
let fields = Data.mkFieldsMap [("AlbumId", _tdColumnField "AlbumId" _tdIntType), ("ArtistId", _tdColumnField "ArtistId" _tdIntType), ("Title", _tdColumnField "Title" _tdStringType)] let fields = Data.mkFieldsMap [("AlbumId", _tdColumnField _tdAlbumsTableName "AlbumId"), ("ArtistId", _tdColumnField _tdAlbumsTableName "ArtistId"), ("Title", _tdColumnField _tdAlbumsTableName "Title")]
in Data.emptyQuery & qFields ?~ fields in Data.emptyQuery & qFields ?~ fields
customersQuery :: Query customersQuery :: Query
customersQuery = customersQuery =
let fields = let fields =
Data.mkFieldsMap Data.mkFieldsMap
[ ("CustomerId", _tdColumnField "CustomerId" _tdIntType), [ ("CustomerId", _tdColumnField _tdCustomersTableName "CustomerId"),
("FirstName", _tdColumnField "FirstName" _tdStringType), ("FirstName", _tdColumnField _tdCustomersTableName "FirstName"),
("LastName", _tdColumnField "LastName" _tdStringType), ("LastName", _tdColumnField _tdCustomersTableName "LastName"),
("Country", _tdColumnField "Country" _tdStringType), ("Country", _tdColumnField _tdCustomersTableName "Country"),
("SupportRepId", _tdColumnField "SupportRepId" _tdIntType) ("SupportRepId", _tdColumnField _tdCustomersTableName "SupportRepId")
] ]
in Data.emptyQuery & qFields ?~ fields in Data.emptyQuery & qFields ?~ fields
@ -281,10 +281,10 @@ spec TestData {..} sourceName config subqueryComparisonCapabilities = describe "
employeesQuery = employeesQuery =
let fields = let fields =
Data.mkFieldsMap Data.mkFieldsMap
[ ("EmployeeId", _tdColumnField "EmployeeId" _tdIntType), [ ("EmployeeId", _tdColumnField _tdEmployeesTableName "EmployeeId"),
("FirstName", _tdColumnField "FirstName" _tdStringType), ("FirstName", _tdColumnField _tdEmployeesTableName "FirstName"),
("LastName", _tdColumnField "LastName" _tdStringType), ("LastName", _tdColumnField _tdEmployeesTableName "LastName"),
("Country", _tdColumnField "Country" _tdStringType) ("Country", _tdColumnField _tdEmployeesTableName "Country")
] ]
in Data.emptyQuery & qFields ?~ fields in Data.emptyQuery & qFields ?~ fields
@ -294,3 +294,10 @@ spec TestData {..} sourceName config subqueryComparisonCapabilities = describe "
subqueryRows :: Traversal' FieldValue (HashMap FieldName FieldValue) subqueryRows :: Traversal' FieldValue (HashMap FieldName FieldValue)
subqueryRows = _RelationshipFieldValue . qrRows . _Just . traverse subqueryRows = _RelationshipFieldValue . qrRows . _Just . traverse
albumTitleScalarType = _tdFindColumnScalarType _tdAlbumsTableName "Title"
artistNameScalarType = _tdFindColumnScalarType _tdArtistsTableName "Name"
employeeIdScalarType = _tdFindColumnScalarType _tdEmployeesTableName "EmployeeId"
employeeCountryScalarType = _tdFindColumnScalarType _tdEmployeesTableName "Country"
employeeFirstNameScalarType = _tdFindColumnScalarType _tdEmployeesTableName "FirstName"
employeeLastNameScalarType = _tdFindColumnScalarType _tdEmployeesTableName "LastName"

View File

@ -44,9 +44,23 @@ backendTypeMetadata =
max: DateTime max: DateTime
min: DateTime min: DateTime
graphql_type: String graphql_type: String
number:
aggregate_functions:
max: number
min: number
stddev: number
stddev_pop: number
stddev_samp: number
sum: number
var_pop: number
var_samp: number
variance: number
graphql_type: Float
string: string:
aggregate_functions: aggregate_functions:
longest: string longest: string
max: string
min: string
shortest: string shortest: string
graphql_type: String graphql_type: String
|], |],

View File

@ -51,15 +51,22 @@ backendTypeMetadata =
_lt: string _lt: string
_lte: string _lte: string
_neq: string _neq: string
aggregate_functions:
min: string
max: string
decimal: decimal:
comparison_operators: comparison_operators:
_modulus_is_zero: number _modulus_is_zero: decimal
_eq: number _eq: decimal
_gt: number _gt: decimal
_gte: number _gte: decimal
_lt: number _lt: decimal
_lte: number _lte: decimal
_neq: number _neq: decimal
aggregate_functions:
min: decimal
max: decimal
sum: decimal
number: number:
comparison_operators: comparison_operators:
_modulus_is_zero: number _modulus_is_zero: number
@ -69,6 +76,10 @@ backendTypeMetadata =
_lt: number _lt: number
_lte: number _lte: number
_neq: number _neq: number
aggregate_functions:
min: number
max: number
sum: number
bool: bool:
comparison_operators: comparison_operators:
_and: bool _and: bool

View File

@ -1,3 +1,5 @@
{-# LANGUAGE QuasiQuotes #-}
-- | Mock Agent Warp server backend -- | Mock Agent Warp server backend
module Harness.Backend.DataConnector.Mock.Server module Harness.Backend.DataConnector.Mock.Server
( MockConfig (..), ( MockConfig (..),
@ -15,6 +17,7 @@ import Data.Proxy
import Data.SOP.BasicFunctors qualified as SOP import Data.SOP.BasicFunctors qualified as SOP
import Hasura.Backends.DataConnector.API qualified as API import Hasura.Backends.DataConnector.API qualified as API
import Hasura.Prelude import Hasura.Prelude
import Language.GraphQL.Draft.Syntax.QQ qualified as G
import Network.Wai.Handler.Warp qualified as Warp import Network.Wai.Handler.Warp qualified as Warp
import Servant import Servant
@ -79,15 +82,27 @@ capabilities =
scalarTypesCapabilities = scalarTypesCapabilities =
API.ScalarTypesCapabilities $ API.ScalarTypesCapabilities $
HashMap.fromList HashMap.fromList
[ mkScalarTypeCapability "MyInt" $ Just API.GraphQLInt, [ mkScalarTypeCapability "number" minMaxFunctions $ Just API.GraphQLFloat,
mkScalarTypeCapability "MyFloat" $ Just API.GraphQLFloat, mkScalarTypeCapability "string" minMaxFunctions $ Just API.GraphQLString,
mkScalarTypeCapability "MyString" $ Just API.GraphQLString, mkScalarTypeCapability "MyInt" mempty $ Just API.GraphQLInt,
mkScalarTypeCapability "MyBoolean" $ Just API.GraphQLBoolean, mkScalarTypeCapability "MyFloat" mempty $ Just API.GraphQLFloat,
mkScalarTypeCapability "MyID" $ Just API.GraphQLID, mkScalarTypeCapability "MyString" mempty $ Just API.GraphQLString,
mkScalarTypeCapability "MyAnything" $ Nothing mkScalarTypeCapability "MyBoolean" mempty $ Just API.GraphQLBoolean,
mkScalarTypeCapability "MyID" mempty $ Just API.GraphQLID,
mkScalarTypeCapability "MyAnything" mempty Nothing
] ]
mkScalarTypeCapability :: Text -> Maybe API.GraphQLType -> (API.ScalarType, API.ScalarTypeCapabilities) mkScalarTypeCapability :: Text -> (API.ScalarType -> API.AggregateFunctions) -> Maybe API.GraphQLType -> (API.ScalarType, API.ScalarTypeCapabilities)
mkScalarTypeCapability name gqlType = (API.CustomTy name, mempty {API._stcGraphQLType = gqlType}) mkScalarTypeCapability name aggregateFunctions gqlType =
(scalarType, API.ScalarTypeCapabilities mempty (aggregateFunctions scalarType) gqlType)
where
scalarType = API.ScalarType name
minMaxFunctions :: API.ScalarType -> API.AggregateFunctions
minMaxFunctions resultType =
API.AggregateFunctions $
HashMap.fromList $
(,resultType)
<$> [[G.name|min|], [G.name|max|]]
-- | Stock Schema for a Chinook Agent -- | Stock Schema for a Chinook Agent
schema :: API.SchemaResponse schema :: API.SchemaResponse
@ -100,7 +115,7 @@ schema =
API._tiColumns = API._tiColumns =
[ API.ColumnInfo [ API.ColumnInfo
{ API._ciName = API.ColumnName "ArtistId", { API._ciName = API.ColumnName "ArtistId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "Artist primary key identifier", API._ciDescription = Just "Artist primary key identifier",
API._ciInsertable = True, API._ciInsertable = True,
@ -108,7 +123,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Name", { API._ciName = API.ColumnName "Name",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The name of the artist", API._ciDescription = Just "The name of the artist",
API._ciInsertable = True, API._ciInsertable = True,
@ -128,7 +143,7 @@ schema =
API._tiColumns = API._tiColumns =
[ API.ColumnInfo [ API.ColumnInfo
{ API._ciName = API.ColumnName "AlbumId", { API._ciName = API.ColumnName "AlbumId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "Album primary key identifier", API._ciDescription = Just "Album primary key identifier",
API._ciInsertable = True, API._ciInsertable = True,
@ -136,7 +151,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Title", { API._ciName = API.ColumnName "Title",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "The title of the album", API._ciDescription = Just "The title of the album",
API._ciInsertable = True, API._ciInsertable = True,
@ -144,7 +159,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "ArtistId", { API._ciName = API.ColumnName "ArtistId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "The ID of the artist that created the album", API._ciDescription = Just "The ID of the artist that created the album",
API._ciInsertable = True, API._ciInsertable = True,
@ -166,7 +181,7 @@ schema =
API._tiColumns = API._tiColumns =
[ API.ColumnInfo [ API.ColumnInfo
{ API._ciName = API.ColumnName "CustomerId", { API._ciName = API.ColumnName "CustomerId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "Customer primary key identifier", API._ciDescription = Just "Customer primary key identifier",
API._ciInsertable = True, API._ciInsertable = True,
@ -174,7 +189,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "FirstName", { API._ciName = API.ColumnName "FirstName",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "The customer's first name", API._ciDescription = Just "The customer's first name",
API._ciInsertable = True, API._ciInsertable = True,
@ -182,7 +197,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "LastName", { API._ciName = API.ColumnName "LastName",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "The customer's last name", API._ciDescription = Just "The customer's last name",
API._ciInsertable = True, API._ciInsertable = True,
@ -190,7 +205,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Company", { API._ciName = API.ColumnName "Company",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The customer's company name", API._ciDescription = Just "The customer's company name",
API._ciInsertable = True, API._ciInsertable = True,
@ -198,7 +213,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Address", { API._ciName = API.ColumnName "Address",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The customer's address line (street number, street)", API._ciDescription = Just "The customer's address line (street number, street)",
API._ciInsertable = True, API._ciInsertable = True,
@ -206,7 +221,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "City", { API._ciName = API.ColumnName "City",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The customer's address city", API._ciDescription = Just "The customer's address city",
API._ciInsertable = True, API._ciInsertable = True,
@ -214,7 +229,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "State", { API._ciName = API.ColumnName "State",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The customer's address state", API._ciDescription = Just "The customer's address state",
API._ciInsertable = True, API._ciInsertable = True,
@ -222,7 +237,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Country", { API._ciName = API.ColumnName "Country",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The customer's address country", API._ciDescription = Just "The customer's address country",
API._ciInsertable = True, API._ciInsertable = True,
@ -230,7 +245,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "PostalCode", { API._ciName = API.ColumnName "PostalCode",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The customer's address postal code", API._ciDescription = Just "The customer's address postal code",
API._ciInsertable = True, API._ciInsertable = True,
@ -238,7 +253,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Phone", { API._ciName = API.ColumnName "Phone",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The customer's phone number", API._ciDescription = Just "The customer's phone number",
API._ciInsertable = True, API._ciInsertable = True,
@ -246,7 +261,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Fax", { API._ciName = API.ColumnName "Fax",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The customer's fax number", API._ciDescription = Just "The customer's fax number",
API._ciInsertable = True, API._ciInsertable = True,
@ -254,7 +269,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Email", { API._ciName = API.ColumnName "Email",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "The customer's email address", API._ciDescription = Just "The customer's email address",
API._ciInsertable = True, API._ciInsertable = True,
@ -262,7 +277,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "SupportRepId", { API._ciName = API.ColumnName "SupportRepId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The ID of the Employee who is this customer's support representative", API._ciDescription = Just "The ID of the Employee who is this customer's support representative",
API._ciInsertable = True, API._ciInsertable = True,
@ -284,7 +299,7 @@ schema =
API._tiColumns = API._tiColumns =
[ API.ColumnInfo [ API.ColumnInfo
{ API._ciName = API.ColumnName "EmployeeId", { API._ciName = API.ColumnName "EmployeeId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "Employee primary key identifier", API._ciDescription = Just "Employee primary key identifier",
API._ciInsertable = True, API._ciInsertable = True,
@ -292,7 +307,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "LastName", { API._ciName = API.ColumnName "LastName",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "The employee's last name", API._ciDescription = Just "The employee's last name",
API._ciInsertable = True, API._ciInsertable = True,
@ -300,7 +315,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "FirstName", { API._ciName = API.ColumnName "FirstName",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "The employee's first name", API._ciDescription = Just "The employee's first name",
API._ciInsertable = True, API._ciInsertable = True,
@ -308,7 +323,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Title", { API._ciName = API.ColumnName "Title",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The employee's job title", API._ciDescription = Just "The employee's job title",
API._ciInsertable = True, API._ciInsertable = True,
@ -316,7 +331,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "ReportsTo", { API._ciName = API.ColumnName "ReportsTo",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The employee's report", API._ciDescription = Just "The employee's report",
API._ciInsertable = True, API._ciInsertable = True,
@ -324,7 +339,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "BirthDate", { API._ciName = API.ColumnName "BirthDate",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The employee's birth date", API._ciDescription = Just "The employee's birth date",
API._ciInsertable = True, API._ciInsertable = True,
@ -332,7 +347,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "HireDate", { API._ciName = API.ColumnName "HireDate",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The employee's hire date", API._ciDescription = Just "The employee's hire date",
API._ciInsertable = True, API._ciInsertable = True,
@ -340,7 +355,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Address", { API._ciName = API.ColumnName "Address",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The employee's address line (street number, street)", API._ciDescription = Just "The employee's address line (street number, street)",
API._ciInsertable = True, API._ciInsertable = True,
@ -348,7 +363,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "City", { API._ciName = API.ColumnName "City",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The employee's address city", API._ciDescription = Just "The employee's address city",
API._ciInsertable = True, API._ciInsertable = True,
@ -356,7 +371,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "State", { API._ciName = API.ColumnName "State",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The employee's address state", API._ciDescription = Just "The employee's address state",
API._ciInsertable = True, API._ciInsertable = True,
@ -364,7 +379,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Country", { API._ciName = API.ColumnName "Country",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The employee's address country", API._ciDescription = Just "The employee's address country",
API._ciInsertable = True, API._ciInsertable = True,
@ -372,7 +387,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "PostalCode", { API._ciName = API.ColumnName "PostalCode",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The employee's address postal code", API._ciDescription = Just "The employee's address postal code",
API._ciInsertable = True, API._ciInsertable = True,
@ -380,7 +395,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Phone", { API._ciName = API.ColumnName "Phone",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The employee's phone number", API._ciDescription = Just "The employee's phone number",
API._ciInsertable = True, API._ciInsertable = True,
@ -388,7 +403,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Fax", { API._ciName = API.ColumnName "Fax",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The employee's fax number", API._ciDescription = Just "The employee's fax number",
API._ciInsertable = True, API._ciInsertable = True,
@ -396,7 +411,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Email", { API._ciName = API.ColumnName "Email",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The employee's email address", API._ciDescription = Just "The employee's email address",
API._ciInsertable = True, API._ciInsertable = True,
@ -418,7 +433,7 @@ schema =
API._tiColumns = API._tiColumns =
[ API.ColumnInfo [ API.ColumnInfo
{ API._ciName = API.ColumnName "GenreId", { API._ciName = API.ColumnName "GenreId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "Genre primary key identifier", API._ciDescription = Just "Genre primary key identifier",
API._ciInsertable = True, API._ciInsertable = True,
@ -426,7 +441,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Name", { API._ciName = API.ColumnName "Name",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The name of the genre", API._ciDescription = Just "The name of the genre",
API._ciInsertable = True, API._ciInsertable = True,
@ -446,7 +461,7 @@ schema =
API._tiColumns = API._tiColumns =
[ API.ColumnInfo [ API.ColumnInfo
{ API._ciName = API.ColumnName "InvoiceId", { API._ciName = API.ColumnName "InvoiceId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "Invoice primary key identifier", API._ciDescription = Just "Invoice primary key identifier",
API._ciInsertable = True, API._ciInsertable = True,
@ -454,7 +469,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "CustomerId", { API._ciName = API.ColumnName "CustomerId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "ID of the customer who bought the music", API._ciDescription = Just "ID of the customer who bought the music",
API._ciInsertable = True, API._ciInsertable = True,
@ -462,7 +477,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "InvoiceDate", { API._ciName = API.ColumnName "InvoiceDate",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "Date of the invoice", API._ciDescription = Just "Date of the invoice",
API._ciInsertable = True, API._ciInsertable = True,
@ -470,7 +485,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "BillingAddress", { API._ciName = API.ColumnName "BillingAddress",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The invoice's billing address line (street number, street)", API._ciDescription = Just "The invoice's billing address line (street number, street)",
API._ciInsertable = True, API._ciInsertable = True,
@ -478,7 +493,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "BillingCity", { API._ciName = API.ColumnName "BillingCity",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The invoice's billing address city", API._ciDescription = Just "The invoice's billing address city",
API._ciInsertable = True, API._ciInsertable = True,
@ -486,7 +501,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "BillingState", { API._ciName = API.ColumnName "BillingState",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The invoice's billing address state", API._ciDescription = Just "The invoice's billing address state",
API._ciInsertable = True, API._ciInsertable = True,
@ -494,7 +509,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "BillingCountry", { API._ciName = API.ColumnName "BillingCountry",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The invoice's billing address country", API._ciDescription = Just "The invoice's billing address country",
API._ciInsertable = True, API._ciInsertable = True,
@ -502,7 +517,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "BillingPostalCode", { API._ciName = API.ColumnName "BillingPostalCode",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The invoice's billing address postal code", API._ciDescription = Just "The invoice's billing address postal code",
API._ciInsertable = True, API._ciInsertable = True,
@ -510,7 +525,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Total", { API._ciName = API.ColumnName "Total",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "The total amount due on the invoice", API._ciDescription = Just "The total amount due on the invoice",
API._ciInsertable = True, API._ciInsertable = True,
@ -533,7 +548,7 @@ schema =
API._tiColumns = API._tiColumns =
[ API.ColumnInfo [ API.ColumnInfo
{ API._ciName = API.ColumnName "InvoiceLineId", { API._ciName = API.ColumnName "InvoiceLineId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "Invoice Line primary key identifier", API._ciDescription = Just "Invoice Line primary key identifier",
API._ciInsertable = True, API._ciInsertable = True,
@ -541,7 +556,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "InvoiceId", { API._ciName = API.ColumnName "InvoiceId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "ID of the invoice the line belongs to", API._ciDescription = Just "ID of the invoice the line belongs to",
API._ciInsertable = True, API._ciInsertable = True,
@ -549,7 +564,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "TrackId", { API._ciName = API.ColumnName "TrackId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "ID of the music track being purchased", API._ciDescription = Just "ID of the music track being purchased",
API._ciInsertable = True, API._ciInsertable = True,
@ -557,7 +572,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "UnitPrice", { API._ciName = API.ColumnName "UnitPrice",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "Price of each individual track unit", API._ciDescription = Just "Price of each individual track unit",
API._ciInsertable = True, API._ciInsertable = True,
@ -565,7 +580,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Quantity", { API._ciName = API.ColumnName "Quantity",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "Quantity of the track purchased", API._ciDescription = Just "Quantity of the track purchased",
API._ciInsertable = True, API._ciInsertable = True,
@ -590,7 +605,7 @@ schema =
API._tiColumns = API._tiColumns =
[ API.ColumnInfo [ API.ColumnInfo
{ API._ciName = API.ColumnName "MediaTypeId", { API._ciName = API.ColumnName "MediaTypeId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "Media Type primary key identifier", API._ciDescription = Just "Media Type primary key identifier",
API._ciInsertable = True, API._ciInsertable = True,
@ -598,7 +613,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Name", { API._ciName = API.ColumnName "Name",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The name of the media type format", API._ciDescription = Just "The name of the media type format",
API._ciInsertable = True, API._ciInsertable = True,
@ -618,7 +633,7 @@ schema =
API._tiColumns = API._tiColumns =
[ API.ColumnInfo [ API.ColumnInfo
{ API._ciName = API.ColumnName "TrackId", { API._ciName = API.ColumnName "TrackId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "The ID of the track", API._ciDescription = Just "The ID of the track",
API._ciInsertable = True, API._ciInsertable = True,
@ -626,7 +641,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Name", { API._ciName = API.ColumnName "Name",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "The name of the track", API._ciDescription = Just "The name of the track",
API._ciInsertable = True, API._ciInsertable = True,
@ -634,7 +649,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "AlbumId", { API._ciName = API.ColumnName "AlbumId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The ID of the album the track belongs to", API._ciDescription = Just "The ID of the album the track belongs to",
API._ciInsertable = True, API._ciInsertable = True,
@ -642,7 +657,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "MediaTypeId", { API._ciName = API.ColumnName "MediaTypeId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "The ID of the media type the track is encoded with", API._ciDescription = Just "The ID of the media type the track is encoded with",
API._ciInsertable = True, API._ciInsertable = True,
@ -650,7 +665,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "GenreId", { API._ciName = API.ColumnName "GenreId",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The ID of the genre of the track", API._ciDescription = Just "The ID of the genre of the track",
API._ciInsertable = True, API._ciInsertable = True,
@ -658,7 +673,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Composer", { API._ciName = API.ColumnName "Composer",
API._ciType = API.StringTy, API._ciType = API.ScalarType "string",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The name of the composer of the track", API._ciDescription = Just "The name of the composer of the track",
API._ciInsertable = True, API._ciInsertable = True,
@ -666,7 +681,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Milliseconds", { API._ciName = API.ColumnName "Milliseconds",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "The length of the track in milliseconds", API._ciDescription = Just "The length of the track in milliseconds",
API._ciInsertable = True, API._ciInsertable = True,
@ -674,7 +689,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "Bytes", { API._ciName = API.ColumnName "Bytes",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = True, API._ciNullable = True,
API._ciDescription = Just "The size of the track in bytes", API._ciDescription = Just "The size of the track in bytes",
API._ciInsertable = True, API._ciInsertable = True,
@ -682,7 +697,7 @@ schema =
}, },
API.ColumnInfo API.ColumnInfo
{ API._ciName = API.ColumnName "UnitPrice", { API._ciName = API.ColumnName "UnitPrice",
API._ciType = API.NumberTy, API._ciType = API.ScalarType "number",
API._ciNullable = False, API._ciNullable = False,
API._ciDescription = Just "The price of the track", API._ciDescription = Just "The price of the track",
API._ciInsertable = True, API._ciInsertable = True,
@ -706,12 +721,12 @@ schema =
{ API._tiName = mkTableName "MyCustomScalarsTable", { API._tiName = mkTableName "MyCustomScalarsTable",
API._tiType = API.Table, API._tiType = API.Table,
API._tiColumns = API._tiColumns =
[ API.ColumnInfo (API.ColumnName "MyIntColumn") (API.CustomTy "MyInt") False Nothing True True, [ API.ColumnInfo (API.ColumnName "MyIntColumn") (API.ScalarType "MyInt") False Nothing True True,
API.ColumnInfo (API.ColumnName "MyFloatColumn") (API.CustomTy "MyFloat") False Nothing True True, API.ColumnInfo (API.ColumnName "MyFloatColumn") (API.ScalarType "MyFloat") False Nothing True True,
API.ColumnInfo (API.ColumnName "MyStringColumn") (API.CustomTy "MyString") False Nothing True True, API.ColumnInfo (API.ColumnName "MyStringColumn") (API.ScalarType "MyString") False Nothing True True,
API.ColumnInfo (API.ColumnName "MyBooleanColumn") (API.CustomTy "MyBoolean") False Nothing True True, API.ColumnInfo (API.ColumnName "MyBooleanColumn") (API.ScalarType "MyBoolean") False Nothing True True,
API.ColumnInfo (API.ColumnName "MyIDColumn") (API.CustomTy "MyID") False Nothing True True, API.ColumnInfo (API.ColumnName "MyIDColumn") (API.ScalarType "MyID") False Nothing True True,
API.ColumnInfo (API.ColumnName "MyAnythingColumn") (API.CustomTy "MyAnything") False Nothing True True API.ColumnInfo (API.ColumnName "MyAnythingColumn") (API.ScalarType "MyAnything") False Nothing True True
], ],
API._tiPrimaryKey = [], API._tiPrimaryKey = [],
API._tiDescription = Nothing, API._tiDescription = Nothing,

View File

@ -19,6 +19,7 @@ library
, ekg-core , ekg-core
, fast-logger , fast-logger
, graphql-engine , graphql-engine
, graphql-parser
, haskell-src-meta , haskell-src-meta
, hasura-prelude , hasura-prelude
, hedgehog , hedgehog

View File

@ -82,15 +82,10 @@ instance Backend 'DataConnector where
type HealthCheckTest 'DataConnector = Void type HealthCheckTest 'DataConnector = Void
isComparableType :: ScalarType 'DataConnector -> Bool isComparableType :: ScalarType 'DataConnector -> Bool
isComparableType = \case isComparableType = const False
DC.NumberTy -> True
DC.StringTy -> True
DC.BoolTy -> False
DC.CustomTy _ _ -> False
isNumType :: ScalarType 'DataConnector -> Bool isNumType :: ScalarType 'DataConnector -> Bool
isNumType DC.NumberTy = True isNumType = const False
isNumType _ = False
getCustomAggregateOperators :: DC.SourceConfig -> HashMap G.Name (HashMap DC.ScalarType DC.ScalarType) getCustomAggregateOperators :: DC.SourceConfig -> HashMap G.Name (HashMap DC.ScalarType DC.ScalarType)
getCustomAggregateOperators DC.SourceConfig {..} = getCustomAggregateOperators DC.SourceConfig {..} =
@ -180,10 +175,7 @@ parseValue :: DC.ScalarType -> J.Value -> J.Parser J.Value
parseValue type' val = parseValue type' val =
case (type', val) of case (type', val) of
(_, J.Null) -> pure J.Null (_, J.Null) -> pure J.Null
(DC.StringTy, value) -> J.String <$> J.parseJSON value (DC.ScalarType _ graphQLType, value) -> case graphQLType of
(DC.BoolTy, value) -> J.Bool <$> J.parseJSON value
(DC.NumberTy, value) -> J.Number <$> J.parseJSON value
(DC.CustomTy _ graphQLType, value) -> case graphQLType of
Nothing -> pure value Nothing -> pure value
Just DC.GraphQLInt -> (J.Number . fromIntegral) <$> J.parseJSON @Int value Just DC.GraphQLInt -> (J.Number . fromIntegral) <$> J.parseJSON @Int value
Just DC.GraphQLFloat -> (J.Number . fromFloatDigits) <$> J.parseJSON @Double value Just DC.GraphQLFloat -> (J.Number . fromFloatDigits) <$> J.parseJSON @Double value
@ -196,4 +188,7 @@ parseValue type' val =
columnTypeToScalarType :: ColumnType 'DataConnector -> DC.ScalarType columnTypeToScalarType :: ColumnType 'DataConnector -> DC.ScalarType
columnTypeToScalarType = \case columnTypeToScalarType = \case
ColumnScalar scalarType -> scalarType ColumnScalar scalarType -> scalarType
ColumnEnumReference _ -> DC.StringTy -- Data connectors does not yet support enum tables.
-- If/when we add this support, we probably want to
-- embed the enum scalar type name within the `EnumReference` record type
ColumnEnumReference _ -> error "columnTypeToScalarType got enum"

View File

@ -64,7 +64,11 @@ instance BackendMetadata 'DataConnector where
parseBoolExpOperations = parseBoolExpOperations' parseBoolExpOperations = parseBoolExpOperations'
parseCollectableType = parseCollectableType' parseCollectableType = parseCollectableType'
buildComputedFieldInfo = error "buildComputedFieldInfo: not implemented for the Data Connector backend." buildComputedFieldInfo = error "buildComputedFieldInfo: not implemented for the Data Connector backend."
-- If/when we implement enums for Data Connector backend, we will also need to fix columnTypeToScalarType function
-- in Hasura.Backends.DataConnector.Adapter.Backend. See note there for more information.
fetchAndValidateEnumValues = error "fetchAndValidateEnumValues: not implemented for the Data Connector backend." fetchAndValidateEnumValues = error "fetchAndValidateEnumValues: not implemented for the Data Connector backend."
buildFunctionInfo = error "buildFunctionInfo: not implemented for the Data Connector backend." buildFunctionInfo = error "buildFunctionInfo: not implemented for the Data Connector backend."
updateColumnInEventTrigger = error "updateColumnInEventTrigger: not implemented for the Data Connector backend." updateColumnInEventTrigger = error "updateColumnInEventTrigger: not implemented for the Data Connector backend."
postDropSourceHook _sourceConfig _tableTriggerMap = pure () postDropSourceHook _sourceConfig _tableTriggerMap = pure ()

View File

@ -76,7 +76,13 @@ instance BackendSchema 'DataConnector where
comparisonExps = comparisonExps' comparisonExps = comparisonExps'
countTypeInput = countTypeInput' countTypeInput = countTypeInput'
aggregateOrderByCountType = DC.NumberTy
-- aggregateOrderByCountType is only used when generating Relay schemas, and Data Connector backends do not yet support Relay
-- If/when we want to support this we would need to add something to Capabilities to tell HGE what (integer-like) scalar
-- type should be used to represent the result of a count aggregate in relay order-by queries.
aggregateOrderByCountType =
error "aggregateOrderByCountType: not implemented for Data Connector backend"
computedField = computedField =
error "computedField: not implemented for the Data Connector backend." error "computedField: not implemented for the Data Connector backend."
@ -173,24 +179,20 @@ columnParser' ::
GQL.Nullability -> GQL.Nullability ->
GS.C.SchemaT r m (P.Parser 'P.Both n (IR.ValueWithOrigin (RQL.ColumnValue 'DataConnector))) GS.C.SchemaT r m (P.Parser 'P.Both n (IR.ValueWithOrigin (RQL.ColumnValue 'DataConnector)))
columnParser' columnType nullability = case columnType of columnParser' columnType nullability = case columnType of
RQL.ColumnScalar scalarType -> RQL.ColumnScalar scalarType@(DC.ScalarType name graphQLType) ->
P.memoizeOn 'columnParser' (scalarType, nullability) $ P.memoizeOn 'columnParser' (scalarType, nullability) $
GS.C.peelWithOrigin . fmap (RQL.ColumnValue columnType) . possiblyNullable' scalarType nullability GS.C.peelWithOrigin . fmap (RQL.ColumnValue columnType) . possiblyNullable' scalarType nullability
<$> case scalarType of <$> do
DC.StringTy -> pure $ J.String <$> P.string gqlName <-
DC.NumberTy -> pure $ J.Number <$> P.scientific GQL.mkName name
DC.BoolTy -> pure $ J.Bool <$> P.boolean `onNothing` throw400 ValidationFailed ("The column type name " <> name <<> " is not a valid GraphQL name")
DC.CustomTy name graphQLType -> do pure $ case graphQLType of
gqlName <- Nothing -> P.jsonScalar gqlName (Just "A custom scalar type")
GQL.mkName name Just DC.GraphQLInt -> (J.Number . fromIntegral) <$> P.namedInt gqlName
`onNothing` throw400 ValidationFailed ("The column type name " <> name <<> " is not a valid GraphQL name") Just DC.GraphQLFloat -> (J.Number . fromFloatDigits) <$> P.namedFloat gqlName
pure $ case graphQLType of Just DC.GraphQLString -> J.String <$> P.namedString gqlName
Nothing -> P.jsonScalar gqlName (Just "A custom scalar type") Just DC.GraphQLBoolean -> J.Bool <$> P.namedBoolean gqlName
Just DC.GraphQLInt -> (J.Number . fromIntegral) <$> P.namedInt gqlName Just DC.GraphQLID -> J.String <$> P.namedIdentifier gqlName
Just DC.GraphQLFloat -> (J.Number . fromFloatDigits) <$> P.namedFloat gqlName
Just DC.GraphQLString -> J.String <$> P.namedString gqlName
Just DC.GraphQLBoolean -> J.Bool <$> P.namedBoolean gqlName
Just DC.GraphQLID -> J.String <$> P.namedIdentifier gqlName
RQL.ColumnEnumReference (RQL.EnumReference tableName enumValues customTableName) -> RQL.ColumnEnumReference (RQL.EnumReference tableName enumValues customTableName) ->
case nonEmpty (Map.toList enumValues) of case nonEmpty (Map.toList enumValues) of
Just enumValuesList -> Just enumValuesList ->

View File

@ -48,7 +48,6 @@ import Data.Text.NonEmpty (NonEmptyText, mkNonEmptyTextUnsafe)
import Hasura.Backends.DataConnector.API qualified as API import Hasura.Backends.DataConnector.API qualified as API
import Hasura.Base.ErrorValue qualified as ErrorValue import Hasura.Base.ErrorValue qualified as ErrorValue
import Hasura.Base.ToErrorValue (ToErrorValue (..)) import Hasura.Base.ToErrorValue (ToErrorValue (..))
import Hasura.GraphQL.Parser.Name.TypeSystem (_Boolean, _Float, _Int, _String)
import Hasura.Metadata.DTO.Placeholder (placeholderCodecViaJSON) import Hasura.Metadata.DTO.Placeholder (placeholderCodecViaJSON)
import Hasura.Prelude import Hasura.Prelude
import Language.GraphQL.Draft.Syntax qualified as GQL import Language.GraphQL.Draft.Syntax qualified as GQL
@ -329,43 +328,28 @@ instance Witch.From OrderDirection API.OrderDirection where
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
data ScalarType data ScalarType
= StringTy = ScalarType Text (Maybe API.GraphQLType)
| NumberTy
| BoolTy
| CustomTy Text (Maybe API.GraphQLType)
deriving stock (Eq, Generic, Ord, Show) deriving stock (Eq, Generic, Ord, Show)
deriving anyclass (FromJSON, FromJSONKey, Hashable, NFData, ToJSON, ToJSONKey) deriving anyclass (FromJSON, FromJSONKey, Hashable, NFData, ToJSON, ToJSONKey)
instance ToTxt ScalarType where instance ToTxt ScalarType where
toTxt = tshow toTxt (ScalarType name _) = name
instance ToErrorValue ScalarType where instance ToErrorValue ScalarType where
toErrorValue = ErrorValue.squote . tshow toErrorValue = ErrorValue.squote . toTxt
instance Witch.From ScalarType API.ScalarType where instance Witch.From ScalarType API.ScalarType where
from = \case from (ScalarType name _) = API.ScalarType name
StringTy -> API.StringTy
NumberTy -> API.NumberTy
BoolTy -> API.BoolTy
CustomTy name _ -> API.CustomTy name
mkScalarType :: API.Capabilities -> API.ScalarType -> ScalarType mkScalarType :: API.Capabilities -> API.ScalarType -> ScalarType
mkScalarType API.Capabilities {..} apiType = case apiType of mkScalarType API.Capabilities {..} apiType@(API.ScalarType name) =
API.StringTy -> StringTy ScalarType name graphQLType
API.NumberTy -> NumberTy where
API.BoolTy -> BoolTy graphQLType = HashMap.lookup apiType (API.unScalarTypesCapabilities _cScalarTypes) >>= API._stcGraphQLType
API.CustomTy name -> CustomTy name graphQLType
where
graphQLType = HashMap.lookup apiType (API.unScalarTypesCapabilities _cScalarTypes) >>= API._stcGraphQLType
fromGQLType :: GQL.Name -> API.ScalarType fromGQLType :: GQL.Name -> API.ScalarType
fromGQLType typeName = fromGQLType typeName =
if API.ScalarType $ GQL.unName typeName
| typeName == _String -> API.StringTy
| typeName == _Int -> API.NumberTy
| typeName == _Float -> API.NumberTy
| typeName == _Boolean -> API.BoolTy
| otherwise -> API.CustomTy $ GQL.unName typeName
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View File

@ -436,28 +436,15 @@ mkPlan session (SourceConfig {}) ir = do
parseSessionVariable :: SessionVariable -> SessionVarType 'DataConnector -> Text -> m Literal parseSessionVariable :: SessionVariable -> SessionVarType 'DataConnector -> Text -> m Literal
parseSessionVariable varName varType varValue = do parseSessionVariable varName varType varValue = do
case varType of case varType of
CollectableTypeScalar scalarType -> CollectableTypeScalar scalarType@(ScalarType customTypeName _) ->
case scalarType of parseCustomValue scalarType (customTypeName <> " JSON value")
-- Special case for string: uses literal session variable value rather than trying to parse a JSON string CollectableTypeArray scalarType@(ScalarType customTypeName _) ->
StringTy -> pure . ValueLiteral scalarType $ J.String varValue parseCustomArray scalarType ("JSON array of " <> customTypeName <> " JSON values")
NumberTy -> parseBuiltinValue (ValueLiteral scalarType . J.Number) "number value"
BoolTy -> parseBuiltinValue (ValueLiteral scalarType . J.Bool) "boolean value"
CustomTy customTypeName _ -> parseCustomValue scalarType (customTypeName <> " JSON value")
CollectableTypeArray scalarType ->
case scalarType of
StringTy -> parseBuiltinValue (ArrayLiteral scalarType . fmap J.String) "JSON array of strings"
NumberTy -> parseBuiltinValue (ArrayLiteral scalarType . fmap J.Number) "JSON array of numbers"
BoolTy -> parseBuiltinValue (ArrayLiteral scalarType . fmap J.Bool) "JSON array of booleans"
CustomTy customTypeName _ -> parseCustomArray scalarType ("JSON array of " <> customTypeName <> " JSON values")
where where
parseBuiltinValue :: J.FromJSON a => (a -> Literal) -> Text -> m Literal
parseBuiltinValue =
parseValue' J.parseJSON
parseCustomValue :: ScalarType -> Text -> m Literal parseCustomValue :: ScalarType -> Text -> m Literal
parseCustomValue scalarType description = parseCustomValue scalarType description =
case scalarType of case scalarType of
CustomTy _ (Just GraphQLString) -> ScalarType _ (Just GraphQLString) ->
-- Special case for string: uses literal session variable value rather than trying to parse a JSON string -- Special case for string: uses literal session variable value rather than trying to parse a JSON string
pure . ValueLiteral scalarType $ J.String varValue pure . ValueLiteral scalarType $ J.String varValue
_ -> _ ->

View File

@ -27,11 +27,11 @@ spec = do
(CapabilitiesResponse (defaultCapabilities {_cRelationships = Just RelationshipCapabilities {}}) emptyConfigSchemaResponse Nothing Nothing) (CapabilitiesResponse (defaultCapabilities {_cRelationships = Just RelationshipCapabilities {}}) emptyConfigSchemaResponse Nothing Nothing)
[aesonQQ|{"capabilities": {"relationships": {}}, "config_schemas": {"config_schema": {}, "other_schemas": {}}}|] [aesonQQ|{"capabilities": {"relationships": {}}, "config_schemas": {"config_schema": {}, "other_schemas": {}}}|]
describe "ScalarTypesCapabilities" $ do describe "ScalarTypesCapabilities" $ do
testToFromJSONToSchema (ScalarTypesCapabilities (HashMap.singleton StringTy (ScalarTypeCapabilities mempty mempty Nothing))) [aesonQQ|{"string": {}}|] testToFromJSONToSchema (ScalarTypesCapabilities (HashMap.singleton (ScalarType "string") (ScalarTypeCapabilities mempty mempty Nothing))) [aesonQQ|{"string": {}}|]
jsonOpenApiProperties genScalarTypesCapabilities jsonOpenApiProperties genScalarTypesCapabilities
describe "ScalarTypeCapabilities" $ do describe "ScalarTypeCapabilities" $ do
let comparisonOperators = ComparisonOperators $ HashMap.fromList [([G.name|same_day_as|], CustomTy "DateTime")] let comparisonOperators = ComparisonOperators $ HashMap.fromList [([G.name|same_day_as|], ScalarType "DateTime")]
let aggregateFunctions = AggregateFunctions $ HashMap.fromList [([G.name|max|], CustomTy "DateTime")] let aggregateFunctions = AggregateFunctions $ HashMap.fromList [([G.name|max|], ScalarType "DateTime")]
let graphQLType = Just GraphQLString let graphQLType = Just GraphQLString
let json = let json =
[aesonQQ|{ [aesonQQ|{

View File

@ -21,7 +21,7 @@ spec = do
describe "ColumnInfo" $ do describe "ColumnInfo" $ do
describe "minimal" $ describe "minimal" $
testFromJSON testFromJSON
(ColumnInfo (ColumnName "my_column_name") StringTy False Nothing False False) (ColumnInfo (ColumnName "my_column_name") (ScalarType "string") False Nothing False False)
[aesonQQ| [aesonQQ|
{ "name": "my_column_name", { "name": "my_column_name",
"type": "string", "type": "string",
@ -30,7 +30,7 @@ spec = do
|] |]
describe "non-minimal" $ describe "non-minimal" $
testToFromJSONToSchema testToFromJSONToSchema
(ColumnInfo (ColumnName "my_column_name") NumberTy True (Just "My column description") True True) (ColumnInfo (ColumnName "my_column_name") (ScalarType "number") True (Just "My column description") True True)
[aesonQQ| [aesonQQ|
{ "name": "my_column_name", { "name": "my_column_name",
"type": "number", "type": "number",

View File

@ -68,7 +68,7 @@ spec = do
describe "ComparisonColumn" $ do describe "ComparisonColumn" $ do
testToFromJSONToSchema testToFromJSONToSchema
(ComparisonColumn QueryTable (ColumnName "column_name") StringTy) (ComparisonColumn QueryTable (ColumnName "column_name") (ScalarType "string"))
[aesonQQ|{"path": ["$"], "name": "column_name", "column_type": "string"}|] [aesonQQ|{"path": ["$"], "name": "column_name", "column_type": "string"}|]
jsonOpenApiProperties genComparisonColumn jsonOpenApiProperties genComparisonColumn
@ -83,11 +83,11 @@ spec = do
describe "ComparisonValue" $ do describe "ComparisonValue" $ do
describe "AnotherColumn" $ describe "AnotherColumn" $
testToFromJSONToSchema testToFromJSONToSchema
(AnotherColumn $ ComparisonColumn CurrentTable (ColumnName "my_column_name") StringTy) (AnotherColumn $ ComparisonColumn CurrentTable (ColumnName "my_column_name") (ScalarType "string"))
[aesonQQ|{"type": "column", "column": {"name": "my_column_name", "column_type": "string"}}|] [aesonQQ|{"type": "column", "column": {"name": "my_column_name", "column_type": "string"}}|]
describe "ScalarValue" $ describe "ScalarValue" $
testToFromJSONToSchema testToFromJSONToSchema
(ScalarValue (String "scalar value") StringTy) (ScalarValue (String "scalar value") (ScalarType "string"))
[aesonQQ|{"type": "scalar", "value": "scalar value", "value_type": "string"}|] [aesonQQ|{"type": "scalar", "value": "scalar value", "value_type": "string"}|]
jsonOpenApiProperties genComparisonValue jsonOpenApiProperties genComparisonValue
@ -112,8 +112,8 @@ spec = do
jsonOpenApiProperties genExistsInTable jsonOpenApiProperties genExistsInTable
describe "Expression" $ do describe "Expression" $ do
let comparisonColumn = ComparisonColumn CurrentTable (ColumnName "my_column_name") StringTy let comparisonColumn = ComparisonColumn CurrentTable (ColumnName "my_column_name") (ScalarType "string")
let scalarValue = ScalarValue (String "scalar value") StringTy let scalarValue = ScalarValue (String "scalar value") (ScalarType "string")
let scalarValues = [String "scalar value"] let scalarValues = [String "scalar value"]
let unaryComparisonExpression = ApplyUnaryComparisonOperator IsNull comparisonColumn let unaryComparisonExpression = ApplyUnaryComparisonOperator IsNull comparisonColumn
@ -195,7 +195,7 @@ spec = do
describe "BinaryArrayComparisonOperator" $ do describe "BinaryArrayComparisonOperator" $ do
testToFromJSONToSchema testToFromJSONToSchema
(ApplyBinaryArrayComparisonOperator In comparisonColumn scalarValues StringTy) (ApplyBinaryArrayComparisonOperator In comparisonColumn scalarValues (ScalarType "string"))
[aesonQQ| [aesonQQ|
{ {
"type": "binary_arr_op", "type": "binary_arr_op",

View File

@ -46,7 +46,7 @@ spec = do
describe "InsertFieldSchema" $ do describe "InsertFieldSchema" $ do
describe "ColumnInsert" $ do describe "ColumnInsert" $ do
testToFromJSONToSchema testToFromJSONToSchema
(ColumnInsert (ColumnInsertSchema (ColumnName "my_column") NumberTy)) (ColumnInsert (ColumnInsertSchema (ColumnName "my_column") (ScalarType "number")))
[aesonQQ| [aesonQQ|
{ "type": "column", { "type": "column",
"column": "my_column", "column": "my_column",
@ -70,7 +70,7 @@ spec = do
jsonOpenApiProperties genInsertFieldSchema jsonOpenApiProperties genInsertFieldSchema
describe "MutationOperation" $ do describe "MutationOperation" $ do
let returningFields = [(FieldName "field", ColumnField (ColumnName "my_column") StringTy)] let returningFields = [(FieldName "field", ColumnField (ColumnName "my_column") (ScalarType "string"))]
describe "InsertOperation" $ do describe "InsertOperation" $ do
testToFromJSONToSchema testToFromJSONToSchema
(InsertOperation (InsertMutationOperation (TableName ["my_table"]) [] returningFields)) (InsertOperation (InsertMutationOperation (TableName ["my_table"]) [] returningFields))
@ -172,7 +172,7 @@ spec = do
describe "RowUpdate" $ do describe "RowUpdate" $ do
describe "IncrementColumnRowUpdate" $ describe "IncrementColumnRowUpdate" $
testToFromJSONToSchema testToFromJSONToSchema
(IncrementColumn $ RowColumnValue (ColumnName "my_column") (Number 10) NumberTy) (IncrementColumn $ RowColumnValue (ColumnName "my_column") (Number 10) (ScalarType "number"))
[aesonQQ| [aesonQQ|
{ "type": "increment", { "type": "increment",
"column": "my_column", "column": "my_column",
@ -181,7 +181,7 @@ spec = do
|] |]
describe "SetColumnRowUpdate" $ describe "SetColumnRowUpdate" $
testToFromJSONToSchema testToFromJSONToSchema
(SetColumn $ RowColumnValue (ColumnName "my_column") (Number 10) NumberTy) (SetColumn $ RowColumnValue (ColumnName "my_column") (Number 10) (ScalarType "number"))
[aesonQQ| [aesonQQ|
{ "type": "set", { "type": "set",
"column": "my_column", "column": "my_column",
@ -192,7 +192,7 @@ spec = do
describe "RowColumnValue" $ do describe "RowColumnValue" $ do
testToFromJSONToSchema testToFromJSONToSchema
(RowColumnValue (ColumnName "my_column") (String "a value") StringTy) (RowColumnValue (ColumnName "my_column") (String "a value") (ScalarType "string"))
[aesonQQ| [aesonQQ|
{ "column": "my_column", { "column": "my_column",
"value": "a value", "value": "a value",

View File

@ -33,7 +33,7 @@ spec = do
describe "Field" $ do describe "Field" $ do
describe "ColumnField" $ describe "ColumnField" $
testToFromJSONToSchema testToFromJSONToSchema
(ColumnField (ColumnName "my_column_name") StringTy) (ColumnField (ColumnName "my_column_name") (ScalarType "string"))
[aesonQQ| [aesonQQ|
{ "type": "column", { "type": "column",
"column": "my_column_name", "column": "my_column_name",
@ -55,7 +55,7 @@ spec = do
describe "Query" $ do describe "Query" $ do
let query = let query =
Query Query
{ _qFields = Just $ HashMap.fromList [(FieldName "my_field_alias", ColumnField (ColumnName "my_field_name") StringTy)], { _qFields = Just $ HashMap.fromList [(FieldName "my_field_alias", ColumnField (ColumnName "my_field_name") (ScalarType "string"))],
_qAggregates = Just $ HashMap.fromList [(FieldName "my_aggregate", StarCount)], _qAggregates = Just $ HashMap.fromList [(FieldName "my_aggregate", StarCount)],
_qLimit = Just 10, _qLimit = Just 10,
_qOffset = Just 20, _qOffset = Just 20,

View File

@ -7,29 +7,16 @@ import Hasura.Backends.DataConnector.API.V0.Scalar
import Hasura.Generator.Common (defaultRange, genArbitraryAlphaNumTextExcluding) import Hasura.Generator.Common (defaultRange, genArbitraryAlphaNumTextExcluding)
import Hasura.Prelude import Hasura.Prelude
import Hedgehog import Hedgehog
import Hedgehog.Gen qualified as Gen
import Test.Aeson.Utils import Test.Aeson.Utils
import Test.Hspec import Test.Hspec
spec :: Spec spec :: Spec
spec = do spec = do
describe "ScalarType" $ do describe "ScalarType" $ do
describe "StringTy" $ testToFromJSONToSchema (ScalarType "foo") [aesonQQ|"foo"|]
testToFromJSONToSchema StringTy [aesonQQ|"string"|]
describe "NumberTy" $
testToFromJSONToSchema NumberTy [aesonQQ|"number"|]
describe "BoolTy" $
testToFromJSONToSchema BoolTy [aesonQQ|"bool"|]
describe "CustomTy" $
testToFromJSONToSchema (CustomTy "foo") [aesonQQ|"foo"|]
jsonOpenApiProperties genScalarType jsonOpenApiProperties genScalarType
genScalarType :: (MonadGen m, GenBase m ~ Identity) => m ScalarType genScalarType :: (MonadGen m, GenBase m ~ Identity) => m ScalarType
genScalarType = genScalarType =
Gen.choice ScalarType
[ pure StringTy, <$> genArbitraryAlphaNumTextExcluding ["string", "number", "bool"] defaultRange
pure NumberTy,
pure BoolTy,
CustomTy
<$> genArbitraryAlphaNumTextExcluding ["string", "number", "bool"] defaultRange
]

View File

@ -34,7 +34,7 @@ spec = do
( TableInfo ( TableInfo
(TableName ["my_table_name"]) (TableName ["my_table_name"])
View View
[ColumnInfo (ColumnName "id") StringTy False Nothing False False] [ColumnInfo (ColumnName "id") (ScalarType "string") False Nothing False False]
[ColumnName "id"] [ColumnName "id"]
(ForeignKeys mempty) (ForeignKeys mempty)
(Just "my description") (Just "my description")
@ -58,7 +58,7 @@ spec = do
( TableInfo ( TableInfo
(TableName ["my_table_name"]) (TableName ["my_table_name"])
Table Table
[ColumnInfo (ColumnName "id") StringTy False Nothing False False] [ColumnInfo (ColumnName "id") (ScalarType "string") False Nothing False False]
[ColumnName "id"] [ColumnName "id"]
(ForeignKeys $ HashMap.singleton (ConstraintName "Artist") (Constraint (TableName ["artist_table"]) (HashMap.singleton (ColumnName "ArtistId") (ColumnName "ArtistId")))) (ForeignKeys $ HashMap.singleton (ConstraintName "Artist") (Constraint (TableName ["artist_table"]) (HashMap.singleton (ColumnName "ArtistId") (ColumnName "ArtistId"))))
(Just "my description") (Just "my description")