mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 08:02:15 +03:00
Aggregates Root Field - Part 1: OpenDD (#683)
This is Part 1 in a stacked PR set that delivers aggregate root field support. * Part 2: Metadata Resolve: https://github.com/hasura/v3-engine/pull/684 * Part 3: GraphQL API: https://github.com/hasura/v3-engine/pull/685 JIRA: [V3ENGINE-159](https://hasurahq.atlassian.net/browse/V3ENGINE-159) ## Description This PR is the first cut in implementing aggregates functionality for v3, as defined in the [Aggregates and Grouping RFC](https://github.com/hasura/v3-engine/blob/main/rfcs/aggregations.md). This PR modifies the Open DD schema and adds the `AggregateExpression` metadata object. It also modifies the `Model` and `GraphqlConfig` types and adds new fields that are required to link in aggregates functionality. For more information, please see the below RFC links. This PR implements only the minimum properties required to get a aggregates root fields in the GraphQL API. There is more defined in the RFC that will be implemented in later iterations. RFC links: * [AggregateExpression](https://github.com/hasura/v3-engine/blob/main/rfcs/aggregations.md#aggregateexpression-new) * [Model](https://github.com/hasura/v3-engine/blob/main/rfcs/aggregations.md#model--object-type) * [GraphqlConfig](https://github.com/hasura/v3-engine/blob/main/rfcs/aggregations.md#graphql-config) ## Changelog ### Product _(Select all products this will be available in)_ - [x] community-edition - [x] cloud <!-- product : end : DO NOT REMOVE --> ### Type - [ ] highlight - [x] enhancement - [ ] bugfix - [ ] behaviour-change - [ ] performance-enhancement - [ ] security-fix <!-- type : end : DO NOT REMOVE --> ### Changelog entry Support for aggregate GraphQL root fields via the new AggregateExpression OpenDD type and its use on the Model type <!-- changelog-entry : end : DO NOT REMOVE --> <!-- changelog : end : DO NOT REMOVE --> [V3ENGINE-159]: https://hasurahq.atlassian.net/browse/V3ENGINE-159?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ V3_GIT_ORIGIN_REV_ID: 6969ee73036a011e3026b58545c0286a65749067
This commit is contained in:
parent
87d6e2a9b6
commit
e07197e1be
@ -7,6 +7,7 @@ use crate::types::error::{Error, GraphqlConfigError};
|
||||
use lang_graphql::ast::common as ast;
|
||||
use open_dds::accessor::QualifiedObject;
|
||||
use open_dds::graphql_config::{self, OrderByDirection};
|
||||
use open_dds::types::GraphQlFieldName;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
@ -40,7 +41,12 @@ lazy_static::lazy_static! {
|
||||
enum_type_names: vec![graphql_config::OrderByEnumTypeName{
|
||||
type_name: "order_by".to_string(),
|
||||
directions: vec![graphql_config::OrderByDirection::Asc, graphql_config::OrderByDirection::Desc],
|
||||
}] })
|
||||
}] }),
|
||||
aggregate: Some(graphql_config::AggregateGraphqlConfig {
|
||||
filter_input_field_name: GraphQlFieldName("filter_input".to_string()),
|
||||
count_field_name: GraphQlFieldName("_count".to_string()),
|
||||
count_distinct_field_name: GraphQlFieldName("_count_distinct".to_string()),
|
||||
})
|
||||
},
|
||||
mutation: graphql_config::MutationGraphqlConfig{
|
||||
root_operation_type_name: "Mutation".to_string(),
|
||||
|
@ -336,6 +336,62 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/AggregateExpression",
|
||||
"title": "AggregateExpression",
|
||||
"examples": [
|
||||
{
|
||||
"kind": "AggregateExpression",
|
||||
"version": "v1",
|
||||
"definition": {
|
||||
"name": "Invoice_aggregate_exp",
|
||||
"operand": {
|
||||
"object": {
|
||||
"aggregatedType": "Invoice",
|
||||
"aggregatableFields": [
|
||||
{
|
||||
"fieldName": "Total",
|
||||
"aggregateExpression": "Float_aggregate_exp"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"graphql": {
|
||||
"selectTypeName": "Invoice_aggregate_fields"
|
||||
},
|
||||
"description": "Aggregate over Invoices"
|
||||
}
|
||||
}
|
||||
],
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"definition",
|
||||
"kind",
|
||||
"version"
|
||||
],
|
||||
"properties": {
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"AggregateExpression"
|
||||
]
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"v1"
|
||||
]
|
||||
},
|
||||
"definition": {
|
||||
"$ref": "#/definitions/AggregateExpressionV1"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/Model",
|
||||
"title": "Model",
|
||||
@ -1204,21 +1260,26 @@
|
||||
"OperatorName": {
|
||||
"type": "string"
|
||||
},
|
||||
"GraphqlApolloFederationConfig": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/GraphqlApolloFederationConfig",
|
||||
"title": "GraphqlApolloFederationConfig",
|
||||
"description": "Configuration for the GraphQL schema of Hasura features for Apollo Federation.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"enableRootFields"
|
||||
],
|
||||
"properties": {
|
||||
"enableRootFields": {
|
||||
"description": "Adds the `_entities` and `_services` root fields required for Apollo Federation.",
|
||||
"type": "boolean"
|
||||
"OrderByDirection2": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/OrderByDirection2",
|
||||
"title": "OrderByDirection",
|
||||
"description": "Sort direction.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Ascending.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Asc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Descending.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Desc"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
]
|
||||
},
|
||||
"FieldIsNullPredicate": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/FieldIsNullPredicate",
|
||||
@ -1974,6 +2035,456 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"AggregateExpressionV1": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/AggregateExpressionV1",
|
||||
"title": "AggregateExpressionV1",
|
||||
"description": "Definition of how to aggregate over a particular operand type",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"operand"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "The name of the command.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AggregateExpressionName"
|
||||
}
|
||||
]
|
||||
},
|
||||
"operand": {
|
||||
"description": "The type this aggregation expression aggregates over, and its associated configuration",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AggregateOperand"
|
||||
}
|
||||
]
|
||||
},
|
||||
"count": {
|
||||
"description": "Configuration for the count aggregate function used over the operand",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AggregateCountDefinition"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"countDistinct": {
|
||||
"description": "Configuration for the count distinct aggregate function used over the operand",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AggregateCountDefinition"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"graphql": {
|
||||
"description": "Configuration for how this command should appear in the GraphQL schema.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AggregateExpressionGraphQlDefinition"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
"description": "The description of the command. Gets added to the description of the command's root field in the GraphQL schema.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"AggregateExpressionName": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/AggregateExpressionName",
|
||||
"title": "AggregateExpressionName",
|
||||
"description": "The name of an aggregate expression.",
|
||||
"type": "string",
|
||||
"pattern": "^[_a-zA-Z][_a-zA-Z0-9]*$"
|
||||
},
|
||||
"AggregateOperand": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/AggregateOperand",
|
||||
"title": "AggregateOperand",
|
||||
"description": "Definition of an aggregate expression's operand",
|
||||
"oneOf": [
|
||||
{
|
||||
"title": "Object",
|
||||
"description": "If the operand is an object type",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"object"
|
||||
],
|
||||
"properties": {
|
||||
"object": {
|
||||
"$ref": "#/definitions/ObjectAggregateOperand"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"title": "Scalar",
|
||||
"description": "If the operand is a scalar type",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"scalar"
|
||||
],
|
||||
"properties": {
|
||||
"scalar": {
|
||||
"$ref": "#/definitions/ScalarAggregateOperand"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"ObjectAggregateOperand": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/ObjectAggregateOperand",
|
||||
"title": "ObjectAggregateOperand",
|
||||
"description": "Definition of an aggregate over an object-typed operand",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"aggregatableFields",
|
||||
"aggregatedType"
|
||||
],
|
||||
"properties": {
|
||||
"aggregatedType": {
|
||||
"description": "The name of the object type the aggregate expression is aggregating",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/CustomTypeName"
|
||||
}
|
||||
]
|
||||
},
|
||||
"aggregatableFields": {
|
||||
"description": "The fields on the object that are aggregatable",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/AggregatableFieldDefinition"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"AggregatableFieldDefinition": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/AggregatableFieldDefinition",
|
||||
"title": "AggregatableFieldDefinition",
|
||||
"description": "Definition of an aggregatable field on an object type",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"aggregateExpression",
|
||||
"fieldName"
|
||||
],
|
||||
"properties": {
|
||||
"fieldName": {
|
||||
"description": "The name of the field on the operand aggregated type that is aggregatable",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/FieldName"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
"description": "A description of the aggregatable field. Gets added to the description of the field in the GraphQL schema.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"aggregateExpression": {
|
||||
"description": "The aggregate expression used to aggregate the type of the field",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AggregateExpressionName"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ScalarAggregateOperand": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/ScalarAggregateOperand",
|
||||
"title": "ScalarAggregateOperand",
|
||||
"description": "Definition of an aggregate over a scalar-typed operand",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"aggregatedType",
|
||||
"aggregationFunctions",
|
||||
"dataConnectorAggregationFunctionMapping"
|
||||
],
|
||||
"properties": {
|
||||
"aggregatedType": {
|
||||
"description": "The name of the scalar type the aggregate expression is aggregating",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/TypeName"
|
||||
}
|
||||
]
|
||||
},
|
||||
"aggregationFunctions": {
|
||||
"description": "The aggregation functions that operate over the scalar type",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/AggregationFunctionDefinition"
|
||||
}
|
||||
},
|
||||
"dataConnectorAggregationFunctionMapping": {
|
||||
"description": "Mapping of aggregation functions to corresponding aggregation functions in various data connectors",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/DataConnectorAggregationFunctionMapping"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"AggregateGraphqlConfig": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/AggregateGraphqlConfig",
|
||||
"title": "AggregateGraphqlConfig",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"countDistinctFieldName",
|
||||
"countFieldName",
|
||||
"filterInputFieldName"
|
||||
],
|
||||
"properties": {
|
||||
"filterInputFieldName": {
|
||||
"description": "The name of the filter input parameter of aggregate fields and field name in predicates",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/GraphQlFieldName"
|
||||
}
|
||||
]
|
||||
},
|
||||
"countFieldName": {
|
||||
"description": "The name of the _count field used for the count aggregate function",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/GraphQlFieldName"
|
||||
}
|
||||
]
|
||||
},
|
||||
"countDistinctFieldName": {
|
||||
"description": "The name of the _count_distinct field used for the count distinct aggregate function",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/GraphQlFieldName"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"AggregationFunctionDefinition": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/AggregationFunctionDefinition",
|
||||
"title": "AggregationFunctionDefinition",
|
||||
"description": "Definition of an aggregation function",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"returnType"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "The name of the aggregation function",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AggregationFunctionName"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
"description": "A description of the aggregation function. Gets added to the description of the field in the GraphQL schema.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"returnType": {
|
||||
"$ref": "#/definitions/TypeReference"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"AggregationFunctionName": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/AggregationFunctionName",
|
||||
"title": "AggregationFunctionName",
|
||||
"description": "The name of an aggregation function.",
|
||||
"type": "string",
|
||||
"pattern": "^[_a-zA-Z][_a-zA-Z0-9]*$"
|
||||
},
|
||||
"DataConnectorAggregationFunctionMapping": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/DataConnectorAggregationFunctionMapping",
|
||||
"title": "DataConnectorAggregationFunctionMapping",
|
||||
"description": "Definition of how to map an aggregate expression's aggregation functions to data connector aggregation functions.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"dataConnectorName",
|
||||
"dataConnectorScalarType",
|
||||
"functionMapping"
|
||||
],
|
||||
"properties": {
|
||||
"dataConnectorName": {
|
||||
"description": "The data connector being mapped to",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DataConnectorName"
|
||||
}
|
||||
]
|
||||
},
|
||||
"dataConnectorScalarType": {
|
||||
"description": "The matching scalar type in the data connector for the operand scalar type",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DataConnectorScalarType"
|
||||
}
|
||||
]
|
||||
},
|
||||
"functionMapping": {
|
||||
"description": "Mapping from Open DD aggregation function to data connector aggregation function",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AggregationFunctionMappings"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"GraphqlApolloFederationConfig": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/GraphqlApolloFederationConfig",
|
||||
"title": "GraphqlApolloFederationConfig",
|
||||
"description": "Configuration for the GraphQL schema of Hasura features for Apollo Federation.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"enableRootFields"
|
||||
],
|
||||
"properties": {
|
||||
"enableRootFields": {
|
||||
"description": "Adds the `_entities` and `_services` root fields required for Apollo Federation.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"MutationGraphqlConfig": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/MutationGraphqlConfig",
|
||||
"title": "MutationGraphqlConfig",
|
||||
"description": "Configuration for the GraphQL schema of Hasura features for mutations.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"rootOperationTypeName"
|
||||
],
|
||||
"properties": {
|
||||
"rootOperationTypeName": {
|
||||
"description": "The name of the root operation type name for mutations. Usually `mutation`.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"AggregationFunctionMappings": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/AggregationFunctionMappings",
|
||||
"title": "AggregationFunctionMappings",
|
||||
"description": "Mapping of aggregation functions to their matching aggregation functions in the data connector.",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/AggregateFunctionMapping"
|
||||
}
|
||||
},
|
||||
"AggregateFunctionMapping": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/AggregateFunctionMapping",
|
||||
"title": "AggregateFunctionMapping",
|
||||
"description": "Definition of how to map the aggregation function to a function in the data connector",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "The name of the aggregation function in the data connector",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DataConnectorAggregationFunctionName"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"DataConnectorAggregationFunctionName": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/DataConnectorAggregationFunctionName",
|
||||
"title": "DataConnectorAggregationFunctionName",
|
||||
"description": "The name of an aggregation function in a data connector",
|
||||
"type": "string"
|
||||
},
|
||||
"AggregateCountDefinition": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/AggregateCountDefinition",
|
||||
"title": "AggregateCountDefinition",
|
||||
"description": "Definition of a count aggregation function",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"enable"
|
||||
],
|
||||
"properties": {
|
||||
"enable": {
|
||||
"description": "Whether or not the aggregate function is available for use or not",
|
||||
"type": "boolean"
|
||||
},
|
||||
"description": {
|
||||
"description": "A description of the aggregation function. Gets added to the description of the field in the GraphQL schema.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"AggregateExpressionGraphQlDefinition": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/AggregateExpressionGraphQlDefinition",
|
||||
"title": "AggregateExpressionGraphQlDefinition",
|
||||
"description": "The definition of how an aggregate expression should appear in the GraphQL API.",
|
||||
"examples": [
|
||||
{
|
||||
"selectTypeName": "Invoice_aggregate_fields"
|
||||
}
|
||||
],
|
||||
"type": "object",
|
||||
"required": [
|
||||
"selectTypeName"
|
||||
],
|
||||
"properties": {
|
||||
"selectTypeName": {
|
||||
"description": "The type name to use for the aggregate selection type",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/GraphQlTypeName"
|
||||
}
|
||||
]
|
||||
},
|
||||
"deprecated": {
|
||||
"description": "Whether this command root field is deprecated. If set, this will be added to the graphql schema as a deprecated field.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Deprecated"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ModelV1": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/ModelV1",
|
||||
"title": "ModelV1",
|
||||
@ -2043,6 +2554,17 @@
|
||||
"$ref": "#/definitions/OrderableField"
|
||||
}
|
||||
},
|
||||
"aggregateExpression": {
|
||||
"description": "The name of the AggregateExpression that defines how to aggregate over this model",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AggregateExpressionName"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"graphql": {
|
||||
"description": "Configuration for how this model should appear in the GraphQL schema.",
|
||||
"anyOf": [
|
||||
@ -2246,7 +2768,11 @@
|
||||
"queryRootField": "ArticleMany",
|
||||
"description": "Description for the select many ArticleMany"
|
||||
},
|
||||
"orderByExpressionType": "Article_Order_By"
|
||||
"orderByExpressionType": "Article_Order_By",
|
||||
"aggregate": {
|
||||
"queryRootField": "ArticleAggregate",
|
||||
"description": "Aggregate over Articles"
|
||||
}
|
||||
}
|
||||
],
|
||||
"type": "object",
|
||||
@ -2304,6 +2830,28 @@
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"filterInputTypeName": {
|
||||
"description": "The type name of the input type used to hold the filtering settings used by aggregates (etc) to filter their input before processing",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/GraphQlTypeName"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"aggregate": {
|
||||
"description": "Configures the query root field added to the GraphQL API that can be used to aggregate over the model",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ModelAggregateGraphQlDefinition"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@ -2413,6 +2961,43 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ModelAggregateGraphQlDefinition": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/ModelAggregateGraphQlDefinition",
|
||||
"title": "ModelAggregateGraphQlDefinition",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"queryRootField"
|
||||
],
|
||||
"properties": {
|
||||
"queryRootField": {
|
||||
"description": "The name of the query root field for this API.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/GraphQlFieldName"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
"description": "The description of the aggregate graphql definition of the model. Gets added to the description of the aggregate root field of the model in the graphql schema.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"deprecated": {
|
||||
"description": "Whether this aggregate query field is deprecated. If set, the deprecation status is added to the aggregate root field's graphql schema.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Deprecated"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"CommandV1": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/CommandV1",
|
||||
"title": "CommandV1",
|
||||
@ -3622,6 +4207,17 @@
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"aggregate": {
|
||||
"description": "Configuration for aggregates",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AggregateGraphqlConfig"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@ -3803,43 +4399,6 @@
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"OrderByDirection2": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/OrderByDirection2",
|
||||
"title": "OrderByDirection",
|
||||
"description": "Sort direction.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Ascending.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Asc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Descending.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Desc"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"MutationGraphqlConfig": {
|
||||
"$id": "https://hasura.io/jsonschemas/metadata/MutationGraphqlConfig",
|
||||
"title": "MutationGraphqlConfig",
|
||||
"description": "Configuration for the GraphQL schema of Hasura features for mutations.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"rootOperationTypeName"
|
||||
],
|
||||
"properties": {
|
||||
"rootOperationTypeName": {
|
||||
"description": "The name of the root operation type name for mutations. Usually `mutation`.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
use crate::{graphql_config, MetadataWithVersion, OpenDdSupergraphObject};
|
||||
|
||||
use super::{
|
||||
boolean_expression, commands, data_connector, flags, models, permissions, relationships, types,
|
||||
Metadata, OpenDdSubgraphObject,
|
||||
aggregates, boolean_expression, commands, data_connector, flags, models, permissions,
|
||||
relationships, types, Metadata, OpenDdSubgraphObject,
|
||||
};
|
||||
|
||||
pub struct QualifiedObject<T> {
|
||||
@ -31,6 +31,7 @@ pub struct MetadataAccessor {
|
||||
pub boolean_expression_types: Vec<QualifiedObject<boolean_expression::BooleanExpressionTypeV1>>,
|
||||
pub data_connector_scalar_representations:
|
||||
Vec<QualifiedObject<types::DataConnectorScalarRepresentationV1>>,
|
||||
pub aggregate_expressions: Vec<QualifiedObject<aggregates::AggregateExpressionV1>>,
|
||||
pub models: Vec<QualifiedObject<models::ModelV1>>,
|
||||
pub type_permissions: Vec<QualifiedObject<permissions::TypePermissionsV1>>,
|
||||
pub model_permissions: Vec<QualifiedObject<permissions::ModelPermissionsV1>>,
|
||||
@ -57,7 +58,7 @@ fn load_metadata_objects(
|
||||
OpenDdSubgraphObject::GraphqlConfig(graphql_config) => {
|
||||
accessor
|
||||
.graphql_config
|
||||
.push(QualifiedObject::new(subgraph, graphql_config));
|
||||
.push(QualifiedObject::new(subgraph, *graphql_config));
|
||||
}
|
||||
OpenDdSubgraphObject::ObjectType(object_type) => {
|
||||
accessor
|
||||
@ -91,6 +92,12 @@ fn load_metadata_objects(
|
||||
scalar_representation.upgrade(),
|
||||
));
|
||||
}
|
||||
OpenDdSubgraphObject::AggregateExpression(aggregate_expression) => {
|
||||
accessor.aggregate_expressions.push(QualifiedObject::new(
|
||||
subgraph,
|
||||
aggregate_expression.upgrade(),
|
||||
));
|
||||
}
|
||||
OpenDdSubgraphObject::Model(model) => {
|
||||
accessor
|
||||
.models
|
||||
@ -185,6 +192,7 @@ impl MetadataAccessor {
|
||||
object_boolean_expression_types: vec![],
|
||||
boolean_expression_types: vec![],
|
||||
data_connector_scalar_representations: vec![],
|
||||
aggregate_expressions: vec![],
|
||||
models: vec![],
|
||||
type_permissions: vec![],
|
||||
model_permissions: vec![],
|
||||
|
294
v3/crates/open-dds/src/aggregates.rs
Normal file
294
v3/crates/open-dds/src/aggregates.rs
Normal file
@ -0,0 +1,294 @@
|
||||
use std::ops::Deref;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
data_connector::{DataConnectorName, DataConnectorScalarType},
|
||||
identifier::Identifier,
|
||||
impl_JsonSchema_with_OpenDd_for,
|
||||
types::{CustomTypeName, Deprecated, FieldName, GraphQlTypeName, TypeName, TypeReference},
|
||||
};
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Hash,
|
||||
ref_cast::RefCast,
|
||||
derive_more::Display,
|
||||
opendds_derive::OpenDd,
|
||||
)]
|
||||
/// The name of an aggregate expression.
|
||||
pub struct AggregateExpressionName(pub Identifier);
|
||||
|
||||
impl_JsonSchema_with_OpenDd_for!(AggregateExpressionName);
|
||||
|
||||
#[derive(Serialize, Clone, Debug, PartialEq, opendds_derive::OpenDd)]
|
||||
#[serde(tag = "version", content = "definition")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[opendd(
|
||||
as_versioned_with_definition,
|
||||
json_schema(
|
||||
title = "AggregateExpression",
|
||||
example = "AggregateExpression::example"
|
||||
)
|
||||
)]
|
||||
pub enum AggregateExpression {
|
||||
V1(AggregateExpressionV1),
|
||||
}
|
||||
|
||||
impl AggregateExpression {
|
||||
fn example() -> serde_json::Value {
|
||||
serde_json::json!({
|
||||
"kind": "AggregateExpression",
|
||||
"version": "v1",
|
||||
"definition": {
|
||||
"name": "Invoice_aggregate_exp",
|
||||
"operand": {
|
||||
"object": {
|
||||
"aggregatedType": "Invoice",
|
||||
"aggregatableFields": [
|
||||
{
|
||||
"fieldName": "Total",
|
||||
"aggregateExpression": "Float_aggregate_exp"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"graphql": {
|
||||
"selectTypeName": "Invoice_aggregate_fields",
|
||||
},
|
||||
"description": "Aggregate over Invoices",
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn upgrade(self) -> AggregateExpressionV1 {
|
||||
match self {
|
||||
AggregateExpression::V1(v1) => v1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone, Debug, PartialEq, opendds_derive::OpenDd)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
#[opendd(json_schema(title = "AggregateExpressionV1"))]
|
||||
/// Definition of how to aggregate over a particular operand type
|
||||
pub struct AggregateExpressionV1 {
|
||||
/// The name of the command.
|
||||
pub name: AggregateExpressionName,
|
||||
/// The type this aggregation expression aggregates over, and its associated configuration
|
||||
pub operand: AggregateOperand,
|
||||
/// Configuration for the count aggregate function used over the operand
|
||||
pub count: Option<AggregateCountDefinition>,
|
||||
/// Configuration for the count distinct aggregate function used over the operand
|
||||
pub count_distinct: Option<AggregateCountDefinition>,
|
||||
/// Configuration for how this command should appear in the GraphQL schema.
|
||||
pub graphql: Option<AggregateExpressionGraphQlDefinition>,
|
||||
/// The description of the command.
|
||||
/// Gets added to the description of the command's root field in the GraphQL schema.
|
||||
pub description: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, opendds_derive::OpenDd,
|
||||
)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
/// Definition of an aggregate expression's operand
|
||||
#[schemars(title = "AggregateOperand")]
|
||||
pub enum AggregateOperand {
|
||||
/// If the operand is an object type
|
||||
#[schemars(title = "Object")]
|
||||
Object(ObjectAggregateOperand),
|
||||
/// If the operand is a scalar type
|
||||
#[schemars(title = "Scalar")]
|
||||
Scalar(ScalarAggregateOperand),
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash, JsonSchema, opendds_derive::OpenDd,
|
||||
)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
#[schemars(title = "ObjectAggregateOperand")]
|
||||
/// Definition of an aggregate over an object-typed operand
|
||||
pub struct ObjectAggregateOperand {
|
||||
/// The name of the object type the aggregate expression is aggregating
|
||||
pub aggregated_type: CustomTypeName,
|
||||
/// The fields on the object that are aggregatable
|
||||
#[opendd(default, json_schema(default_exp = "serde_json::json!([])"))]
|
||||
pub aggregatable_fields: Vec<AggregatableFieldDefinition>,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash, JsonSchema, opendds_derive::OpenDd,
|
||||
)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
#[schemars(title = "AggregatableFieldDefinition")]
|
||||
/// Definition of an aggregatable field on an object type
|
||||
pub struct AggregatableFieldDefinition {
|
||||
/// The name of the field on the operand aggregated type that is aggregatable
|
||||
pub field_name: FieldName,
|
||||
/// A description of the aggregatable field.
|
||||
/// Gets added to the description of the field in the GraphQL schema.
|
||||
pub description: Option<String>,
|
||||
/// The aggregate expression used to aggregate the type of the field
|
||||
pub aggregate_expression: AggregateExpressionName,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, opendds_derive::OpenDd,
|
||||
)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
#[schemars(title = "ScalarAggregateOperand")]
|
||||
/// Definition of an aggregate over a scalar-typed operand
|
||||
pub struct ScalarAggregateOperand {
|
||||
/// The name of the scalar type the aggregate expression is aggregating
|
||||
pub aggregated_type: TypeName,
|
||||
/// The aggregation functions that operate over the scalar type
|
||||
pub aggregation_functions: Vec<AggregationFunctionDefinition>,
|
||||
/// Mapping of aggregation functions to corresponding aggregation functions in various data connectors
|
||||
#[opendd(default, json_schema(default_exp = "serde_json::json!([])"))]
|
||||
pub data_connector_aggregation_function_mapping: Vec<DataConnectorAggregationFunctionMapping>,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash, JsonSchema, opendds_derive::OpenDd,
|
||||
)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
#[schemars(title = "AggregationFunctionDefinition")]
|
||||
/// Definition of an aggregation function
|
||||
pub struct AggregationFunctionDefinition {
|
||||
/// The name of the aggregation function
|
||||
pub name: AggregationFunctionName,
|
||||
/// A description of the aggregation function.
|
||||
/// Gets added to the description of the field in the GraphQL schema.
|
||||
pub description: Option<String>,
|
||||
// The type that the aggregation function returns
|
||||
pub return_type: TypeReference,
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Hash,
|
||||
ref_cast::RefCast,
|
||||
derive_more::Display,
|
||||
opendds_derive::OpenDd,
|
||||
)]
|
||||
/// The name of an aggregation function.
|
||||
pub struct AggregationFunctionName(pub Identifier);
|
||||
|
||||
impl_JsonSchema_with_OpenDd_for!(AggregationFunctionName);
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Hash,
|
||||
ref_cast::RefCast,
|
||||
derive_more::Display,
|
||||
opendds_derive::OpenDd,
|
||||
)]
|
||||
/// The name of an aggregation function in a data connector
|
||||
pub struct DataConnectorAggregationFunctionName(pub String);
|
||||
|
||||
impl_JsonSchema_with_OpenDd_for!(DataConnectorAggregationFunctionName);
|
||||
|
||||
#[derive(
|
||||
Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, opendds_derive::OpenDd,
|
||||
)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
#[schemars(title = "DataConnectorAggregationFunctionMapping")]
|
||||
/// Definition of how to map an aggregate expression's aggregation functions to
|
||||
/// data connector aggregation functions.
|
||||
pub struct DataConnectorAggregationFunctionMapping {
|
||||
/// The data connector being mapped to
|
||||
pub data_connector_name: DataConnectorName,
|
||||
/// The matching scalar type in the data connector for the operand scalar type
|
||||
pub data_connector_scalar_type: DataConnectorScalarType,
|
||||
/// Mapping from Open DD aggregation function to data connector aggregation function
|
||||
#[opendd(default)]
|
||||
pub function_mapping: AggregationFunctionMappings,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq, JsonSchema, opendds_derive::OpenDd,
|
||||
)]
|
||||
#[schemars(title = "AggregationFunctionMappings")]
|
||||
/// Mapping of aggregation functions to their matching aggregation functions in the data connector.
|
||||
// We wrap maps into newtype structs so that we have a type and title for them in the JSONSchema which
|
||||
// makes it easier to auto-generate documentation.
|
||||
pub struct AggregationFunctionMappings(
|
||||
pub IndexMap<AggregationFunctionName, AggregateFunctionMapping>,
|
||||
);
|
||||
|
||||
impl Deref for AggregationFunctionMappings {
|
||||
type Target = IndexMap<AggregationFunctionName, AggregateFunctionMapping>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash, JsonSchema, opendds_derive::OpenDd,
|
||||
)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
#[schemars(title = "AggregateFunctionMapping")]
|
||||
/// Definition of how to map the aggregation function to a function in the data connector
|
||||
pub struct AggregateFunctionMapping {
|
||||
/// The name of the aggregation function in the data connector
|
||||
pub name: DataConnectorAggregationFunctionName,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone, Debug, PartialEq, opendds_derive::OpenDd)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
#[opendd(json_schema(title = "AggregateCountDefinition"))]
|
||||
/// Definition of a count aggregation function
|
||||
pub struct AggregateCountDefinition {
|
||||
/// Whether or not the aggregate function is available for use or not
|
||||
pub enable: bool,
|
||||
/// A description of the aggregation function.
|
||||
/// Gets added to the description of the field in the GraphQL schema.
|
||||
pub description: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone, Debug, PartialEq, Eq, opendds_derive::OpenDd)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
#[opendd(json_schema(
|
||||
title = "AggregateExpressionGraphQlDefinition",
|
||||
example = "AggregateExpressionGraphQlDefinition::example"
|
||||
))]
|
||||
/// The definition of how an aggregate expression should appear in the GraphQL API.
|
||||
pub struct AggregateExpressionGraphQlDefinition {
|
||||
/// The type name to use for the aggregate selection type
|
||||
pub select_type_name: GraphQlTypeName,
|
||||
/// Whether this command root field is deprecated.
|
||||
/// If set, this will be added to the graphql schema as a deprecated field.
|
||||
pub deprecated: Option<Deprecated>,
|
||||
}
|
||||
|
||||
impl AggregateExpressionGraphQlDefinition {
|
||||
fn example() -> serde_json::Value {
|
||||
serde_json::json!({
|
||||
"selectTypeName": "Invoice_aggregate_fields",
|
||||
})
|
||||
}
|
||||
}
|
@ -5,6 +5,8 @@
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::GraphQlFieldName;
|
||||
|
||||
#[derive(Serialize, Clone, Debug, PartialEq, opendds_derive::OpenDd)]
|
||||
#[serde(tag = "version", content = "definition")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@ -49,6 +51,8 @@ pub struct QueryGraphqlConfig {
|
||||
pub filter_input: Option<FilterInputGraphqlConfig>,
|
||||
/// Configuration for the sort operation.
|
||||
pub order_by_input: Option<OrderByInputGraphqlConfig>,
|
||||
/// Configuration for aggregates
|
||||
pub aggregate: Option<AggregateGraphqlConfig>,
|
||||
}
|
||||
|
||||
/// Configuration for the arguments input.
|
||||
@ -176,3 +180,16 @@ pub struct GraphqlApolloFederationConfig {
|
||||
/// Adds the `_entities` and `_services` root fields required for Apollo Federation.
|
||||
pub enable_root_fields: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone, Debug, PartialEq, opendds_derive::OpenDd)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
#[opendd(json_schema(title = "AggregateGraphqlConfig"))]
|
||||
pub struct AggregateGraphqlConfig {
|
||||
/// The name of the filter input parameter of aggregate fields and field name in predicates
|
||||
pub filter_input_field_name: GraphQlFieldName,
|
||||
/// The name of the _count field used for the count aggregate function
|
||||
pub count_field_name: GraphQlFieldName,
|
||||
/// The name of the _count_distinct field used for the count distinct aggregate function
|
||||
pub count_distinct_field_name: GraphQlFieldName,
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ use schemars::{schema::Schema::Object as SchemaObjectVariant, JsonSchema};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub mod accessor;
|
||||
pub mod aggregates;
|
||||
pub mod arguments;
|
||||
pub mod boolean_expression;
|
||||
pub mod commands;
|
||||
@ -79,8 +80,10 @@ pub enum OpenDdSubgraphObject {
|
||||
DataConnectorLink(data_connector::DataConnectorLink),
|
||||
|
||||
// GraphQL "super-graph" level config
|
||||
// This is boxed because it bloats the enum's size
|
||||
// See: https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant
|
||||
#[opendd(hidden = true)]
|
||||
GraphqlConfig(graphql_config::GraphqlConfig),
|
||||
GraphqlConfig(Box<graphql_config::GraphqlConfig>),
|
||||
|
||||
// Types
|
||||
ObjectType(types::ObjectType),
|
||||
@ -92,6 +95,9 @@ pub enum OpenDdSubgraphObject {
|
||||
// Data Connector Scalar Representation
|
||||
DataConnectorScalarRepresentation(types::DataConnectorScalarRepresentation),
|
||||
|
||||
// Aggregate Expressions
|
||||
AggregateExpression(aggregates::AggregateExpression),
|
||||
|
||||
// Models
|
||||
Model(models::Model),
|
||||
|
||||
|
@ -2,6 +2,7 @@ use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
aggregates::AggregateExpressionName,
|
||||
arguments::ArgumentDefinition,
|
||||
commands::ArgumentMapping,
|
||||
data_connector::DataConnectorName,
|
||||
@ -129,6 +130,8 @@ pub struct ModelV1 {
|
||||
pub filter_expression_type: Option<CustomTypeName>,
|
||||
/// A list of fields that can be used to order the objects in this model.
|
||||
pub orderable_fields: Vec<OrderableField>,
|
||||
/// The name of the AggregateExpression that defines how to aggregate over this model
|
||||
pub aggregate_expression: Option<AggregateExpressionName>,
|
||||
/// Configuration for how this model should appear in the GraphQL schema.
|
||||
pub graphql: Option<ModelGraphQlDefinition>,
|
||||
/// The description of the model.
|
||||
@ -183,6 +186,12 @@ pub struct ModelGraphQlDefinition {
|
||||
pub order_by_expression_type: Option<GraphQlTypeName>,
|
||||
/// Apollo Federation configuration
|
||||
pub apollo_federation: Option<ModelApolloFederationConfiguration>,
|
||||
/// The type name of the input type used to hold the filtering settings used by
|
||||
/// aggregates (etc) to filter their input before processing
|
||||
pub filter_input_type_name: Option<GraphQlTypeName>,
|
||||
/// Configures the query root field added to the GraphQL API that can be used to
|
||||
/// aggregate over the model
|
||||
pub aggregate: Option<ModelAggregateGraphQlDefinition>,
|
||||
}
|
||||
|
||||
impl ModelGraphQlDefinition {
|
||||
@ -201,7 +210,11 @@ impl ModelGraphQlDefinition {
|
||||
"queryRootField": "ArticleMany",
|
||||
"description": "Description for the select many ArticleMany"
|
||||
},
|
||||
"orderByExpressionType": "Article_Order_By"
|
||||
"orderByExpressionType": "Article_Order_By",
|
||||
"aggregate": {
|
||||
"queryRootField": "ArticleAggregate",
|
||||
"description": "Aggregate over Articles"
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -293,3 +306,18 @@ pub struct ModelApolloFederationConfiguration {
|
||||
/// Whether this model should be used as the source for fetching _entity for object of its type.
|
||||
pub entity_source: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone, Debug, PartialEq, opendds_derive::OpenDd)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
#[opendd(json_schema(title = "ModelAggregateGraphQlDefinition"))]
|
||||
pub struct ModelAggregateGraphQlDefinition {
|
||||
/// The name of the query root field for this API.
|
||||
pub query_root_field: GraphQlFieldName,
|
||||
/// The description of the aggregate graphql definition of the model.
|
||||
/// Gets added to the description of the aggregate root field of the model in the graphql schema.
|
||||
pub description: Option<String>,
|
||||
/// Whether this aggregate query field is deprecated.
|
||||
/// If set, the deprecation status is added to the aggregate root field's graphql schema.
|
||||
pub deprecated: Option<Deprecated>,
|
||||
}
|
||||
|
@ -38,6 +38,20 @@ impl_OpenDd_default_for!(i32);
|
||||
impl_OpenDd_default_for!(u32);
|
||||
impl_OpenDd_default_for!(());
|
||||
|
||||
impl<T: OpenDd> OpenDd for Box<T> {
|
||||
fn deserialize(json: serde_json::Value) -> Result<Self, OpenDdDeserializeError> {
|
||||
T::deserialize(json).map(Box::new)
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||
T::json_schema(gen)
|
||||
}
|
||||
|
||||
fn _schema_name() -> String {
|
||||
T::_schema_name()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: OpenDd> OpenDd for Option<T> {
|
||||
fn deserialize(json: serde_json::Value) -> Result<Self, OpenDdDeserializeError> {
|
||||
match json {
|
||||
|
Loading…
Reference in New Issue
Block a user