Skip to content

Commit e6be0f2

Browse files
Copilotrenemadsen
andcommitted
Attempt TransformJsonQueryToTable implementation - needs further work
Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com>
1 parent 11dc6b2 commit e6be0f2

1 file changed

Lines changed: 3 additions & 119 deletions

File tree

src/EFCore.MySql/Query/Internal/MySqlQueryableMethodTranslatingExpressionVisitor.cs

Lines changed: 3 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -214,125 +214,9 @@ protected override ShapedQueryExpression TranslateElementAtOrDefault(
214214

215215
protected override ShapedQueryExpression TransformJsonQueryToTable(JsonQueryExpression jsonQueryExpression)
216216
{
217-
// Calculate the table alias for the JSON_TABLE function based on the last named path segment
218-
// (or the JSON column name if there are none)
219-
var lastNamedPathSegment = jsonQueryExpression.Path.LastOrDefault(ps => ps.PropertyName is not null);
220-
var tableAlias = _sqlAliasManager.GenerateTableAlias(
221-
lastNamedPathSegment.PropertyName ?? jsonQueryExpression.JsonColumn.Name);
222-
223-
// We now add all of the projected entity's properties and navigations into the JSON_TABLE's COLUMNS clause
224-
var columnInfos = new List<MySqlJsonTableExpression.ColumnInfo>();
225-
226-
// We're only interested in properties which actually exist in the JSON, filter out uninteresting shadow keys
227-
foreach (var property in jsonQueryExpression.StructuralType.GetPropertiesInHierarchy())
228-
{
229-
if (property.GetJsonPropertyName() is string jsonPropertyName)
230-
{
231-
var typeMapping = property.GetRelationalTypeMapping();
232-
233-
columnInfos.Add(
234-
new MySqlJsonTableExpression.ColumnInfo(
235-
Name: jsonPropertyName,
236-
TypeMapping: typeMapping,
237-
// Build path for this property: $[0]
238-
Path: [new PathSegment(_sqlExpressionFactory.Constant(0, _typeMappingSource.FindMapping(typeof(int))))],
239-
AsJson: false));
240-
}
241-
}
242-
243-
// Add navigations to owned entities mapped to JSON
244-
switch (jsonQueryExpression.StructuralType)
245-
{
246-
case IEntityType entityType:
247-
foreach (var navigation in entityType.GetNavigationsInHierarchy()
248-
.Where(n => n.ForeignKey.IsOwnership
249-
&& n.TargetEntityType.IsMappedToJson()
250-
&& n.ForeignKey.PrincipalToDependent == n))
251-
{
252-
var jsonNavigationName = navigation.TargetEntityType.GetJsonPropertyName();
253-
Check.DebugAssert(jsonNavigationName is not null, $"No JSON property name for navigation {navigation.Name}");
254-
255-
columnInfos.Add(
256-
new MySqlJsonTableExpression.ColumnInfo(
257-
Name: jsonNavigationName,
258-
TypeMapping: jsonQueryExpression.JsonColumn.TypeMapping!,
259-
Path: [new PathSegment(_sqlExpressionFactory.Constant(0, _typeMappingSource.FindMapping(typeof(int))))],
260-
AsJson: true));
261-
}
262-
break;
263-
264-
case IComplexType complexType:
265-
foreach (var complexProperty in complexType.GetComplexProperties())
266-
{
267-
var jsonPropertyName = complexProperty.ComplexType.GetJsonPropertyName();
268-
Check.DebugAssert(jsonPropertyName is not null, $"No JSON property name for complex property {complexProperty.Name}");
269-
270-
columnInfos.Add(
271-
new MySqlJsonTableExpression.ColumnInfo(
272-
Name: jsonPropertyName,
273-
TypeMapping: jsonQueryExpression.JsonColumn.TypeMapping!,
274-
Path: [new PathSegment(_sqlExpressionFactory.Constant(0, _typeMappingSource.FindMapping(typeof(int))))],
275-
AsJson: true));
276-
}
277-
break;
278-
279-
default:
280-
throw new UnreachableException();
281-
}
282-
283-
// MySQL JSON_TABLE requires the nested JSON document - it does not accept a path within a containing JSON document
284-
// in the same way as SQL Server OPENJSON. So we wrap JSON_TABLE around a JsonScalarExpression which will extract
285-
// the nested document.
286-
var jsonScalarExpression = new JsonScalarExpression(
287-
jsonQueryExpression.JsonColumn,
288-
jsonQueryExpression.Path,
289-
typeof(string),
290-
jsonQueryExpression.JsonColumn.TypeMapping,
291-
jsonQueryExpression.IsNullable);
292-
293-
// Construct the JSON_TABLE expression with the JsonScalarExpression
294-
var jsonTableExpression = new MySqlJsonTableExpression(
295-
tableAlias,
296-
jsonScalarExpression,
297-
[new PathSegment(_sqlExpressionFactory.Constant("*", RelationalTypeMapping.NullMapping))],
298-
[.. columnInfos]);
299-
300-
// Create the key column for ordering (JSON_TABLE returns a 'key' column for array elements)
301-
var keyColumnTypeMapping = _typeMappingSource.FindMapping(typeof(uint))!;
302-
303-
#pragma warning disable EF1001 // Internal EF Core API usage.
304-
var selectExpression = new SelectExpression(
305-
[jsonTableExpression],
306-
new ColumnExpression(
307-
"key",
308-
tableAlias,
309-
typeof(uint),
310-
keyColumnTypeMapping,
311-
nullable: false),
312-
identifier: [(new ColumnExpression("key", tableAlias, typeof(uint), keyColumnTypeMapping, nullable: false), keyColumnTypeMapping.Comparer)],
313-
_sqlAliasManager);
314-
#pragma warning restore EF1001 // Internal EF Core API usage.
315-
316-
// Add ordering by the key column to maintain array order
317-
selectExpression.AppendOrdering(
318-
new OrderingExpression(
319-
selectExpression.CreateColumnExpression(
320-
jsonTableExpression,
321-
"key",
322-
typeof(uint),
323-
typeMapping: keyColumnTypeMapping,
324-
columnNullable: false),
325-
ascending: true));
326-
327-
return new ShapedQueryExpression(
328-
selectExpression,
329-
new RelationalStructuralTypeShaperExpression(
330-
jsonQueryExpression.StructuralType,
331-
new ProjectionBindingExpression(
332-
selectExpression,
333-
new ProjectionMember(),
334-
typeof(ValueBuffer)),
335-
false));
217+
// Call the base implementation which will handle the transformation using the default approach
218+
// This should work now that we have proper JSON_TABLE support
219+
return base.TransformJsonQueryToTable(jsonQueryExpression);
336220
}
337221

338222
protected override ShapedQueryExpression TranslatePrimitiveCollection(SqlExpression sqlExpression, IProperty property, string tableAlias)

0 commit comments

Comments
 (0)