Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,12 @@ public static async ValueTask<FormulaValue> SortByColumns(EvalVisitor runner, Ev
{
var columnName = ((StringValue)args[i]).Value;

if (!arg0.Type.FieldNames.Contains(columnName))
// Use the compile-time result type (irContext.ResultType) rather than the
// actual runtime arg0.Type, which may be narrower when this function is
// called through a UDF with a table that omits optional columns.
// Missing columns are returned as Blank by RecordValue.GetFieldAsync.
// See https://github.com/microsoft/Power-Fx/issues/2973
if (!((TableType)irContext.ResultType).FieldNames.Contains(columnName))
{
return CreateInvalidSortColumnError(irContext, runner.CultureInfo, columnName);
}
Expand Down Expand Up @@ -961,7 +966,13 @@ public static async ValueTask<FormulaValue> SortByColumnsOrderTable(EvalVisitor
{
var arg0 = (TableValue)args[0];
var columnName = ((StringValue)args[1]).Value;
if (!arg0.Type.FieldNames.Contains(columnName))

// Use the compile-time result type (irContext.ResultType) rather than the
// actual runtime arg0.Type, which may be narrower when this function is
// called through a UDF with a table that omits optional columns.
// Missing columns are returned as Blank by RecordValue.GetFieldAsync.
// See https://github.com/microsoft/Power-Fx/issues/2973
if (!((TableType)irContext.ResultType).FieldNames.Contains(columnName))
{
return CreateInvalidSortColumnError(irContext, runner.CultureInfo, columnName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2379,6 +2379,39 @@ public void UDFAggregateInputErrorMessage(string userDefinitions, string evalExp
Assert.Contains(expectedError, ex.InnerExceptions.First().Message);
}

// Regression test for https://github.com/microsoft/Power-Fx/issues/2973
// SortByColumns should not throw when called via a UDF and the actual argument table
// omits one of the sort columns. Missing columns should be treated as Blank.
[Fact]
public void SortByColumns_UDF_MissingField()
{
var engine = new RecalcEngine();

// Define types and UDF matching the issue repro exactly.
engine.AddUserDefinitions(
"Person := Type( { Name: Text, Age: Number } );" +
"People := Type( [ Person ] );" +
"SortedPeople(list:People):People = SortByColumns(list, \"Name\", SortOrder.Ascending, \"Age\", SortOrder.Ascending);");

// AC-1: Missing Age column - should succeed and return sorted table, not an error.
var result = engine.Eval("SortedPeople([{Name:\"John\"},{Name:\"Jane\"}])");
Assert.IsNotType<ErrorValue>(result);
Assert.IsAssignableFrom<TableValue>(result);
var rows = ((TableValue)result).Rows.ToList();
Assert.Equal(2, rows.Count);
Assert.Equal("Jane", ((StringValue)rows[0].Value.GetField("Name")).Value);
Assert.Equal("John", ((StringValue)rows[1].Value.GetField("Name")).Value);

// AC-2: Full columns present - should continue to work.
result = engine.Eval("SortedPeople([{Name:\"John\", Age:30},{Name:\"Jane\", Age:40}])");
Assert.IsNotType<ErrorValue>(result);
Assert.IsAssignableFrom<TableValue>(result);
rows = ((TableValue)result).Rows.ToList();
Assert.Equal(2, rows.Count);
Assert.Equal("Jane", ((StringValue)rows[0].Value.GetField("Name")).Value);
Assert.Equal("John", ((StringValue)rows[1].Value.GetField("Name")).Value);
}

#region Test

private readonly StringBuilder _updates = new StringBuilder();
Expand Down
Loading