Skip to content

Commit 968c7c8

Browse files
committed
Add unit test for ValuesExpression column-name backfill during pruning
Protects the case where leading VALUES columns stay referenced while a later column is pruned — the path that previously repeated the pruned column's name in newColumnNames.
1 parent 60b1d5b commit 968c7c8

1 file changed

Lines changed: 55 additions & 0 deletions

File tree

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
5+
6+
namespace Microsoft.EntityFrameworkCore.Query;
7+
8+
public class SqlTreePrunerTest
9+
{
10+
[Fact]
11+
public void PruneValues_preserves_leading_column_names_when_pruning_a_later_column()
12+
{
13+
// VALUES (_ord, Kept, Dropped) where only _ord and Kept are referenced.
14+
// The first unreferenced column is at index 2, so PruneValues must backfill
15+
// ColumnNames[0] and ColumnNames[1] — not repeat the pruned column's name (#38700 Copilot).
16+
const string alias = "v";
17+
var intMapping = IntTypeMapping.Default;
18+
19+
var values = new ValuesExpression(
20+
alias,
21+
[
22+
new RowValueExpression(
23+
[
24+
new SqlConstantExpression(0, intMapping),
25+
new SqlConstantExpression(10, intMapping),
26+
new SqlConstantExpression(20, intMapping)
27+
])
28+
],
29+
[
30+
RelationalQueryableMethodTranslatingExpressionVisitor.ValuesOrderingColumnName,
31+
"Kept",
32+
"Dropped"
33+
]);
34+
35+
var pruner = new TestSqlTreePruner();
36+
pruner.RegisterColumn(alias, RelationalQueryableMethodTranslatingExpressionVisitor.ValuesOrderingColumnName);
37+
pruner.RegisterColumn(alias, "Kept");
38+
39+
var pruned = pruner.PruneValuesPublic(values);
40+
41+
Assert.Equal(
42+
[RelationalQueryableMethodTranslatingExpressionVisitor.ValuesOrderingColumnName, "Kept"],
43+
pruned.ColumnNames);
44+
Assert.Equal(2, Assert.Single(pruned.RowValues!).Values.Count);
45+
}
46+
47+
private sealed class TestSqlTreePruner : SqlTreePruner
48+
{
49+
public void RegisterColumn(string tableAlias, string columnName)
50+
=> Visit(new ColumnExpression(columnName, tableAlias, typeof(int), IntTypeMapping.Default, nullable: false));
51+
52+
public ValuesExpression PruneValuesPublic(ValuesExpression values)
53+
=> PruneValues(values);
54+
}
55+
}

0 commit comments

Comments
 (0)