Skip to content

Improve relational model integration in Query#38346

Open
AndriySvyryd wants to merge 5 commits into
mainfrom
QueryModel
Open

Improve relational model integration in Query#38346
AndriySvyryd wants to merge 5 commits into
mainfrom
QueryModel

Conversation

@AndriySvyryd
Copy link
Copy Markdown
Member

@AndriySvyryd AndriySvyryd commented Jun 2, 2026

Fixes #38060
Fixes #35466
Fixes #32853

The query pipeline previously fell back to model‑wide accessors (GetJsonPropertyName, container‑column‑by‑name scans) at translation time, which produced wrong/ambiguous results under entity splitting, TPT, and JSON‑on‑view scenarios. This change threads the actual table set and JSON element metadata through the existing relational query expressions and consolidates priority logic in one place.

Changes

  • New GetQueryMappings() internal helper (RelationalTypeBaseExtensions) returns storage mappings in priority order — default SQL query → default function → view → table — and replaces all GetViewOrTableMappings() call sites in the query pipeline. Casts directly to the concrete List<TMapping> runtime type and filters in place to avoid LINQ allocations.
  • StructuralTypeProjectionExpression.TableMap (optional IReadOnlyDictionary<ITableBase, string>) — threaded through TPT, single‑table, entity‑splitting and TPC CreateSelect branches, preserved across MakeNullable, UpdateEntityType, VisitChildren, set‑op merge, and subquery lift. BindProperty, TryRewriteEntityEquality, and GenerateMaterializationCondition now scope their principal‑split‑table lookup to the actually‑projected tables.
  • JsonQueryExpression.FindJsonElement(IPropertyBase) — returns the IRelationalJsonElement whose containing column matches JsonColumn when available, otherwise the first element from the property's mappings. BindProperty/BindStructuralProperty and the OPENJSON/json_each translators in RelationalQueryableMethodTranslatingExpressionVisitor, SqlServer, and Sqlite now use this instead of model‑wide GetJsonPropertyName().
  • JsonProjectionInfo.JsonColumn + ColumnExpression.Column preservation in MakeNullable/ApplyTypeMapping — the shaper now uses the column resolved at CreateSelect time, falling back to a model scan only when there's no underlying IColumnBase (synthetic JSON columns over OPENJSON/json_each).

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot reviewed 34 out of 35 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • src/EFCore.Relational/Properties/RelationalStrings.Designer.cs: Language not supported

Comment thread src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs Outdated
@AndriySvyryd AndriySvyryd marked this pull request as ready for review June 2, 2026 06:54
@AndriySvyryd AndriySvyryd requested a review from a team as a code owner June 2, 2026 06:54
Copilot AI review requested due to automatic review settings June 2, 2026 06:54
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 36 out of 37 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • src/EFCore.Relational/Properties/RelationalStrings.Designer.cs: Language not supported

Comment on lines +4251 to +4258
// Preserve the underlying model column through subquery boundaries so JsonQueryExpression.FindJsonElement keeps
// matching after lifts (e.g. LiftJsonQueryFromSubquery wraps the json column in a JsonScalarExpression).
column: subqueryProjection.Expression switch
{
ColumnExpression { Column: { } column } => column,
JsonScalarExpression { Json: ColumnExpression { Column: { } jsonColumn } } => jsonColumn,
_ => null
},
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

👀

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks a bit odd... The idea here was for ColumnExpression to reference the relational model IColumn it refers to, similar to how TableExpression references its the relational model ITableBase; IIRC I did this specifically so that e.g. the translation can look at a ColumnExpression and know whether it has a database index, since that can affect the translation strategy.

This change makes it so that a ColumnExpression referring to a JsonScalarExpression will point the the relational model column which contains that JSON scalar, which doesn't seem right (or at least changes the meaning of ColumnExpression.Column significantly). I'd propose leaving this null at least for now - ColumnExpression.Column is optional anyway, and doesn't have to be populated.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ok, changed this to only set the containing column when the result is going to be JsonQueryExpression.JsonColumn to preserve the semantics

Comment thread src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs
Copilot AI review requested due to automatic review settings June 4, 2026 20:37
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 23 out of 24 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • src/EFCore.Relational/Properties/RelationalStrings.Designer.cs: Language not supported

Comment thread src/EFCore.Relational/Query/JsonQueryExpression.cs
Comment thread src/EFCore.Relational/Metadata/Internal/RelationalTypeBaseExtensions.cs Outdated
Copilot AI review requested due to automatic review settings June 5, 2026 05:08
@AndriySvyryd AndriySvyryd requested a review from cincuranet June 5, 2026 05:08
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • src/EFCore.Relational/Properties/RelationalStrings.Designer.cs: Language not supported

Comment thread src/EFCore.Relational/Query/JsonQueryExpression.cs Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 5, 2026 05:20
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • src/EFCore.Relational/Properties/RelationalStrings.Designer.cs: Language not supported

Comment thread src/EFCore.Relational/Query/JsonQueryExpression.cs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants