Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Aggregate types in UDF #2775

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

adithyaselv
Copy link
Contributor

@adithyaselv adithyaselv commented Dec 13, 2024

Changes behavior of aggregate types like records and tables in User Defined Functions (UDFs)
Add stricter type checking (restrict allowing more fields than expected) for aggregate types in UDF argument and return.

@adithyaselv adithyaselv changed the title Fix Aggregate types in UDF [Draft] Fix Aggregate types in UDF Dec 13, 2024
@LucGenetier
Copy link
Contributor

✅ No public API change.

@adithyaselv adithyaselv changed the title [Draft] Fix Aggregate types in UDF Fix Aggregate types in UDF Jan 8, 2025
@adithyaselv adithyaselv marked this pull request as ready for review January 8, 2025 16:39
@adithyaselv adithyaselv requested a review from a team as a code owner January 8, 2025 16:39
for (int i = 0; i < argTypes.Length; i++)
{
if ((argTypes[i].IsTableNonObjNull || argTypes[i].IsRecordNonObjNull) &&
!ParamTypes[i].Accepts(argTypes[i], exact: true, useLegacyDateTimeAccepts: false, usePowerFxV1CompatibilityRules: context.Features.PowerFxV1CompatibilityRules, true) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true

Can you use a named argument to make it easier to understand what this parameter means?

{
if ((argTypes[i].IsTableNonObjNull || argTypes[i].IsRecordNonObjNull) &&
!ParamTypes[i].Accepts(argTypes[i], exact: true, useLegacyDateTimeAccepts: false, usePowerFxV1CompatibilityRules: context.Features.PowerFxV1CompatibilityRules, true) &&
!argTypes[i].CoercesTo(ParamTypes[i], true, false, context.Features, true))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true, false

Can you use named arguments?

@@ -4221,6 +4221,10 @@
<value>The stated function return type '{0}' does not match the return type of the function body '{1}'.</value>
<comment>This error message shows up when expected return type does not match with actual return type. The arguments '{0}' and '{1}' will be replaced with data types. For example, "The stated function return type 'Number' does not match the return type of the function body 'Table'"</comment>
</data>
<data name="ErrUDF_ReturnTypeSchemaDoesNotMatch" xml:space="preserve">
<value>The schema of stated function return type '{0}' does not match the schema of return type of the function body.</value>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The schema of stated function return type '{0}' does not match the schema of return type of the function body

This message is a little confusing. In the example from the test f():T = {x: 5, y: 5}; T := Type({x: Number});, the message will say something like "The schema of the state function return type 'Record' does not match the schema of return type of the function body" - but the maker did return a record. For example, we could say which field is extra / missing.

/// <returns>
/// True if <see cref="DType"/> accepts <paramref name="type"/>, false otherwise.
/// </returns>
public bool Accepts(DType type, bool exact, bool useLegacyDateTimeAccepts, bool usePowerFxV1CompatibilityRules)
public bool Accepts(DType type, bool exact, bool useLegacyDateTimeAccepts, bool usePowerFxV1CompatibilityRules, bool restrictiveAggregateTypes = false)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

restrictiveAggregateTypes

Can you add tests to DTypeTests.cs? It is good to have unit tests closer to where the definition is

[InlineData(
"f():T = {x: 5, y: 5}; T := Type({x: Number});",
"",
false)]
Copy link
Contributor

@CarlosFigueiraMSFT CarlosFigueiraMSFT Jan 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

false

Can we have the tests check whether the error comes from the UDF definition or from its usage? Currently we just check that there is an error in any of those.

That will also help to catch a more restrictive exception like we had before (InvalidOperationException vs. Exception)

@CarlosFigueiraMSFT
Copy link
Contributor

    public void CheckTypesOnDeclaration(CheckTypesContext context, DType actualBodyReturnType, TexlBinding binding)

Not related to your changes, but since you are touching this file: this function is only used in this class (8 lines above). Can you make it private?


Refers to: src/libraries/Microsoft.PowerFx.Core/Functions/UserDefinedFunction.cs:188 in 00c51ac. [](commit_id = 00c51ac, deletion_comment = False)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants