diff --git a/src/vtlengine/Operators/Aggregation.py b/src/vtlengine/Operators/Aggregation.py index 33178cd99..095927356 100644 --- a/src/vtlengine/Operators/Aggregation.py +++ b/src/vtlengine/Operators/Aggregation.py @@ -147,8 +147,10 @@ def validate( # type: ignore[override] for comp_name, comp in operand.components.items(): if comp.role == Role.ATTRIBUTE: del result_components[comp_name] - # TimeInterval is not supported as a measure in aggregate operations - if any( + # TimeInterval is not supported as a measure in aggregate operations. + # count is exempt: it only reports the number of Data Points, so the Measures it + # is given are replaced by int_var below rather than aggregated (issue #937). + if cls.op != COUNT and any( comp.role == Role.MEASURE and comp.data_type is TimeInterval for comp in result_components.values() ): diff --git a/tests/Bugs/data/DataSet/input/GH_937_1-1.csv b/tests/Bugs/data/DataSet/input/GH_937_1-1.csv new file mode 100644 index 000000000..77c12c6b0 --- /dev/null +++ b/tests/Bugs/data/DataSet/input/GH_937_1-1.csv @@ -0,0 +1,4 @@ +Id_1,Id_2,Me_1,Me_2 +1,a,1.0,2020-01-01/2020-12-31 +1,b,2.0,2021-01-01/2021-12-31 +2,a,3.0,2022-01-01/2022-12-31 diff --git a/tests/Bugs/data/DataSet/output/GH_937_1-1.csv b/tests/Bugs/data/DataSet/output/GH_937_1-1.csv new file mode 100644 index 000000000..a3e52b27e --- /dev/null +++ b/tests/Bugs/data/DataSet/output/GH_937_1-1.csv @@ -0,0 +1,2 @@ +int_var +3 diff --git a/tests/Bugs/data/DataSet/output/GH_937_1-2.csv b/tests/Bugs/data/DataSet/output/GH_937_1-2.csv new file mode 100644 index 000000000..bee4812da --- /dev/null +++ b/tests/Bugs/data/DataSet/output/GH_937_1-2.csv @@ -0,0 +1,3 @@ +Id_1,int_var +1,2 +2,1 diff --git a/tests/Bugs/data/DataStructure/input/GH_937_1-1.json b/tests/Bugs/data/DataStructure/input/GH_937_1-1.json new file mode 100644 index 000000000..2b542c03c --- /dev/null +++ b/tests/Bugs/data/DataStructure/input/GH_937_1-1.json @@ -0,0 +1,33 @@ +{ + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + { + "name": "Id_1", + "role": "Identifier", + "type": "Integer", + "nullable": false + }, + { + "name": "Id_2", + "role": "Identifier", + "type": "String", + "nullable": false + }, + { + "name": "Me_1", + "role": "Measure", + "type": "Number", + "nullable": true + }, + { + "name": "Me_2", + "role": "Measure", + "type": "Time", + "nullable": true + } + ] + } + ] +} diff --git a/tests/Bugs/data/DataStructure/output/GH_937_1-1.json b/tests/Bugs/data/DataStructure/output/GH_937_1-1.json new file mode 100644 index 000000000..7e6215291 --- /dev/null +++ b/tests/Bugs/data/DataStructure/output/GH_937_1-1.json @@ -0,0 +1,15 @@ +{ + "datasets": [ + { + "name": "DS_r1", + "DataStructure": [ + { + "name": "int_var", + "role": "Measure", + "type": "Integer", + "nullable": true + } + ] + } + ] +} diff --git a/tests/Bugs/data/DataStructure/output/GH_937_1-2.json b/tests/Bugs/data/DataStructure/output/GH_937_1-2.json new file mode 100644 index 000000000..60cd31967 --- /dev/null +++ b/tests/Bugs/data/DataStructure/output/GH_937_1-2.json @@ -0,0 +1,21 @@ +{ + "datasets": [ + { + "name": "DS_r2", + "DataStructure": [ + { + "name": "Id_1", + "role": "Identifier", + "type": "Integer", + "nullable": false + }, + { + "name": "int_var", + "role": "Measure", + "type": "Integer", + "nullable": true + } + ] + } + ] +} diff --git a/tests/Bugs/data/vtl/GH_937_1.vtl b/tests/Bugs/data/vtl/GH_937_1.vtl new file mode 100644 index 000000000..a029d3fd5 --- /dev/null +++ b/tests/Bugs/data/vtl/GH_937_1.vtl @@ -0,0 +1,2 @@ +DS_r1 <- count(DS_1); +DS_r2 <- count(DS_1 group by Id_1); diff --git a/tests/Bugs/test_bugs.py b/tests/Bugs/test_bugs.py index 8dc1858e9..c9b0eff52 100644 --- a/tests/Bugs/test_bugs.py +++ b/tests/Bugs/test_bugs.py @@ -2067,6 +2067,24 @@ def test_GL_410(self): code=code, number_inputs=number_inputs, exception_code=message ) + def test_GH_937_1(self): + """ + Status: OK + Description: count only reports the number of Data Points, so it does not + aggregate the Measures it is given: the reference manual types its + operand as a plain dataset, states no Additional Constraints, and + counts a String Measure in its own example. A Time Measure was + rejected anyway, because the guard against aggregating one ran + before count replaced every Measure with int_var. + Git Issue: https://github.com/Meaningful-Data/vtlengine/issues/937 + Goal: Check Result. + """ + code = "GH_937_1" + number_inputs = 1 + references_names = ["1", "2"] + + self.BaseTest(code=code, number_inputs=number_inputs, references_names=references_names) + class DataValidationBugs(BugHelper): """ """ diff --git a/tests/TypeChecking/AggregateOperators/test_aggregate_operators.py b/tests/TypeChecking/AggregateOperators/test_aggregate_operators.py index a70d67c1b..a52ceb7d9 100644 --- a/tests/TypeChecking/AggregateOperators/test_aggregate_operators.py +++ b/tests/TypeChecking/AggregateOperators/test_aggregate_operators.py @@ -229,11 +229,9 @@ def test_13(self): """ code = "10-1-13" number_inputs = 1 - exception_code = "1-1-19-12" + references_names = ["DS_r"] - self.NewSemanticExceptionTest( - code=code, number_inputs=number_inputs, exception_code=exception_code - ) + self.BaseTest(code=code, number_inputs=number_inputs, references_names=references_names) def test_14(self): """ @@ -1506,11 +1504,9 @@ def test_12(self): """ code = "10-2-12" number_inputs = 1 - exception_code = "1-1-19-12" + references_names = ["DS_r"] - self.NewSemanticExceptionTest( - code=code, number_inputs=number_inputs, exception_code=exception_code - ) + self.BaseTest(code=code, number_inputs=number_inputs, references_names=references_names) def test_13(self): """