diff --git a/ndc-models/src/lib.rs b/ndc-models/src/lib.rs index 2f92f924..f8047035 100644 --- a/ndc-models/src/lib.rs +++ b/ndc-models/src/lib.rs @@ -337,10 +337,15 @@ pub enum ComparisonOperatorDefinition { #[serde(tag = "type", rename_all = "snake_case")] #[schemars(title = "Aggregate Function Definition")] pub enum AggregateFunctionDefinition { - Sum, Min, Max, - Average, + Sum { + /// The scalar type of the result of this function, which should have + /// one of the type representations Int64 or Float64, depending on + /// whether this function is defined on a scalar type with an integer or + /// floating-point representation, respectively. + result_type: ScalarTypeName, + }, Custom { /// The scalar or object type of the result of this function result_type: Type, diff --git a/ndc-models/tests/json_schema/schema_response.jsonschema b/ndc-models/tests/json_schema/schema_response.jsonschema index 5681f252..9adfe39b 100644 --- a/ndc-models/tests/json_schema/schema_response.jsonschema +++ b/ndc-models/tests/json_schema/schema_response.jsonschema @@ -428,20 +428,6 @@ "title": "Aggregate Function Definition", "description": "The definition of an aggregation function on a scalar type", "oneOf": [ - { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "sum" - ] - } - } - }, { "type": "object", "required": [ @@ -473,14 +459,19 @@ { "type": "object", "required": [ + "result_type", "type" ], "properties": { "type": { "type": "string", "enum": [ - "average" + "sum" ] + }, + "result_type": { + "description": "The scalar type of the result of this function, which should have one of the type representations Int64 or Float64, depending on whether this function is defined on a scalar type with an integer or floating-point representation, respectively.", + "type": "string" } } }, diff --git a/ndc-test/src/error.rs b/ndc-test/src/error.rs index 89f9ece4..9c6e0160 100644 --- a/ndc-test/src/error.rs +++ b/ndc-test/src/error.rs @@ -52,6 +52,8 @@ pub enum Error { UnexpectedField(ndc_models::FieldName), #[error("scalar type {0} has multiple equality operators")] MultipleEqualityOperators(ndc_models::ScalarTypeName), + #[error("scalar type {0} has an invalid type representation")] + InvalidTypeRepresentation(ndc_models::ScalarTypeName), #[error("error response from connector: {0:?}")] ConnectorError(ndc_models::ErrorResponse), #[error("cannot open snapshot file: {0:?}")] diff --git a/ndc-test/src/test_cases/schema.rs b/ndc-test/src/test_cases/schema.rs index 08d8e5f4..bda8a0f5 100644 --- a/ndc-test/src/test_cases/schema.rs +++ b/ndc-test/src/test_cases/schema.rs @@ -26,6 +26,18 @@ pub async fn validate_schema( for (type_name, scalar_type) in &schema.scalar_types { for aggregate_function in scalar_type.aggregate_functions.values() { match aggregate_function { + models::AggregateFunctionDefinition::Sum { result_type } => { + let Some(scalar_type) = schema.scalar_types.get(result_type) else { + return Err(Error::NamedTypeIsNotDefined(result_type.inner().clone())); + }; + let Some( + models::TypeRepresentation::Int64 | models::TypeRepresentation::Float64, + ) = scalar_type.representation + else { + return Err(Error::InvalidTypeRepresentation(result_type.clone())); + }; + Ok(()) + } models::AggregateFunctionDefinition::Custom { result_type } => { validate_type(schema, result_type) } diff --git a/specification/src/specification/schema/scalar-types.md b/specification/src/specification/schema/scalar-types.md index 31be36d7..b372b2c3 100644 --- a/specification/src/specification/schema/scalar-types.md +++ b/specification/src/specification/schema/scalar-types.md @@ -164,15 +164,9 @@ For example: An aggregation function defined using type `sum` should return the numerical sum of its provided values. -A `sum` function should ignore the order of its input values, and should be invariant of partitioning, that is: `sum(x, sum(y, z))` = `sum(x, y, z)` for any partitioning `x, y, z` of the input values. - -#### `average` - -An aggregation function defined using type `average` should return the numerical average of its provided values. +The result type should be provided explicitly, in the `result_type` field, and should be a scalar type with a type representation of either `Int64` or `Float64`, depending on whether the scalar type defining this function has an integer representation or floating point representation, -Its implicit result type, i.e. the type of the aggregated values, is the same as the scalar type on which the function is defined, but with nulls allowed if not allowed already. - -An `average` function should return null for an empty set of input values. +A `sum` function should ignore the order of its input values, and should be invariant of partitioning, that is: `sum(x, sum(y, z))` = `sum(x, y, z)` for any partitioning `x, y, z` of the input values. #### `min`, `max`