From 05e697083548e441477ece30a14f41777829d8d3 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Sun, 11 Feb 2024 11:00:23 +0100 Subject: [PATCH] Sync to EF 9.0.0-preview.1.24081.2 --- Directory.Packages.props | 10 +- EFCore.PG.sln.DotSettings | 4 + .../PgTableValuedFunctionExpression.cs | 27 +- .../Internal/PgUnnestExpression.cs | 8 + ...NpgsqlDeleteConvertingExpressionVisitor.cs | 4 +- .../Query/Internal/NpgsqlQuerySqlGenerator.cs | 9 +- .../NpgsqlQueryTranslationPostprocessor.cs | 2 +- ...sqlQueryTranslationPostprocessorFactory.cs | 5 +- ...yableMethodTranslatingExpressionVisitor.cs | 251 +++---- ...thodTranslatingExpressionVisitorFactory.cs | 5 +- .../Internal/NpgsqlUnnestPostprocessor.cs | 4 +- .../NpgsqlCharacterStringTypeMapping.cs | 16 +- .../BadDataJsonDeserializationNpgsqlTest.cs | 9 + .../BuiltInDataTypesNpgsqlTest.cs | 2 +- .../ComplexTypeBulkUpdatesNpgsqlTest.cs | 122 ++++ .../NonSharedModelBulkUpdatesNpgsqlTest.cs | 49 +- .../NorthwindBulkUpdatesNpgsqlTest.cs | 450 ++++++------- ...FiltersInheritanceBulkUpdatesNpgsqlTest.cs | 28 +- .../TPCInheritanceBulkUpdatesNpgsqlTest.cs | 28 +- ...FiltersInheritanceBulkUpdatesNpgsqlTest.cs | 47 +- .../TPTInheritanceBulkUpdatesNpgsqlTest.cs | 42 +- .../JsonTypesNpgsqlTest.cs | 14 +- .../MaterializationInterceptionNpgsqlTest.cs | 32 +- .../MigrationsInfrastructureNpgsqlTest.cs | 20 + .../Migrations/MigrationsNpgsqlTest.cs | 25 +- .../NpgsqlModelBuilderGenericTest.cs | 97 +++ .../NpgsqlModelBuilderTestBase.cs | 40 ++ .../NpgsqlComplianceTest.cs | 1 + .../NpgsqlDatabaseCreatorTest.cs | 4 +- .../AdHocAdvancedMappingsQueryNpgsqlTest.cs | 19 + ...sqlTest.cs => AdHocJsonQueryNpgsqlTest.cs} | 314 ++------- ...t.cs => AdHocManyToManyQueryNpgsqlTest.cs} | 2 +- .../AdHocMiscellaneousQueryNpgsqlTest.cs | 38 ++ .../Query/AdHocNavigationsQueryNpgsqlTest.cs | 17 + .../Query/AdHocQueryFiltersQueryNpgsqlTest.cs | 9 + .../AdHocQuerySplittingQueryNpgsqlTest.cs | 40 ++ .../Query/ArrayQueryTest.cs | 2 +- .../ComplexNavigationsQueryNpgsqlTest.cs | 6 +- .../Query/ComplexTypeQueryNpgsqlTest.cs | 88 +-- .../Query/Ef6GroupByNpgsqlTest.cs | 40 +- .../Query/EntitySplittingQueryNpgsqlTest.cs | 70 +- .../Query/FunkyDataQueryNpgsqlTest.cs | 24 - .../Query/JsonQueryNpgsqlTest.cs | 308 ++++----- .../Query/NorthwindGroupByQueryNpgsqlTest.cs | 612 +++++++++--------- .../NorthwindMiscellaneousQueryNpgsqlTest.cs | 8 +- .../NorthwindSetOperationsQueryNpgsqlTest.cs | 20 +- .../Query/NorthwindSqlQueryNpgsqlTest.cs | 8 +- .../PrimitiveCollectionsQueryNpgsqlTest.cs | 341 ++++++++-- .../Query/RangeQueryNpgsqlTest.cs | 12 +- .../Query/SimpleQueryNpgsqlTest.cs | 21 - .../Scaffolding/CompiledModelNpgsqlTest.cs | 59 ++ .../NpgsqlDatabaseModelFactoryTest.cs | 13 +- .../TestUtilities/NpgsqlTestStoreFactory.cs | 1 + .../Update/JsonUpdateNpgsqlTest.cs | 74 +-- .../NodaTimeQueryNpgsqlTest.cs | 24 +- .../Storage/NpgsqlArrayValueConverterTest.cs | 12 +- 56 files changed, 2044 insertions(+), 1493 deletions(-) create mode 100644 test/EFCore.PG.FunctionalTests/BadDataJsonDeserializationNpgsqlTest.cs create mode 100644 test/EFCore.PG.FunctionalTests/ModelBuilding/NpgsqlModelBuilderGenericTest.cs create mode 100644 test/EFCore.PG.FunctionalTests/ModelBuilding/NpgsqlModelBuilderTestBase.cs create mode 100644 test/EFCore.PG.FunctionalTests/Query/AdHocAdvancedMappingsQueryNpgsqlTest.cs rename test/EFCore.PG.FunctionalTests/Query/{JsonQueryAdHocNpgsqlTest.cs => AdHocJsonQueryNpgsqlTest.cs} (53%) rename test/EFCore.PG.FunctionalTests/Query/{ManyToManyHeterogeneousQueryNpgsqlTest.cs => AdHocManyToManyQueryNpgsqlTest.cs} (68%) create mode 100644 test/EFCore.PG.FunctionalTests/Query/AdHocMiscellaneousQueryNpgsqlTest.cs create mode 100644 test/EFCore.PG.FunctionalTests/Query/AdHocNavigationsQueryNpgsqlTest.cs create mode 100644 test/EFCore.PG.FunctionalTests/Query/AdHocQueryFiltersQueryNpgsqlTest.cs create mode 100644 test/EFCore.PG.FunctionalTests/Query/AdHocQuerySplittingQueryNpgsqlTest.cs delete mode 100644 test/EFCore.PG.FunctionalTests/Query/SimpleQueryNpgsqlTest.cs create mode 100644 test/EFCore.PG.FunctionalTests/Scaffolding/CompiledModelNpgsqlTest.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index 19b7d4b62..c6c22d7a8 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,8 +1,8 @@ - 8.0.0 - 8.0.0 - 8.0.0 + 9.0.0-preview.1.24081.2 + 9.0.0-preview.1.24080.9 + 8.0.2 @@ -23,8 +23,8 @@ - - + + diff --git a/EFCore.PG.sln.DotSettings b/EFCore.PG.sln.DotSettings index 06af66077..0ae73aa7c 100644 --- a/EFCore.PG.sln.DotSettings +++ b/EFCore.PG.sln.DotSettings @@ -275,6 +275,7 @@ True True True +<<<<<<< HEAD True True True @@ -391,3 +392,6 @@ True True True + True + True + diff --git a/src/EFCore.PG/Query/Expressions/Internal/PgTableValuedFunctionExpression.cs b/src/EFCore.PG/Query/Expressions/Internal/PgTableValuedFunctionExpression.cs index 19c153129..e4e02bc43 100644 --- a/src/EFCore.PG/Query/Expressions/Internal/PgTableValuedFunctionExpression.cs +++ b/src/EFCore.PG/Query/Expressions/Internal/PgTableValuedFunctionExpression.cs @@ -21,8 +21,7 @@ namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.Expressions.Internal; /// doing so can result in application failures when updating to a new Entity Framework Core release. /// /// -public class PgTableValuedFunctionExpression : TableValuedFunctionExpression, - IEquatable, IClonableTableExpressionBase +public class PgTableValuedFunctionExpression : TableValuedFunctionExpression, IEquatable { /// /// The name of the column to be projected out from the unnest call. @@ -77,15 +76,25 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public override PgTableValuedFunctionExpression Update(IReadOnlyList arguments) - => !arguments.SequenceEqual(Arguments) - ? new PgTableValuedFunctionExpression(Alias, Name, arguments, ColumnInfos, WithOrdinality) - : this; + => arguments.SequenceEqual(Arguments, ReferenceEqualityComparer.Instance) + ? this + : new PgTableValuedFunctionExpression(Alias, Name, arguments, ColumnInfos, WithOrdinality); + + /// + public override TableExpressionBase Clone(string? alias, ExpressionVisitor cloningExpressionVisitor) + { + var arguments = new SqlExpression[Arguments.Count]; + for (var i = 0; i < arguments.Length; i++) + { + arguments[i] = (SqlExpression)cloningExpressionVisitor.Visit(Arguments[i]); + } + + return new PgTableValuedFunctionExpression(Alias, Name, arguments, ColumnInfos, WithOrdinality); + } - // TODO: This is a hack for https://github.com/npgsql/efcore.pg/issues/3023; we notably don't visit the arguments, which we should - // (but can't, since the Clone() API doesn't accept the cloning visitor). /// - public TableExpressionBase Clone() - => new PgTableValuedFunctionExpression(Alias, Name, Arguments, ColumnInfos, WithOrdinality); + public override PgTableValuedFunctionExpression WithAlias(string newAlias) + => new(newAlias, Name, Arguments, ColumnInfos, WithOrdinality); /// protected override void Print(ExpressionPrinter expressionPrinter) diff --git a/src/EFCore.PG/Query/Expressions/Internal/PgUnnestExpression.cs b/src/EFCore.PG/Query/Expressions/Internal/PgUnnestExpression.cs index e27f49d8e..941014fa0 100644 --- a/src/EFCore.PG/Query/Expressions/Internal/PgUnnestExpression.cs +++ b/src/EFCore.PG/Query/Expressions/Internal/PgUnnestExpression.cs @@ -85,4 +85,12 @@ public virtual PgUnnestExpression Update(SqlExpression array) => array == Array ? this : new PgUnnestExpression(Alias, array, ColumnName, WithOrdinality); + + /// + public override TableExpressionBase Clone(string? alias, ExpressionVisitor cloningExpressionVisitor) + => new PgUnnestExpression(alias!, (SqlExpression)cloningExpressionVisitor.Visit(Array), ColumnName, WithOrdinality); + + /// + public override PgTableValuedFunctionExpression WithAlias(string newAlias) + => new(newAlias, Name, Arguments, ColumnInfos, WithOrdinality); } diff --git a/src/EFCore.PG/Query/Internal/NpgsqlDeleteConvertingExpressionVisitor.cs b/src/EFCore.PG/Query/Internal/NpgsqlDeleteConvertingExpressionVisitor.cs index cf7a4f7b5..c2712d10b 100644 --- a/src/EFCore.PG/Query/Internal/NpgsqlDeleteConvertingExpressionVisitor.cs +++ b/src/EFCore.PG/Query/Internal/NpgsqlDeleteConvertingExpressionVisitor.cs @@ -56,7 +56,7 @@ protected virtual Expression VisitDelete(DeleteExpression deleteExpression) switch (tableBase) { case TableExpression tableExpression: - if (tableExpression != deleteExpression.Table) + if (tableExpression.Alias != deleteExpression.Table.Alias) { fromItems.Add(tableExpression); } @@ -64,7 +64,7 @@ protected virtual Expression VisitDelete(DeleteExpression deleteExpression) break; case InnerJoinExpression { Table: { } tableExpression } innerJoinExpression: - if (tableExpression != deleteExpression.Table) + if (tableExpression.Alias != deleteExpression.Table.Alias) { fromItems.Add(tableExpression); } diff --git a/src/EFCore.PG/Query/Internal/NpgsqlQuerySqlGenerator.cs b/src/EFCore.PG/Query/Internal/NpgsqlQuerySqlGenerator.cs index 7569ecd1e..3afb677bf 100644 --- a/src/EFCore.PG/Query/Internal/NpgsqlQuerySqlGenerator.cs +++ b/src/EFCore.PG/Query/Internal/NpgsqlQuerySqlGenerator.cs @@ -760,6 +760,11 @@ protected override Expression VisitValues(ValuesExpression valuesExpression) /// protected override void GenerateValues(ValuesExpression valuesExpression) { + if (valuesExpression.RowValues.Count == 0) + { + throw new InvalidOperationException(RelationalStrings.EmptyCollectionNotSupportedAsInlineQueryRoot); + } + // PostgreSQL supports providing the names of columns projected out of VALUES: (VALUES (1, 3), (2, 4)) AS x(a, b). // But since other databases sometimes don't, the default relational implementation is complex, involving a SELECT for the first row // and a UNION All on the rest. Override to do the nice simple thing. @@ -1540,8 +1545,8 @@ public bool ContainsReferenceToMainTable(SqlExpression sqlExpression) return expression; } - if (expression is ColumnExpression columnExpression - && columnExpression.Table == mainTable) + if (expression is ColumnExpression { TableAlias: var tableAlias } + && tableAlias == mainTable.Alias) { _containsReference = true; diff --git a/src/EFCore.PG/Query/Internal/NpgsqlQueryTranslationPostprocessor.cs b/src/EFCore.PG/Query/Internal/NpgsqlQueryTranslationPostprocessor.cs index 7b9a9828d..de98b5f84 100644 --- a/src/EFCore.PG/Query/Internal/NpgsqlQueryTranslationPostprocessor.cs +++ b/src/EFCore.PG/Query/Internal/NpgsqlQueryTranslationPostprocessor.cs @@ -17,7 +17,7 @@ public class NpgsqlQueryTranslationPostprocessor : RelationalQueryTranslationPos public NpgsqlQueryTranslationPostprocessor( QueryTranslationPostprocessorDependencies dependencies, RelationalQueryTranslationPostprocessorDependencies relationalDependencies, - QueryCompilationContext queryCompilationContext) + RelationalQueryCompilationContext queryCompilationContext) : base(dependencies, relationalDependencies, queryCompilationContext) { } diff --git a/src/EFCore.PG/Query/Internal/NpgsqlQueryTranslationPostprocessorFactory.cs b/src/EFCore.PG/Query/Internal/NpgsqlQueryTranslationPostprocessorFactory.cs index 0d28d80a0..e31cc18be 100644 --- a/src/EFCore.PG/Query/Internal/NpgsqlQueryTranslationPostprocessorFactory.cs +++ b/src/EFCore.PG/Query/Internal/NpgsqlQueryTranslationPostprocessorFactory.cs @@ -34,5 +34,8 @@ public NpgsqlQueryTranslationPostprocessorFactory( /// public virtual QueryTranslationPostprocessor Create(QueryCompilationContext queryCompilationContext) - => new NpgsqlQueryTranslationPostprocessor(Dependencies, RelationalDependencies, queryCompilationContext); + => new NpgsqlQueryTranslationPostprocessor( + Dependencies, + RelationalDependencies, + (RelationalQueryCompilationContext)queryCompilationContext); } diff --git a/src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitor.cs index 208e033d8..d258ebb8c 100644 --- a/src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitor.cs @@ -15,8 +15,11 @@ namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.Internal; /// public class NpgsqlQueryableMethodTranslatingExpressionVisitor : RelationalQueryableMethodTranslatingExpressionVisitor { + private readonly RelationalQueryCompilationContext _queryCompilationContext; private readonly NpgsqlTypeMappingSource _typeMappingSource; private readonly NpgsqlSqlExpressionFactory _sqlExpressionFactory; + private RelationalTypeMapping? _ordinalityTypeMapping; + #region MethodInfos @@ -43,9 +46,10 @@ private static readonly MethodInfo ILike2MethodInfo public NpgsqlQueryableMethodTranslatingExpressionVisitor( QueryableMethodTranslatingExpressionVisitorDependencies dependencies, RelationalQueryableMethodTranslatingExpressionVisitorDependencies relationalDependencies, - QueryCompilationContext queryCompilationContext) + RelationalQueryCompilationContext queryCompilationContext) : base(dependencies, relationalDependencies, queryCompilationContext) { + _queryCompilationContext = queryCompilationContext; _typeMappingSource = (NpgsqlTypeMappingSource)relationalDependencies.TypeMappingSource; _sqlExpressionFactory = (NpgsqlSqlExpressionFactory)relationalDependencies.SqlExpressionFactory; } @@ -59,6 +63,7 @@ public NpgsqlQueryableMethodTranslatingExpressionVisitor( protected NpgsqlQueryableMethodTranslatingExpressionVisitor(NpgsqlQueryableMethodTranslatingExpressionVisitor parentVisitor) : base(parentVisitor) { + _queryCompilationContext = parentVisitor._queryCompilationContext; _typeMappingSource = parentVisitor._typeMappingSource; _sqlExpressionFactory = parentVisitor._sqlExpressionFactory; } @@ -99,7 +104,7 @@ protected override ShapedQueryExpression TranslatePrimitiveCollection( // a special case for geometry collections, where we use SelectExpression selectExpression; -#pragma warning disable EF1001 +#pragma warning disable EF1001 // SelectExpression constructors are currently internal // TODO: Parameters have no type mapping. We can check whether the expression type is one of the NTS geometry collection types, // though in a perfect world we'd actually infer this. In other words, when the type mapping of the element is inferred further on, // we'd replace the unnest expression with ST_Dump. We could even have a special expression type which means "indeterminate, must be @@ -108,8 +113,10 @@ protected override ShapedQueryExpression TranslatePrimitiveCollection( { // TODO: For geometry collection support (not yet supported), see #2850. selectExpression = new SelectExpression( - new TableValuedFunctionExpression(tableAlias, "ST_Dump", new[] { sqlExpression }), - "geom", elementClrType, elementTypeMapping, isElementNullable); + [new TableValuedFunctionExpression(tableAlias, "ST_Dump", new[] { sqlExpression })], + new ColumnExpression("geom", tableAlias, elementClrType.UnwrapNullableType(), elementTypeMapping, isElementNullable), + identifier: [], // TODO + _queryCompilationContext.SqlAliasManager); } else { @@ -123,14 +130,15 @@ protected override ShapedQueryExpression TranslatePrimitiveCollection( // to add ordering like in most other providers (https://www.postgresql.org/docs/current/functions-array.html) // We also don't need to apply any casts or typing, since PG arrays are fully typed (unlike e.g. a JSON string). selectExpression = new SelectExpression( - new PgUnnestExpression(tableAlias, sqlExpression, "value"), - columnName: "value", - columnType: elementClrType, - columnTypeMapping: elementTypeMapping, - isColumnNullable: isElementNullable, - identifierColumnName: "ordinality", - identifierColumnType: typeof(int), - identifierColumnTypeMapping: _typeMappingSource.FindMapping(typeof(int))); + [new PgUnnestExpression(tableAlias, sqlExpression, "value")], + new ColumnExpression( + "value", + tableAlias, + elementClrType.UnwrapNullableType(), + elementTypeMapping, + isElementNullable), + identifier: [GenerateOrdinalityIdentifier(tableAlias)], + _queryCompilationContext.SqlAliasManager); } #pragma warning restore EF1001 @@ -160,7 +168,9 @@ protected override ShapedQueryExpression TransformJsonQueryToTable(JsonQueryExpr // Calculate the table alias for the jsonb_to_recordset function based on the last named path segment // (or the JSON column name if there are none) var lastNamedPathSegment = jsonQueryExpression.Path.LastOrDefault(ps => ps.PropertyName is not null); - var tableAlias = char.ToLowerInvariant((lastNamedPathSegment.PropertyName ?? jsonQueryExpression.JsonColumn.Name)[0]).ToString(); + var tableAlias = + _queryCompilationContext.SqlAliasManager.GenerateTableAlias( + lastNamedPathSegment.PropertyName ?? jsonQueryExpression.JsonColumn.Name); // TODO: This relies on nested JSON columns flowing across the type mapping of the top-most containing JSON column, check this. var functionName = jsonQueryExpression.JsonColumn switch @@ -216,13 +226,13 @@ protected override ShapedQueryExpression TransformJsonQueryToTable(JsonQueryExpr var jsonToRecordSetExpression = new PgTableValuedFunctionExpression( tableAlias, functionName, new[] { jsonScalarExpression }, columnInfos, withOrdinality: true); -#pragma warning disable EF1001 // Internal EF Core API usage. - var selectExpression = new SelectExpression( +#pragma warning disable EF1001 // SelectExpression constructors are currently internal + var selectExpression = CreateSelect( jsonQueryExpression, jsonToRecordSetExpression, - identifierColumnName: "ordinality", - identifierColumnType: typeof(int), - identifierColumnTypeMapping: _typeMappingSource.FindMapping(typeof(int))!); + "ordinality", + typeof(int), + _typeMappingSource.FindMapping(typeof(int))!); #pragma warning restore EF1001 // Internal EF Core API usage. return new ShapedQueryExpression( @@ -253,7 +263,7 @@ static IEnumerable GetAllNavigationsInHierarchy(IEntityType entityT /// protected override Expression ApplyInferredTypeMappings( Expression expression, - IReadOnlyDictionary<(TableExpressionBase, string), RelationalTypeMapping?> inferredTypeMappings) + IReadOnlyDictionary<(string, string), RelationalTypeMapping?> inferredTypeMappings) => new NpgsqlInferredTypeMappingApplier( RelationalDependencies.Model, _typeMappingSource, _sqlExpressionFactory, inferredTypeMappings).Visit(expression); @@ -267,7 +277,7 @@ protected override Expression ApplyInferredTypeMappings( { if (source.QueryExpression is SelectExpression { - Tables: [(PgUnnestExpression or ValuesExpression { ColumnNames: ["_ord", "Value"] }) and var sourceTable], + Tables: [var sourceTable], Predicate: null, GroupBy: [], Having: null, @@ -275,6 +285,7 @@ protected override Expression ApplyInferredTypeMappings( Limit: null, Offset: null } + && TryGetArray(sourceTable, out var array) && TranslateLambdaExpression(source, predicate) is { } translatedPredicate) { switch (translatedPredicate) @@ -287,11 +298,11 @@ protected override Expression ApplyInferredTypeMappings( Pattern: ColumnExpression pattern, EscapeChar: SqlConstantExpression { Value: "" } } - when pattern.Table == sourceTable: + when pattern.TableAlias == sourceTable.Alias: { return BuildSimplifiedShapedQuery( source, - _sqlExpressionFactory.All(match, GetArray(sourceTable), PgAllOperatorType.Like)); + _sqlExpressionFactory.All(match, array, PgAllOperatorType.Like)); } // Pattern match for: new[] { "a", "b", "c" }.All(p => EF.Functions.Like(e.SomeText, p)), @@ -302,11 +313,11 @@ protected override Expression ApplyInferredTypeMappings( Pattern: ColumnExpression pattern, EscapeChar: SqlConstantExpression { Value: "" } } - when pattern.Table == sourceTable: + when pattern.TableAlias == sourceTable.Alias: { return BuildSimplifiedShapedQuery( source, - _sqlExpressionFactory.All(match, GetArray(sourceTable), PgAllOperatorType.ILike)); + _sqlExpressionFactory.All(match, array, PgAllOperatorType.ILike)); } // Pattern match for: e.SomeArray.All(p => ints.Contains(p)) over non-column, @@ -316,9 +327,9 @@ protected override Expression ApplyInferredTypeMappings( Item: ColumnExpression sourceColumn, Array: var otherArray } - when sourceColumn.Table == sourceTable: + when sourceColumn.TableAlias == sourceTable.Alias: { - return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.ContainedBy(GetArray(sourceTable), otherArray)); + return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.ContainedBy(array, otherArray)); } // Pattern match for: new[] { 4, 5 }.All(p => e.SomeArray.Contains(p)) over column, @@ -329,9 +340,9 @@ protected override Expression ApplyInferredTypeMappings( Left: var otherArray, Right: PgNewArrayExpression { Expressions: [ColumnExpression sourceColumn] } } - when sourceColumn.Table == sourceTable: + when sourceColumn.TableAlias == sourceTable.Alias: { - return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.ContainedBy(GetArray(sourceTable), otherArray)); + return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.ContainedBy(array, otherArray)); } } } @@ -349,14 +360,15 @@ protected override Expression ApplyInferredTypeMappings( { if (source.QueryExpression is SelectExpression { - Tables: [(PgUnnestExpression or ValuesExpression { ColumnNames: ["_ord", "Value"] }) and var sourceTable], + Tables: [var sourceTable], Predicate: null, GroupBy: [], Having: null, IsDistinct: false, Limit: null, Offset: null - }) + } + && TryGetArray(sourceTable, out var array)) { // Pattern match: x.Array.Any() // Translation: cardinality(x.array) > 0 instead of EXISTS (SELECT 1 FROM FROM unnest(x.Array)) @@ -367,7 +379,7 @@ protected override Expression ApplyInferredTypeMappings( _sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( "cardinality", - new[] { GetArray(sourceTable) }, + new[] { array }, nullable: true, argumentsPropagateNullability: TrueArrays[1], typeof(int)), @@ -389,10 +401,10 @@ protected override Expression ApplyInferredTypeMappings( Pattern: ColumnExpression pattern, EscapeChar: SqlConstantExpression { Value: "" } } - when pattern.Table == sourceTable: + when pattern.TableAlias == sourceTable.Alias: { return BuildSimplifiedShapedQuery( - source, _sqlExpressionFactory.Any(match, GetArray(sourceTable), PgAnyOperatorType.Like)); + source, _sqlExpressionFactory.Any(match, array, PgAnyOperatorType.Like)); } // Pattern match: new[] { "a", "b", "c" }.Any(p => EF.Functions.Like(e.SomeText, p)) @@ -403,10 +415,10 @@ protected override Expression ApplyInferredTypeMappings( Pattern: ColumnExpression pattern, EscapeChar: SqlConstantExpression { Value: "" } } - when pattern.Table == sourceTable: + when pattern.TableAlias == sourceTable.Alias: { return BuildSimplifiedShapedQuery( - source, _sqlExpressionFactory.Any(match, GetArray(sourceTable), PgAnyOperatorType.ILike)); + source, _sqlExpressionFactory.Any(match, array, PgAnyOperatorType.ILike)); } // Array overlap over non-column @@ -417,9 +429,9 @@ protected override Expression ApplyInferredTypeMappings( Item: ColumnExpression sourceColumn, Array: var otherArray } - when sourceColumn.Table == sourceTable: + when sourceColumn.TableAlias == sourceTable.Alias: { - return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.Overlaps(GetArray(sourceTable), otherArray)); + return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.Overlaps(array, otherArray)); } // Array overlap over column @@ -431,9 +443,9 @@ protected override Expression ApplyInferredTypeMappings( Left: var otherArray, Right: PgNewArrayExpression { Expressions: [ColumnExpression sourceColumn] } } - when sourceColumn.Table == sourceTable: + when sourceColumn.TableAlias == sourceTable.Alias: { - return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.Overlaps(GetArray(sourceTable), otherArray)); + return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.Overlaps(array, otherArray)); } #region LTree translations @@ -446,14 +458,14 @@ protected override Expression ApplyInferredTypeMappings( Left: var ltree, Right: SqlUnaryExpression { OperatorType: ExpressionType.Convert, Operand: ColumnExpression lqueryColumn } } - when lqueryColumn.Table == sourceTable: + when lqueryColumn.TableAlias == sourceTable.Alias: { return BuildSimplifiedShapedQuery( source, new PgBinaryExpression( PgExpressionType.LTreeMatchesAny, ltree, - _sqlExpressionFactory.ApplyTypeMapping(GetArray(sourceTable), _typeMappingSource.FindMapping("lquery[]")), + _sqlExpressionFactory.ApplyTypeMapping(array, _typeMappingSource.FindMapping("lquery[]")), typeof(bool), typeMapping: _typeMappingSource.FindMapping(typeof(bool)))); } @@ -469,13 +481,13 @@ protected override Expression ApplyInferredTypeMappings( // Contains/ContainedBy can happen for non-LTree types too, so check that Right: { TypeMapping: NpgsqlLTreeTypeMapping } ltree } - when ltreeColumn.Table == sourceTable: + when ltreeColumn.TableAlias == sourceTable.Alias: { return BuildSimplifiedShapedQuery( source, new PgBinaryExpression( operatorType, - _sqlExpressionFactory.ApplyDefaultTypeMapping(GetArray(sourceTable)), + _sqlExpressionFactory.ApplyDefaultTypeMapping(array), ltree, typeof(bool), typeMapping: _typeMappingSource.FindMapping(typeof(bool)))); @@ -491,13 +503,13 @@ protected override Expression ApplyInferredTypeMappings( Left: ColumnExpression ltreeColumn, Right: var lquery } - when ltreeColumn.Table == sourceTable: + when ltreeColumn.TableAlias == sourceTable.Alias: { return BuildSimplifiedShapedQuery( source, new PgBinaryExpression( PgExpressionType.LTreeMatches, - _sqlExpressionFactory.ApplyDefaultTypeMapping(GetArray(sourceTable)), + _sqlExpressionFactory.ApplyDefaultTypeMapping(array), lquery, typeof(bool), typeMapping: _typeMappingSource.FindMapping(typeof(bool)))); @@ -512,13 +524,13 @@ protected override Expression ApplyInferredTypeMappings( Left: ColumnExpression ltreeColumn, Right: var lqueries } - when ltreeColumn.Table == sourceTable: + when ltreeColumn.TableAlias == sourceTable.Alias: { return BuildSimplifiedShapedQuery( source, new PgBinaryExpression( PgExpressionType.LTreeMatchesAny, - _sqlExpressionFactory.ApplyDefaultTypeMapping(GetArray(sourceTable)), + _sqlExpressionFactory.ApplyDefaultTypeMapping(array), lqueries, typeof(bool), typeMapping: _typeMappingSource.FindMapping(typeof(bool)))); @@ -578,26 +590,20 @@ protected override Expression ApplyInferredTypeMappings( /// protected override ShapedQueryExpression? TranslateContains(ShapedQueryExpression source, Expression item) { + // Note that most other simplifications convert ValuesExpression to unnest over array constructor, but we avoid doing that + // here for Contains, since the relational translation for ValuesExpression is better. if (source.QueryExpression is SelectExpression { - Tables: [(PgUnnestExpression or ValuesExpression { ColumnNames: ["_ord", "Value"] }) and var sourceTable], + Tables: [PgUnnestExpression { Array: var array }], Predicate: null, GroupBy: [], Having: null, IsDistinct: false, Limit: null, Offset: null - }) - { - if (TranslateExpression(item, applyDefaultTypeMapping: false) is not SqlExpression translatedItem) - { - return null; } - - // Note that most other simplifications here convert ValuesExpression to unnest over array constructor, but we avoid doing that - // here, since the relational translation for ValuesExpression is better. - var array = GetArray(sourceTable); - + && TranslateExpression(item, applyDefaultTypeMapping: false) is SqlExpression translatedItem) + { (translatedItem, array) = _sqlExpressionFactory.ApplyTypeMappingsOnItemAndArray(translatedItem, array); // When the array is a column, we translate Contains to array @> ARRAY[item]. GIN indexes on array are used, but null @@ -685,11 +691,13 @@ protected override Expression ApplyInferredTypeMappings( argumentsPropagateNullability: TrueArrays[1], typeof(int)); +#pragma warning disable EF1001 // SelectExpression constructors are currently internal return source.Update( - _sqlExpressionFactory.Select(translation), + new SelectExpression(translation, _queryCompilationContext.SqlAliasManager), Expression.Convert( new ProjectionBindingExpression(source.QueryExpression, new ProjectionMember(), typeof(int?)), typeof(int))); +#pragma warning restore EF1001 } return base.TranslateCount(source, predicate); @@ -736,16 +744,13 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s // TODO: Conflicting type mappings from both sides? var inferredTypeMapping = projectedColumn1.TypeMapping ?? projectedColumn2.TypeMapping; -#pragma warning disable EF1001 // Internal EF Core API usage. +#pragma warning disable EF1001 // SelectExpression constructors are currently internal + var tableAlias = unnestExpression1.Alias; var selectExpression = new SelectExpression( - new PgUnnestExpression(unnestExpression1.Alias, _sqlExpressionFactory.Add(array1, array2), "value"), - columnName: "value", - columnType: projectedColumn1.Type, - columnTypeMapping: inferredTypeMapping, - isColumnNullable: projectedColumn1.IsNullable || projectedColumn2.IsNullable, - identifierColumnName: "ordinality", - identifierColumnType: typeof(int), - identifierColumnTypeMapping: _typeMappingSource.FindMapping(typeof(int))); + [new PgUnnestExpression(tableAlias, _sqlExpressionFactory.Add(array1, array2), "value")], + new ColumnExpression("value", tableAlias, projectedColumn1.Type, inferredTypeMapping, projectedColumn1.IsNullable || projectedColumn2.IsNullable), + identifier: [GenerateOrdinalityIdentifier(tableAlias)], + _queryCompilationContext.SqlAliasManager); #pragma warning restore EF1001 // Internal EF Core API usage. // TODO: Simplify by using UpdateQueryExpression after https://github.com/dotnet/efcore/issues/31511 @@ -796,11 +801,14 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s && TranslateExpression(index) is { } translatedIndex) { // Note that PostgreSQL arrays are 1-based, so adjust the index. +#pragma warning disable EF1001 // SelectExpression constructors are currently internal return source.UpdateQueryExpression( - _sqlExpressionFactory.Select( + new SelectExpression( _sqlExpressionFactory.ArrayIndex( array, - GenerateOneBasedIndexExpression(translatedIndex), projectedColumn.IsNullable))); + GenerateOneBasedIndexExpression(translatedIndex), projectedColumn.IsNullable), + _queryCompilationContext.SqlAliasManager)); +#pragma warning restore EF1001 } return base.TranslateElementAtOrDefault(source, index, returnDefault); @@ -823,7 +831,7 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s // select expression should already contain our predicate. if (source.QueryExpression is SelectExpression { - Tables: [(PgUnnestExpression or ValuesExpression { ColumnNames: ["_ord", "Value"] }) and var sourceTable], + Tables: [var sourceTable], Predicate: var translatedPredicate, GroupBy: [], Having: null, @@ -832,6 +840,7 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s Offset: null, Orderings: [] } + && TryGetArray(sourceTable, out var array) && translatedPredicate is null ^ predicate is null) { if (translatedPredicate is null) @@ -856,7 +865,7 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s // Contains/ContainedBy can happen for non-LTree types too, so check that Right: { TypeMapping: NpgsqlLTreeTypeMapping } ltree } - when ltreeColumn.Table == sourceTable: + when ltreeColumn.TableAlias == sourceTable.Alias: { return BuildSimplifiedShapedQuery( source, @@ -864,7 +873,7 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s operatorType == PgExpressionType.Contains ? PgExpressionType.LTreeFirstAncestor : PgExpressionType.LTreeFirstDescendent, - _sqlExpressionFactory.ApplyDefaultTypeMapping(GetArray(sourceTable)), + _sqlExpressionFactory.ApplyDefaultTypeMapping(array), ltree, typeof(LTree), _typeMappingSource.FindMapping(typeof(LTree)))); @@ -880,13 +889,13 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s Left: ColumnExpression ltreeColumn, Right: var lquery } - when ltreeColumn.Table == sourceTable: + when ltreeColumn.TableAlias == sourceTable.Alias: { return BuildSimplifiedShapedQuery( source, new PgBinaryExpression( PgExpressionType.LTreeFirstMatches, - _sqlExpressionFactory.ApplyDefaultTypeMapping(GetArray(sourceTable)), + _sqlExpressionFactory.ApplyDefaultTypeMapping(array), lquery, typeof(LTree), _typeMappingSource.FindMapping(typeof(LTree)))); @@ -921,25 +930,24 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s && TryGetProjectedColumn(source, out var projectedColumn) && TranslateExpression(count) is { } translatedCount) { -#pragma warning disable EF1001 // Internal EF Core API usage. +#pragma warning disable EF1001 // SelectExpression constructors are currently internal + var tableAlias = unnestExpression.Alias; var selectExpression = new SelectExpression( - new PgUnnestExpression( - unnestExpression.Alias, - _sqlExpressionFactory.ArraySlice( - array, - lowerBound: GenerateOneBasedIndexExpression(translatedCount), - upperBound: null, - projectedColumn.IsNullable), - "value"), - "value", - projectedColumn.Type, - projectedColumn.TypeMapping, - isColumnNullable: projectedColumn.IsNullable, - // isColumnNullable: /*projectedColumn.IsNullable*/ true, // TODO: This fails because of a shaper check - identifierColumnName: "ordinality", - identifierColumnType: typeof(int), - identifierColumnTypeMapping: _typeMappingSource.FindMapping(typeof(int))); -#pragma warning restore EF1001 // Internal EF Core API usage. + [ + new PgUnnestExpression( + tableAlias, + _sqlExpressionFactory.ArraySlice( + array, + lowerBound: GenerateOneBasedIndexExpression(translatedCount), + upperBound: null, + // isColumnNullable: /*projectedColumn.IsNullable*/ true, // TODO: This fails because of a shaper check + projectedColumn.IsNullable), + "value"), + ], + new ColumnExpression("value", tableAlias, projectedColumn.Type, projectedColumn.TypeMapping, projectedColumn.IsNullable), + identifier: [GenerateOrdinalityIdentifier(tableAlias)], + _queryCompilationContext.SqlAliasManager); +#pragma warning restore EF1001 // TODO: Simplify by using UpdateQueryExpression after https://github.com/dotnet/efcore/issues/31511 Expression shaperExpression = new ProjectionBindingExpression( @@ -1027,16 +1035,12 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s projectedColumn.IsNullable); } -#pragma warning disable EF1001 // Internal EF Core API usage. +#pragma warning disable EF1001 // SelectExpression constructors are currently internal var selectExpression = new SelectExpression( - new PgUnnestExpression(unnestExpression.Alias, sliceExpression, "value"), - "value", - projectedColumn.Type, - projectedColumn.TypeMapping, - isColumnNullable: projectedColumn.IsNullable, - identifierColumnName: "ordinality", - identifierColumnType: typeof(int), - identifierColumnTypeMapping: _typeMappingSource.FindMapping(typeof(int))); + [new PgUnnestExpression(unnestExpression.Alias, sliceExpression, "value")], + new ColumnExpression("value", unnestExpression.Alias, projectedColumn.Type, projectedColumn.TypeMapping, projectedColumn.IsNullable), + [GenerateOrdinalityIdentifier(unnestExpression.Alias)], + _queryCompilationContext.SqlAliasManager); #pragma warning restore EF1001 // Internal EF Core API usage. // TODO: Simplify by using UpdateQueryExpression after https://github.com/dotnet/efcore/issues/31511 @@ -1145,11 +1149,7 @@ protected override bool IsValidSelectExpressionForExecuteDelete( var entityProjectionExpression = (StructuralTypeProjectionExpression)selectExpression.GetProjection(projectionBindingExpression); var column = entityProjectionExpression.BindProperty(shaper.StructuralType.GetProperties().First()); - table = column.Table; - if (table is JoinExpressionBase joinExpressionBase) - { - table = joinExpressionBase.Table; - } + table = selectExpression.Tables.Select(t => t.UnwrapJoin()).Single(t => t.Alias == column.TableAlias); } if (table is TableExpression te) @@ -1207,6 +1207,13 @@ private bool TryGetProjectedColumn( return false; } + private (ColumnExpression, ValueComparer) GenerateOrdinalityIdentifier(string tableAlias) + { + _ordinalityTypeMapping ??= _typeMappingSource.FindMapping("int")!; + return (new ColumnExpression("ordinality", tableAlias, typeof(int), _ordinalityTypeMapping, nullable: false), + _ordinalityTypeMapping.Comparer); + } + /// /// PostgreSQL array indexing is 1-based. If the index happens to be a constant, just increment it. Otherwise, append a +1 in the /// SQL. @@ -1216,28 +1223,29 @@ private SqlExpression GenerateOneBasedIndexExpression(SqlExpression expression) ? _sqlExpressionFactory.Constant(Convert.ToInt32(constant.Value) + 1, constant.TypeMapping) : _sqlExpressionFactory.Add(expression, _sqlExpressionFactory.Constant(1)); +#pragma warning disable EF1001 // SelectExpression constructors are currently internal private ShapedQueryExpression BuildSimplifiedShapedQuery(ShapedQueryExpression source, SqlExpression translation) => source.Update( - _sqlExpressionFactory.Select(translation), + new SelectExpression(translation, _queryCompilationContext.SqlAliasManager), Expression.Convert( new ProjectionBindingExpression(translation, new ProjectionMember(), typeof(bool?)), typeof(bool))); +#pragma warning restore EF1001 /// /// Extracts the out of . /// If a is given, converts its literal values into a . /// - private SqlExpression GetArray(TableExpressionBase tableExpression) + private bool TryGetArray(TableExpressionBase tableExpression, [NotNullWhen(true)] out SqlExpression? array) { - Check.DebugAssert( - tableExpression is PgUnnestExpression or ValuesExpression { ColumnNames: ["_ord", "Value"] }, - "Bad tableExpression"); - switch (tableExpression) { case PgUnnestExpression unnest: - return unnest.Array; + array = unnest.Array; + return true; - case ValuesExpression valuesExpression: + // TODO: We currently don't have information type information on empty ValuesExpression, so we can't transform that into an + // array. + case ValuesExpression { ColumnNames: ["_ord", "Value"], RowValues.Count: > 0 } valuesExpression: { // The source table was a constant collection, so translated by default to ValuesExpression. Convert it to an unnest over // an array constructor. @@ -1249,12 +1257,14 @@ private SqlExpression GetArray(TableExpressionBase tableExpression) elements[i] = valuesExpression.RowValues[i].Values[1]; } - return new PgNewArrayExpression( + array = new PgNewArrayExpression( elements, valuesExpression.RowValues[0].Values[1].Type.MakeArrayType(), typeMapping: null); + return true; } default: - throw new ArgumentException(nameof(tableExpression)); + array = null; + return false; } } @@ -1279,8 +1289,7 @@ public bool ContainsReferenceToMainTable(TableExpressionBase tableExpression) return expression; } - if (expression is ColumnExpression columnExpression - && columnExpression.Table == mainTable) + if (expression is ColumnExpression { TableAlias: var tableAlias} && tableAlias == mainTable.Alias) { _containsReference = true; @@ -1312,7 +1321,7 @@ public NpgsqlInferredTypeMappingApplier( IModel model, NpgsqlTypeMappingSource typeMappingSource, NpgsqlSqlExpressionFactory sqlExpressionFactory, - IReadOnlyDictionary<(TableExpressionBase, string), RelationalTypeMapping?> inferredTypeMappings) + IReadOnlyDictionary<(string, string), RelationalTypeMapping?> inferredTypeMappings) : base(model, sqlExpressionFactory, inferredTypeMappings) { _typeMappingSource = typeMappingSource; @@ -1330,7 +1339,7 @@ protected override Expression VisitExtension(Expression expression) switch (expression) { case PgUnnestExpression unnestExpression - when TryGetInferredTypeMapping(unnestExpression, unnestExpression.ColumnName, out var elementTypeMapping): + when TryGetInferredTypeMapping(unnestExpression.Alias, unnestExpression.ColumnName, out var elementTypeMapping): { var collectionTypeMapping = _typeMappingSource.FindMapping(unnestExpression.Array.Type, Model, elementTypeMapping); diff --git a/src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitorFactory.cs b/src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitorFactory.cs index ad06c1e83..b6e2eb279 100644 --- a/src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitorFactory.cs @@ -45,5 +45,8 @@ public NpgsqlQueryableMethodTranslatingExpressionVisitorFactory( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual QueryableMethodTranslatingExpressionVisitor Create(QueryCompilationContext queryCompilationContext) - => new NpgsqlQueryableMethodTranslatingExpressionVisitor(Dependencies, RelationalDependencies, queryCompilationContext); + => new NpgsqlQueryableMethodTranslatingExpressionVisitor( + Dependencies, + RelationalDependencies, + (RelationalQueryCompilationContext)queryCompilationContext); } diff --git a/src/EFCore.PG/Query/Internal/NpgsqlUnnestPostprocessor.cs b/src/EFCore.PG/Query/Internal/NpgsqlUnnestPostprocessor.cs index 826a7e2aa..1ac0dc924 100644 --- a/src/EFCore.PG/Query/Internal/NpgsqlUnnestPostprocessor.cs +++ b/src/EFCore.PG/Query/Internal/NpgsqlUnnestPostprocessor.cs @@ -44,8 +44,8 @@ public class NpgsqlUnnestPostprocessor : ExpressionVisitor && !selectExpression.Orderings.Select(o => o.Expression) .Concat(selectExpression.Projection.Select(p => p.Expression)) .Any( - p => p is ColumnExpression { Name: "ordinality", Table: var ordinalityTable } - && ordinalityTable == table)) + p => p is ColumnExpression { Name: "ordinality", } ordinalityColumn + && ordinalityColumn.TableAlias == table.Alias)) { if (newTables is null) { diff --git a/src/EFCore.PG/Storage/Internal/Mapping/NpgsqlCharacterStringTypeMapping.cs b/src/EFCore.PG/Storage/Internal/Mapping/NpgsqlCharacterStringTypeMapping.cs index ca0a3095e..5df6a7219 100644 --- a/src/EFCore.PG/Storage/Internal/Mapping/NpgsqlCharacterStringTypeMapping.cs +++ b/src/EFCore.PG/Storage/Internal/Mapping/NpgsqlCharacterStringTypeMapping.cs @@ -122,7 +122,13 @@ protected override void ConfigureParameter(DbParameter parameter) base.ConfigureParameter(parameter); } - private static bool EqualsWithoutTrailingWhitespace(string? a, string? b) + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + public static bool EqualsWithoutTrailingWhitespace(string? a, string? b) => (a, b) switch { (null, null) => true, @@ -131,6 +137,12 @@ private static bool EqualsWithoutTrailingWhitespace(string? a, string? b) _ => a.AsSpan().TrimEnd().SequenceEqual(b.AsSpan().TrimEnd()) }; - private static int GetHashCodeWithoutTrailingWhitespace(string a) + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + public static int GetHashCodeWithoutTrailingWhitespace(string a) => a.TrimEnd().GetHashCode(); } diff --git a/test/EFCore.PG.FunctionalTests/BadDataJsonDeserializationNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/BadDataJsonDeserializationNpgsqlTest.cs new file mode 100644 index 000000000..dcf301eba --- /dev/null +++ b/test/EFCore.PG.FunctionalTests/BadDataJsonDeserializationNpgsqlTest.cs @@ -0,0 +1,9 @@ +#nullable enable + +namespace Npgsql.EntityFrameworkCore.PostgreSQL; + +public class BadDataJsonDeserializationSqlServerTest : BadDataJsonDeserializationTestBase +{ + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + => base.OnConfiguring(optionsBuilder.UseNpgsql(b => b.UseNetTopologySuite())); +} diff --git a/test/EFCore.PG.FunctionalTests/BuiltInDataTypesNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/BuiltInDataTypesNpgsqlTest.cs index 939fa9ae0..4d372c8e1 100644 --- a/test/EFCore.PG.FunctionalTests/BuiltInDataTypesNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/BuiltInDataTypesNpgsqlTest.cs @@ -569,7 +569,7 @@ private static void AssertMappedDataTypes(MappedDataTypes entity, int id) Assert.Equal(new Dictionary { { "a", "b" } }, entity.DictionaryAsHstore); Assert.Equal(new NpgsqlRange(4, true, 8, false), entity.NpgsqlRangeAsRange); - Assert.Equal([2, 3], entity.IntArrayAsIntArray); + Assert.Equal(new[] { 2, 3 }, entity.IntArrayAsIntArray); Assert.Equal( [PhysicalAddress.Parse("08-00-2B-01-02-03"), PhysicalAddress.Parse("08-00-2B-01-02-04")], entity.PhysicalAddressArrayAsMacaddrArray); diff --git a/test/EFCore.PG.FunctionalTests/BulkUpdates/ComplexTypeBulkUpdatesNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/BulkUpdates/ComplexTypeBulkUpdatesNpgsqlTest.cs index 58acbafea..abaa17130 100644 --- a/test/EFCore.PG.FunctionalTests/BulkUpdates/ComplexTypeBulkUpdatesNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/BulkUpdates/ComplexTypeBulkUpdatesNpgsqlTest.cs @@ -94,6 +94,128 @@ public override async Task Update_projected_complex_type_via_OrderBy_Skip_throws AssertExecuteUpdateSql(); } + public override async Task Update_complex_type_to_parameter(bool async) + { + await base.Update_complex_type_to_parameter(async); + + AssertExecuteUpdateSql( + """ +@__complex_type_newAddress_0_AddressLine1='New AddressLine1' +@__complex_type_newAddress_0_AddressLine2='New AddressLine2' +@__complex_type_newAddress_0_Tags={ 'new_tag1', 'new_tag2' } (DbType = Object) +@__complex_type_newAddress_0_ZipCode='99999' (Nullable = true) +@__complex_type_newAddress_0_Code='FR' +@__complex_type_newAddress_0_FullName='France' + +UPDATE "Customer" AS c +SET "ShippingAddress_AddressLine1" = @__complex_type_newAddress_0_AddressLine1, + "ShippingAddress_AddressLine2" = @__complex_type_newAddress_0_AddressLine2, + "ShippingAddress_Tags" = @__complex_type_newAddress_0_Tags, + "ShippingAddress_ZipCode" = @__complex_type_newAddress_0_ZipCode, + "ShippingAddress_Country_Code" = @__complex_type_newAddress_0_Code, + "ShippingAddress_Country_FullName" = @__complex_type_newAddress_0_FullName +"""); + } + + public override async Task Update_nested_complex_type_to_parameter(bool async) + { + await base.Update_nested_complex_type_to_parameter(async); + + AssertExecuteUpdateSql( + """ +@__complex_type_newCountry_0_Code='FR' +@__complex_type_newCountry_0_FullName='France' + +UPDATE "Customer" AS c +SET "ShippingAddress_Country_Code" = @__complex_type_newCountry_0_Code, + "ShippingAddress_Country_FullName" = @__complex_type_newCountry_0_FullName +"""); + } + + public override async Task Update_complex_type_to_another_database_complex_type(bool async) + { + await base.Update_complex_type_to_another_database_complex_type(async); + + AssertExecuteUpdateSql( + """ +UPDATE "Customer" AS c +SET "ShippingAddress_AddressLine1" = c."BillingAddress_AddressLine1", + "ShippingAddress_AddressLine2" = c."BillingAddress_AddressLine2", + "ShippingAddress_Tags" = c."BillingAddress_Tags", + "ShippingAddress_ZipCode" = c."BillingAddress_ZipCode", + "ShippingAddress_Country_Code" = c."ShippingAddress_Country_Code", + "ShippingAddress_Country_FullName" = c."ShippingAddress_Country_FullName" +"""); + } + + public override async Task Update_complex_type_to_inline_without_lambda(bool async) + { + await base.Update_complex_type_to_inline_without_lambda(async); + + AssertExecuteUpdateSql( + """ +UPDATE "Customer" AS c +SET "ShippingAddress_AddressLine1" = 'New AddressLine1', + "ShippingAddress_AddressLine2" = 'New AddressLine2', + "ShippingAddress_Tags" = ARRAY['new_tag1','new_tag2']::text[], + "ShippingAddress_ZipCode" = 99999, + "ShippingAddress_Country_Code" = 'FR', + "ShippingAddress_Country_FullName" = 'France' +"""); + } + + public override async Task Update_complex_type_to_inline_with_lambda(bool async) + { + await base.Update_complex_type_to_inline_with_lambda(async); + + AssertExecuteUpdateSql( + """ +UPDATE "Customer" AS c +SET "ShippingAddress_AddressLine1" = 'New AddressLine1', + "ShippingAddress_AddressLine2" = 'New AddressLine2', + "ShippingAddress_Tags" = ARRAY['new_tag1','new_tag2']::text[], + "ShippingAddress_ZipCode" = 99999, + "ShippingAddress_Country_Code" = 'FR', + "ShippingAddress_Country_FullName" = 'France' +"""); + } + + public override async Task Update_complex_type_to_another_database_complex_type_with_subquery(bool async) + { + await base.Update_complex_type_to_another_database_complex_type_with_subquery(async); + + AssertExecuteUpdateSql( + """ +@__p_0='1' + +UPDATE "Customer" AS c0 +SET "ShippingAddress_AddressLine1" = c1."BillingAddress_AddressLine1", + "ShippingAddress_AddressLine2" = c1."BillingAddress_AddressLine2", + "ShippingAddress_Tags" = c1."BillingAddress_Tags", + "ShippingAddress_ZipCode" = c1."BillingAddress_ZipCode", + "ShippingAddress_Country_Code" = c1."ShippingAddress_Country_Code", + "ShippingAddress_Country_FullName" = c1."ShippingAddress_Country_FullName" +FROM ( + SELECT c."Id", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_Tags", c."BillingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" + FROM "Customer" AS c + ORDER BY c."Id" NULLS FIRST + OFFSET @__p_0 +) AS c1 +WHERE c0."Id" = c1."Id" +"""); + } + + public override async Task Update_collection_inside_complex_type(bool async) + { + await base.Update_collection_inside_complex_type(async); + + AssertExecuteUpdateSql( + """ +UPDATE "Customer" AS c +SET "ShippingAddress_Tags" = ARRAY['new_tag1','new_tag2']::text[] +"""); + } + [ConditionalFact] public virtual void Check_all_tests_overridden() => TestHelpers.AssertAllMethodsOverridden(GetType()); diff --git a/test/EFCore.PG.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesNpgsqlTest.cs index fcd36e8cf..2704ed853 100644 --- a/test/EFCore.PG.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesNpgsqlTest.cs @@ -22,6 +22,24 @@ DELETE FROM "Owner" AS o """); } + public override async Task Delete_with_owned_collection_and_non_natively_translatable_query(bool async) + { + await base.Delete_with_owned_collection_and_non_natively_translatable_query(async); + + AssertSql( + """ +@__p_0='1' + +DELETE FROM "Owner" AS o +WHERE o."Id" IN ( + SELECT o0."Id" + FROM "Owner" AS o0 + ORDER BY o0."Title" NULLS FIRST + OFFSET @__p_0 +) +"""); + } + public override async Task Delete_aggregate_root_when_table_sharing_with_owned(bool async) { await base.Delete_aggregate_root_when_table_sharing_with_owned(async); @@ -77,6 +95,19 @@ public override async Task Update_non_owned_property_on_entity_with_owned2(bool """); } + public override async Task Update_non_owned_property_on_entity_with_owned_in_join(bool async) + { + await base.Update_non_owned_property_on_entity_with_owned_in_join(async); + + AssertSql( + """ +UPDATE "Owner" AS o +SET "Title" = 'NewValue' +FROM "Owner" AS o0 +WHERE o."Id" = o0."Id" +"""); + } + public override async Task Update_owned_and_non_owned_properties_with_table_sharing(bool async) { await base.Update_owned_and_non_owned_properties_with_table_sharing(async); @@ -130,11 +161,25 @@ public override async Task Update_non_main_table_in_entity_with_entity_splitting UPDATE "BlogsPart1" AS b0 SET "Rating" = length(b0."Title")::int, "Title" = b0."Rating"::text +FROM "Blogs" AS b +WHERE b."Id" = b0."Id" """); } - public override Task Delete_entity_with_auto_include(bool async) - => Assert.ThrowsAsync(() => base.Delete_entity_with_auto_include(async)); // #30577 + public override async Task Delete_entity_with_auto_include(bool async) + { + await base.Delete_entity_with_auto_include(async); + + AssertSql( + """ +DELETE FROM "Context30572_Principal" AS c +WHERE c."Id" IN ( + SELECT c0."Id" + FROM "Context30572_Principal" AS c0 + LEFT JOIN "Context30572_Dependent" AS c1 ON c0."DependentId" = c1."Id" +) +"""); + } public override async Task Update_with_alias_uniquification_in_setter_subquery(bool async) { diff --git a/test/EFCore.PG.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesNpgsqlTest.cs index 8bbb02ee0..60c20d9d9 100644 --- a/test/EFCore.PG.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesNpgsqlTest.cs @@ -76,13 +76,13 @@ DELETE FROM "Order Details" AS o WHERE EXISTS ( SELECT 1 FROM ( - SELECT o0."OrderID", o0."ProductID", o0."Discount", o0."Quantity", o0."UnitPrice" + SELECT o0."OrderID", o0."ProductID" FROM "Order Details" AS o0 WHERE o0."OrderID" < 10300 ORDER BY o0."OrderID" NULLS FIRST OFFSET @__p_0 - ) AS t - WHERE t."OrderID" = o."OrderID" AND t."ProductID" = o."ProductID") + ) AS o1 + WHERE o1."OrderID" = o."OrderID" AND o1."ProductID" = o."ProductID") """); } @@ -98,13 +98,13 @@ DELETE FROM "Order Details" AS o WHERE EXISTS ( SELECT 1 FROM ( - SELECT o0."OrderID", o0."ProductID", o0."Discount", o0."Quantity", o0."UnitPrice" + SELECT o0."OrderID", o0."ProductID" FROM "Order Details" AS o0 WHERE o0."OrderID" < 10300 ORDER BY o0."OrderID" NULLS FIRST LIMIT @__p_0 - ) AS t - WHERE t."OrderID" = o."OrderID" AND t."ProductID" = o."ProductID") + ) AS o1 + WHERE o1."OrderID" = o."OrderID" AND o1."ProductID" = o."ProductID") """); } @@ -120,13 +120,13 @@ DELETE FROM "Order Details" AS o WHERE EXISTS ( SELECT 1 FROM ( - SELECT o0."OrderID", o0."ProductID", o0."Discount", o0."Quantity", o0."UnitPrice" + SELECT o0."OrderID", o0."ProductID" FROM "Order Details" AS o0 WHERE o0."OrderID" < 10300 ORDER BY o0."OrderID" NULLS FIRST LIMIT @__p_0 OFFSET @__p_0 - ) AS t - WHERE t."OrderID" = o."OrderID" AND t."ProductID" = o."ProductID") + ) AS o1 + WHERE o1."OrderID" = o."OrderID" AND o1."ProductID" = o."ProductID") """); } @@ -142,12 +142,12 @@ DELETE FROM "Order Details" AS o WHERE EXISTS ( SELECT 1 FROM ( - SELECT o0."OrderID", o0."ProductID", o0."Discount", o0."Quantity", o0."UnitPrice" + SELECT o0."OrderID", o0."ProductID" FROM "Order Details" AS o0 WHERE o0."OrderID" < 10300 OFFSET @__p_0 - ) AS t - WHERE t."OrderID" = o."OrderID" AND t."ProductID" = o."ProductID") + ) AS o1 + WHERE o1."OrderID" = o."OrderID" AND o1."ProductID" = o."ProductID") """); } @@ -163,12 +163,12 @@ DELETE FROM "Order Details" AS o WHERE EXISTS ( SELECT 1 FROM ( - SELECT o0."OrderID", o0."ProductID", o0."Discount", o0."Quantity", o0."UnitPrice" + SELECT o0."OrderID", o0."ProductID" FROM "Order Details" AS o0 WHERE o0."OrderID" < 10300 LIMIT @__p_0 - ) AS t - WHERE t."OrderID" = o."OrderID" AND t."ProductID" = o."ProductID") + ) AS o1 + WHERE o1."OrderID" = o."OrderID" AND o1."ProductID" = o."ProductID") """); } @@ -184,12 +184,12 @@ DELETE FROM "Order Details" AS o WHERE EXISTS ( SELECT 1 FROM ( - SELECT o0."OrderID", o0."ProductID", o0."Discount", o0."Quantity", o0."UnitPrice" + SELECT o0."OrderID", o0."ProductID" FROM "Order Details" AS o0 WHERE o0."OrderID" < 10300 LIMIT @__p_0 OFFSET @__p_0 - ) AS t - WHERE t."OrderID" = o."OrderID" AND t."ProductID" = o."ProductID") + ) AS o1 + WHERE o1."OrderID" = o."OrderID" AND o1."ProductID" = o."ProductID") """); } @@ -262,16 +262,16 @@ DELETE FROM "Order Details" AS o WHERE EXISTS ( SELECT 1 FROM ( - SELECT t."OrderID", t."ProductID", t."Discount", t."Quantity", t."UnitPrice" + SELECT o0."OrderID", o0."ProductID" FROM ( - SELECT o0."OrderID", o0."ProductID", o0."Discount", o0."Quantity", o0."UnitPrice" - FROM "Order Details" AS o0 - WHERE o0."OrderID" < 10300 + SELECT o1."OrderID", o1."ProductID" + FROM "Order Details" AS o1 + WHERE o1."OrderID" < 10300 LIMIT @__p_0 OFFSET @__p_0 - ) AS t + ) AS o0 LIMIT @__p_2 OFFSET @__p_1 - ) AS t0 - WHERE t0."OrderID" = o."OrderID" AND t0."ProductID" = o."ProductID") + ) AS o2 + WHERE o2."OrderID" = o."OrderID" AND o2."ProductID" = o."ProductID") """); } @@ -309,11 +309,11 @@ WHERE EXISTS ( SELECT 1 FROM "Orders" AS o0 INNER JOIN ( - SELECT o1."OrderID", o1."ProductID", o1."Discount", o1."Quantity", o1."UnitPrice" - FROM "Order Details" AS o1 - WHERE o1."ProductID" > 0 - ) AS t ON o0."OrderID" = t."OrderID" - WHERE o0."OrderID" < 10250 AND t."OrderID" = o."OrderID" AND t."ProductID" = o."ProductID") + SELECT o2."OrderID", o2."ProductID" + FROM "Order Details" AS o2 + WHERE o2."ProductID" > 0 + ) AS o1 ON o0."OrderID" = o1."OrderID" + WHERE o0."OrderID" < 10250 AND o1."OrderID" = o."OrderID" AND o1."ProductID" = o."ProductID") """); } @@ -362,8 +362,8 @@ WHERE o0."OrderID" < 10250 SELECT o1."OrderID", o1."ProductID", o1."Discount", o1."Quantity", o1."UnitPrice" FROM "Order Details" AS o1 WHERE o1."OrderID" > 11250 - ) AS t - WHERE t."OrderID" = o."OrderID" AND t."ProductID" = o."ProductID") + ) AS u + WHERE u."OrderID" = o."OrderID" AND u."ProductID" = o."ProductID") """); } @@ -377,15 +377,15 @@ DELETE FROM "Order Details" AS o WHERE EXISTS ( SELECT 1 FROM ( - SELECT o0."OrderID", o0."ProductID", o0."Discount", o0."Quantity", o0."UnitPrice" + SELECT o0."OrderID", o0."ProductID" FROM "Order Details" AS o0 WHERE o0."OrderID" < 10250 UNION ALL - SELECT o1."OrderID", o1."ProductID", o1."Discount", o1."Quantity", o1."UnitPrice" + SELECT o1."OrderID", o1."ProductID" FROM "Order Details" AS o1 WHERE o1."OrderID" > 11250 - ) AS t - WHERE t."OrderID" = o."OrderID" AND t."ProductID" = o."ProductID") + ) AS u + WHERE u."OrderID" = o."OrderID" AND u."ProductID" = o."ProductID") """); } @@ -406,8 +406,8 @@ WHERE o0."OrderID" < 10250 SELECT o1."OrderID", o1."ProductID", o1."Discount", o1."Quantity", o1."UnitPrice" FROM "Order Details" AS o1 WHERE o1."OrderID" > 11250 - ) AS t - WHERE t."OrderID" = o."OrderID" AND t."ProductID" = o."ProductID") + ) AS i + WHERE i."OrderID" = o."OrderID" AND i."ProductID" = o."ProductID") """); } @@ -428,8 +428,8 @@ WHERE o0."OrderID" < 10250 SELECT o1."OrderID", o1."ProductID", o1."Discount", o1."Quantity", o1."UnitPrice" FROM "Order Details" AS o1 WHERE o1."OrderID" > 11250 - ) AS t - WHERE t."OrderID" = o."OrderID" AND t."ProductID" = o."ProductID") + ) AS e + WHERE e."OrderID" = o."OrderID" AND e."ProductID" = o."ProductID") """); } @@ -499,13 +499,13 @@ public override async Task Delete_with_join(bool async) DELETE FROM "Order Details" AS o USING ( - SELECT o0."OrderID", o0."CustomerID", o0."EmployeeID", o0."OrderDate" + SELECT o0."OrderID" FROM "Orders" AS o0 WHERE o0."OrderID" < 10300 ORDER BY o0."OrderID" NULLS FIRST LIMIT @__p_1 OFFSET @__p_0 -) AS t -WHERE o."OrderID" = t."OrderID" +) AS o1 +WHERE o."OrderID" = o1."OrderID" """); } @@ -523,12 +523,12 @@ WHERE EXISTS ( SELECT 1 FROM "Order Details" AS o0 LEFT JOIN ( - SELECT o1."OrderID", o1."CustomerID", o1."EmployeeID", o1."OrderDate" - FROM "Orders" AS o1 - WHERE o1."OrderID" < 10300 - ORDER BY o1."OrderID" NULLS FIRST + SELECT o2."OrderID" + FROM "Orders" AS o2 + WHERE o2."OrderID" < 10300 + ORDER BY o2."OrderID" NULLS FIRST LIMIT @__p_1 OFFSET @__p_0 - ) AS t ON o0."OrderID" = t."OrderID" + ) AS o1 ON o0."OrderID" = o1."OrderID" WHERE o0."OrderID" < 10276 AND o0."OrderID" = o."OrderID" AND o0."ProductID" = o."ProductID") """); } @@ -544,12 +544,12 @@ WHERE EXISTS ( SELECT 1 FROM "Order Details" AS o0 CROSS JOIN ( - SELECT o1."OrderID", o1."CustomerID", o1."EmployeeID", o1."OrderDate" - FROM "Orders" AS o1 - WHERE o1."OrderID" < 10300 - ORDER BY o1."OrderID" NULLS FIRST + SELECT 1 + FROM "Orders" AS o2 + WHERE o2."OrderID" < 10300 + ORDER BY o2."OrderID" NULLS FIRST LIMIT 100 OFFSET 0 - ) AS t + ) AS o1 WHERE o0."OrderID" < 10276 AND o0."OrderID" = o."OrderID" AND o0."ProductID" = o."ProductID") """); } @@ -565,12 +565,12 @@ WHERE EXISTS ( SELECT 1 FROM "Order Details" AS o0 JOIN LATERAL ( - SELECT o1."OrderID", o1."CustomerID", o1."EmployeeID", o1."OrderDate" - FROM "Orders" AS o1 - WHERE o1."OrderID" < o0."OrderID" - ORDER BY o1."OrderID" NULLS FIRST + SELECT 1 + FROM "Orders" AS o2 + WHERE o2."OrderID" < o0."OrderID" + ORDER BY o2."OrderID" NULLS FIRST LIMIT 100 OFFSET 0 - ) AS t ON TRUE + ) AS o1 ON TRUE WHERE o0."OrderID" < 10276 AND o0."OrderID" = o."OrderID" AND o0."ProductID" = o."ProductID") """); } @@ -586,12 +586,12 @@ WHERE EXISTS ( SELECT 1 FROM "Order Details" AS o0 LEFT JOIN LATERAL ( - SELECT o1."OrderID", o1."CustomerID", o1."EmployeeID", o1."OrderDate" - FROM "Orders" AS o1 - WHERE o1."OrderID" < o0."OrderID" - ORDER BY o1."OrderID" NULLS FIRST + SELECT 1 + FROM "Orders" AS o2 + WHERE o2."OrderID" < o0."OrderID" + ORDER BY o2."OrderID" NULLS FIRST LIMIT 100 OFFSET 0 - ) AS t ON TRUE + ) AS o1 ON TRUE WHERE o0."OrderID" < 10276 AND o0."OrderID" = o."OrderID" AND o0."ProductID" = o."ProductID") """); } @@ -728,14 +728,14 @@ public override async Task Update_Where_OrderBy_set_constant(bool async) AssertExecuteUpdateSql( """ -UPDATE "Customers" AS c +UPDATE "Customers" AS c0 SET "ContactName" = 'Updated' FROM ( - SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" - FROM "Customers" AS c0 - WHERE c0."CustomerID" LIKE 'F%' -) AS t -WHERE c."CustomerID" = t."CustomerID" + SELECT c."CustomerID" + FROM "Customers" AS c + WHERE c."CustomerID" LIKE 'F%' +) AS c1 +WHERE c0."CustomerID" = c1."CustomerID" """); } @@ -747,16 +747,16 @@ public override async Task Update_Where_OrderBy_Skip_set_constant(bool async) """ @__p_0='4' -UPDATE "Customers" AS c +UPDATE "Customers" AS c0 SET "ContactName" = 'Updated' FROM ( - SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" - FROM "Customers" AS c0 - WHERE c0."CustomerID" LIKE 'F%' - ORDER BY c0."City" NULLS FIRST + SELECT c."CustomerID" + FROM "Customers" AS c + WHERE c."CustomerID" LIKE 'F%' + ORDER BY c."City" NULLS FIRST OFFSET @__p_0 -) AS t -WHERE c."CustomerID" = t."CustomerID" +) AS c1 +WHERE c0."CustomerID" = c1."CustomerID" """); } @@ -768,16 +768,16 @@ public override async Task Update_Where_OrderBy_Take_set_constant(bool async) """ @__p_0='4' -UPDATE "Customers" AS c +UPDATE "Customers" AS c0 SET "ContactName" = 'Updated' FROM ( - SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" - FROM "Customers" AS c0 - WHERE c0."CustomerID" LIKE 'F%' - ORDER BY c0."City" NULLS FIRST + SELECT c."CustomerID" + FROM "Customers" AS c + WHERE c."CustomerID" LIKE 'F%' + ORDER BY c."City" NULLS FIRST LIMIT @__p_0 -) AS t -WHERE c."CustomerID" = t."CustomerID" +) AS c1 +WHERE c0."CustomerID" = c1."CustomerID" """); } @@ -790,16 +790,16 @@ public override async Task Update_Where_OrderBy_Skip_Take_set_constant(bool asyn @__p_1='4' @__p_0='2' -UPDATE "Customers" AS c +UPDATE "Customers" AS c0 SET "ContactName" = 'Updated' FROM ( - SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" - FROM "Customers" AS c0 - WHERE c0."CustomerID" LIKE 'F%' - ORDER BY c0."City" NULLS FIRST + SELECT c."CustomerID" + FROM "Customers" AS c + WHERE c."CustomerID" LIKE 'F%' + ORDER BY c."City" NULLS FIRST LIMIT @__p_1 OFFSET @__p_0 -) AS t -WHERE c."CustomerID" = t."CustomerID" +) AS c1 +WHERE c0."CustomerID" = c1."CustomerID" """); } @@ -812,21 +812,21 @@ public override async Task Update_Where_OrderBy_Skip_Take_Skip_Take_set_constant @__p_1='6' @__p_0='2' -UPDATE "Customers" AS c +UPDATE "Customers" AS c1 SET "ContactName" = 'Updated' FROM ( - SELECT t."CustomerID", t."Address", t."City", t."CompanyName", t."ContactName", t."ContactTitle", t."Country", t."Fax", t."Phone", t."PostalCode", t."Region" + SELECT c0."CustomerID" FROM ( - SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" - FROM "Customers" AS c0 - WHERE c0."CustomerID" LIKE 'F%' - ORDER BY c0."City" NULLS FIRST + SELECT c."CustomerID", c."City" + FROM "Customers" AS c + WHERE c."CustomerID" LIKE 'F%' + ORDER BY c."City" NULLS FIRST LIMIT @__p_1 OFFSET @__p_0 - ) AS t - ORDER BY t."City" NULLS FIRST + ) AS c0 + ORDER BY c0."City" NULLS FIRST LIMIT @__p_0 OFFSET @__p_0 -) AS t0 -WHERE c."CustomerID" = t0."CustomerID" +) AS c2 +WHERE c1."CustomerID" = c2."CustomerID" """); } @@ -903,14 +903,14 @@ public override async Task Update_Where_Distinct_set_constant(bool async) AssertExecuteUpdateSql( """ -UPDATE "Customers" AS c +UPDATE "Customers" AS c0 SET "ContactName" = 'Updated' FROM ( - SELECT DISTINCT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" - FROM "Customers" AS c0 - WHERE c0."CustomerID" LIKE 'F%' -) AS t -WHERE c."CustomerID" = t."CustomerID" + SELECT DISTINCT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region" + FROM "Customers" AS c + WHERE c."CustomerID" LIKE 'F%' +) AS c1 +WHERE c0."CustomerID" = c1."CustomerID" """); } @@ -920,15 +920,15 @@ public override async Task Update_Where_using_navigation_set_null(bool async) AssertExecuteUpdateSql( """ -UPDATE "Orders" AS o +UPDATE "Orders" AS o0 SET "OrderDate" = NULL FROM ( - SELECT o0."OrderID", o0."CustomerID", o0."EmployeeID", o0."OrderDate", c."CustomerID" AS "CustomerID0" - FROM "Orders" AS o0 - LEFT JOIN "Customers" AS c ON o0."CustomerID" = c."CustomerID" + SELECT o."OrderID" + FROM "Orders" AS o + LEFT JOIN "Customers" AS c ON o."CustomerID" = c."CustomerID" WHERE c."City" = 'Seattle' -) AS t -WHERE o."OrderID" = t."OrderID" +) AS s +WHERE o0."OrderID" = s."OrderID" """); } @@ -1077,18 +1077,18 @@ public override async Task Update_Union_set_constant(bool async) AssertExecuteUpdateSql( """ -UPDATE "Customers" AS c +UPDATE "Customers" AS c1 SET "ContactName" = 'Updated' FROM ( + SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region" + FROM "Customers" AS c + WHERE c."CustomerID" LIKE 'F%' + UNION SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" FROM "Customers" AS c0 - WHERE c0."CustomerID" LIKE 'F%' - UNION - SELECT c1."CustomerID", c1."Address", c1."City", c1."CompanyName", c1."ContactName", c1."ContactTitle", c1."Country", c1."Fax", c1."Phone", c1."PostalCode", c1."Region" - FROM "Customers" AS c1 - WHERE c1."CustomerID" LIKE 'A%' -) AS t -WHERE c."CustomerID" = t."CustomerID" + WHERE c0."CustomerID" LIKE 'A%' +) AS u +WHERE c1."CustomerID" = u."CustomerID" """); } @@ -1098,18 +1098,18 @@ public override async Task Update_Concat_set_constant(bool async) AssertExecuteUpdateSql( """ -UPDATE "Customers" AS c +UPDATE "Customers" AS c1 SET "ContactName" = 'Updated' FROM ( - SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" - FROM "Customers" AS c0 - WHERE c0."CustomerID" LIKE 'F%' + SELECT c."CustomerID" + FROM "Customers" AS c + WHERE c."CustomerID" LIKE 'F%' UNION ALL - SELECT c1."CustomerID", c1."Address", c1."City", c1."CompanyName", c1."ContactName", c1."ContactTitle", c1."Country", c1."Fax", c1."Phone", c1."PostalCode", c1."Region" - FROM "Customers" AS c1 - WHERE c1."CustomerID" LIKE 'A%' -) AS t -WHERE c."CustomerID" = t."CustomerID" + SELECT c0."CustomerID" + FROM "Customers" AS c0 + WHERE c0."CustomerID" LIKE 'A%' +) AS u +WHERE c1."CustomerID" = u."CustomerID" """); } @@ -1119,18 +1119,18 @@ public override async Task Update_Except_set_constant(bool async) AssertExecuteUpdateSql( """ -UPDATE "Customers" AS c +UPDATE "Customers" AS c1 SET "ContactName" = 'Updated' FROM ( + SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region" + FROM "Customers" AS c + WHERE c."CustomerID" LIKE 'F%' + EXCEPT SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" FROM "Customers" AS c0 - WHERE c0."CustomerID" LIKE 'F%' - EXCEPT - SELECT c1."CustomerID", c1."Address", c1."City", c1."CompanyName", c1."ContactName", c1."ContactTitle", c1."Country", c1."Fax", c1."Phone", c1."PostalCode", c1."Region" - FROM "Customers" AS c1 - WHERE c1."CustomerID" LIKE 'A%' -) AS t -WHERE c."CustomerID" = t."CustomerID" + WHERE c0."CustomerID" LIKE 'A%' +) AS e +WHERE c1."CustomerID" = e."CustomerID" """); } @@ -1140,18 +1140,18 @@ public override async Task Update_Intersect_set_constant(bool async) AssertExecuteUpdateSql( """ -UPDATE "Customers" AS c +UPDATE "Customers" AS c1 SET "ContactName" = 'Updated' FROM ( + SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region" + FROM "Customers" AS c + WHERE c."CustomerID" LIKE 'F%' + INTERSECT SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" FROM "Customers" AS c0 - WHERE c0."CustomerID" LIKE 'F%' - INTERSECT - SELECT c1."CustomerID", c1."Address", c1."City", c1."CompanyName", c1."ContactName", c1."ContactTitle", c1."Country", c1."Fax", c1."Phone", c1."PostalCode", c1."Region" - FROM "Customers" AS c1 - WHERE c1."CustomerID" LIKE 'A%' -) AS t -WHERE c."CustomerID" = t."CustomerID" + WHERE c0."CustomerID" LIKE 'A%' +) AS i +WHERE c1."CustomerID" = i."CustomerID" """); } @@ -1164,11 +1164,11 @@ public override async Task Update_with_join_set_constant(bool async) UPDATE "Customers" AS c SET "ContactName" = 'Updated' FROM ( - SELECT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate" + SELECT o."CustomerID" FROM "Orders" AS o WHERE o."OrderID" < 10300 -) AS t -WHERE c."CustomerID" = t."CustomerID" AND c."CustomerID" LIKE 'F%' +) AS o0 +WHERE c."CustomerID" = o0."CustomerID" AND c."CustomerID" LIKE 'F%' """); } @@ -1178,19 +1178,19 @@ public override async Task Update_with_left_join_set_constant(bool async) AssertExecuteUpdateSql( """ -UPDATE "Customers" AS c +UPDATE "Customers" AS c0 SET "ContactName" = 'Updated' FROM ( - SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region", t."OrderID", t."CustomerID" AS "CustomerID0", t."EmployeeID", t."OrderDate" - FROM "Customers" AS c0 + SELECT c."CustomerID" + FROM "Customers" AS c LEFT JOIN ( - SELECT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate" + SELECT o."CustomerID" FROM "Orders" AS o WHERE o."OrderID" < 10300 - ) AS t ON c0."CustomerID" = t."CustomerID" - WHERE c0."CustomerID" LIKE 'F%' -) AS t0 -WHERE c."CustomerID" = t0."CustomerID" + ) AS o0 ON c."CustomerID" = o0."CustomerID" + WHERE c."CustomerID" LIKE 'F%' +) AS s +WHERE c0."CustomerID" = s."CustomerID" """); } @@ -1203,10 +1203,10 @@ public override async Task Update_with_cross_join_set_constant(bool async) UPDATE "Customers" AS c SET "ContactName" = 'Updated' FROM ( - SELECT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate" + SELECT 1 FROM "Orders" AS o WHERE o."OrderID" < 10300 -) AS t +) AS o0 WHERE c."CustomerID" LIKE 'F%' """); } @@ -1217,19 +1217,19 @@ public override async Task Update_with_cross_apply_set_constant(bool async) AssertExecuteUpdateSql( """ -UPDATE "Customers" AS c +UPDATE "Customers" AS c0 SET "ContactName" = 'Updated' FROM ( - SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region", t."OrderID", t."CustomerID" AS "CustomerID0", t."EmployeeID", t."OrderDate" - FROM "Customers" AS c0 + SELECT c."CustomerID" + FROM "Customers" AS c JOIN LATERAL ( - SELECT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate" + SELECT 1 FROM "Orders" AS o - WHERE o."OrderID" < 10300 AND date_part('year', o."OrderDate")::int < length(c0."ContactName")::int - ) AS t ON TRUE - WHERE c0."CustomerID" LIKE 'F%' -) AS t0 -WHERE c."CustomerID" = t0."CustomerID" + WHERE o."OrderID" < 10300 AND date_part('year', o."OrderDate")::int < length(c."ContactName")::int + ) AS o0 ON TRUE + WHERE c."CustomerID" LIKE 'F%' +) AS s +WHERE c0."CustomerID" = s."CustomerID" """); } @@ -1239,19 +1239,19 @@ public override async Task Update_with_outer_apply_set_constant(bool async) AssertExecuteUpdateSql( """ -UPDATE "Customers" AS c +UPDATE "Customers" AS c0 SET "ContactName" = 'Updated' FROM ( - SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region", t."OrderID", t."CustomerID" AS "CustomerID0", t."EmployeeID", t."OrderDate" - FROM "Customers" AS c0 + SELECT c."CustomerID" + FROM "Customers" AS c LEFT JOIN LATERAL ( - SELECT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate" + SELECT 1 FROM "Orders" AS o - WHERE o."OrderID" < 10300 AND date_part('year', o."OrderDate")::int < length(c0."ContactName")::int - ) AS t ON TRUE - WHERE c0."CustomerID" LIKE 'F%' -) AS t0 -WHERE c."CustomerID" = t0."CustomerID" + WHERE o."OrderID" < 10300 AND date_part('year', o."OrderDate")::int < length(c."ContactName")::int + ) AS o0 ON TRUE + WHERE c."CustomerID" LIKE 'F%' +) AS s +WHERE c0."CustomerID" = s."CustomerID" """); } @@ -1262,24 +1262,24 @@ public override async Task Update_with_cross_join_left_join_set_constant(bool as AssertExecuteUpdateSql( """ -UPDATE "Customers" AS c +UPDATE "Customers" AS c2 SET "ContactName" = 'Updated' FROM ( - SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region", t."CustomerID" AS "CustomerID0", t."Address" AS "Address0", t."City" AS "City0", t."CompanyName" AS "CompanyName0", t."ContactName" AS "ContactName0", t."ContactTitle" AS "ContactTitle0", t."Country" AS "Country0", t."Fax" AS "Fax0", t."Phone" AS "Phone0", t."PostalCode" AS "PostalCode0", t."Region" AS "Region0", t0."OrderID", t0."CustomerID" AS "CustomerID1", t0."EmployeeID", t0."OrderDate" - FROM "Customers" AS c0 + SELECT c."CustomerID" + FROM "Customers" AS c CROSS JOIN ( - SELECT c1."CustomerID", c1."Address", c1."City", c1."CompanyName", c1."ContactName", c1."ContactTitle", c1."Country", c1."Fax", c1."Phone", c1."PostalCode", c1."Region" - FROM "Customers" AS c1 - WHERE c1."City" LIKE 'S%' - ) AS t + SELECT 1 + FROM "Customers" AS c0 + WHERE c0."City" LIKE 'S%' + ) AS c1 LEFT JOIN ( - SELECT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate" + SELECT o."CustomerID" FROM "Orders" AS o WHERE o."OrderID" < 10300 - ) AS t0 ON c0."CustomerID" = t0."CustomerID" - WHERE c0."CustomerID" LIKE 'F%' -) AS t1 -WHERE c."CustomerID" = t1."CustomerID" + ) AS o0 ON c."CustomerID" = o0."CustomerID" + WHERE c."CustomerID" LIKE 'F%' +) AS s +WHERE c2."CustomerID" = s."CustomerID" """); } @@ -1290,24 +1290,24 @@ public override async Task Update_with_cross_join_cross_apply_set_constant(bool AssertExecuteUpdateSql( """ -UPDATE "Customers" AS c +UPDATE "Customers" AS c2 SET "ContactName" = 'Updated' FROM ( - SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region", t0."OrderID", t0."CustomerID" AS "CustomerID0", t0."EmployeeID", t0."OrderDate", t."CustomerID" AS "CustomerID1" - FROM "Customers" AS c0 + SELECT c."CustomerID" + FROM "Customers" AS c CROSS JOIN ( - SELECT c1."CustomerID" - FROM "Customers" AS c1 - WHERE c1."City" LIKE 'S%' - ) AS t + SELECT 1 + FROM "Customers" AS c0 + WHERE c0."City" LIKE 'S%' + ) AS c1 JOIN LATERAL ( - SELECT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate" + SELECT 1 FROM "Orders" AS o - WHERE o."OrderID" < 10300 AND date_part('year', o."OrderDate")::int < length(c0."ContactName")::int - ) AS t0 ON TRUE - WHERE c0."CustomerID" LIKE 'F%' -) AS t1 -WHERE c."CustomerID" = t1."CustomerID" + WHERE o."OrderID" < 10300 AND date_part('year', o."OrderDate")::int < length(c."ContactName")::int + ) AS o0 ON TRUE + WHERE c."CustomerID" LIKE 'F%' +) AS s +WHERE c2."CustomerID" = s."CustomerID" """); } @@ -1318,24 +1318,24 @@ public override async Task Update_with_cross_join_outer_apply_set_constant(bool AssertExecuteUpdateSql( """ -UPDATE "Customers" AS c +UPDATE "Customers" AS c2 SET "ContactName" = 'Updated' FROM ( - SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region", t."CustomerID" AS "CustomerID0", t."Address" AS "Address0", t."City" AS "City0", t."CompanyName" AS "CompanyName0", t."ContactName" AS "ContactName0", t."ContactTitle" AS "ContactTitle0", t."Country" AS "Country0", t."Fax" AS "Fax0", t."Phone" AS "Phone0", t."PostalCode" AS "PostalCode0", t."Region" AS "Region0", t0."OrderID", t0."CustomerID" AS "CustomerID1", t0."EmployeeID", t0."OrderDate" - FROM "Customers" AS c0 + SELECT c."CustomerID" + FROM "Customers" AS c CROSS JOIN ( - SELECT c1."CustomerID", c1."Address", c1."City", c1."CompanyName", c1."ContactName", c1."ContactTitle", c1."Country", c1."Fax", c1."Phone", c1."PostalCode", c1."Region" - FROM "Customers" AS c1 - WHERE c1."City" LIKE 'S%' - ) AS t + SELECT 1 + FROM "Customers" AS c0 + WHERE c0."City" LIKE 'S%' + ) AS c1 LEFT JOIN LATERAL ( - SELECT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate" + SELECT 1 FROM "Orders" AS o - WHERE o."OrderID" < 10300 AND date_part('year', o."OrderDate")::int < length(c0."ContactName")::int - ) AS t0 ON TRUE - WHERE c0."CustomerID" LIKE 'F%' -) AS t1 -WHERE c."CustomerID" = t1."CustomerID" + WHERE o."OrderID" < 10300 AND date_part('year', o."OrderDate")::int < length(c."ContactName")::int + ) AS o0 ON TRUE + WHERE c."CustomerID" LIKE 'F%' +) AS s +WHERE c2."CustomerID" = s."CustomerID" """); } @@ -1352,19 +1352,19 @@ public override async Task Update_Where_SelectMany_subquery_set_null(bool async) AssertExecuteUpdateSql( """ -UPDATE "Orders" AS o +UPDATE "Orders" AS o1 SET "OrderDate" = NULL FROM ( - SELECT t."OrderID", t."CustomerID", t."EmployeeID", t."OrderDate", c."CustomerID" AS "CustomerID0" + SELECT o0."OrderID" FROM "Customers" AS c INNER JOIN ( - SELECT o0."OrderID", o0."CustomerID", o0."EmployeeID", o0."OrderDate" - FROM "Orders" AS o0 - WHERE date_part('year', o0."OrderDate")::int = 1997 - ) AS t ON c."CustomerID" = t."CustomerID" + SELECT o."OrderID", o."CustomerID" + FROM "Orders" AS o + WHERE date_part('year', o."OrderDate")::int = 1997 + ) AS o0 ON c."CustomerID" = o0."CustomerID" WHERE c."CustomerID" LIKE 'F%' -) AS t0 -WHERE o."OrderID" = t0."OrderID" +) AS s +WHERE o1."OrderID" = s."OrderID" """); } @@ -1392,12 +1392,12 @@ public override async Task Update_Where_Join_set_property_from_joined_table(bool AssertExecuteUpdateSql( """ UPDATE "Customers" AS c -SET "City" = t."City" +SET "City" = c1."City" FROM ( - SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" + SELECT c0."City" FROM "Customers" AS c0 WHERE c0."CustomerID" = 'ALFKI' -) AS t +) AS c1 WHERE c."CustomerID" LIKE 'F%' """); } diff --git a/test/EFCore.PG.FunctionalTests/BulkUpdates/TPCFiltersInheritanceBulkUpdatesNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/BulkUpdates/TPCFiltersInheritanceBulkUpdatesNpgsqlTest.cs index 79a758d0c..ae128131e 100644 --- a/test/EFCore.PG.FunctionalTests/BulkUpdates/TPCFiltersInheritanceBulkUpdatesNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/BulkUpdates/TPCFiltersInheritanceBulkUpdatesNpgsqlTest.cs @@ -35,13 +35,13 @@ DELETE FROM "Countries" AS c WHERE ( SELECT count(*)::int FROM ( - SELECT e."Id", e."CountryId", e."Name", e."Species", e."EagleId", e."IsFlightless", e."Group", NULL AS "FoundOn", 'Eagle' AS "Discriminator" + SELECT e."CountryId" FROM "Eagle" AS e UNION ALL - SELECT k."Id", k."CountryId", k."Name", k."Species", k."EagleId", k."IsFlightless", NULL AS "Group", k."FoundOn", 'Kiwi' AS "Discriminator" + SELECT k."CountryId" FROM "Kiwi" AS k - ) AS t - WHERE t."CountryId" = 1 AND c."Id" = t."CountryId" AND t."CountryId" > 0) > 0 + ) AS u + WHERE u."CountryId" = 1 AND c."Id" = u."CountryId" AND u."CountryId" > 0) > 0 """); } @@ -55,10 +55,10 @@ DELETE FROM "Countries" AS c WHERE ( SELECT count(*)::int FROM ( - SELECT k."Id", k."CountryId", k."Name", k."Species", k."EagleId", k."IsFlightless", NULL AS "Group", k."FoundOn", 'Kiwi' AS "Discriminator" + SELECT k."CountryId" FROM "Kiwi" AS k - ) AS t - WHERE t."CountryId" = 1 AND c."Id" = t."CountryId" AND t."CountryId" > 0) > 0 + ) AS u + WHERE u."CountryId" = 1 AND c."Id" = u."CountryId" AND u."CountryId" > 0) > 0 """); } @@ -153,13 +153,13 @@ public override async Task Update_where_using_hierarchy(bool async) WHERE ( SELECT count(*)::int FROM ( - SELECT e."Id", e."CountryId", e."Name", e."Species", e."EagleId", e."IsFlightless", e."Group", NULL AS "FoundOn", 'Eagle' AS "Discriminator" + SELECT e."CountryId" FROM "Eagle" AS e UNION ALL - SELECT k."Id", k."CountryId", k."Name", k."Species", k."EagleId", k."IsFlightless", NULL AS "Group", k."FoundOn", 'Kiwi' AS "Discriminator" + SELECT k."CountryId" FROM "Kiwi" AS k - ) AS t - WHERE t."CountryId" = 1 AND c."Id" = t."CountryId" AND t."CountryId" > 0) > 0 + ) AS u + WHERE u."CountryId" = 1 AND c."Id" = u."CountryId" AND u."CountryId" > 0) > 0 """); } @@ -187,10 +187,10 @@ public override async Task Update_where_using_hierarchy_derived(bool async) WHERE ( SELECT count(*)::int FROM ( - SELECT k."Id", k."CountryId", k."Name", k."Species", k."EagleId", k."IsFlightless", NULL AS "Group", k."FoundOn", 'Kiwi' AS "Discriminator" + SELECT k."CountryId" FROM "Kiwi" AS k - ) AS t - WHERE t."CountryId" = 1 AND c."Id" = t."CountryId" AND t."CountryId" > 0) > 0 + ) AS u + WHERE u."CountryId" = 1 AND c."Id" = u."CountryId" AND u."CountryId" > 0) > 0 """); } diff --git a/test/EFCore.PG.FunctionalTests/BulkUpdates/TPCInheritanceBulkUpdatesNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/BulkUpdates/TPCInheritanceBulkUpdatesNpgsqlTest.cs index 6b68719e9..f16b4aad5 100644 --- a/test/EFCore.PG.FunctionalTests/BulkUpdates/TPCInheritanceBulkUpdatesNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/BulkUpdates/TPCInheritanceBulkUpdatesNpgsqlTest.cs @@ -35,13 +35,13 @@ DELETE FROM "Countries" AS c WHERE ( SELECT count(*)::int FROM ( - SELECT e."Id", e."CountryId", e."Name", e."Species", e."EagleId", e."IsFlightless", e."Group", NULL AS "FoundOn", 'Eagle' AS "Discriminator" + SELECT e."CountryId" FROM "Eagle" AS e UNION ALL - SELECT k."Id", k."CountryId", k."Name", k."Species", k."EagleId", k."IsFlightless", NULL AS "Group", k."FoundOn", 'Kiwi' AS "Discriminator" + SELECT k."CountryId" FROM "Kiwi" AS k - ) AS t - WHERE c."Id" = t."CountryId" AND t."CountryId" > 0) > 0 + ) AS u + WHERE c."Id" = u."CountryId" AND u."CountryId" > 0) > 0 """); } @@ -55,10 +55,10 @@ DELETE FROM "Countries" AS c WHERE ( SELECT count(*)::int FROM ( - SELECT k."Id", k."CountryId", k."Name", k."Species", k."EagleId", k."IsFlightless", NULL AS "Group", k."FoundOn", 'Kiwi' AS "Discriminator" + SELECT k."CountryId" FROM "Kiwi" AS k - ) AS t - WHERE c."Id" = t."CountryId" AND t."CountryId" > 0) > 0 + ) AS u + WHERE c."Id" = u."CountryId" AND u."CountryId" > 0) > 0 """); } @@ -151,13 +151,13 @@ public override async Task Update_where_using_hierarchy(bool async) WHERE ( SELECT count(*)::int FROM ( - SELECT e."Id", e."CountryId", e."Name", e."Species", e."EagleId", e."IsFlightless", e."Group", NULL AS "FoundOn", 'Eagle' AS "Discriminator" + SELECT e."CountryId" FROM "Eagle" AS e UNION ALL - SELECT k."Id", k."CountryId", k."Name", k."Species", k."EagleId", k."IsFlightless", NULL AS "Group", k."FoundOn", 'Kiwi' AS "Discriminator" + SELECT k."CountryId" FROM "Kiwi" AS k - ) AS t - WHERE c."Id" = t."CountryId" AND t."CountryId" > 0) > 0 + ) AS u + WHERE c."Id" = u."CountryId" AND u."CountryId" > 0) > 0 """); } @@ -184,10 +184,10 @@ public override async Task Update_where_using_hierarchy_derived(bool async) WHERE ( SELECT count(*)::int FROM ( - SELECT k."Id", k."CountryId", k."Name", k."Species", k."EagleId", k."IsFlightless", NULL AS "Group", k."FoundOn", 'Kiwi' AS "Discriminator" + SELECT k."CountryId" FROM "Kiwi" AS k - ) AS t - WHERE c."Id" = t."CountryId" AND t."CountryId" > 0) > 0 + ) AS u + WHERE c."Id" = u."CountryId" AND u."CountryId" > 0) > 0 """); } diff --git a/test/EFCore.PG.FunctionalTests/BulkUpdates/TPTFiltersInheritanceBulkUpdatesNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/BulkUpdates/TPTFiltersInheritanceBulkUpdatesNpgsqlTest.cs index 9e9a1477e..6ecf13d06 100644 --- a/test/EFCore.PG.FunctionalTests/BulkUpdates/TPTFiltersInheritanceBulkUpdatesNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/BulkUpdates/TPTFiltersInheritanceBulkUpdatesNpgsqlTest.cs @@ -31,9 +31,6 @@ DELETE FROM "Countries" AS c WHERE ( SELECT count(*)::int FROM "Animals" AS a - LEFT JOIN "Birds" AS b ON a."Id" = b."Id" - LEFT JOIN "Eagle" AS e ON a."Id" = e."Id" - LEFT JOIN "Kiwi" AS k ON a."Id" = k."Id" WHERE a."CountryId" = 1 AND c."Id" = a."CountryId" AND a."CountryId" > 0) > 0 """); } @@ -48,8 +45,6 @@ DELETE FROM "Countries" AS c WHERE ( SELECT count(*)::int FROM "Animals" AS a - LEFT JOIN "Birds" AS b ON a."Id" = b."Id" - LEFT JOIN "Eagle" AS e ON a."Id" = e."Id" LEFT JOIN "Kiwi" AS k ON a."Id" = k."Id" WHERE a."CountryId" = 1 AND c."Id" = a."CountryId" AND k."Id" IS NOT NULL AND a."CountryId" > 0) > 0 """); @@ -83,20 +78,14 @@ public override async Task Update_base_type(bool async) // TODO: This over-complex SQL would get pruned after https://github.com/dotnet/efcore/issues/31083 AssertExecuteUpdateSql( """ -UPDATE "Animals" AS a +UPDATE "Animals" AS a0 SET "Name" = 'Animal' FROM ( - SELECT a0."Id", a0."CountryId", a0."Name", a0."Species", b0."EagleId", b0."IsFlightless", e0."Group", k0."FoundOn", CASE - WHEN k0."Id" IS NOT NULL THEN 'Kiwi' - WHEN e0."Id" IS NOT NULL THEN 'Eagle' - END AS "Discriminator" - FROM "Animals" AS a0 - LEFT JOIN "Birds" AS b0 ON a0."Id" = b0."Id" - LEFT JOIN "Eagle" AS e0 ON a0."Id" = e0."Id" - LEFT JOIN "Kiwi" AS k0 ON a0."Id" = k0."Id" - WHERE a0."CountryId" = 1 AND a0."Name" = 'Great spotted kiwi' -) AS t -WHERE a."Id" = t."Id" + SELECT a."Id" + FROM "Animals" AS a + WHERE a."CountryId" = 1 AND a."Name" = 'Great spotted kiwi' +) AS s +WHERE a0."Id" = s."Id" """); } @@ -107,20 +96,17 @@ public override async Task Update_base_type_with_OfType(bool async) // TODO: This over-complex SQL would get pruned after https://github.com/dotnet/efcore/issues/31083 AssertExecuteUpdateSql( """ -UPDATE "Animals" AS a +UPDATE "Animals" AS a0 SET "Name" = 'NewBird' FROM "Birds" AS b, - "Kiwi" AS k, + "Kiwi" AS k0, ( - SELECT a0."Id", a0."CountryId", a0."Name", a0."Species", b0."EagleId", b0."IsFlightless", k0."FoundOn", CASE - WHEN k0."Id" IS NOT NULL THEN 'Kiwi' - END AS "Discriminator" - FROM "Animals" AS a0 - LEFT JOIN "Birds" AS b0 ON a0."Id" = b0."Id" - LEFT JOIN "Kiwi" AS k0 ON a0."Id" = k0."Id" - WHERE a0."CountryId" = 1 AND k0."Id" IS NOT NULL - ) AS t -WHERE a."Id" = t."Id" AND a."Id" = k."Id" AND a."Id" = b."Id" + SELECT a."Id" + FROM "Animals" AS a + LEFT JOIN "Kiwi" AS k ON a."Id" = k."Id" + WHERE a."CountryId" = 1 AND k."Id" IS NOT NULL + ) AS s +WHERE a0."Id" = s."Id" AND a0."Id" = k0."Id" AND a0."Id" = b."Id" """); } @@ -191,9 +177,6 @@ public override async Task Update_where_using_hierarchy(bool async) WHERE ( SELECT count(*)::int FROM "Animals" AS a - LEFT JOIN "Birds" AS b ON a."Id" = b."Id" - LEFT JOIN "Eagle" AS e ON a."Id" = e."Id" - LEFT JOIN "Kiwi" AS k ON a."Id" = k."Id" WHERE a."CountryId" = 1 AND c."Id" = a."CountryId" AND a."CountryId" > 0) > 0 """); } @@ -209,8 +192,6 @@ public override async Task Update_where_using_hierarchy_derived(bool async) WHERE ( SELECT count(*)::int FROM "Animals" AS a - LEFT JOIN "Birds" AS b ON a."Id" = b."Id" - LEFT JOIN "Eagle" AS e ON a."Id" = e."Id" LEFT JOIN "Kiwi" AS k ON a."Id" = k."Id" WHERE a."CountryId" = 1 AND c."Id" = a."CountryId" AND k."Id" IS NOT NULL AND a."CountryId" > 0) > 0 """); diff --git a/test/EFCore.PG.FunctionalTests/BulkUpdates/TPTInheritanceBulkUpdatesNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/BulkUpdates/TPTInheritanceBulkUpdatesNpgsqlTest.cs index d2e87b654..9516e6ec7 100644 --- a/test/EFCore.PG.FunctionalTests/BulkUpdates/TPTInheritanceBulkUpdatesNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/BulkUpdates/TPTInheritanceBulkUpdatesNpgsqlTest.cs @@ -63,20 +63,14 @@ public override async Task Update_base_type(bool async) // TODO: This over-complex SQL would get pruned after https://github.com/dotnet/efcore/issues/31083 AssertExecuteUpdateSql( """ -UPDATE "Animals" AS a +UPDATE "Animals" AS a0 SET "Name" = 'Animal' FROM ( - SELECT a0."Id", a0."CountryId", a0."Name", a0."Species", b0."EagleId", b0."IsFlightless", e0."Group", k0."FoundOn", CASE - WHEN k0."Id" IS NOT NULL THEN 'Kiwi' - WHEN e0."Id" IS NOT NULL THEN 'Eagle' - END AS "Discriminator" - FROM "Animals" AS a0 - LEFT JOIN "Birds" AS b0 ON a0."Id" = b0."Id" - LEFT JOIN "Eagle" AS e0 ON a0."Id" = e0."Id" - LEFT JOIN "Kiwi" AS k0 ON a0."Id" = k0."Id" - WHERE a0."Name" = 'Great spotted kiwi' -) AS t -WHERE a."Id" = t."Id" + SELECT a."Id" + FROM "Animals" AS a + WHERE a."Name" = 'Great spotted kiwi' +) AS s +WHERE a0."Id" = s."Id" """); } @@ -87,20 +81,17 @@ public override async Task Update_base_type_with_OfType(bool async) // TODO: This over-complex SQL would get pruned after https://github.com/dotnet/efcore/issues/31083 AssertExecuteUpdateSql( """ -UPDATE "Animals" AS a +UPDATE "Animals" AS a0 SET "Name" = 'NewBird' FROM "Birds" AS b, - "Kiwi" AS k, + "Kiwi" AS k0, ( - SELECT a0."Id", a0."CountryId", a0."Name", a0."Species", b0."EagleId", b0."IsFlightless", k0."FoundOn", CASE - WHEN k0."Id" IS NOT NULL THEN 'Kiwi' - END AS "Discriminator" - FROM "Animals" AS a0 - LEFT JOIN "Birds" AS b0 ON a0."Id" = b0."Id" - LEFT JOIN "Kiwi" AS k0 ON a0."Id" = k0."Id" - WHERE k0."Id" IS NOT NULL - ) AS t -WHERE a."Id" = t."Id" AND a."Id" = k."Id" AND a."Id" = b."Id" + SELECT a."Id" + FROM "Animals" AS a + LEFT JOIN "Kiwi" AS k ON a."Id" = k."Id" + WHERE k."Id" IS NOT NULL + ) AS s +WHERE a0."Id" = s."Id" AND a0."Id" = k0."Id" AND a0."Id" = b."Id" """); } @@ -171,9 +162,6 @@ public override async Task Update_where_using_hierarchy(bool async) WHERE ( SELECT count(*)::int FROM "Animals" AS a - LEFT JOIN "Birds" AS b ON a."Id" = b."Id" - LEFT JOIN "Eagle" AS e ON a."Id" = e."Id" - LEFT JOIN "Kiwi" AS k ON a."Id" = k."Id" WHERE c."Id" = a."CountryId" AND a."CountryId" > 0) > 0 """); } @@ -189,8 +177,6 @@ public override async Task Update_where_using_hierarchy_derived(bool async) WHERE ( SELECT count(*)::int FROM "Animals" AS a - LEFT JOIN "Birds" AS b ON a."Id" = b."Id" - LEFT JOIN "Eagle" AS e ON a."Id" = e."Id" LEFT JOIN "Kiwi" AS k ON a."Id" = k."Id" WHERE c."Id" = a."CountryId" AND k."Id" IS NOT NULL AND a."CountryId" > 0) > 0 """); diff --git a/test/EFCore.PG.FunctionalTests/JsonTypesNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/JsonTypesNpgsqlTest.cs index db8e54053..c02e580e1 100644 --- a/test/EFCore.PG.FunctionalTests/JsonTypesNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/JsonTypesNpgsqlTest.cs @@ -4,6 +4,8 @@ using System.Globalization; using System.Numerics; +using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure; +using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities; namespace Npgsql.EntityFrameworkCore.PostgreSQL; @@ -452,8 +454,16 @@ protected class LogSequenceNumberType public NpgsqlLogSequenceNumber LogSequenceNumber { get; set; } } - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - => base.OnConfiguring(optionsBuilder.UseNpgsql(b => b.UseNetTopologySuite())); + protected override ITestStoreFactory TestStoreFactory => NpgsqlTestStoreFactory.Instance; + + protected override IServiceCollection AddServices(IServiceCollection serviceCollection) + => serviceCollection.AddEntityFrameworkNpgsqlNetTopologySuite(); + + protected override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) + { + new NpgsqlDbContextOptionsBuilder(builder).UseNetTopologySuite(); + return builder; + } static JsonTypesNpgsqlTest() { diff --git a/test/EFCore.PG.FunctionalTests/MaterializationInterceptionNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/MaterializationInterceptionNpgsqlTest.cs index b571ed37c..31735e9ff 100644 --- a/test/EFCore.PG.FunctionalTests/MaterializationInterceptionNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/MaterializationInterceptionNpgsqlTest.cs @@ -6,11 +6,10 @@ namespace Npgsql.EntityFrameworkCore.PostgreSQL; -public class MaterializationInterceptionNpgsqlTest(MaterializationInterceptionNpgsqlTest.MaterializationInterceptionNpgsqlFixture fixture) - : MaterializationInterceptionTestBase(fixture), - IClassFixture +public class MaterializationInterceptionNpgsqlTest : + MaterializationInterceptionTestBase { - public class SqlServerLibraryContext(DbContextOptions options) : LibraryContext(options) + public class NpgsqlLibraryContext(DbContextOptions options) : LibraryContext(options) { protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -23,27 +22,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) } } - public override LibraryContext CreateContext(IEnumerable interceptors, bool inject) - => new SqlServerLibraryContext(Fixture.CreateOptions(interceptors, inject)); - - public class MaterializationInterceptionNpgsqlFixture : SingletonInterceptorsFixtureBase - { - protected override string StoreName - => "MaterializationInterception"; - - protected override ITestStoreFactory TestStoreFactory - => NpgsqlTestStoreFactory.Instance; - - protected override IServiceCollection InjectInterceptors( - IServiceCollection serviceCollection, - IEnumerable injectedInterceptors) - => base.InjectInterceptors(serviceCollection.AddEntityFrameworkNpgsql(), injectedInterceptors); - - public override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) - { - new NpgsqlDbContextOptionsBuilder(base.AddOptions(builder)) - .ExecutionStrategy(d => new NpgsqlExecutionStrategy(d)); - return builder; - } - } + protected override ITestStoreFactory TestStoreFactory + => NpgsqlTestStoreFactory.Instance; } diff --git a/test/EFCore.PG.FunctionalTests/Migrations/MigrationsInfrastructureNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Migrations/MigrationsInfrastructureNpgsqlTest.cs index 43139f7bb..18a8eadcc 100644 --- a/test/EFCore.PG.FunctionalTests/Migrations/MigrationsInfrastructureNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Migrations/MigrationsInfrastructureNpgsqlTest.cs @@ -14,6 +14,26 @@ public override void Can_get_active_provider() Assert.Equal("Npgsql.EntityFrameworkCore.PostgreSQL", ActiveProvider); } + [ConditionalFact(Skip = "https://github.com/dotnet/efcore/issues/33056")] + public override void Can_apply_all_migrations() + => base.Can_apply_all_migrations(); + + [ConditionalFact(Skip = "https://github.com/dotnet/efcore/issues/33056")] + public override void Can_apply_range_of_migrations() + => base.Can_apply_range_of_migrations(); + + [ConditionalFact(Skip = "https://github.com/dotnet/efcore/issues/33056")] + public override void Can_revert_all_migrations() + => base.Can_revert_all_migrations(); + + [ConditionalFact(Skip = "https://github.com/dotnet/efcore/issues/33056")] + public override void Can_revert_one_migrations() + => base.Can_revert_one_migrations(); + + [ConditionalFact(Skip = "https://github.com/dotnet/efcore/issues/33056")] + public override Task Can_apply_all_migrations_async() + => base.Can_apply_all_migrations_async(); + [ConditionalFact] public async Task Empty_Migration_Creates_Database() { diff --git a/test/EFCore.PG.FunctionalTests/Migrations/MigrationsNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Migrations/MigrationsNpgsqlTest.cs index 338273052..0c558c943 100644 --- a/test/EFCore.PG.FunctionalTests/Migrations/MigrationsNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Migrations/MigrationsNpgsqlTest.cs @@ -1703,8 +1703,31 @@ public override async Task Alter_column_reset_collation() @"ALTER TABLE ""People"" ALTER COLUMN ""Name"" TYPE text COLLATE ""default"";"); } + public override async Task Convert_string_column_to_a_json_column_containing_reference() + { + var exception = + await Assert.ThrowsAsync(() => base.Convert_string_column_to_a_json_column_containing_reference()); + + Assert.Equal("42804", exception.SqlState); // column "Name" cannot be cast automatically to type jsonb + } + + public override async Task Convert_string_column_to_a_json_column_containing_required_reference() + { + var exception = + await Assert.ThrowsAsync(() => base.Convert_string_column_to_a_json_column_containing_required_reference()); + + Assert.Equal("42804", exception.SqlState); // column "Name" cannot be cast automatically to type jsonb + } + + public override async Task Convert_string_column_to_a_json_column_containing_collection() + { + var exception = + await Assert.ThrowsAsync(() => base.Convert_string_column_to_a_json_column_containing_collection()); + + Assert.Equal("42804", exception.SqlState); // column "Name" cannot be cast automatically to type jsonb + } + #pragma warning disable CS0618 - [Fact] public async Task Alter_column_change_default_column_collation() { await Test( diff --git a/test/EFCore.PG.FunctionalTests/ModelBuilding/NpgsqlModelBuilderGenericTest.cs b/test/EFCore.PG.FunctionalTests/ModelBuilding/NpgsqlModelBuilderGenericTest.cs new file mode 100644 index 000000000..8dc5b2348 --- /dev/null +++ b/test/EFCore.PG.FunctionalTests/ModelBuilding/NpgsqlModelBuilderGenericTest.cs @@ -0,0 +1,97 @@ +using Xunit.Sdk; + +namespace Npgsql.EntityFrameworkCore.PostgreSQL.ModelBuilding; + +#nullable enable + +public class NpgsqlModelBuilderGenericTest : NpgsqlModelBuilderTestBase +{ + public class NpgsqlGenericNonRelationship(NpgsqlModelBuilderFixture fixture) : NpgsqlNonRelationship(fixture) + { + // https://github.com/dotnet/efcore/issues/33059 + public override void Can_add_multiple_indexes() + => Assert.Throws(() => base.Can_add_multiple_indexes()); + + // PostgreSQL actually does support mapping multi-dimensional arrays, so no exception is thrown as expected + protected override void Mapping_throws_for_non_ignored_three_dimensional_array() + => Assert.Throws(() => base.Mapping_throws_for_non_ignored_three_dimensional_array()); + + protected override TestModelBuilder CreateModelBuilder( + Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } + + public class NpgsqlGenericComplexType(NpgsqlModelBuilderFixture fixture) : NpgsqlComplexType(fixture) + { + // https://github.com/dotnet/efcore/issues/33059 + public override void Access_mode_can_be_overridden_at_entity_and_property_levels() + => Assert.Throws(() => base.Access_mode_can_be_overridden_at_entity_and_property_levels()); + + // https://github.com/dotnet/efcore/issues/33059 + public override void Complex_properties_not_discovered_by_convention() + => Assert.Throws(() => base.Complex_properties_not_discovered_by_convention()); + + protected override TestModelBuilder CreateModelBuilder( + Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } + + public class NpgsqlGenericInheritance(NpgsqlModelBuilderFixture fixture) : NpgsqlInheritance(fixture) + { + protected override TestModelBuilder CreateModelBuilder( + Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } + + public class NpgsqlGenericOneToMany(NpgsqlModelBuilderFixture fixture) : NpgsqlOneToMany(fixture) + { + protected override TestModelBuilder CreateModelBuilder( + Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } + + public class NpgsqlGenericManyToOne(NpgsqlModelBuilderFixture fixture) : NpgsqlManyToOne(fixture) + { + protected override TestModelBuilder CreateModelBuilder( + Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } + + public class NpgsqlGenericOneToOne(NpgsqlModelBuilderFixture fixture) : NpgsqlOneToOne(fixture) + { + protected override TestModelBuilder CreateModelBuilder( + Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } + + public class NpgsqlGenericManyToMany(NpgsqlModelBuilderFixture fixture) : NpgsqlManyToMany(fixture) + { + // https://github.com/dotnet/efcore/issues/33059 + public override void Can_use_implicit_shared_type_with_default_name_and_implicit_relationships_as_join_entity() + => Assert.Throws( + () => base.Can_use_implicit_shared_type_with_default_name_and_implicit_relationships_as_join_entity()); + + protected override TestModelBuilder CreateModelBuilder( + Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } + + public class NpgsqlGenericOwnedTypes(NpgsqlModelBuilderFixture fixture) : NpgsqlOwnedTypes(fixture) + { + // https://github.com/dotnet/efcore/issues/33059 + public override void Can_configure_chained_ownerships() + => Assert.Throws(() => base.Can_configure_chained_ownerships()); + + // https://github.com/dotnet/efcore/issues/33059 + public override void Can_configure_chained_ownerships_different_order() + => Assert.Throws(() => base.Can_configure_chained_ownerships_different_order()); + + // PostgreSQL stored procedures do not support result columns + public override void Can_use_sproc_mapping_with_owned_reference() + => Assert.Throws(() => base.Can_use_sproc_mapping_with_owned_reference()); + + protected override TestModelBuilder CreateModelBuilder( + Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } +} diff --git a/test/EFCore.PG.FunctionalTests/ModelBuilding/NpgsqlModelBuilderTestBase.cs b/test/EFCore.PG.FunctionalTests/ModelBuilding/NpgsqlModelBuilderTestBase.cs new file mode 100644 index 000000000..95f42a658 --- /dev/null +++ b/test/EFCore.PG.FunctionalTests/ModelBuilding/NpgsqlModelBuilderTestBase.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore.ModelBuilding; +using Npgsql.EntityFrameworkCore.PostgreSQL.Internal; +using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities; + +#nullable enable + +namespace Npgsql.EntityFrameworkCore.PostgreSQL.ModelBuilding; + +public class NpgsqlModelBuilderTestBase : RelationalModelBuilderTest +{ + public abstract class NpgsqlNonRelationship(NpgsqlModelBuilderFixture fixture) + : RelationalNonRelationshipTestBase(fixture), IClassFixture; + + public abstract class NpgsqlComplexType(NpgsqlModelBuilderFixture fixture) + : RelationalComplexTypeTestBase(fixture), IClassFixture; + + public abstract class NpgsqlInheritance(NpgsqlModelBuilderFixture fixture) + : RelationalInheritanceTestBase(fixture), IClassFixture; + + public abstract class NpgsqlOneToMany(NpgsqlModelBuilderFixture fixture) + : RelationalOneToManyTestBase(fixture), IClassFixture; + + public abstract class NpgsqlManyToOne(NpgsqlModelBuilderFixture fixture) + : RelationalManyToOneTestBase(fixture), IClassFixture; + + public abstract class NpgsqlOneToOne(NpgsqlModelBuilderFixture fixture) + : RelationalOneToOneTestBase(fixture), IClassFixture; + + public abstract class NpgsqlManyToMany(NpgsqlModelBuilderFixture fixture) + : RelationalManyToManyTestBase(fixture), IClassFixture; + + public abstract class NpgsqlOwnedTypes(NpgsqlModelBuilderFixture fixture) + : RelationalOwnedTypesTestBase(fixture), IClassFixture; + + public class NpgsqlModelBuilderFixture : RelationalModelBuilderFixture + { + public override TestHelpers TestHelpers + => NpgsqlTestHelpers.Instance; + } +} diff --git a/test/EFCore.PG.FunctionalTests/NpgsqlComplianceTest.cs b/test/EFCore.PG.FunctionalTests/NpgsqlComplianceTest.cs index 3f5aa7ae5..b51dea3bc 100644 --- a/test/EFCore.PG.FunctionalTests/NpgsqlComplianceTest.cs +++ b/test/EFCore.PG.FunctionalTests/NpgsqlComplianceTest.cs @@ -5,6 +5,7 @@ public class NpgsqlComplianceTest : RelationalComplianceTestBase protected override ICollection IgnoredTestBases { get; } = new HashSet { // Not implemented + typeof(CompiledModelTestBase), typeof(CompiledModelRelationalTestBase), // ##3087 typeof(FromSqlSprocQueryTestBase<>), typeof(UdfDbFunctionTestBase<>), typeof(UpdateSqlGeneratorTestBase), diff --git a/test/EFCore.PG.FunctionalTests/NpgsqlDatabaseCreatorTest.cs b/test/EFCore.PG.FunctionalTests/NpgsqlDatabaseCreatorTest.cs index 5efd47db1..2c9d7e992 100644 --- a/test/EFCore.PG.FunctionalTests/NpgsqlDatabaseCreatorTest.cs +++ b/test/EFCore.PG.FunctionalTests/NpgsqlDatabaseCreatorTest.cs @@ -208,7 +208,7 @@ private static async Task Creates_physical_database_and_schema_test( Assert.Equal(14, columns.Length); Assert.Equal( - [ + new[] { "Blogs.AndChew (bytea)", "Blogs.AndRow (bytea)", "Blogs.Cheese (text)", @@ -223,7 +223,7 @@ private static async Task Creates_physical_database_and_schema_test( "Blogs.TheGu (uuid)", "Blogs.ToEat (smallint)", "Blogs.WayRound (bigint)" - ], + }, columns); } diff --git a/test/EFCore.PG.FunctionalTests/Query/AdHocAdvancedMappingsQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/AdHocAdvancedMappingsQueryNpgsqlTest.cs new file mode 100644 index 000000000..dd80b867a --- /dev/null +++ b/test/EFCore.PG.FunctionalTests/Query/AdHocAdvancedMappingsQueryNpgsqlTest.cs @@ -0,0 +1,19 @@ +using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities; + +namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query; + +public class AdHocAdvancedMappingsQueryNpgsqlTest : AdHocAdvancedMappingsQueryRelationalTestBase +{ + protected override ITestStoreFactory TestStoreFactory + => NpgsqlTestStoreFactory.Instance; + + // Cannot write DateTime with Kind=Unspecified to PostgreSQL type 'timestamp with time zone', only UTC is supported. + public override Task Query_generates_correct_datetime2_parameter_definition(int? fractionalSeconds, string postfix) + => Assert.ThrowsAsync( + () => base.Query_generates_correct_datetime2_parameter_definition(fractionalSeconds, postfix)); + + // Cannot write DateTimeOffset with Offset=10:00:00 to PostgreSQL type 'timestamp with time zone', only offset 0 (UTC) is supported. + public override Task Query_generates_correct_datetimeoffset_parameter_definition(int? fractionalSeconds, string postfix) + => Assert.ThrowsAsync( + () => base.Query_generates_correct_datetime2_parameter_definition(fractionalSeconds, postfix)); +} diff --git a/test/EFCore.PG.FunctionalTests/Query/JsonQueryAdHocNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/AdHocJsonQueryNpgsqlTest.cs similarity index 53% rename from test/EFCore.PG.FunctionalTests/Query/JsonQueryAdHocNpgsqlTest.cs rename to test/EFCore.PG.FunctionalTests/Query/AdHocJsonQueryNpgsqlTest.cs index a26bb18fd..edb0f85fc 100644 --- a/test/EFCore.PG.FunctionalTests/Query/JsonQueryAdHocNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/AdHocJsonQueryNpgsqlTest.cs @@ -1,106 +1,12 @@ -using Microsoft.EntityFrameworkCore.Diagnostics.Internal; -using Npgsql.EntityFrameworkCore.PostgreSQL.Diagnostics.Internal; using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities; namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query; -public class JsonQueryAdHocNpgsqlTest : JsonQueryAdHocTestBase +public class AdHocJsonQueryNpgsqlTest : AdHocJsonQueryTestBase { protected override ITestStoreFactory TestStoreFactory => NpgsqlTestStoreFactory.Instance; - [ConditionalTheory(Skip = "https://github.com/dotnet/efcore/issues/32235")] - public override Task Junk_in_json_basic_tracking(bool async) - => base.Junk_in_json_basic_tracking(async); - - [ConditionalTheory(Skip = "https://github.com/dotnet/efcore/issues/32235")] - public override Task Junk_in_json_basic_no_tracking(bool async) - => base.Junk_in_json_basic_no_tracking(async); - - [ConditionalTheory, MemberData(nameof(IsAsyncData))] - public virtual async Task Json_predicate_on_bytea(bool async) - { - var contextFactory = await InitializeAsync( - seed: context => - { - context.Entities.AddRange( - new TypesContainerEntity { JsonEntity = new TypesJsonEntity { Bytea = [1, 2, 3] } }, - new TypesContainerEntity { JsonEntity = new TypesJsonEntity { Bytea = [1, 2, 4] } }); - context.SaveChanges(); - }); - - using (var context = contextFactory.CreateContext()) - { - var query = context.Entities.Where(x => x.JsonEntity.Bytea == new byte[] { 1, 2, 4 }); - - var result = async - ? await query.SingleAsync() - : query.Single(); - - Assert.Equal(2, result.Id); - - AssertSql( - """ -SELECT e."Id", e."JsonEntity" -FROM "Entities" AS e -WHERE (decode(e."JsonEntity" ->> 'Bytea', 'base64')) = BYTEA E'\\x010204' -LIMIT 2 -"""); - } - } - - [ConditionalTheory, MemberData(nameof(IsAsyncData))] - public virtual async Task Json_predicate_on_interval(bool async) - { - var contextFactory = await InitializeAsync( - seed: context => - { - context.Entities.AddRange( - new TypesContainerEntity { JsonEntity = new TypesJsonEntity { Interval = new TimeSpan(1, 2, 3, 4, 123, 456) } }, - new TypesContainerEntity { JsonEntity = new TypesJsonEntity { Interval = new TimeSpan(2, 2, 3, 4, 123, 456) } }); - context.SaveChanges(); - }); - - using (var context = contextFactory.CreateContext()) - { - var query = context.Entities.Where(x => x.JsonEntity.Interval == new TimeSpan(2, 2, 3, 4, 123, 456)); - - var result = async - ? await query.SingleAsync() - : query.Single(); - - Assert.Equal(2, result.Id); - - AssertSql( - """ -SELECT e."Id", e."JsonEntity" -FROM "Entities" AS e -WHERE (CAST(e."JsonEntity" ->> 'Interval' AS interval)) = INTERVAL '2 02:03:04.123456' -LIMIT 2 -"""); - } - } - - protected class TypesDbContext(DbContextOptions options) : DbContext(options) - { - public DbSet Entities { get; set; } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - => modelBuilder.Entity().OwnsOne(b => b.JsonEntity).ToJson(); - } - - public class TypesContainerEntity - { - public int Id { get; set; } - public TypesJsonEntity JsonEntity { get; set; } - } - - public class TypesJsonEntity - { - public byte[] Bytea { get; set; } - public TimeSpan Interval { get; set; } - } - protected override void Seed29219(MyContext29219 ctx) { var entity1 = new MyEntity29219 @@ -227,6 +133,14 @@ protected override void SeedJunkInJson(MyContextJunkInJson ctx) '{{"Name":"r1","JunkCollection":[{{"Foo":"junk value"}}],"JunkReference":{{"Something":"SomeValue" }},"Number":1.5,"NestedCollection":[{{"DoB":"2000-02-01T00:00:00","JunkReference":{{"Something":"SomeValue"}}}},{{"DoB":"2000-02-02T00:00:00"}}],"NestedReference":{{"DoB":"2000-01-01T00:00:00"}}}}', '{{"MyBool":true,"JunkCollection":[{{"Foo":"junk value"}}],"Name":"r1 ctor","JunkReference":{{"Something":"SomeValue" }},"NestedCollection":[{{"DoB":"2001-02-01T00:00:00"}},{{"DoB":"2001-02-02T00:00:00"}}],"NestedReference":{{"JunkCollection":[{{"Foo":"junk value"}}],"DoB":"2001-01-01T00:00:00"}}}}', 1) +"""); + + protected override void SeedTrickyBuffering(MyContextTrickyBuffering ctx) + => ctx.Database.ExecuteSqlRaw( + """ +INSERT INTO "Entities" ("Reference", "Id") +VALUES( +'{{"Name": "r1", "Number": 7, "JunkReference":{{"Something": "SomeValue" }}, "JunkCollection": [{{"Foo": "junk value"}}], "NestedReference": {{"DoB": "2000-01-01T00:00:00Z"}}, "NestedCollection": [{{"DoB": "2000-02-01T00:00:00Z", "JunkReference": {{"Something": "SomeValue"}}}}, {{"DoB": "2000-02-02T00:00:00Z"}}]}}',1) """); protected override void SeedShadowProperties(MyContextShadowProperties ctx) @@ -261,200 +175,90 @@ protected override void SeedNotICollection(MyContextNotICollection ctx) """); } - #region EnumLegacyValues - [ConditionalTheory, MemberData(nameof(IsAsyncData))] - public virtual async Task Read_enum_property_with_legacy_values(bool async) + public virtual async Task Json_predicate_on_bytea(bool async) { - var contextFactory = await InitializeAsync( - seed: SeedEnumLegacyValues); + var contextFactory = await InitializeAsync( + seed: context => + { + context.Entities.AddRange( + new TypesContainerEntity { JsonEntity = new TypesJsonEntity { Bytea = [1, 2, 3] } }, + new TypesContainerEntity { JsonEntity = new TypesJsonEntity { Bytea = [1, 2, 4] } }); + context.SaveChanges(); + }); using (var context = contextFactory.CreateContext()) { - var query = context.Entities.Select( - x => new - { - x.Reference.IntEnum, - x.Reference.ByteEnum, - x.Reference.LongEnum, - x.Reference.NullableEnum - }); - - var exception = async - ? await (Assert.ThrowsAsync(() => query.ToListAsync())) - : Assert.Throws(() => query.ToList()); - - // Conversion failed when converting the text value '...' to data type int - Assert.Equal("22P02", exception.SqlState); - } - } + var query = context.Entities.Where(x => x.JsonEntity.Bytea == new byte[] { 1, 2, 4 }); - [ConditionalTheory, MemberData(nameof(IsAsyncData))] - public virtual async Task Read_json_entity_with_enum_properties_with_legacy_values(bool async) - { - var contextFactory = await InitializeAsync( - seed: SeedEnumLegacyValues, - shouldLogCategory: c => c == DbLoggerCategory.Query.Name); + var result = async + ? await query.SingleAsync() + : query.Single(); - using (var context = contextFactory.CreateContext()) - { - var query = context.Entities.Select(x => x.Reference).AsNoTracking(); + Assert.Equal(2, result.Id); - var result = async - ? await query.ToListAsync() - : query.ToList(); - - Assert.Single(result); - Assert.Equal(ByteEnumLegacyValues.Redmond, result[0].ByteEnum); - Assert.Equal(IntEnumLegacyValues.Foo, result[0].IntEnum); - Assert.Equal(LongEnumLegacyValues.Three, result[0].LongEnum); - Assert.Equal(ULongEnumLegacyValues.Three, result[0].ULongEnum); - Assert.Equal(IntEnumLegacyValues.Bar, result[0].NullableEnum); + AssertSql( + """ +SELECT e."Id", e."JsonEntity" +FROM "Entities" AS e +WHERE (decode(e."JsonEntity" ->> 'Bytea', 'base64')) = BYTEA E'\\x010204' +LIMIT 2 +"""); } - - var testLogger = new TestLogger(); - Assert.Single( - ListLoggerFactory.Log.Where( - l => l.Message == CoreResources.LogStringEnumValueInJson(testLogger).GenerateMessage(nameof(ByteEnumLegacyValues)))); - Assert.Single( - ListLoggerFactory.Log.Where( - l => l.Message == CoreResources.LogStringEnumValueInJson(testLogger).GenerateMessage(nameof(IntEnumLegacyValues)))); - Assert.Single( - ListLoggerFactory.Log.Where( - l => l.Message == CoreResources.LogStringEnumValueInJson(testLogger).GenerateMessage(nameof(LongEnumLegacyValues)))); - Assert.Single( - ListLoggerFactory.Log.Where( - l => l.Message == CoreResources.LogStringEnumValueInJson(testLogger).GenerateMessage(nameof(ULongEnumLegacyValues)))); } [ConditionalTheory, MemberData(nameof(IsAsyncData))] - public virtual async Task Read_json_entity_collection_with_enum_properties_with_legacy_values(bool async) + public virtual async Task Json_predicate_on_interval(bool async) { - var contextFactory = await InitializeAsync( - seed: SeedEnumLegacyValues, - shouldLogCategory: c => c == DbLoggerCategory.Query.Name); + var contextFactory = await InitializeAsync( + seed: context => + { + context.Entities.AddRange( + new TypesContainerEntity { JsonEntity = new TypesJsonEntity { Interval = new TimeSpan(1, 2, 3, 4, 123, 456) } }, + new TypesContainerEntity { JsonEntity = new TypesJsonEntity { Interval = new TimeSpan(2, 2, 3, 4, 123, 456) } }); + context.SaveChanges(); + }); using (var context = contextFactory.CreateContext()) { - var query = context.Entities.Select(x => x.Collection).AsNoTracking(); + var query = context.Entities.Where(x => x.JsonEntity.Interval == new TimeSpan(2, 2, 3, 4, 123, 456)); var result = async - ? await query.ToListAsync() - : query.ToList(); - - Assert.Single(result); - Assert.Equal(2, result[0].Count); - Assert.Equal(ByteEnumLegacyValues.Bellevue, result[0][0].ByteEnum); - Assert.Equal(IntEnumLegacyValues.Foo, result[0][0].IntEnum); - Assert.Equal(LongEnumLegacyValues.One, result[0][0].LongEnum); - Assert.Equal(ULongEnumLegacyValues.One, result[0][0].ULongEnum); - Assert.Equal(IntEnumLegacyValues.Bar, result[0][0].NullableEnum); - Assert.Equal(ByteEnumLegacyValues.Seattle, result[0][1].ByteEnum); - Assert.Equal(IntEnumLegacyValues.Baz, result[0][1].IntEnum); - Assert.Equal(LongEnumLegacyValues.Two, result[0][1].LongEnum); - Assert.Equal(ULongEnumLegacyValues.Two, result[0][1].ULongEnum); - Assert.Null(result[0][1].NullableEnum); - } + ? await query.SingleAsync() + : query.Single(); - var testLogger = new TestLogger(); - Assert.Single( - ListLoggerFactory.Log.Where( - l => l.Message == CoreResources.LogStringEnumValueInJson(testLogger).GenerateMessage(nameof(ByteEnumLegacyValues)))); - Assert.Single( - ListLoggerFactory.Log.Where( - l => l.Message == CoreResources.LogStringEnumValueInJson(testLogger).GenerateMessage(nameof(IntEnumLegacyValues)))); - Assert.Single( - ListLoggerFactory.Log.Where( - l => l.Message == CoreResources.LogStringEnumValueInJson(testLogger).GenerateMessage(nameof(LongEnumLegacyValues)))); - Assert.Single( - ListLoggerFactory.Log.Where( - l => l.Message == CoreResources.LogStringEnumValueInJson(testLogger).GenerateMessage(nameof(ULongEnumLegacyValues)))); - } + Assert.Equal(2, result.Id); - private void SeedEnumLegacyValues(MyContextEnumLegacyValues ctx) - => ctx.Database.ExecuteSqlRaw( - """ -INSERT INTO "Entities" ("Collection", "Reference", "Id", "Name") -VALUES( -'[{{"ByteEnum":"Bellevue","IntEnum":"Foo","LongEnum":"One","ULongEnum":"One","Name":"e1_c1","NullableEnum":"Bar"}},{{"ByteEnum":"Seattle","IntEnum":"Baz","LongEnum":"Two","ULongEnum":"Two","Name":"e1_c2","NullableEnum":null}}]', -'{{"ByteEnum":"Redmond","IntEnum":"Foo","LongEnum":"Three","ULongEnum":"Three","Name":"e1_r","NullableEnum":"Bar"}}', -1, -'e1') + AssertSql( + """ +SELECT e."Id", e."JsonEntity" +FROM "Entities" AS e +WHERE (CAST(e."JsonEntity" ->> 'Interval' AS interval)) = INTERVAL '2 02:03:04.123456' +LIMIT 2 """); - - private class MyContextEnumLegacyValues(DbContextOptions options) : DbContext( - (new DbContextOptionsBuilder(options)).ConfigureWarnings(b => b.Log(CoreEventId.StringEnumValueInJson)).Options) - { - // ReSharper disable once UnusedAutoPropertyAccessor.Local - public DbSet Entities { get; set; } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.Entity().Property(x => x.Id).ValueGeneratedNever(); - modelBuilder.Entity().OwnsOne(x => x.Reference, b => b.ToJson()); - modelBuilder.Entity().OwnsMany(x => x.Collection, b => b.ToJson()); } } - private class MyEntityEnumLegacyValues - { - public int Id { get; set; } - public string Name { get; set; } - - public MyJsonEntityEnumLegacyValues Reference { get; set; } - public List Collection { get; set; } - } - - private class MyJsonEntityEnumLegacyValues - { - public string Name { get; set; } - - // ReSharper disable once UnusedAutoPropertyAccessor.Local - public IntEnumLegacyValues IntEnum { get; set; } - - // ReSharper disable once UnusedAutoPropertyAccessor.Local - public ByteEnumLegacyValues ByteEnum { get; set; } - - // ReSharper disable once UnusedAutoPropertyAccessor.Local - public LongEnumLegacyValues LongEnum { get; set; } - - // ReSharper disable once UnusedAutoPropertyAccessor.Local - public ULongEnumLegacyValues ULongEnum { get; set; } - - // ReSharper disable once UnusedAutoPropertyAccessor.Local - public IntEnumLegacyValues? NullableEnum { get; set; } - } - - private enum IntEnumLegacyValues + protected class TypesDbContext(DbContextOptions options) : DbContext(options) { - Foo = int.MinValue, - Bar, - Baz = int.MaxValue, - } + public DbSet Entities { get; set; } - private enum ByteEnumLegacyValues : byte - { - Seattle, - Redmond, - Bellevue = 255, + protected override void OnModelCreating(ModelBuilder modelBuilder) + => modelBuilder.Entity().OwnsOne(b => b.JsonEntity).ToJson(); } - private enum LongEnumLegacyValues : long + public class TypesContainerEntity { - One = long.MinValue, - Two = 1, - Three = long.MaxValue, + public int Id { get; set; } + public TypesJsonEntity JsonEntity { get; set; } } - private enum ULongEnumLegacyValues : ulong + public class TypesJsonEntity { - One = ulong.MinValue, - Two = 1, - Three = ulong.MaxValue, + public byte[] Bytea { get; set; } + public TimeSpan Interval { get; set; } } - #endregion - protected void AssertSql(params string[] expected) => TestSqlLoggerFactory.AssertBaseline(expected); } diff --git a/test/EFCore.PG.FunctionalTests/Query/ManyToManyHeterogeneousQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/AdHocManyToManyQueryNpgsqlTest.cs similarity index 68% rename from test/EFCore.PG.FunctionalTests/Query/ManyToManyHeterogeneousQueryNpgsqlTest.cs rename to test/EFCore.PG.FunctionalTests/Query/AdHocManyToManyQueryNpgsqlTest.cs index 6f13329a9..eb60e4c60 100644 --- a/test/EFCore.PG.FunctionalTests/Query/ManyToManyHeterogeneousQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/AdHocManyToManyQueryNpgsqlTest.cs @@ -2,7 +2,7 @@ namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query; -public class ManyToManyHeterogeneousQuerySqlServerTest : ManyToManyHeterogeneousQueryRelationalTestBase +public class AdHocManyToManyQueryNpgsqlTest : AdHocManyToManyQueryRelationalTestBase { protected override ITestStoreFactory TestStoreFactory => NpgsqlTestStoreFactory.Instance; diff --git a/test/EFCore.PG.FunctionalTests/Query/AdHocMiscellaneousQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/AdHocMiscellaneousQueryNpgsqlTest.cs new file mode 100644 index 000000000..0e1b6a5d4 --- /dev/null +++ b/test/EFCore.PG.FunctionalTests/Query/AdHocMiscellaneousQueryNpgsqlTest.cs @@ -0,0 +1,38 @@ +using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities; + +namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query; + +public class AdHocMiscellaneousQueryNpgsqlTest : AdHocMiscellaneousQueryRelationalTestBase +{ + protected override ITestStoreFactory TestStoreFactory + => NpgsqlTestStoreFactory.Instance; + + protected override void Seed2951(Context2951 context) + => context.Database.ExecuteSqlRaw( + """ +CREATE TABLE "ZeroKey" ("Id" int); +INSERT INTO "ZeroKey" VALUES (NULL) +"""); + + // https://github.com/dotnet/efcore/pull/32542/files#r1485633978 + public override Task Nested_queries_does_not_cause_concurrency_exception_sync(bool tracking) + => Assert.ThrowsAsync( + () => base.Nested_queries_does_not_cause_concurrency_exception_sync(tracking)); + + // https://github.com/dotnet/efcore/pull/32542/files#r1485633978 + public override Task Select_nested_projection() + => Assert.ThrowsAsync( + () => base.Select_nested_projection()); + + // Writes DateTime with Kind=Unspecified to timestamptz + public override Task SelectMany_where_Select(bool async) + => Task.CompletedTask; + + // Writes DateTime with Kind=Unspecified to timestamptz + public override Task Subquery_first_member_compared_to_null(bool async) + => Task.CompletedTask; + + [ConditionalTheory(Skip = "https://github.com/dotnet/efcore/pull/27995/files#r874038747")] + public override Task StoreType_for_UDF_used(bool async) + => base.StoreType_for_UDF_used(async); +} diff --git a/test/EFCore.PG.FunctionalTests/Query/AdHocNavigationsQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/AdHocNavigationsQueryNpgsqlTest.cs new file mode 100644 index 000000000..dbbd481b3 --- /dev/null +++ b/test/EFCore.PG.FunctionalTests/Query/AdHocNavigationsQueryNpgsqlTest.cs @@ -0,0 +1,17 @@ +using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities; + +namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query; + +public class AdHocNavigationsQueryNpgsqlTest : AdHocNavigationsQueryRelationalTestBase +{ + // Cannot write DateTime with Kind=Local to PostgreSQL type 'timestamp with time zone', only UTC is supported. + public override Task Reference_include_on_derived_type_with_sibling_works() + => Assert.ThrowsAsync(() => base.Reference_include_on_derived_type_with_sibling_works()); + + // https://github.com/dotnet/efcore/pull/32542/files#r1485618022 + public override Task Nested_include_queries_do_not_populate_navigation_twice() + => Assert.ThrowsAsync(() => base.Nested_include_queries_do_not_populate_navigation_twice()); + + protected override ITestStoreFactory TestStoreFactory + => NpgsqlTestStoreFactory.Instance; +} diff --git a/test/EFCore.PG.FunctionalTests/Query/AdHocQueryFiltersQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/AdHocQueryFiltersQueryNpgsqlTest.cs new file mode 100644 index 000000000..a6c0b0c17 --- /dev/null +++ b/test/EFCore.PG.FunctionalTests/Query/AdHocQueryFiltersQueryNpgsqlTest.cs @@ -0,0 +1,9 @@ +using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities; + +namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query; + +public class AdHocQueryFiltersQueryNpgsqlTest : AdHocQueryFiltersQueryRelationalTestBase +{ + protected override ITestStoreFactory TestStoreFactory + => NpgsqlTestStoreFactory.Instance; +} diff --git a/test/EFCore.PG.FunctionalTests/Query/AdHocQuerySplittingQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/AdHocQuerySplittingQueryNpgsqlTest.cs new file mode 100644 index 000000000..927fe2ff8 --- /dev/null +++ b/test/EFCore.PG.FunctionalTests/Query/AdHocQuerySplittingQueryNpgsqlTest.cs @@ -0,0 +1,40 @@ +using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure; +using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal; +using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities; + +namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query; + +public class AdHocQuerySplittingQueryNpgsqlTest : AdHocQuerySplittingQueryTestBase +{ + protected override DbContextOptionsBuilder SetQuerySplittingBehavior( + DbContextOptionsBuilder optionsBuilder, + QuerySplittingBehavior splittingBehavior) + { + new NpgsqlDbContextOptionsBuilder(optionsBuilder).UseQuerySplittingBehavior(splittingBehavior); + + return optionsBuilder; + } + + protected override DbContextOptionsBuilder ClearQuerySplittingBehavior(DbContextOptionsBuilder optionsBuilder) + { + var extension = optionsBuilder.Options.FindExtension(); + if (extension == null) + { + extension = new NpgsqlOptionsExtension(); + } + else + { + _querySplittingBehaviorFieldInfo.SetValue(extension, null); + } + + ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension); + + return optionsBuilder; + } + + private static readonly FieldInfo _querySplittingBehaviorFieldInfo = + typeof(RelationalOptionsExtension).GetField("_querySplittingBehavior", BindingFlags.NonPublic | BindingFlags.Instance); + + protected override ITestStoreFactory TestStoreFactory + => NpgsqlTestStoreFactory.Instance; +} diff --git a/test/EFCore.PG.FunctionalTests/Query/ArrayQueryTest.cs b/test/EFCore.PG.FunctionalTests/Query/ArrayQueryTest.cs index dd35fc5f4..1a34cb9d4 100644 --- a/test/EFCore.PG.FunctionalTests/Query/ArrayQueryTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/ArrayQueryTest.cs @@ -24,7 +24,7 @@ public void Roundtrip() using var ctx = CreateContext(); var x = ctx.SomeEntities.Single(e => e.Id == 1); - Assert.Equal([3, 4], x.IntArray); + Assert.Equal(new[] { 3, 4 }, x.IntArray); Assert.Equal([3, 4], x.IntList); Assert.Equal([3, 4, null], x.NullableIntArray); Assert.Equal( diff --git a/test/EFCore.PG.FunctionalTests/Query/ComplexNavigationsQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/ComplexNavigationsQueryNpgsqlTest.cs index 6ec76cd82..1771836d8 100644 --- a/test/EFCore.PG.FunctionalTests/Query/ComplexNavigationsQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/ComplexNavigationsQueryNpgsqlTest.cs @@ -10,9 +10,9 @@ public ComplexNavigationsQueryNpgsqlTest(ComplexNavigationsQueryNpgsqlFixture fi Fixture.TestSqlLoggerFactory.Clear(); } - [ConditionalTheory(Skip = "https://github.com/dotnet/efcore/issues/26353")] - public override Task Subquery_with_Distinct_Skip_FirstOrDefault_without_OrderBy(bool async) - => base.Subquery_with_Distinct_Skip_FirstOrDefault_without_OrderBy(async); + // https://github.com/dotnet/efcore/pull/33060 + public override Task Max_in_multi_level_nested_subquery(bool async) + => Assert.ThrowsAsync(() => base.Max_in_multi_level_nested_subquery(async)); public override async Task Join_with_result_selector_returning_queryable_throws_validation_error(bool async) => await Assert.ThrowsAsync( diff --git a/test/EFCore.PG.FunctionalTests/Query/ComplexTypeQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/ComplexTypeQueryNpgsqlTest.cs index 1d4e555bd..d490537cc 100644 --- a/test/EFCore.PG.FunctionalTests/Query/ComplexTypeQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/ComplexTypeQueryNpgsqlTest.cs @@ -18,7 +18,7 @@ public override async Task Filter_on_property_inside_complex_type(bool async) AssertSql( """ -SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" +SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_Tags", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c WHERE c."ShippingAddress_ZipCode" = 7728 """); @@ -30,7 +30,7 @@ public override async Task Filter_on_property_inside_nested_complex_type(bool as AssertSql( """ -SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" +SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_Tags", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c WHERE c."ShippingAddress_Country_Code" = 'DE' """); @@ -44,14 +44,14 @@ public override async Task Filter_on_property_inside_complex_type_after_subquery """ @__p_0='1' -SELECT DISTINCT t."Id", t."Name", t."BillingAddress_AddressLine1", t."BillingAddress_AddressLine2", t."BillingAddress_ZipCode", t."BillingAddress_Country_Code", t."BillingAddress_Country_FullName", t."ShippingAddress_AddressLine1", t."ShippingAddress_AddressLine2", t."ShippingAddress_ZipCode", t."ShippingAddress_Country_Code", t."ShippingAddress_Country_FullName" +SELECT DISTINCT c0."Id", c0."Name", c0."BillingAddress_AddressLine1", c0."BillingAddress_AddressLine2", c0."BillingAddress_Tags", c0."BillingAddress_ZipCode", c0."BillingAddress_Country_Code", c0."BillingAddress_Country_FullName", c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_Tags", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName" FROM ( - SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" + SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_Tags", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c ORDER BY c."Id" NULLS FIRST OFFSET @__p_0 -) AS t -WHERE t."ShippingAddress_ZipCode" = 7728 +) AS c0 +WHERE c0."ShippingAddress_ZipCode" = 7728 """); } @@ -63,14 +63,14 @@ public override async Task Filter_on_property_inside_nested_complex_type_after_s """ @__p_0='1' -SELECT DISTINCT t."Id", t."Name", t."BillingAddress_AddressLine1", t."BillingAddress_AddressLine2", t."BillingAddress_ZipCode", t."BillingAddress_Country_Code", t."BillingAddress_Country_FullName", t."ShippingAddress_AddressLine1", t."ShippingAddress_AddressLine2", t."ShippingAddress_ZipCode", t."ShippingAddress_Country_Code", t."ShippingAddress_Country_FullName" +SELECT DISTINCT c0."Id", c0."Name", c0."BillingAddress_AddressLine1", c0."BillingAddress_AddressLine2", c0."BillingAddress_Tags", c0."BillingAddress_ZipCode", c0."BillingAddress_Country_Code", c0."BillingAddress_Country_FullName", c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_Tags", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName" FROM ( - SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" + SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_Tags", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c ORDER BY c."Id" NULLS FIRST OFFSET @__p_0 -) AS t -WHERE t."ShippingAddress_Country_Code" = 'DE' +) AS c0 +WHERE c0."ShippingAddress_Country_Code" = 'DE' """); } @@ -80,7 +80,7 @@ public override async Task Filter_on_required_property_inside_required_complex_t AssertSql( """ -SELECT c."Id", c."OptionalCustomerId", c."RequiredCustomerId", c0."Id", c0."Name", c0."BillingAddress_AddressLine1", c0."BillingAddress_AddressLine2", c0."BillingAddress_ZipCode", c0."BillingAddress_Country_Code", c0."BillingAddress_Country_FullName", c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName", c1."Id", c1."Name", c1."BillingAddress_AddressLine1", c1."BillingAddress_AddressLine2", c1."BillingAddress_ZipCode", c1."BillingAddress_Country_Code", c1."BillingAddress_Country_FullName", c1."ShippingAddress_AddressLine1", c1."ShippingAddress_AddressLine2", c1."ShippingAddress_ZipCode", c1."ShippingAddress_Country_Code", c1."ShippingAddress_Country_FullName" +SELECT c."Id", c."OptionalCustomerId", c."RequiredCustomerId", c0."Id", c0."Name", c0."BillingAddress_AddressLine1", c0."BillingAddress_AddressLine2", c0."BillingAddress_Tags", c0."BillingAddress_ZipCode", c0."BillingAddress_Country_Code", c0."BillingAddress_Country_FullName", c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_Tags", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName", c1."Id", c1."Name", c1."BillingAddress_AddressLine1", c1."BillingAddress_AddressLine2", c1."BillingAddress_Tags", c1."BillingAddress_ZipCode", c1."BillingAddress_Country_Code", c1."BillingAddress_Country_FullName", c1."ShippingAddress_AddressLine1", c1."ShippingAddress_AddressLine2", c1."ShippingAddress_Tags", c1."ShippingAddress_ZipCode", c1."ShippingAddress_Country_Code", c1."ShippingAddress_Country_FullName" FROM "CustomerGroup" AS c LEFT JOIN "Customer" AS c0 ON c."OptionalCustomerId" = c0."Id" INNER JOIN "Customer" AS c1 ON c."RequiredCustomerId" = c1."Id" @@ -94,7 +94,7 @@ public override async Task Filter_on_required_property_inside_required_complex_t AssertSql( """ -SELECT c."Id", c."OptionalCustomerId", c."RequiredCustomerId", c1."Id", c1."Name", c1."BillingAddress_AddressLine1", c1."BillingAddress_AddressLine2", c1."BillingAddress_ZipCode", c1."BillingAddress_Country_Code", c1."BillingAddress_Country_FullName", c1."ShippingAddress_AddressLine1", c1."ShippingAddress_AddressLine2", c1."ShippingAddress_ZipCode", c1."ShippingAddress_Country_Code", c1."ShippingAddress_Country_FullName", c0."Id", c0."Name", c0."BillingAddress_AddressLine1", c0."BillingAddress_AddressLine2", c0."BillingAddress_ZipCode", c0."BillingAddress_Country_Code", c0."BillingAddress_Country_FullName", c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName" +SELECT c."Id", c."OptionalCustomerId", c."RequiredCustomerId", c1."Id", c1."Name", c1."BillingAddress_AddressLine1", c1."BillingAddress_AddressLine2", c1."BillingAddress_Tags", c1."BillingAddress_ZipCode", c1."BillingAddress_Country_Code", c1."BillingAddress_Country_FullName", c1."ShippingAddress_AddressLine1", c1."ShippingAddress_AddressLine2", c1."ShippingAddress_Tags", c1."ShippingAddress_ZipCode", c1."ShippingAddress_Country_Code", c1."ShippingAddress_Country_FullName", c0."Id", c0."Name", c0."BillingAddress_AddressLine1", c0."BillingAddress_AddressLine2", c0."BillingAddress_Tags", c0."BillingAddress_ZipCode", c0."BillingAddress_Country_Code", c0."BillingAddress_Country_FullName", c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_Tags", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName" FROM "CustomerGroup" AS c INNER JOIN "Customer" AS c0 ON c."RequiredCustomerId" = c0."Id" LEFT JOIN "Customer" AS c1 ON c."OptionalCustomerId" = c1."Id" @@ -118,7 +118,7 @@ public override async Task Project_complex_type_via_required_navigation(bool asy AssertSql( """ -SELECT c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName" +SELECT c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_Tags", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName" FROM "CustomerGroup" AS c INNER JOIN "Customer" AS c0 ON c."RequiredCustomerId" = c0."Id" """); @@ -132,13 +132,13 @@ public override async Task Load_complex_type_after_subquery_on_entity_type(bool """ @__p_0='1' -SELECT DISTINCT t."Id", t."Name", t."BillingAddress_AddressLine1", t."BillingAddress_AddressLine2", t."BillingAddress_ZipCode", t."BillingAddress_Country_Code", t."BillingAddress_Country_FullName", t."ShippingAddress_AddressLine1", t."ShippingAddress_AddressLine2", t."ShippingAddress_ZipCode", t."ShippingAddress_Country_Code", t."ShippingAddress_Country_FullName" +SELECT DISTINCT c0."Id", c0."Name", c0."BillingAddress_AddressLine1", c0."BillingAddress_AddressLine2", c0."BillingAddress_Tags", c0."BillingAddress_ZipCode", c0."BillingAddress_Country_Code", c0."BillingAddress_Country_FullName", c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_Tags", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName" FROM ( - SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" + SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_Tags", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c ORDER BY c."Id" NULLS FIRST OFFSET @__p_0 -) AS t +) AS c0 """); } @@ -148,7 +148,7 @@ public override async Task Select_complex_type(bool async) AssertSql( """ -SELECT c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" +SELECT c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c """); } @@ -181,7 +181,7 @@ public override async Task Select_complex_type_Where(bool async) AssertSql( """ -SELECT c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" +SELECT c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c WHERE c."ShippingAddress_ZipCode" = 7728 """); @@ -193,7 +193,7 @@ public override async Task Select_complex_type_Distinct(bool async) AssertSql( """ -SELECT DISTINCT c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" +SELECT DISTINCT c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c """); } @@ -204,9 +204,9 @@ public override async Task Complex_type_equals_complex_type(bool async) AssertSql( """ -SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" +SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_Tags", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c -WHERE c."ShippingAddress_AddressLine1" = c."BillingAddress_AddressLine1" AND (c."ShippingAddress_AddressLine2" = c."BillingAddress_AddressLine2" OR (c."ShippingAddress_AddressLine2" IS NULL AND c."BillingAddress_AddressLine2" IS NULL)) AND c."ShippingAddress_ZipCode" = c."BillingAddress_ZipCode" +WHERE c."ShippingAddress_AddressLine1" = c."BillingAddress_AddressLine1" AND (c."ShippingAddress_AddressLine2" = c."BillingAddress_AddressLine2" OR (c."ShippingAddress_AddressLine2" IS NULL AND c."BillingAddress_AddressLine2" IS NULL)) AND c."ShippingAddress_Tags" = c."BillingAddress_Tags" AND c."ShippingAddress_ZipCode" = c."BillingAddress_ZipCode" """); } @@ -216,9 +216,9 @@ public override async Task Complex_type_equals_constant(bool async) AssertSql( """ -SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" +SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_Tags", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c -WHERE c."ShippingAddress_AddressLine1" = '804 S. Lakeshore Road' AND c."ShippingAddress_AddressLine2" IS NULL AND c."ShippingAddress_ZipCode" = 38654 AND c."ShippingAddress_Country_Code" = 'US' AND c."ShippingAddress_Country_FullName" = 'United States' +WHERE c."ShippingAddress_AddressLine1" = '804 S. Lakeshore Road' AND c."ShippingAddress_AddressLine2" IS NULL AND c."ShippingAddress_Tags" = ARRAY['foo','bar']::text[] AND c."ShippingAddress_ZipCode" = 38654 AND c."ShippingAddress_Country_Code" = 'US' AND c."ShippingAddress_Country_FullName" = 'United States' """); } @@ -229,13 +229,14 @@ public override async Task Complex_type_equals_parameter(bool async) AssertSql( """ @__entity_equality_address_0_AddressLine1='804 S. Lakeshore Road' +@__entity_equality_address_0_Tags={ 'foo', 'bar' } (DbType = Object) @__entity_equality_address_0_ZipCode='38654' (Nullable = true) @__entity_equality_address_0_Code='US' @__entity_equality_address_0_FullName='United States' -SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" +SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_Tags", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c -WHERE c."ShippingAddress_AddressLine1" = @__entity_equality_address_0_AddressLine1 AND c."ShippingAddress_AddressLine2" IS NULL AND c."ShippingAddress_ZipCode" = @__entity_equality_address_0_ZipCode AND c."ShippingAddress_Country_Code" = @__entity_equality_address_0_Code AND c."ShippingAddress_Country_FullName" = @__entity_equality_address_0_FullName +WHERE c."ShippingAddress_AddressLine1" = @__entity_equality_address_0_AddressLine1 AND c."ShippingAddress_AddressLine2" IS NULL AND c."ShippingAddress_Tags" = @__entity_equality_address_0_Tags AND c."ShippingAddress_ZipCode" = @__entity_equality_address_0_ZipCode AND c."ShippingAddress_Country_Code" = @__entity_equality_address_0_Code AND c."ShippingAddress_Country_FullName" = @__entity_equality_address_0_FullName """); } @@ -260,16 +261,17 @@ public override async Task Contains_over_complex_type(bool async) AssertSql( """ @__entity_equality_address_0_AddressLine1='804 S. Lakeshore Road' +@__entity_equality_address_0_Tags={ 'foo', 'bar' } (DbType = Object) @__entity_equality_address_0_ZipCode='38654' (Nullable = true) @__entity_equality_address_0_Code='US' @__entity_equality_address_0_FullName='United States' -SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" +SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_Tags", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c WHERE EXISTS ( SELECT 1 FROM "Customer" AS c0 - WHERE c0."ShippingAddress_AddressLine1" = @__entity_equality_address_0_AddressLine1 AND c0."ShippingAddress_AddressLine2" IS NULL AND c0."ShippingAddress_ZipCode" = @__entity_equality_address_0_ZipCode AND c0."ShippingAddress_Country_Code" = @__entity_equality_address_0_Code AND c0."ShippingAddress_Country_FullName" = @__entity_equality_address_0_FullName) + WHERE c0."ShippingAddress_AddressLine1" = @__entity_equality_address_0_AddressLine1 AND c0."ShippingAddress_AddressLine2" IS NULL AND c0."ShippingAddress_Tags" = @__entity_equality_address_0_Tags AND c0."ShippingAddress_ZipCode" = @__entity_equality_address_0_ZipCode AND c0."ShippingAddress_Country_Code" = @__entity_equality_address_0_Code AND c0."ShippingAddress_Country_FullName" = @__entity_equality_address_0_FullName) """); } @@ -279,11 +281,11 @@ public override async Task Concat_complex_type(bool async) AssertSql( """ -SELECT c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" +SELECT c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c WHERE c."Id" = 1 UNION ALL -SELECT c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName" +SELECT c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_Tags", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName" FROM "Customer" AS c0 WHERE c0."Id" = 2 """); @@ -295,11 +297,11 @@ public override async Task Concat_entity_type_containing_complex_property(bool a AssertSql( """ -SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" +SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_Tags", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c WHERE c."Id" = 1 UNION ALL -SELECT c0."Id", c0."Name", c0."BillingAddress_AddressLine1", c0."BillingAddress_AddressLine2", c0."BillingAddress_ZipCode", c0."BillingAddress_Country_Code", c0."BillingAddress_Country_FullName", c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName" +SELECT c0."Id", c0."Name", c0."BillingAddress_AddressLine1", c0."BillingAddress_AddressLine2", c0."BillingAddress_Tags", c0."BillingAddress_ZipCode", c0."BillingAddress_Country_Code", c0."BillingAddress_Country_FullName", c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_Tags", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName" FROM "Customer" AS c0 WHERE c0."Id" = 2 """); @@ -311,11 +313,11 @@ public override async Task Union_entity_type_containing_complex_property(bool as AssertSql( """ -SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" +SELECT c."Id", c."Name", c."BillingAddress_AddressLine1", c."BillingAddress_AddressLine2", c."BillingAddress_Tags", c."BillingAddress_ZipCode", c."BillingAddress_Country_Code", c."BillingAddress_Country_FullName", c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c WHERE c."Id" = 1 UNION -SELECT c0."Id", c0."Name", c0."BillingAddress_AddressLine1", c0."BillingAddress_AddressLine2", c0."BillingAddress_ZipCode", c0."BillingAddress_Country_Code", c0."BillingAddress_Country_FullName", c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName" +SELECT c0."Id", c0."Name", c0."BillingAddress_AddressLine1", c0."BillingAddress_AddressLine2", c0."BillingAddress_Tags", c0."BillingAddress_ZipCode", c0."BillingAddress_Country_Code", c0."BillingAddress_Country_FullName", c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_Tags", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName" FROM "Customer" AS c0 WHERE c0."Id" = 2 """); @@ -327,11 +329,11 @@ public override async Task Union_complex_type(bool async) AssertSql( """ -SELECT c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" +SELECT c."ShippingAddress_AddressLine1", c."ShippingAddress_AddressLine2", c."ShippingAddress_Tags", c."ShippingAddress_ZipCode", c."ShippingAddress_Country_Code", c."ShippingAddress_Country_FullName" FROM "Customer" AS c WHERE c."Id" = 1 UNION -SELECT c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName" +SELECT c0."ShippingAddress_AddressLine1", c0."ShippingAddress_AddressLine2", c0."ShippingAddress_Tags", c0."ShippingAddress_ZipCode", c0."ShippingAddress_Country_Code", c0."ShippingAddress_Country_FullName" FROM "Customer" AS c0 WHERE c0."Id" = 2 """); @@ -411,14 +413,14 @@ public override async Task Filter_on_property_inside_struct_complex_type_after_s """ @__p_0='1' -SELECT DISTINCT t."Id", t."Name", t."BillingAddress_AddressLine1", t."BillingAddress_AddressLine2", t."BillingAddress_ZipCode", t."BillingAddress_Country_Code", t."BillingAddress_Country_FullName", t."ShippingAddress_AddressLine1", t."ShippingAddress_AddressLine2", t."ShippingAddress_ZipCode", t."ShippingAddress_Country_Code", t."ShippingAddress_Country_FullName" +SELECT DISTINCT v0."Id", v0."Name", v0."BillingAddress_AddressLine1", v0."BillingAddress_AddressLine2", v0."BillingAddress_ZipCode", v0."BillingAddress_Country_Code", v0."BillingAddress_Country_FullName", v0."ShippingAddress_AddressLine1", v0."ShippingAddress_AddressLine2", v0."ShippingAddress_ZipCode", v0."ShippingAddress_Country_Code", v0."ShippingAddress_Country_FullName" FROM ( SELECT v."Id", v."Name", v."BillingAddress_AddressLine1", v."BillingAddress_AddressLine2", v."BillingAddress_ZipCode", v."BillingAddress_Country_Code", v."BillingAddress_Country_FullName", v."ShippingAddress_AddressLine1", v."ShippingAddress_AddressLine2", v."ShippingAddress_ZipCode", v."ShippingAddress_Country_Code", v."ShippingAddress_Country_FullName" FROM "ValuedCustomer" AS v ORDER BY v."Id" NULLS FIRST OFFSET @__p_0 -) AS t -WHERE t."ShippingAddress_ZipCode" = 7728 +) AS v0 +WHERE v0."ShippingAddress_ZipCode" = 7728 """); } @@ -430,14 +432,14 @@ public override async Task Filter_on_property_inside_nested_struct_complex_type_ """ @__p_0='1' -SELECT DISTINCT t."Id", t."Name", t."BillingAddress_AddressLine1", t."BillingAddress_AddressLine2", t."BillingAddress_ZipCode", t."BillingAddress_Country_Code", t."BillingAddress_Country_FullName", t."ShippingAddress_AddressLine1", t."ShippingAddress_AddressLine2", t."ShippingAddress_ZipCode", t."ShippingAddress_Country_Code", t."ShippingAddress_Country_FullName" +SELECT DISTINCT v0."Id", v0."Name", v0."BillingAddress_AddressLine1", v0."BillingAddress_AddressLine2", v0."BillingAddress_ZipCode", v0."BillingAddress_Country_Code", v0."BillingAddress_Country_FullName", v0."ShippingAddress_AddressLine1", v0."ShippingAddress_AddressLine2", v0."ShippingAddress_ZipCode", v0."ShippingAddress_Country_Code", v0."ShippingAddress_Country_FullName" FROM ( SELECT v."Id", v."Name", v."BillingAddress_AddressLine1", v."BillingAddress_AddressLine2", v."BillingAddress_ZipCode", v."BillingAddress_Country_Code", v."BillingAddress_Country_FullName", v."ShippingAddress_AddressLine1", v."ShippingAddress_AddressLine2", v."ShippingAddress_ZipCode", v."ShippingAddress_Country_Code", v."ShippingAddress_Country_FullName" FROM "ValuedCustomer" AS v ORDER BY v."Id" NULLS FIRST OFFSET @__p_0 -) AS t -WHERE t."ShippingAddress_Country_Code" = 'DE' +) AS v0 +WHERE v0."ShippingAddress_Country_Code" = 'DE' """); } @@ -500,13 +502,13 @@ public override async Task Load_struct_complex_type_after_subquery_on_entity_typ """ @__p_0='1' -SELECT DISTINCT t."Id", t."Name", t."BillingAddress_AddressLine1", t."BillingAddress_AddressLine2", t."BillingAddress_ZipCode", t."BillingAddress_Country_Code", t."BillingAddress_Country_FullName", t."ShippingAddress_AddressLine1", t."ShippingAddress_AddressLine2", t."ShippingAddress_ZipCode", t."ShippingAddress_Country_Code", t."ShippingAddress_Country_FullName" +SELECT DISTINCT v0."Id", v0."Name", v0."BillingAddress_AddressLine1", v0."BillingAddress_AddressLine2", v0."BillingAddress_ZipCode", v0."BillingAddress_Country_Code", v0."BillingAddress_Country_FullName", v0."ShippingAddress_AddressLine1", v0."ShippingAddress_AddressLine2", v0."ShippingAddress_ZipCode", v0."ShippingAddress_Country_Code", v0."ShippingAddress_Country_FullName" FROM ( SELECT v."Id", v."Name", v."BillingAddress_AddressLine1", v."BillingAddress_AddressLine2", v."BillingAddress_ZipCode", v."BillingAddress_Country_Code", v."BillingAddress_Country_FullName", v."ShippingAddress_AddressLine1", v."ShippingAddress_AddressLine2", v."ShippingAddress_ZipCode", v."ShippingAddress_Country_Code", v."ShippingAddress_Country_FullName" FROM "ValuedCustomer" AS v ORDER BY v."Id" NULLS FIRST OFFSET @__p_0 -) AS t +) AS v0 """); } diff --git a/test/EFCore.PG.FunctionalTests/Query/Ef6GroupByNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/Ef6GroupByNpgsqlTest.cs index 141f111d5..b83d9748a 100644 --- a/test/EFCore.PG.FunctionalTests/Query/Ef6GroupByNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/Ef6GroupByNpgsqlTest.cs @@ -18,17 +18,17 @@ public override async Task Whats_new_2021_sample_3(bool async) AssertSql( """ SELECT ( - SELECT p1."LastName" - FROM "Person" AS p1 - WHERE p1."MiddleInitial" = 'Q' AND p1."Age" = 20 AND (p."LastName" = p1."LastName" OR (p."LastName" IS NULL AND p1."LastName" IS NULL)) + SELECT p0."LastName" + FROM "Person" AS p0 + WHERE p0."MiddleInitial" = 'Q' AND p0."Age" = 20 AND (p."LastName" = p0."LastName" OR (p."LastName" IS NULL AND p0."LastName" IS NULL)) LIMIT 1) FROM "Person" AS p WHERE p."MiddleInitial" = 'Q' AND p."Age" = 20 GROUP BY p."LastName" ORDER BY length(( - SELECT p1."LastName" - FROM "Person" AS p1 - WHERE p1."MiddleInitial" = 'Q' AND p1."Age" = 20 AND (p."LastName" = p1."LastName" OR (p."LastName" IS NULL AND p1."LastName" IS NULL)) + SELECT p0."LastName" + FROM "Person" AS p0 + WHERE p0."MiddleInitial" = 'Q' AND p0."Age" = 20 AND (p."LastName" = p0."LastName" OR (p."LastName" IS NULL AND p0."LastName" IS NULL)) LIMIT 1))::int NULLS FIRST """); } @@ -40,16 +40,16 @@ public override async Task Whats_new_2021_sample_5(bool async) AssertSql( """ SELECT ( - SELECT p1."LastName" - FROM "Person" AS p1 - WHERE p."FirstName" = p1."FirstName" OR (p."FirstName" IS NULL AND p1."FirstName" IS NULL) + SELECT p0."LastName" + FROM "Person" AS p0 + WHERE p."FirstName" = p0."FirstName" OR (p."FirstName" IS NULL AND p0."FirstName" IS NULL) LIMIT 1) FROM "Person" AS p GROUP BY p."FirstName" ORDER BY ( - SELECT p1."LastName" - FROM "Person" AS p1 - WHERE p."FirstName" = p1."FirstName" OR (p."FirstName" IS NULL AND p1."FirstName" IS NULL) + SELECT p0."LastName" + FROM "Person" AS p0 + WHERE p."FirstName" = p0."FirstName" OR (p."FirstName" IS NULL AND p0."FirstName" IS NULL) LIMIT 1) NULLS FIRST """); } @@ -61,25 +61,21 @@ public override async Task Whats_new_2021_sample_6(bool async) AssertSql( """ SELECT ( - SELECT p1."MiddleInitial" - FROM "Person" AS p1 - WHERE p1."Age" = 20 AND p."Id" = p1."Id" + SELECT p0."MiddleInitial" + FROM "Person" AS p0 + WHERE p0."Age" = 20 AND p."Id" = p0."Id" LIMIT 1) FROM "Person" AS p WHERE p."Age" = 20 GROUP BY p."Id" ORDER BY ( - SELECT p1."MiddleInitial" - FROM "Person" AS p1 - WHERE p1."Age" = 20 AND p."Id" = p1."Id" + SELECT p0."MiddleInitial" + FROM "Person" AS p0 + WHERE p0."Age" = 20 AND p."Id" = p0."Id" LIMIT 1) NULLS FIRST """); } - [ConditionalTheory(Skip = "https://github.com/dotnet/efcore/issues/27155")] - public override Task Whats_new_2021_sample_10(bool async) - => base.Whats_new_2021_sample_10(async); - private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.PG.FunctionalTests/Query/EntitySplittingQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/EntitySplittingQueryNpgsqlTest.cs index b9987f8e0..aff617fd7 100644 --- a/test/EFCore.PG.FunctionalTests/Query/EntitySplittingQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/EntitySplittingQueryNpgsqlTest.cs @@ -54,9 +54,9 @@ public override async Task Can_query_entity_which_is_split_selecting_only_part_2 AssertSql( """ -SELECT e."Id", s0."IntValue3", s0."StringValue3" +SELECT e."Id", s."IntValue3", s."StringValue3" FROM "EntityOne" AS e -INNER JOIN "SplitEntityOnePart2" AS s0 ON e."Id" = s0."Id" +INNER JOIN "SplitEntityOnePart2" AS s ON e."Id" = s."Id" """); } @@ -78,14 +78,14 @@ public override async Task Include_reference_to_split_entity(bool async) AssertSql( """ -SELECT e."Id", e."EntityOneId", e."Name", t."Id", t."EntityThreeId", t."IntValue1", t."IntValue2", t."IntValue3", t."IntValue4", t."StringValue1", t."StringValue2", t."StringValue3", t."StringValue4" +SELECT e."Id", e."EntityOneId", e."Name", s1."Id", s1."EntityThreeId", s1."IntValue1", s1."IntValue2", s1."IntValue3", s1."IntValue4", s1."StringValue1", s1."StringValue2", s1."StringValue3", s1."StringValue4" FROM "EntityTwo" AS e LEFT JOIN ( SELECT e0."Id", e0."EntityThreeId", e0."IntValue1", e0."IntValue2", s0."IntValue3", s."IntValue4", e0."StringValue1", e0."StringValue2", s0."StringValue3", s."StringValue4" FROM "EntityOne" AS e0 INNER JOIN "SplitEntityOnePart3" AS s ON e0."Id" = s."Id" INNER JOIN "SplitEntityOnePart2" AS s0 ON e0."Id" = s0."Id" -) AS t ON e."EntityOneId" = t."Id" +) AS s1 ON e."EntityOneId" = s1."Id" """); } @@ -95,14 +95,14 @@ public override async Task Include_collection_to_split_entity(bool async) AssertSql( """ -SELECT e."Id", e."Name", t."Id", t."EntityThreeId", t."IntValue1", t."IntValue2", t."IntValue3", t."IntValue4", t."StringValue1", t."StringValue2", t."StringValue3", t."StringValue4" +SELECT e."Id", e."Name", s1."Id", s1."EntityThreeId", s1."IntValue1", s1."IntValue2", s1."IntValue3", s1."IntValue4", s1."StringValue1", s1."StringValue2", s1."StringValue3", s1."StringValue4" FROM "EntityThree" AS e LEFT JOIN ( SELECT e0."Id", e0."EntityThreeId", e0."IntValue1", e0."IntValue2", s0."IntValue3", s."IntValue4", e0."StringValue1", e0."StringValue2", s0."StringValue3", s."StringValue4" FROM "EntityOne" AS e0 INNER JOIN "SplitEntityOnePart3" AS s ON e0."Id" = s."Id" INNER JOIN "SplitEntityOnePart2" AS s0 ON e0."Id" = s0."Id" -) AS t ON e."Id" = t."EntityThreeId" +) AS s1 ON e."Id" = s1."EntityThreeId" ORDER BY e."Id" NULLS FIRST """); } @@ -113,15 +113,15 @@ public override async Task Include_reference_to_split_entity_including_reference AssertSql( """ -SELECT e."Id", e."EntityOneId", e."Name", t."Id", t."EntityThreeId", t."IntValue1", t."IntValue2", t."IntValue3", t."IntValue4", t."StringValue1", t."StringValue2", t."StringValue3", t."StringValue4", e1."Id", e1."Name" +SELECT e."Id", e."EntityOneId", e."Name", s1."Id", s1."EntityThreeId", s1."IntValue1", s1."IntValue2", s1."IntValue3", s1."IntValue4", s1."StringValue1", s1."StringValue2", s1."StringValue3", s1."StringValue4", e1."Id", e1."Name" FROM "EntityTwo" AS e LEFT JOIN ( SELECT e0."Id", e0."EntityThreeId", e0."IntValue1", e0."IntValue2", s0."IntValue3", s."IntValue4", e0."StringValue1", e0."StringValue2", s0."StringValue3", s."StringValue4" FROM "EntityOne" AS e0 INNER JOIN "SplitEntityOnePart3" AS s ON e0."Id" = s."Id" INNER JOIN "SplitEntityOnePart2" AS s0 ON e0."Id" = s0."Id" -) AS t ON e."EntityOneId" = t."Id" -LEFT JOIN "EntityThree" AS e1 ON t."EntityThreeId" = e1."Id" +) AS s1 ON e."EntityOneId" = s1."Id" +LEFT JOIN "EntityThree" AS e1 ON s1."EntityThreeId" = e1."Id" """); } @@ -131,7 +131,7 @@ public override async Task Include_collection_to_split_entity_including_collecti AssertSql( """ -SELECT e."Id", e."Name", t."Id", t."EntityThreeId", t."IntValue1", t."IntValue2", t."IntValue3", t."IntValue4", t."StringValue1", t."StringValue2", t."StringValue3", t."StringValue4", t."Id0", t."EntityOneId", t."Name" +SELECT e."Id", e."Name", s1."Id", s1."EntityThreeId", s1."IntValue1", s1."IntValue2", s1."IntValue3", s1."IntValue4", s1."StringValue1", s1."StringValue2", s1."StringValue3", s1."StringValue4", s1."Id0", s1."EntityOneId", s1."Name" FROM "EntityThree" AS e LEFT JOIN ( SELECT e0."Id", e0."EntityThreeId", e0."IntValue1", e0."IntValue2", s0."IntValue3", s."IntValue4", e0."StringValue1", e0."StringValue2", s0."StringValue3", s."StringValue4", e1."Id" AS "Id0", e1."EntityOneId", e1."Name" @@ -139,8 +139,8 @@ LEFT JOIN ( INNER JOIN "SplitEntityOnePart3" AS s ON e0."Id" = s."Id" INNER JOIN "SplitEntityOnePart2" AS s0 ON e0."Id" = s0."Id" LEFT JOIN "EntityTwo" AS e1 ON e0."Id" = e1."EntityOneId" -) AS t ON e."Id" = t."EntityThreeId" -ORDER BY e."Id" NULLS FIRST, t."Id" NULLS FIRST +) AS s1 ON e."Id" = s1."EntityThreeId" +ORDER BY e."Id" NULLS FIRST, s1."Id" NULLS FIRST """); } @@ -179,9 +179,9 @@ public override async Task Custom_projection_trim_when_multiple_tables(bool asyn AssertSql( """ -SELECT e."IntValue1", s0."IntValue3", e0."Id", e0."Name" +SELECT e."IntValue1", s."IntValue3", e0."Id", e0."Name" FROM "EntityOne" AS e -INNER JOIN "SplitEntityOnePart2" AS s0 ON e."Id" = s0."Id" +INNER JOIN "SplitEntityOnePart2" AS s ON e."Id" = s."Id" LEFT JOIN "EntityThree" AS e0 ON e."EntityThreeId" = e0."Id" """); } @@ -447,7 +447,7 @@ public override async Task Tpc_entity_owning_a_split_reference_on_leaf_with_tabl AssertSql( """ -SELECT t."Id", t."BaseValue", t."MiddleValue", t."SiblingValue", t."LeafValue", t."Discriminator", l."Id", l."OwnedReference_Id", l."OwnedReference_OwnedIntValue1", l."OwnedReference_OwnedIntValue2", o0."OwnedIntValue3", o."OwnedIntValue4", l."OwnedReference_OwnedStringValue1", l."OwnedReference_OwnedStringValue2", o0."OwnedStringValue3", o."OwnedStringValue4" +SELECT u."Id", u."BaseValue", u."MiddleValue", u."SiblingValue", u."LeafValue", u."Discriminator", l0."Id", l0."OwnedReference_Id", l0."OwnedReference_OwnedIntValue1", l0."OwnedReference_OwnedIntValue2", o0."OwnedIntValue3", o."OwnedIntValue4", l0."OwnedReference_OwnedStringValue1", l0."OwnedReference_OwnedStringValue2", o0."OwnedStringValue3", o."OwnedStringValue4" FROM ( SELECT b."Id", b."BaseValue", NULL::int AS "MiddleValue", NULL::int AS "SiblingValue", NULL::int AS "LeafValue", 'BaseEntity' AS "Discriminator" FROM "BaseEntity" AS b @@ -458,12 +458,12 @@ UNION ALL SELECT s."Id", s."BaseValue", NULL AS "MiddleValue", s."SiblingValue", NULL AS "LeafValue", 'SiblingEntity' AS "Discriminator" FROM "SiblingEntity" AS s UNION ALL - SELECT l0."Id", l0."BaseValue", l0."MiddleValue", NULL AS "SiblingValue", l0."LeafValue", 'LeafEntity' AS "Discriminator" - FROM "LeafEntity" AS l0 -) AS t -LEFT JOIN "LeafEntity" AS l ON t."Id" = l."Id" -LEFT JOIN "OwnedReferencePart4" AS o ON l."Id" = o."LeafEntityId" -LEFT JOIN "OwnedReferencePart3" AS o0 ON l."Id" = o0."LeafEntityId" + SELECT l."Id", l."BaseValue", l."MiddleValue", NULL AS "SiblingValue", l."LeafValue", 'LeafEntity' AS "Discriminator" + FROM "LeafEntity" AS l +) AS u +LEFT JOIN "LeafEntity" AS l0 ON u."Id" = l0."Id" +LEFT JOIN "OwnedReferencePart4" AS o ON l0."Id" = o."LeafEntityId" +LEFT JOIN "OwnedReferencePart3" AS o0 ON l0."Id" = o0."LeafEntityId" """); } @@ -576,7 +576,7 @@ public override async Task Tpc_entity_owning_a_split_reference_on_base_without_t AssertSql( """ -SELECT t."Id", t."BaseValue", t."MiddleValue", t."SiblingValue", t."LeafValue", t."Discriminator", o."BaseEntityId", o."Id", o."OwnedIntValue1", o."OwnedIntValue2", o1."OwnedIntValue3", o0."OwnedIntValue4", o."OwnedStringValue1", o."OwnedStringValue2", o1."OwnedStringValue3", o0."OwnedStringValue4" +SELECT u."Id", u."BaseValue", u."MiddleValue", u."SiblingValue", u."LeafValue", u."Discriminator", o."BaseEntityId", o."Id", o."OwnedIntValue1", o."OwnedIntValue2", o1."OwnedIntValue3", o0."OwnedIntValue4", o."OwnedStringValue1", o."OwnedStringValue2", o1."OwnedStringValue3", o0."OwnedStringValue4" FROM ( SELECT b."Id", b."BaseValue", NULL::int AS "MiddleValue", NULL::int AS "SiblingValue", NULL::int AS "LeafValue", 'BaseEntity' AS "Discriminator" FROM "BaseEntity" AS b @@ -589,8 +589,8 @@ UNION ALL UNION ALL SELECT l."Id", l."BaseValue", l."MiddleValue", NULL AS "SiblingValue", l."LeafValue", 'LeafEntity' AS "Discriminator" FROM "LeafEntity" AS l -) AS t -LEFT JOIN "OwnedReferencePart1" AS o ON t."Id" = o."BaseEntityId" +) AS u +LEFT JOIN "OwnedReferencePart1" AS o ON u."Id" = o."BaseEntityId" LEFT JOIN "OwnedReferencePart4" AS o0 ON o."BaseEntityId" = o0."BaseEntityId" LEFT JOIN "OwnedReferencePart3" AS o1 ON o."BaseEntityId" = o1."BaseEntityId" """); @@ -618,7 +618,7 @@ public override async Task Tpc_entity_owning_a_split_reference_on_middle_without AssertSql( """ -SELECT t."Id", t."BaseValue", t."MiddleValue", t."SiblingValue", t."LeafValue", t."Discriminator", o."MiddleEntityId", o."Id", o."OwnedIntValue1", o."OwnedIntValue2", o1."OwnedIntValue3", o0."OwnedIntValue4", o."OwnedStringValue1", o."OwnedStringValue2", o1."OwnedStringValue3", o0."OwnedStringValue4" +SELECT u."Id", u."BaseValue", u."MiddleValue", u."SiblingValue", u."LeafValue", u."Discriminator", o."MiddleEntityId", o."Id", o."OwnedIntValue1", o."OwnedIntValue2", o1."OwnedIntValue3", o0."OwnedIntValue4", o."OwnedStringValue1", o."OwnedStringValue2", o1."OwnedStringValue3", o0."OwnedStringValue4" FROM ( SELECT b."Id", b."BaseValue", NULL::int AS "MiddleValue", NULL::int AS "SiblingValue", NULL::int AS "LeafValue", 'BaseEntity' AS "Discriminator" FROM "BaseEntity" AS b @@ -631,8 +631,8 @@ UNION ALL UNION ALL SELECT l."Id", l."BaseValue", l."MiddleValue", NULL AS "SiblingValue", l."LeafValue", 'LeafEntity' AS "Discriminator" FROM "LeafEntity" AS l -) AS t -LEFT JOIN "OwnedReferencePart1" AS o ON t."Id" = o."MiddleEntityId" +) AS u +LEFT JOIN "OwnedReferencePart1" AS o ON u."Id" = o."MiddleEntityId" LEFT JOIN "OwnedReferencePart4" AS o0 ON o."MiddleEntityId" = o0."MiddleEntityId" LEFT JOIN "OwnedReferencePart3" AS o1 ON o."MiddleEntityId" = o1."MiddleEntityId" """); @@ -684,7 +684,7 @@ public override async Task Tpc_entity_owning_a_split_collection_on_base(bool asy AssertSql( """ -SELECT t."Id", t."BaseValue", t."MiddleValue", t."SiblingValue", t."LeafValue", t."Discriminator", t0."BaseEntityId", t0."Id", t0."OwnedIntValue1", t0."OwnedIntValue2", t0."OwnedIntValue3", t0."OwnedIntValue4", t0."OwnedStringValue1", t0."OwnedStringValue2", t0."OwnedStringValue3", t0."OwnedStringValue4" +SELECT u."Id", u."BaseValue", u."MiddleValue", u."SiblingValue", u."LeafValue", u."Discriminator", s0."BaseEntityId", s0."Id", s0."OwnedIntValue1", s0."OwnedIntValue2", s0."OwnedIntValue3", s0."OwnedIntValue4", s0."OwnedStringValue1", s0."OwnedStringValue2", s0."OwnedStringValue3", s0."OwnedStringValue4" FROM ( SELECT b."Id", b."BaseValue", NULL::int AS "MiddleValue", NULL::int AS "SiblingValue", NULL::int AS "LeafValue", 'BaseEntity' AS "Discriminator" FROM "BaseEntity" AS b @@ -697,14 +697,14 @@ UNION ALL UNION ALL SELECT l."Id", l."BaseValue", l."MiddleValue", NULL AS "SiblingValue", l."LeafValue", 'LeafEntity' AS "Discriminator" FROM "LeafEntity" AS l -) AS t +) AS u LEFT JOIN ( SELECT o."BaseEntityId", o."Id", o."OwnedIntValue1", o."OwnedIntValue2", o1."OwnedIntValue3", o0."OwnedIntValue4", o."OwnedStringValue1", o."OwnedStringValue2", o1."OwnedStringValue3", o0."OwnedStringValue4" FROM "OwnedReferencePart1" AS o INNER JOIN "OwnedReferencePart4" AS o0 ON o."BaseEntityId" = o0."BaseEntityId" AND o."Id" = o0."Id" INNER JOIN "OwnedReferencePart3" AS o1 ON o."BaseEntityId" = o1."BaseEntityId" AND o."Id" = o1."Id" -) AS t0 ON t."Id" = t0."BaseEntityId" -ORDER BY t."Id" NULLS FIRST, t0."BaseEntityId" NULLS FIRST +) AS s0 ON u."Id" = s0."BaseEntityId" +ORDER BY u."Id" NULLS FIRST, s0."BaseEntityId" NULLS FIRST """); } @@ -730,7 +730,7 @@ public override async Task Tpc_entity_owning_a_split_collection_on_middle(bool a AssertSql( """ -SELECT t."Id", t."BaseValue", t."MiddleValue", t."SiblingValue", t."LeafValue", t."Discriminator", t0."MiddleEntityId", t0."Id", t0."OwnedIntValue1", t0."OwnedIntValue2", t0."OwnedIntValue3", t0."OwnedIntValue4", t0."OwnedStringValue1", t0."OwnedStringValue2", t0."OwnedStringValue3", t0."OwnedStringValue4" +SELECT u."Id", u."BaseValue", u."MiddleValue", u."SiblingValue", u."LeafValue", u."Discriminator", s0."MiddleEntityId", s0."Id", s0."OwnedIntValue1", s0."OwnedIntValue2", s0."OwnedIntValue3", s0."OwnedIntValue4", s0."OwnedStringValue1", s0."OwnedStringValue2", s0."OwnedStringValue3", s0."OwnedStringValue4" FROM ( SELECT b."Id", b."BaseValue", NULL::int AS "MiddleValue", NULL::int AS "SiblingValue", NULL::int AS "LeafValue", 'BaseEntity' AS "Discriminator" FROM "BaseEntity" AS b @@ -743,14 +743,14 @@ UNION ALL UNION ALL SELECT l."Id", l."BaseValue", l."MiddleValue", NULL AS "SiblingValue", l."LeafValue", 'LeafEntity' AS "Discriminator" FROM "LeafEntity" AS l -) AS t +) AS u LEFT JOIN ( SELECT o."MiddleEntityId", o."Id", o."OwnedIntValue1", o."OwnedIntValue2", o1."OwnedIntValue3", o0."OwnedIntValue4", o."OwnedStringValue1", o."OwnedStringValue2", o1."OwnedStringValue3", o0."OwnedStringValue4" FROM "OwnedReferencePart1" AS o INNER JOIN "OwnedReferencePart4" AS o0 ON o."MiddleEntityId" = o0."MiddleEntityId" AND o."Id" = o0."Id" INNER JOIN "OwnedReferencePart3" AS o1 ON o."MiddleEntityId" = o1."MiddleEntityId" AND o."Id" = o1."Id" -) AS t0 ON t."Id" = t0."MiddleEntityId" -ORDER BY t."Id" NULLS FIRST, t0."MiddleEntityId" NULLS FIRST +) AS s0 ON u."Id" = s0."MiddleEntityId" +ORDER BY u."Id" NULLS FIRST, s0."MiddleEntityId" NULLS FIRST """); } diff --git a/test/EFCore.PG.FunctionalTests/Query/FunkyDataQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/FunkyDataQueryNpgsqlTest.cs index 32d7971dc..0d9e16de1 100644 --- a/test/EFCore.PG.FunctionalTests/Query/FunkyDataQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/FunkyDataQueryNpgsqlTest.cs @@ -35,30 +35,6 @@ await AssertQuery( ss => ss.Set().Where(c => c.FirstName != null && c.FirstName.StartsWith(param))); } - [ConditionalTheory] // TODO: Remove, test was introduced upstream - [MemberData(nameof(IsAsyncData))] - public virtual async Task String_Contains_and_StartsWith_with_same_parameter(bool async) - { - var s = "B"; - - await AssertQuery( - async, - ss => ss.Set().Where( - c => c.FirstName.Contains(s) || c.LastName.StartsWith(s)), - ss => ss.Set().Where( - c => c.FirstName.MaybeScalar(f => f.Contains(s)) == true || c.LastName.MaybeScalar(l => l.StartsWith(s)) == true)); - - AssertSql( - """ -@__s_0_contains='%B%' -@__s_0_startswith='B%' - -SELECT f."Id", f."FirstName", f."LastName", f."NullableBool" -FROM "FunkyCustomers" AS f -WHERE f."FirstName" LIKE @__s_0_contains ESCAPE '\' OR f."LastName" LIKE @__s_0_startswith ESCAPE '\' -"""); - } - private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.PG.FunctionalTests/Query/JsonQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/JsonQueryNpgsqlTest.cs index 081b7c140..0149ad5d2 100644 --- a/test/EFCore.PG.FunctionalTests/Query/JsonQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/JsonQueryNpgsqlTest.cs @@ -279,16 +279,16 @@ public override async Task Json_subquery_property_pushdown_length(bool async) """ @__p_0='3' -SELECT length(t0.c)::int +SELECT length(j1.c)::int FROM ( - SELECT DISTINCT t.c + SELECT DISTINCT j0.c FROM ( SELECT j."OwnedReferenceRoot" #>> '{OwnedReferenceBranch,OwnedReferenceLeaf,SomethingSomething}' AS c FROM "JsonEntitiesBasic" AS j ORDER BY j."Id" NULLS FIRST LIMIT @__p_0 - ) AS t -) AS t0 + ) AS j0 +) AS j1 """); } @@ -300,16 +300,16 @@ public override async Task Json_subquery_reference_pushdown_reference(bool async """ @__p_0='10' -SELECT t0.c -> 'OwnedReferenceBranch', t0."Id" +SELECT j1.c -> 'OwnedReferenceBranch', j1."Id" FROM ( - SELECT DISTINCT t.c AS c, t."Id" + SELECT DISTINCT j0.c AS c, j0."Id" FROM ( SELECT j."OwnedReferenceRoot" AS c, j."Id" FROM "JsonEntitiesBasic" AS j ORDER BY j."Id" NULLS FIRST LIMIT @__p_0 - ) AS t -) AS t0 + ) AS j0 +) AS j1 """); } @@ -368,24 +368,24 @@ public override async Task Json_subquery_reference_pushdown_reference_pushdown_r """ @__p_0='10' -SELECT t2.c -> 'OwnedReferenceLeaf', t2."Id" +SELECT j3.c -> 'OwnedReferenceLeaf', j3."Id" FROM ( - SELECT DISTINCT t1.c AS c, t1."Id" + SELECT DISTINCT j2.c AS c, j2."Id" FROM ( - SELECT t0.c -> 'OwnedReferenceBranch' AS c, t0."Id" + SELECT j1.c -> 'OwnedReferenceBranch' AS c, j1."Id" FROM ( - SELECT DISTINCT t.c AS c, t."Id", t.c AS c0 + SELECT DISTINCT j0.c AS c, j0."Id", j0.c AS c0 FROM ( SELECT j."OwnedReferenceRoot" AS c, j."Id" FROM "JsonEntitiesBasic" AS j ORDER BY j."Id" NULLS FIRST LIMIT @__p_0 - ) AS t - ) AS t0 - ORDER BY t0.c0 ->> 'Name' NULLS FIRST + ) AS j0 + ) AS j1 + ORDER BY j1.c0 ->> 'Name' NULLS FIRST LIMIT @__p_0 - ) AS t1 -) AS t2 + ) AS j2 +) AS j3 """); } @@ -397,24 +397,24 @@ public override async Task Json_subquery_reference_pushdown_reference_pushdown_c """ @__p_0='10' -SELECT t2.c -> 'OwnedCollectionLeaf', t2."Id" +SELECT j3.c -> 'OwnedCollectionLeaf', j3."Id" FROM ( - SELECT DISTINCT t1.c AS c, t1."Id" + SELECT DISTINCT j2.c AS c, j2."Id" FROM ( - SELECT t0.c -> 'OwnedReferenceBranch' AS c, t0."Id" + SELECT j1.c -> 'OwnedReferenceBranch' AS c, j1."Id" FROM ( - SELECT DISTINCT t.c AS c, t."Id", t.c AS c0 + SELECT DISTINCT j0.c AS c, j0."Id", j0.c AS c0 FROM ( SELECT j."OwnedReferenceRoot" AS c, j."Id" FROM "JsonEntitiesBasic" AS j ORDER BY j."Id" NULLS FIRST LIMIT @__p_0 - ) AS t - ) AS t0 - ORDER BY t0.c0 ->> 'Name' NULLS FIRST + ) AS j0 + ) AS j1 + ORDER BY j1.c0 ->> 'Name' NULLS FIRST LIMIT @__p_0 - ) AS t1 -) AS t2 + ) AS j2 +) AS j3 """); } @@ -426,16 +426,16 @@ public override async Task Json_subquery_reference_pushdown_property(bool async) """ @__p_0='10' -SELECT t0.c ->> 'SomethingSomething' +SELECT j1.c ->> 'SomethingSomething' FROM ( - SELECT DISTINCT t.c AS c, t."Id" + SELECT DISTINCT j0.c AS c, j0."Id" FROM ( SELECT j."OwnedReferenceRoot" #> '{OwnedReferenceBranch,OwnedReferenceLeaf}' AS c, j."Id" FROM "JsonEntitiesBasic" AS j ORDER BY j."Id" NULLS FIRST LIMIT @__p_0 - ) AS t -) AS t0 + ) AS j0 +) AS j1 """); } @@ -560,14 +560,14 @@ public override async Task Project_json_entity_FirstOrDefault_subquery(bool asyn AssertSql( """ -SELECT t.c, t."Id" +SELECT j1.c, j1."Id" FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT j0."OwnedReferenceRoot" -> 'OwnedReferenceBranch' AS c, j0."Id" FROM "JsonEntitiesBasic" AS j0 ORDER BY j0."Id" NULLS FIRST LIMIT 1 -) AS t ON TRUE +) AS j1 ON TRUE ORDER BY j."Id" NULLS FIRST """); } @@ -602,14 +602,14 @@ public override async Task Project_json_entity_FirstOrDefault_subquery_deduplica AssertSql( """ -SELECT t.c, t."Id", t.c0, t."Id0", t.c1, t.c2, t.c3, t.c4 +SELECT j1.c, j1."Id", j1.c0, j1."Id0", j1.c1, j1.c2, j1.c3, j1.c4 FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT j."OwnedReferenceRoot" -> 'OwnedCollectionBranch' AS c, j."Id", j0."OwnedReferenceRoot" AS c0, j0."Id" AS "Id0", j0."OwnedReferenceRoot" -> 'OwnedReferenceBranch' AS c1, j0."OwnedReferenceRoot" ->> 'Name' AS c2, CAST(j."OwnedReferenceRoot" #>> '{OwnedReferenceBranch,Enum}' AS integer) AS c3, 1 AS c4 FROM "JsonEntitiesBasic" AS j0 ORDER BY j0."Id" NULLS FIRST LIMIT 1 -) AS t ON TRUE +) AS j1 ON TRUE ORDER BY j."Id" NULLS FIRST """); } @@ -620,14 +620,14 @@ public override async Task Project_json_entity_FirstOrDefault_subquery_deduplica AssertSql( """ -SELECT t.c, t."Id", t.c0, t."Id0", t.c1, t.c2, t.c3, t.c4 +SELECT j1.c, j1."Id", j1.c0, j1."Id0", j1.c1, j1.c2, j1.c3, j1.c4 FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT j."OwnedReferenceRoot" -> 'OwnedCollectionBranch' AS c, j."Id", j0."OwnedReferenceRoot" AS c0, j0."Id" AS "Id0", j0."OwnedReferenceRoot" -> 'OwnedReferenceBranch' AS c1, j0."OwnedReferenceRoot" ->> 'Name' AS c2, CAST(j."OwnedReferenceRoot" #>> '{OwnedReferenceBranch,Enum}' AS integer) AS c3, 1 AS c4 FROM "JsonEntitiesBasic" AS j0 ORDER BY j0."Id" NULLS FIRST LIMIT 1 -) AS t ON TRUE +) AS j1 ON TRUE ORDER BY j."Id" NULLS FIRST """); } @@ -638,14 +638,14 @@ public override async Task Project_json_entity_FirstOrDefault_subquery_deduplica AssertSql( """ -SELECT t.c, t."Id", t.c0 +SELECT j1.c, j1."Id", j1.c0 FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT j."OwnedReferenceRoot" -> 'OwnedCollectionBranch' AS c, j."Id", 1 AS c0 FROM "JsonEntitiesBasic" AS j0 ORDER BY j0."Id" NULLS FIRST LIMIT 1 -) AS t ON TRUE +) AS j1 ON TRUE ORDER BY j."Id" NULLS FIRST """); } @@ -1066,7 +1066,7 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedReferenceRoot" -> 'OwnedCollectionBra "OwnedCollectionLeaf" jsonb, "OwnedReferenceLeaf" jsonb )) WITH ORDINALITY AS o - WHERE o."Enum" = 2 + WHERE o."Enum" = -3 LIMIT 1 OFFSET 0) = 'e1_r_c2_r' """); } @@ -1080,9 +1080,9 @@ public override async Task Json_collection_Skip(bool async) SELECT j."Id", j."EntityBasicId", j."Name", j."OwnedCollectionRoot", j."OwnedReferenceRoot" FROM "JsonEntitiesBasic" AS j WHERE ( - SELECT t.c + SELECT o0.c FROM ( - SELECT o."OwnedReferenceLeaf" ->> 'SomethingSomething' AS c, o.ordinality + SELECT o."OwnedReferenceLeaf" ->> 'SomethingSomething' AS c FROM ROWS FROM (jsonb_to_recordset(j."OwnedReferenceRoot" -> 'OwnedCollectionBranch') AS ( "Date" timestamp without time zone, "Enum" integer, @@ -1094,7 +1094,7 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedReferenceRoot" -> 'OwnedCollectionBra "OwnedReferenceLeaf" jsonb )) WITH ORDINALITY AS o OFFSET 1 - ) AS t + ) AS o0 LIMIT 1 OFFSET 0) = 'e1_r_c2_r' """); } @@ -1108,9 +1108,9 @@ public override async Task Json_collection_OrderByDescending_Skip_ElementAt(bool SELECT j."Id", j."EntityBasicId", j."Name", j."OwnedCollectionRoot", j."OwnedReferenceRoot" FROM "JsonEntitiesBasic" AS j WHERE ( - SELECT t.c + SELECT o0.c FROM ( - SELECT o."OwnedReferenceLeaf" ->> 'SomethingSomething' AS c, o.ordinality, o."Date" AS c0 + SELECT o."OwnedReferenceLeaf" ->> 'SomethingSomething' AS c, o."Date" AS c0 FROM ROWS FROM (jsonb_to_recordset(j."OwnedReferenceRoot" -> 'OwnedCollectionBranch') AS ( "Date" timestamp without time zone, "Enum" integer, @@ -1123,8 +1123,8 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedReferenceRoot" -> 'OwnedCollectionBra )) WITH ORDINALITY AS o ORDER BY o."Date" DESC NULLS LAST OFFSET 1 - ) AS t - ORDER BY t.c0 DESC NULLS LAST + ) AS o0 + ORDER BY o0.c0 DESC NULLS LAST LIMIT 1 OFFSET 0) = 'e1_r_c1_r' """); } @@ -1152,7 +1152,7 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedReferenceRoot" -> 'OwnedCollectionBra "OwnedReferenceLeaf" jsonb )) WITH ORDINALITY AS o WHERE (o."OwnedReferenceLeaf" ->> 'SomethingSomething') = 'e1_r_c2_r' - ) AS t) = 1 + ) AS o0) = 1 """); } @@ -1236,7 +1236,7 @@ public override async Task Json_collection_in_projection_with_composition_where_ AssertSql( """ -SELECT j."Id", t."Name", t."Number", t.ordinality +SELECT j."Id", o0."Name", o0."Number", o0.ordinality FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT o."Name", o."Number", o.ordinality @@ -1249,7 +1249,7 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedCollectionRoot") AS ( "OwnedReferenceBranch" jsonb )) WITH ORDINALITY AS o WHERE o."Name" = 'Foo' -) AS t ON TRUE +) AS o0 ON TRUE ORDER BY j."Id" NULLS FIRST """); } @@ -1260,7 +1260,7 @@ public override async Task Json_collection_in_projection_with_composition_where_ AssertSql( """ -SELECT j."Id", t."Names", t."Numbers", t.ordinality +SELECT j."Id", o0."Names", o0."Numbers", o0.ordinality FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT o."Names", o."Numbers", o.ordinality @@ -1273,7 +1273,7 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedCollectionRoot") AS ( "OwnedReferenceBranch" jsonb )) WITH ORDINALITY AS o WHERE o."Name" = 'Foo' -) AS t ON TRUE +) AS o0 ON TRUE ORDER BY j."Id" NULLS FIRST """); } @@ -1284,7 +1284,7 @@ public override async Task Json_collection_filter_in_projection(bool async) AssertSql( """ -SELECT j."Id", t."Id", t."Name", t."Names", t."Number", t."Numbers", t.c, t.c0, t.ordinality +SELECT j."Id", o0."Id", o0."Name", o0."Names", o0."Number", o0."Numbers", o0.c, o0.c0, o0.ordinality FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT j."Id", o."Name", o."Names", o."Number", o."Numbers", o."OwnedCollectionBranch" AS c, o."OwnedReferenceBranch" AS c0, o.ordinality @@ -1297,7 +1297,7 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedCollectionRoot") AS ( "OwnedReferenceBranch" jsonb )) WITH ORDINALITY AS o WHERE o."Name" <> 'Foo' OR o."Name" IS NULL -) AS t ON TRUE +) AS o0 ON TRUE ORDER BY j."Id" NULLS FIRST """); } @@ -1308,10 +1308,10 @@ public override async Task Json_nested_collection_filter_in_projection(bool asyn AssertSql( """ -SELECT j."Id", t0.ordinality, t0."Id", t0."Date", t0."Enum", t0."Enums", t0."Fraction", t0."NullableEnum", t0."NullableEnums", t0.c, t0.c0, t0.ordinality0 +SELECT j."Id", s.ordinality, s."Id", s."Date", s."Enum", s."Enums", s."Fraction", s."NullableEnum", s."NullableEnums", s.c, s.c0, s.ordinality0 FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( - SELECT o.ordinality, t."Id", t."Date", t."Enum", t."Enums", t."Fraction", t."NullableEnum", t."NullableEnums", t.c, t.c0, t.ordinality AS ordinality0 + SELECT o.ordinality, o1."Id", o1."Date", o1."Enum", o1."Enums", o1."Fraction", o1."NullableEnum", o1."NullableEnums", o1.c, o1.c0, o1.ordinality AS ordinality0 FROM ROWS FROM (jsonb_to_recordset(j."OwnedCollectionRoot") AS ( "Name" text, "Names" text[], @@ -1333,9 +1333,9 @@ FROM ROWS FROM (jsonb_to_recordset(o."OwnedCollectionBranch") AS ( "OwnedReferenceLeaf" jsonb )) WITH ORDINALITY AS o0 WHERE o0."Date" <> TIMESTAMP '2000-01-01T00:00:00' - ) AS t ON TRUE -) AS t0 ON TRUE -ORDER BY j."Id" NULLS FIRST, t0.ordinality NULLS FIRST + ) AS o1 ON TRUE +) AS s ON TRUE +ORDER BY j."Id" NULLS FIRST, s.ordinality NULLS FIRST """); } @@ -1345,7 +1345,7 @@ public override async Task Json_nested_collection_anonymous_projection_in_projec AssertSql( """ -SELECT j."Id", t.ordinality, t.c, t.c0, t.c1, t.c2, t.c3, t."Id", t.c4, t.ordinality0 +SELECT j."Id", s.ordinality, s.c, s.c0, s.c1, s.c2, s.c3, s."Id", s.c4, s.ordinality0 FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT o.ordinality, o0."Date" AS c, o0."Enum" AS c0, o0."Enums" AS c1, o0."Fraction" AS c2, o0."OwnedReferenceLeaf" AS c3, j."Id", o0."OwnedCollectionLeaf" AS c4, o0.ordinality AS ordinality0 @@ -1367,8 +1367,8 @@ LEFT JOIN LATERAL ROWS FROM (jsonb_to_recordset(o."OwnedCollectionBranch") AS ( "OwnedCollectionLeaf" jsonb, "OwnedReferenceLeaf" jsonb )) WITH ORDINALITY AS o0 ON TRUE -) AS t ON TRUE -ORDER BY j."Id" NULLS FIRST, t.ordinality NULLS FIRST +) AS s ON TRUE +ORDER BY j."Id" NULLS FIRST, s.ordinality NULLS FIRST """); } @@ -1378,7 +1378,7 @@ public override async Task Json_collection_skip_take_in_projection(bool async) AssertSql( """ -SELECT j."Id", t."Id", t."Name", t."Names", t."Number", t."Numbers", t.c, t.c0, t.ordinality +SELECT j."Id", o0."Id", o0."Name", o0."Names", o0."Number", o0."Numbers", o0.c, o0.c0, o0.ordinality FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT j."Id", o."Name", o."Names", o."Number", o."Numbers", o."OwnedCollectionBranch" AS c, o."OwnedReferenceBranch" AS c0, o.ordinality, o."Name" AS c1 @@ -1392,8 +1392,8 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedCollectionRoot") AS ( )) WITH ORDINALITY AS o ORDER BY o."Name" NULLS FIRST LIMIT 5 OFFSET 1 -) AS t ON TRUE -ORDER BY j."Id" NULLS FIRST, t.c1 NULLS FIRST +) AS o0 ON TRUE +ORDER BY j."Id" NULLS FIRST, o0.c1 NULLS FIRST """); } @@ -1403,7 +1403,7 @@ public override async Task Json_collection_skip_take_in_projection_project_into_ AssertSql( """ -SELECT j."Id", t.c, t.c0, t.c1, t.c2, t.c3, t."Id", t.c4, t.ordinality +SELECT j."Id", o0.c, o0.c0, o0.c1, o0.c2, o0.c3, o0."Id", o0.c4, o0.ordinality FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT o."Name" AS c, o."Names" AS c0, o."Number" AS c1, o."Numbers" AS c2, o."OwnedCollectionBranch" AS c3, j."Id", o."OwnedReferenceBranch" AS c4, o.ordinality @@ -1417,8 +1417,8 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedCollectionRoot") AS ( )) WITH ORDINALITY AS o ORDER BY o."Name" NULLS FIRST LIMIT 5 OFFSET 1 -) AS t ON TRUE -ORDER BY j."Id" NULLS FIRST, t.c NULLS FIRST +) AS o0 ON TRUE +ORDER BY j."Id" NULLS FIRST, o0.c NULLS FIRST """); } @@ -1428,7 +1428,7 @@ public override async Task Json_collection_skip_take_in_projection_with_json_ref AssertSql( """ -SELECT j."Id", t.c, t."Id", t.ordinality +SELECT j."Id", o0.c, o0."Id", o0.ordinality FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT o."OwnedReferenceBranch" AS c, j."Id", o.ordinality, o."Name" AS c0 @@ -1442,8 +1442,8 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedCollectionRoot") AS ( )) WITH ORDINALITY AS o ORDER BY o."Name" NULLS FIRST LIMIT 5 OFFSET 1 -) AS t ON TRUE -ORDER BY j."Id" NULLS FIRST, t.c0 NULLS FIRST +) AS o0 ON TRUE +ORDER BY j."Id" NULLS FIRST, o0.c0 NULLS FIRST """); } @@ -1453,7 +1453,7 @@ public override async Task Json_collection_distinct_in_projection(bool async) AssertSql( """ -SELECT j."Id", t."Id", t."Name", t."Names", t."Number", t."Numbers", t.c, t.c0 +SELECT j."Id", o0."Id", o0."Name", o0."Names", o0."Number", o0."Numbers", o0.c, o0.c0 FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT DISTINCT j."Id", o."Name", o."Names", o."Number", o."Numbers", o."OwnedCollectionBranch" AS c, o."OwnedReferenceBranch" AS c0 @@ -1465,8 +1465,8 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedCollectionRoot") AS ( "OwnedCollectionBranch" jsonb, "OwnedReferenceBranch" jsonb )) WITH ORDINALITY AS o -) AS t ON TRUE -ORDER BY j."Id" NULLS FIRST, t."Name" NULLS FIRST, t."Names" NULLS FIRST, t."Number" NULLS FIRST +) AS o0 ON TRUE +ORDER BY j."Id" NULLS FIRST, o0."Name" NULLS FIRST, o0."Names" NULLS FIRST, o0."Number" NULLS FIRST """); } @@ -1483,13 +1483,13 @@ public override async Task Json_collection_leaf_filter_in_projection(bool async) AssertSql( """ -SELECT j."Id", t."Id", t."SomethingSomething", t.ordinality +SELECT j."Id", o0."Id", o0."SomethingSomething", o0.ordinality FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT j."Id", o."SomethingSomething", o.ordinality FROM ROWS FROM (jsonb_to_recordset(j."OwnedReferenceRoot" #> '{OwnedReferenceBranch,OwnedCollectionLeaf}') AS ("SomethingSomething" text)) WITH ORDINALITY AS o WHERE o."SomethingSomething" <> 'Baz' OR o."SomethingSomething" IS NULL -) AS t ON TRUE +) AS o0 ON TRUE ORDER BY j."Id" NULLS FIRST """); } @@ -1500,13 +1500,13 @@ public override async Task Json_multiple_collection_projections(bool async) AssertSql( """ -SELECT j."Id", t."Id", t."SomethingSomething", t.ordinality, t0."Id", t0."Name", t0."Names", t0."Number", t0."Numbers", t0.c, t0.c0, t1.ordinality, t1."Id", t1."Date", t1."Enum", t1."Enums", t1."Fraction", t1."NullableEnum", t1."NullableEnums", t1.c, t1.c0, t1.ordinality0, j0."Id", j0."Name", j0."ParentId" +SELECT j."Id", o4."Id", o4."SomethingSomething", o4.ordinality, o1."Id", o1."Name", o1."Names", o1."Number", o1."Numbers", o1.c, o1.c0, s.ordinality, s."Id", s."Date", s."Enum", s."Enums", s."Fraction", s."NullableEnum", s."NullableEnums", s.c, s.c0, s.ordinality0, j0."Id", j0."Name", j0."ParentId" FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT j."Id", o."SomethingSomething", o.ordinality FROM ROWS FROM (jsonb_to_recordset(j."OwnedReferenceRoot" #> '{OwnedReferenceBranch,OwnedCollectionLeaf}') AS ("SomethingSomething" text)) WITH ORDINALITY AS o WHERE o."SomethingSomething" <> 'Baz' OR o."SomethingSomething" IS NULL -) AS t ON TRUE +) AS o4 ON TRUE LEFT JOIN LATERAL ( SELECT DISTINCT j."Id", o0."Name", o0."Names", o0."Number", o0."Numbers", o0."OwnedCollectionBranch" AS c, o0."OwnedReferenceBranch" AS c0 FROM ROWS FROM (jsonb_to_recordset(j."OwnedCollectionRoot") AS ( @@ -1517,9 +1517,9 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedCollectionRoot") AS ( "OwnedCollectionBranch" jsonb, "OwnedReferenceBranch" jsonb )) WITH ORDINALITY AS o0 -) AS t0 ON TRUE +) AS o1 ON TRUE LEFT JOIN LATERAL ( - SELECT o1.ordinality, t2."Id", t2."Date", t2."Enum", t2."Enums", t2."Fraction", t2."NullableEnum", t2."NullableEnums", t2.c, t2.c0, t2.ordinality AS ordinality0 + SELECT o2.ordinality, o5."Id", o5."Date", o5."Enum", o5."Enums", o5."Fraction", o5."NullableEnum", o5."NullableEnums", o5.c, o5.c0, o5.ordinality AS ordinality0 FROM ROWS FROM (jsonb_to_recordset(j."OwnedCollectionRoot") AS ( "Name" text, "Names" text[], @@ -1527,10 +1527,10 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedCollectionRoot") AS ( "Numbers" integer[], "OwnedCollectionBranch" jsonb, "OwnedReferenceBranch" jsonb - )) WITH ORDINALITY AS o1 + )) WITH ORDINALITY AS o2 LEFT JOIN LATERAL ( - SELECT j."Id", o2."Date", o2."Enum", o2."Enums", o2."Fraction", o2."NullableEnum", o2."NullableEnums", o2."OwnedCollectionLeaf" AS c, o2."OwnedReferenceLeaf" AS c0, o2.ordinality - FROM ROWS FROM (jsonb_to_recordset(o1."OwnedCollectionBranch") AS ( + SELECT j."Id", o3."Date", o3."Enum", o3."Enums", o3."Fraction", o3."NullableEnum", o3."NullableEnums", o3."OwnedCollectionLeaf" AS c, o3."OwnedReferenceLeaf" AS c0, o3.ordinality + FROM ROWS FROM (jsonb_to_recordset(o2."OwnedCollectionBranch") AS ( "Date" timestamp without time zone, "Enum" integer, "Enums" integer[], @@ -1539,12 +1539,12 @@ FROM ROWS FROM (jsonb_to_recordset(o1."OwnedCollectionBranch") AS ( "NullableEnums" integer[], "OwnedCollectionLeaf" jsonb, "OwnedReferenceLeaf" jsonb - )) WITH ORDINALITY AS o2 - WHERE o2."Date" <> TIMESTAMP '2000-01-01T00:00:00' - ) AS t2 ON TRUE -) AS t1 ON TRUE + )) WITH ORDINALITY AS o3 + WHERE o3."Date" <> TIMESTAMP '2000-01-01T00:00:00' + ) AS o5 ON TRUE +) AS s ON TRUE LEFT JOIN "JsonEntitiesBasicForCollection" AS j0 ON j."Id" = j0."ParentId" -ORDER BY j."Id" NULLS FIRST, t.ordinality NULLS FIRST, t0."Name" NULLS FIRST, t0."Names" NULLS FIRST, t0."Number" NULLS FIRST, t0."Numbers" NULLS FIRST, t1.ordinality NULLS FIRST, t1.ordinality0 NULLS FIRST +ORDER BY j."Id" NULLS FIRST, o4.ordinality NULLS FIRST, o1."Name" NULLS FIRST, o1."Names" NULLS FIRST, o1."Number" NULLS FIRST, o1."Numbers" NULLS FIRST, s.ordinality NULLS FIRST, s.ordinality0 NULLS FIRST """); } @@ -1554,7 +1554,7 @@ public override async Task Json_branch_collection_distinct_and_other_collection( AssertSql( """ -SELECT j."Id", t."Id", t."Date", t."Enum", t."Enums", t."Fraction", t."NullableEnum", t."NullableEnums", t.c, t.c0, j0."Id", j0."Name", j0."ParentId" +SELECT j."Id", o0."Id", o0."Date", o0."Enum", o0."Enums", o0."Fraction", o0."NullableEnum", o0."NullableEnums", o0.c, o0.c0, j0."Id", j0."Name", j0."ParentId" FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT DISTINCT j."Id", o."Date", o."Enum", o."Enums", o."Fraction", o."NullableEnum", o."NullableEnums", o."OwnedCollectionLeaf" AS c, o."OwnedReferenceLeaf" AS c0 @@ -1568,9 +1568,9 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedReferenceRoot" -> 'OwnedCollectionBra "OwnedCollectionLeaf" jsonb, "OwnedReferenceLeaf" jsonb )) WITH ORDINALITY AS o -) AS t ON TRUE +) AS o0 ON TRUE LEFT JOIN "JsonEntitiesBasicForCollection" AS j0 ON j."Id" = j0."ParentId" -ORDER BY j."Id" NULLS FIRST, t."Date" NULLS FIRST, t."Enum" NULLS FIRST, t."Enums" NULLS FIRST, t."Fraction" NULLS FIRST, t."NullableEnum" NULLS FIRST, t."NullableEnums" NULLS FIRST +ORDER BY j."Id" NULLS FIRST, o0."Date" NULLS FIRST, o0."Enum" NULLS FIRST, o0."Enums" NULLS FIRST, o0."Fraction" NULLS FIRST, o0."NullableEnum" NULLS FIRST, o0."NullableEnums" NULLS FIRST """); } @@ -1580,14 +1580,14 @@ public override async Task Json_leaf_collection_distinct_and_other_collection(bo AssertSql( """ -SELECT j."Id", t."Id", t."SomethingSomething", j0."Id", j0."Name", j0."ParentId" +SELECT j."Id", o0."Id", o0."SomethingSomething", j0."Id", j0."Name", j0."ParentId" FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT DISTINCT j."Id", o."SomethingSomething" FROM ROWS FROM (jsonb_to_recordset(j."OwnedReferenceRoot" #> '{OwnedReferenceBranch,OwnedCollectionLeaf}') AS ("SomethingSomething" text)) WITH ORDINALITY AS o -) AS t ON TRUE +) AS o0 ON TRUE LEFT JOIN "JsonEntitiesBasicForCollection" AS j0 ON j."Id" = j0."ParentId" -ORDER BY j."Id" NULLS FIRST, t."SomethingSomething" NULLS FIRST +ORDER BY j."Id" NULLS FIRST, o0."SomethingSomething" NULLS FIRST """); } @@ -1752,7 +1752,7 @@ public override async Task Json_collection_Select_entity_in_anonymous_object_Ele AssertSql( """ -SELECT t.c, t."Id", t.c0 +SELECT o0.c, o0."Id", o0.c0 FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT o."OwnedReferenceBranch" AS c, j."Id", 1 AS c0 @@ -1765,7 +1765,7 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedCollectionRoot") AS ( "OwnedReferenceBranch" jsonb )) WITH ORDINALITY AS o LIMIT 1 OFFSET 0 -) AS t ON TRUE +) AS o0 ON TRUE ORDER BY j."Id" NULLS FIRST """); } @@ -1776,7 +1776,7 @@ public override async Task Json_collection_Select_entity_with_initializer_Elemen AssertSql( """ -SELECT t."Id", t.c +SELECT o0."Id", o0.c FROM "JsonEntitiesBasic" AS j LEFT JOIN LATERAL ( SELECT j."Id", 1 AS c @@ -1789,7 +1789,7 @@ FROM ROWS FROM (jsonb_to_recordset(j."OwnedCollectionRoot") AS ( "OwnedReferenceBranch" jsonb )) WITH ORDINALITY AS o LIMIT 1 OFFSET 0 -) AS t ON TRUE +) AS o0 ON TRUE """); } @@ -2030,12 +2030,12 @@ public override async Task Group_by_on_json_scalar(bool async) AssertSql( """ -SELECT t."Key", count(*)::int AS "Count" +SELECT j0."Key", count(*)::int AS "Count" FROM ( SELECT j."OwnedReferenceRoot" ->> 'Name' AS "Key" FROM "JsonEntitiesBasic" AS j -) AS t -GROUP BY t."Key" +) AS j0 +GROUP BY j0."Key" """); } @@ -2045,12 +2045,12 @@ public override async Task Group_by_on_json_scalar_using_collection_indexer(bool AssertSql( """ -SELECT t."Key", count(*)::int AS "Count" +SELECT j0."Key", count(*)::int AS "Count" FROM ( SELECT j."OwnedCollectionRoot" #>> '{0,Name}' AS "Key" FROM "JsonEntitiesBasic" AS j -) AS t -GROUP BY t."Key" +) AS j0 +GROUP BY j0."Key" """); } @@ -2060,26 +2060,26 @@ public override async Task Group_by_First_on_json_scalar(bool async) AssertSql( """ -SELECT t1."Id", t1."EntityBasicId", t1."Name", t1.c, t1.c0 +SELECT j5."Id", j5."EntityBasicId", j5."Name", j5.c, j5.c0 FROM ( - SELECT t."Key" + SELECT j0."Key" FROM ( SELECT j."OwnedReferenceRoot" ->> 'Name' AS "Key" FROM "JsonEntitiesBasic" AS j - ) AS t - GROUP BY t."Key" -) AS t0 + ) AS j0 + GROUP BY j0."Key" +) AS j3 LEFT JOIN ( - SELECT t2."Id", t2."EntityBasicId", t2."Name", t2.c AS c, t2.c0 AS c0, t2."Key" + SELECT j4."Id", j4."EntityBasicId", j4."Name", j4.c AS c, j4.c0 AS c0, j4."Key" FROM ( - SELECT t3."Id", t3."EntityBasicId", t3."Name", t3.c AS c, t3.c0 AS c0, t3."Key", ROW_NUMBER() OVER(PARTITION BY t3."Key" ORDER BY t3."Id" NULLS FIRST) AS row + SELECT j1."Id", j1."EntityBasicId", j1."Name", j1.c AS c, j1.c0 AS c0, j1."Key", ROW_NUMBER() OVER(PARTITION BY j1."Key" ORDER BY j1."Id" NULLS FIRST) AS row FROM ( - SELECT j0."Id", j0."EntityBasicId", j0."Name", j0."OwnedCollectionRoot" AS c, j0."OwnedReferenceRoot" AS c0, j0."OwnedReferenceRoot" ->> 'Name' AS "Key" - FROM "JsonEntitiesBasic" AS j0 - ) AS t3 - ) AS t2 - WHERE t2.row <= 1 -) AS t1 ON t0."Key" = t1."Key" + SELECT j2."Id", j2."EntityBasicId", j2."Name", j2."OwnedCollectionRoot" AS c, j2."OwnedReferenceRoot" AS c0, j2."OwnedReferenceRoot" ->> 'Name' AS "Key" + FROM "JsonEntitiesBasic" AS j2 + ) AS j1 + ) AS j4 + WHERE j4.row <= 1 +) AS j5 ON j3."Key" = j5."Key" """); } @@ -2089,26 +2089,26 @@ public override async Task Group_by_FirstOrDefault_on_json_scalar(bool async) AssertSql( """ -SELECT t1."Id", t1."EntityBasicId", t1."Name", t1.c, t1.c0 +SELECT j5."Id", j5."EntityBasicId", j5."Name", j5.c, j5.c0 FROM ( - SELECT t."Key" + SELECT j0."Key" FROM ( SELECT j."OwnedReferenceRoot" ->> 'Name' AS "Key" FROM "JsonEntitiesBasic" AS j - ) AS t - GROUP BY t."Key" -) AS t0 + ) AS j0 + GROUP BY j0."Key" +) AS j3 LEFT JOIN ( - SELECT t2."Id", t2."EntityBasicId", t2."Name", t2.c AS c, t2.c0 AS c0, t2."Key" + SELECT j4."Id", j4."EntityBasicId", j4."Name", j4.c AS c, j4.c0 AS c0, j4."Key" FROM ( - SELECT t3."Id", t3."EntityBasicId", t3."Name", t3.c AS c, t3.c0 AS c0, t3."Key", ROW_NUMBER() OVER(PARTITION BY t3."Key" ORDER BY t3."Id" NULLS FIRST) AS row + SELECT j1."Id", j1."EntityBasicId", j1."Name", j1.c AS c, j1.c0 AS c0, j1."Key", ROW_NUMBER() OVER(PARTITION BY j1."Key" ORDER BY j1."Id" NULLS FIRST) AS row FROM ( - SELECT j0."Id", j0."EntityBasicId", j0."Name", j0."OwnedCollectionRoot" AS c, j0."OwnedReferenceRoot" AS c0, j0."OwnedReferenceRoot" ->> 'Name' AS "Key" - FROM "JsonEntitiesBasic" AS j0 - ) AS t3 - ) AS t2 - WHERE t2.row <= 1 -) AS t1 ON t0."Key" = t1."Key" + SELECT j2."Id", j2."EntityBasicId", j2."Name", j2."OwnedCollectionRoot" AS c, j2."OwnedReferenceRoot" AS c0, j2."OwnedReferenceRoot" ->> 'Name' AS "Key" + FROM "JsonEntitiesBasic" AS j2 + ) AS j1 + ) AS j4 + WHERE j4.row <= 1 +) AS j5 ON j3."Key" = j5."Key" """); } @@ -2118,27 +2118,27 @@ public override async Task Group_by_Skip_Take_on_json_scalar(bool async) AssertSql( """ -SELECT t0."Key", t1."Id", t1."EntityBasicId", t1."Name", t1.c, t1.c0 +SELECT j3."Key", j5."Id", j5."EntityBasicId", j5."Name", j5.c, j5.c0 FROM ( - SELECT t."Key" + SELECT j0."Key" FROM ( SELECT j."OwnedReferenceRoot" ->> 'Name' AS "Key" FROM "JsonEntitiesBasic" AS j - ) AS t - GROUP BY t."Key" -) AS t0 + ) AS j0 + GROUP BY j0."Key" +) AS j3 LEFT JOIN ( - SELECT t2."Id", t2."EntityBasicId", t2."Name", t2.c, t2.c0, t2."Key" + SELECT j4."Id", j4."EntityBasicId", j4."Name", j4.c, j4.c0, j4."Key" FROM ( - SELECT t3."Id", t3."EntityBasicId", t3."Name", t3.c AS c, t3.c0 AS c0, t3."Key", ROW_NUMBER() OVER(PARTITION BY t3."Key" ORDER BY t3."Id" NULLS FIRST) AS row + SELECT j1."Id", j1."EntityBasicId", j1."Name", j1.c AS c, j1.c0 AS c0, j1."Key", ROW_NUMBER() OVER(PARTITION BY j1."Key" ORDER BY j1."Id" NULLS FIRST) AS row FROM ( - SELECT j0."Id", j0."EntityBasicId", j0."Name", j0."OwnedCollectionRoot" AS c, j0."OwnedReferenceRoot" AS c0, j0."OwnedReferenceRoot" ->> 'Name' AS "Key" - FROM "JsonEntitiesBasic" AS j0 - ) AS t3 - ) AS t2 - WHERE 1 < t2.row AND t2.row <= 6 -) AS t1 ON t0."Key" = t1."Key" -ORDER BY t0."Key" NULLS FIRST, t1."Key" NULLS FIRST, t1."Id" NULLS FIRST + SELECT j2."Id", j2."EntityBasicId", j2."Name", j2."OwnedCollectionRoot" AS c, j2."OwnedReferenceRoot" AS c0, j2."OwnedReferenceRoot" ->> 'Name' AS "Key" + FROM "JsonEntitiesBasic" AS j2 + ) AS j1 + ) AS j4 + WHERE 1 < j4.row AND j4.row <= 6 +) AS j5 ON j3."Key" = j5."Key" +ORDER BY j3."Key" NULLS FIRST, j5."Key" NULLS FIRST, j5."Id" NULLS FIRST """); } @@ -2157,18 +2157,18 @@ public override async Task Group_by_json_scalar_Skip_First_project_json_scalar(b AssertSql( """ SELECT ( - SELECT CAST(t0.c0 #>> '{OwnedReferenceBranch,Enum}' AS integer) + SELECT CAST(j1.c0 #>> '{OwnedReferenceBranch,Enum}' AS integer) FROM ( - SELECT j0."Id", j0."EntityBasicId", j0."Name", j0."OwnedCollectionRoot" AS c, j0."OwnedReferenceRoot" AS c0, j0."OwnedReferenceRoot" ->> 'Name' AS "Key" - FROM "JsonEntitiesBasic" AS j0 - ) AS t0 - WHERE t."Key" = t0."Key" OR (t."Key" IS NULL AND t0."Key" IS NULL) + SELECT j2."OwnedReferenceRoot" AS c0, j2."OwnedReferenceRoot" ->> 'Name' AS "Key" + FROM "JsonEntitiesBasic" AS j2 + ) AS j1 + WHERE j0."Key" = j1."Key" OR (j0."Key" IS NULL AND j1."Key" IS NULL) LIMIT 1) FROM ( SELECT j."OwnedReferenceRoot" ->> 'Name' AS "Key" FROM "JsonEntitiesBasic" AS j -) AS t -GROUP BY t."Key" +) AS j0 +GROUP BY j0."Key" """); } @@ -2535,7 +2535,7 @@ public override async Task Json_predicate_on_enum(bool async) """ SELECT j."Id", j."TestDateTimeCollection", j."TestDecimalCollection", j."TestDefaultStringCollection", j."TestEnumWithIntConverterCollection", j."TestGuidCollection", j."TestInt32Collection", j."TestInt64Collection", j."TestMaxLengthStringCollection", j."TestNullableEnumWithConverterThatHandlesNullsCollection", j."TestSignedByteCollection", j."TestSingleCollection", j."TestTimeSpanCollection", j."TestUnsignedInt32Collection", j."Collection", j."Reference" FROM "JsonEntitiesAllTypes" AS j -WHERE (CAST(j."Reference" ->> 'TestEnum' AS integer)) <> 1 OR (CAST(j."Reference" ->> 'TestEnum' AS integer)) IS NULL +WHERE (CAST(j."Reference" ->> 'TestEnum' AS integer)) <> 2 OR (CAST(j."Reference" ->> 'TestEnum' AS integer)) IS NULL """); } @@ -2547,7 +2547,7 @@ public override async Task Json_predicate_on_enumwithintconverter(bool async) """ SELECT j."Id", j."TestDateTimeCollection", j."TestDecimalCollection", j."TestDefaultStringCollection", j."TestEnumWithIntConverterCollection", j."TestGuidCollection", j."TestInt32Collection", j."TestInt64Collection", j."TestMaxLengthStringCollection", j."TestNullableEnumWithConverterThatHandlesNullsCollection", j."TestSignedByteCollection", j."TestSingleCollection", j."TestTimeSpanCollection", j."TestUnsignedInt32Collection", j."Collection", j."Reference" FROM "JsonEntitiesAllTypes" AS j -WHERE (CAST(j."Reference" ->> 'TestEnumWithIntConverter' AS integer)) <> 2 OR (CAST(j."Reference" ->> 'TestEnumWithIntConverter' AS integer)) IS NULL +WHERE (CAST(j."Reference" ->> 'TestEnumWithIntConverter' AS integer)) <> -3 OR (CAST(j."Reference" ->> 'TestEnumWithIntConverter' AS integer)) IS NULL """); } @@ -2607,7 +2607,7 @@ public override async Task Json_predicate_on_nullableenum1(bool async) """ SELECT j."Id", j."TestDateTimeCollection", j."TestDecimalCollection", j."TestDefaultStringCollection", j."TestEnumWithIntConverterCollection", j."TestGuidCollection", j."TestInt32Collection", j."TestInt64Collection", j."TestMaxLengthStringCollection", j."TestNullableEnumWithConverterThatHandlesNullsCollection", j."TestSignedByteCollection", j."TestSingleCollection", j."TestTimeSpanCollection", j."TestUnsignedInt32Collection", j."Collection", j."Reference" FROM "JsonEntitiesAllTypes" AS j -WHERE (CAST(j."Reference" ->> 'TestNullableEnum' AS integer)) <> 0 OR (CAST(j."Reference" ->> 'TestNullableEnum' AS integer)) IS NULL +WHERE (CAST(j."Reference" ->> 'TestNullableEnum' AS integer)) <> -1 OR (CAST(j."Reference" ->> 'TestNullableEnum' AS integer)) IS NULL """); } @@ -2631,7 +2631,7 @@ public override async Task Json_predicate_on_nullableenumwithconverter1(bool asy """ SELECT j."Id", j."TestDateTimeCollection", j."TestDecimalCollection", j."TestDefaultStringCollection", j."TestEnumWithIntConverterCollection", j."TestGuidCollection", j."TestInt32Collection", j."TestInt64Collection", j."TestMaxLengthStringCollection", j."TestNullableEnumWithConverterThatHandlesNullsCollection", j."TestSignedByteCollection", j."TestSingleCollection", j."TestTimeSpanCollection", j."TestUnsignedInt32Collection", j."Collection", j."Reference" FROM "JsonEntitiesAllTypes" AS j -WHERE (CAST(j."Reference" ->> 'TestNullableEnumWithIntConverter' AS integer)) <> 1 OR (CAST(j."Reference" ->> 'TestNullableEnumWithIntConverter' AS integer)) IS NULL +WHERE (CAST(j."Reference" ->> 'TestNullableEnumWithIntConverter' AS integer)) <> 2 OR (CAST(j."Reference" ->> 'TestNullableEnumWithIntConverter' AS integer)) IS NULL """); } diff --git a/test/EFCore.PG.FunctionalTests/Query/NorthwindGroupByQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/NorthwindGroupByQueryNpgsqlTest.cs index 52bf83e88..1f497fa40 100644 --- a/test/EFCore.PG.FunctionalTests/Query/NorthwindGroupByQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/NorthwindGroupByQueryNpgsqlTest.cs @@ -252,12 +252,12 @@ public override async Task GroupBy_Property_Select_Key_with_constant(bool async) AssertSql( """ -SELECT t."Name", t."CustomerID" AS "Value", count(*)::int AS "Count" +SELECT o0."Name", o0."CustomerID" AS "Value", count(*)::int AS "Count" FROM ( SELECT o."CustomerID", 'CustomerID' AS "Name" FROM "Orders" AS o -) AS t -GROUP BY t."Name", t."CustomerID" +) AS o0 +GROUP BY o0."Name", o0."CustomerID" """); } @@ -636,12 +636,12 @@ public override async Task GroupBy_Constant_Select_Sum_Min_Key_Max_Avg(bool asyn AssertSql( """ -SELECT COALESCE(sum(t."OrderID"), 0)::int AS "Sum", min(t."OrderID") AS "Min", t."Key", max(t."OrderID") AS "Max", avg(t."OrderID"::double precision) AS "Avg" +SELECT COALESCE(sum(o0."OrderID"), 0)::int AS "Sum", min(o0."OrderID") AS "Min", o0."Key", max(o0."OrderID") AS "Max", avg(o0."OrderID"::double precision) AS "Avg" FROM ( SELECT o."OrderID", 2 AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -651,12 +651,12 @@ public override async Task GroupBy_Constant_with_element_selector_Select_Sum(boo AssertSql( """ -SELECT COALESCE(sum(t."OrderID"), 0)::int AS "Sum" +SELECT COALESCE(sum(o0."OrderID"), 0)::int AS "Sum" FROM ( SELECT o."OrderID", 2 AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -666,12 +666,12 @@ public override async Task GroupBy_Constant_with_element_selector_Select_Sum2(bo AssertSql( """ -SELECT COALESCE(sum(t."OrderID"), 0)::int AS "Sum" +SELECT COALESCE(sum(o0."OrderID"), 0)::int AS "Sum" FROM ( SELECT o."OrderID", 2 AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -681,12 +681,12 @@ public override async Task GroupBy_Constant_with_element_selector_Select_Sum3(bo AssertSql( """ -SELECT COALESCE(sum(t."OrderID"), 0)::int AS "Sum" +SELECT COALESCE(sum(o0."OrderID"), 0)::int AS "Sum" FROM ( SELECT o."OrderID", 2 AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -696,13 +696,13 @@ public override async Task GroupBy_after_predicate_Constant_Select_Sum_Min_Key_M AssertSql( """ -SELECT COALESCE(sum(t."OrderID"), 0)::int AS "Sum", min(t."OrderID") AS "Min", t."Key" AS "Random", max(t."OrderID") AS "Max", avg(t."OrderID"::double precision) AS "Avg" +SELECT COALESCE(sum(o0."OrderID"), 0)::int AS "Sum", min(o0."OrderID") AS "Min", o0."Key" AS "Random", max(o0."OrderID") AS "Max", avg(o0."OrderID"::double precision) AS "Avg" FROM ( SELECT o."OrderID", 2 AS "Key" FROM "Orders" AS o WHERE o."OrderID" > 10500 -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -712,12 +712,12 @@ public override async Task GroupBy_Constant_with_element_selector_Select_Sum_Min AssertSql( """ -SELECT COALESCE(sum(t."OrderID"), 0)::int AS "Sum", t."Key" +SELECT COALESCE(sum(o0."OrderID"), 0)::int AS "Sum", o0."Key" FROM ( SELECT o."OrderID", 2 AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -727,13 +727,13 @@ public override async Task GroupBy_constant_with_where_on_grouping_with_aggregat AssertSql( """ -SELECT min(t."OrderDate") FILTER (WHERE 1 = t."Key") AS "Min", max(t."OrderDate") FILTER (WHERE 1 = t."Key") AS "Max", COALESCE(sum(t."OrderID") FILTER (WHERE 1 = t."Key"), 0)::int AS "Sum", avg(t."OrderID"::double precision) FILTER (WHERE 1 = t."Key") AS "Average" +SELECT min(o0."OrderDate") FILTER (WHERE 1 = o0."Key") AS "Min", max(o0."OrderDate") FILTER (WHERE 1 = o0."Key") AS "Max", COALESCE(sum(o0."OrderID") FILTER (WHERE 1 = o0."Key"), 0)::int AS "Sum", avg(o0."OrderID"::double precision) FILTER (WHERE 1 = o0."Key") AS "Average" FROM ( SELECT o."OrderID", o."OrderDate", 1 AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" -ORDER BY t."Key" NULLS FIRST +) AS o0 +GROUP BY o0."Key" +ORDER BY o0."Key" NULLS FIRST """); } @@ -745,12 +745,12 @@ public override async Task GroupBy_param_Select_Sum_Min_Key_Max_Avg(bool async) """ @__a_0='2' -SELECT COALESCE(sum(t."OrderID"), 0)::int AS "Sum", min(t."OrderID") AS "Min", t."Key", max(t."OrderID") AS "Max", avg(t."OrderID"::double precision) AS "Avg" +SELECT COALESCE(sum(o0."OrderID"), 0)::int AS "Sum", min(o0."OrderID") AS "Min", o0."Key", max(o0."OrderID") AS "Max", avg(o0."OrderID"::double precision) AS "Avg" FROM ( SELECT o."OrderID", @__a_0 AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -762,12 +762,12 @@ public override async Task GroupBy_param_with_element_selector_Select_Sum(bool a """ @__a_0='2' -SELECT COALESCE(sum(t."OrderID"), 0)::int AS "Sum" +SELECT COALESCE(sum(o0."OrderID"), 0)::int AS "Sum" FROM ( SELECT o."OrderID", @__a_0 AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -779,12 +779,12 @@ public override async Task GroupBy_param_with_element_selector_Select_Sum2(bool """ @__a_0='2' -SELECT COALESCE(sum(t."OrderID"), 0)::int AS "Sum" +SELECT COALESCE(sum(o0."OrderID"), 0)::int AS "Sum" FROM ( SELECT o."OrderID", @__a_0 AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -796,12 +796,12 @@ public override async Task GroupBy_param_with_element_selector_Select_Sum3(bool """ @__a_0='2' -SELECT COALESCE(sum(t."OrderID"), 0)::int AS "Sum" +SELECT COALESCE(sum(o0."OrderID"), 0)::int AS "Sum" FROM ( SELECT o."OrderID", @__a_0 AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -813,12 +813,12 @@ public override async Task GroupBy_param_with_element_selector_Select_Sum_Min_Ke """ @__a_0='2' -SELECT COALESCE(sum(t."OrderID"), 0)::int AS "Sum", t."Key" +SELECT COALESCE(sum(o0."OrderID"), 0)::int AS "Sum", o0."Key" FROM ( SELECT o."OrderID", @__a_0 AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -828,13 +828,13 @@ public override async Task GroupBy_anonymous_key_type_mismatch_with_aggregate(bo AssertSql( """ -SELECT count(*)::int AS "I0", t."I0" AS "I1" +SELECT count(*)::int AS "I0", o0."I0" AS "I1" FROM ( SELECT date_part('year', o."OrderDate")::int AS "I0" FROM "Orders" AS o -) AS t -GROUP BY t."I0" -ORDER BY t."I0" NULLS FIRST +) AS o0 +GROUP BY o0."I0" +ORDER BY o0."I0" NULLS FIRST """); } @@ -1081,12 +1081,12 @@ public override async Task GroupBy_conditional_properties(bool async) AssertSql( """ -SELECT t."OrderMonth", t."CustomerID" AS "Customer", count(*)::int AS "Count" +SELECT o0."OrderMonth", o0."CustomerID" AS "Customer", count(*)::int AS "Count" FROM ( SELECT o."CustomerID", NULL AS "OrderMonth" FROM "Orders" AS o -) AS t -GROUP BY t."OrderMonth", t."CustomerID" +) AS o0 +GROUP BY o0."OrderMonth", o0."CustomerID" """); } @@ -1096,12 +1096,12 @@ public override async Task GroupBy_empty_key_Aggregate(bool async) AssertSql( """ -SELECT COALESCE(sum(t."OrderID"), 0)::int +SELECT COALESCE(sum(o0."OrderID"), 0)::int FROM ( SELECT o."OrderID", 1 AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -1111,12 +1111,12 @@ public override async Task GroupBy_empty_key_Aggregate_Key(bool async) AssertSql( """ -SELECT COALESCE(sum(t."OrderID"), 0)::int AS "Sum" +SELECT COALESCE(sum(o0."OrderID"), 0)::int AS "Sum" FROM ( SELECT o."OrderID", 1 AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -1140,14 +1140,14 @@ public override async Task OrderBy_Skip_GroupBy_Aggregate(bool async) """ @__p_0='80' -SELECT avg(t."OrderID"::double precision) +SELECT avg(o0."OrderID"::double precision) FROM ( SELECT o."OrderID", o."CustomerID" FROM "Orders" AS o ORDER BY o."OrderID" NULLS FIRST OFFSET @__p_0 -) AS t -GROUP BY t."CustomerID" +) AS o0 +GROUP BY o0."CustomerID" """); } @@ -1159,14 +1159,14 @@ public override async Task OrderBy_Take_GroupBy_Aggregate(bool async) """ @__p_0='500' -SELECT min(t."OrderID") +SELECT min(o0."OrderID") FROM ( SELECT o."OrderID", o."CustomerID" FROM "Orders" AS o ORDER BY o."OrderID" NULLS FIRST LIMIT @__p_0 -) AS t -GROUP BY t."CustomerID" +) AS o0 +GROUP BY o0."CustomerID" """); } @@ -1179,14 +1179,14 @@ public override async Task OrderBy_Skip_Take_GroupBy_Aggregate(bool async) @__p_1='500' @__p_0='80' -SELECT max(t."OrderID") +SELECT max(o0."OrderID") FROM ( SELECT o."OrderID", o."CustomerID" FROM "Orders" AS o ORDER BY o."OrderID" NULLS FIRST LIMIT @__p_1 OFFSET @__p_0 -) AS t -GROUP BY t."CustomerID" +) AS o0 +GROUP BY o0."CustomerID" """); } @@ -1196,12 +1196,12 @@ public override async Task Distinct_GroupBy_Aggregate(bool async) AssertSql( """ -SELECT t."CustomerID" AS "Key", count(*)::int AS c +SELECT o0."CustomerID" AS "Key", count(*)::int AS c FROM ( SELECT DISTINCT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate" FROM "Orders" AS o -) AS t -GROUP BY t."CustomerID" +) AS o0 +GROUP BY o0."CustomerID" """); } @@ -1211,12 +1211,12 @@ public override async Task Anonymous_projection_Distinct_GroupBy_Aggregate(bool AssertSql( """ -SELECT t."EmployeeID" AS "Key", count(*)::int AS c +SELECT o0."EmployeeID" AS "Key", count(*)::int AS c FROM ( SELECT DISTINCT o."OrderID", o."EmployeeID" FROM "Orders" AS o -) AS t -GROUP BY t."EmployeeID" +) AS o0 +GROUP BY o0."EmployeeID" """); } @@ -1269,22 +1269,22 @@ public override async Task Join_complex_GroupBy_Aggregate(bool async) @__p_2='50' @__p_1='10' -SELECT t0."CustomerID" AS "Key", avg(t."OrderID"::double precision) AS "Count" +SELECT c0."CustomerID" AS "Key", avg(o0."OrderID"::double precision) AS "Count" FROM ( SELECT o."OrderID", o."CustomerID" FROM "Orders" AS o WHERE o."OrderID" < 10400 ORDER BY o."OrderDate" NULLS FIRST LIMIT @__p_0 -) AS t +) AS o0 INNER JOIN ( SELECT c."CustomerID" FROM "Customers" AS c WHERE c."CustomerID" NOT IN ('DRACD', 'FOLKO') ORDER BY c."City" NULLS FIRST LIMIT @__p_2 OFFSET @__p_1 -) AS t0 ON t."CustomerID" = t0."CustomerID" -GROUP BY t0."CustomerID" +) AS c0 ON o0."CustomerID" = c0."CustomerID" +GROUP BY c0."CustomerID" """); } @@ -1377,23 +1377,23 @@ public override async Task GroupJoin_complex_GroupBy_Aggregate(bool async) @__p_0='10' @__p_2='100' -SELECT t0."CustomerID" AS "Key", avg(t0."OrderID"::double precision) AS "Count" +SELECT o0."CustomerID" AS "Key", avg(o0."OrderID"::double precision) AS "Count" FROM ( SELECT c."CustomerID" FROM "Customers" AS c WHERE c."CustomerID" NOT IN ('DRACD', 'FOLKO') ORDER BY c."City" NULLS FIRST LIMIT @__p_1 OFFSET @__p_0 -) AS t +) AS c0 INNER JOIN ( SELECT o."OrderID", o."CustomerID" FROM "Orders" AS o WHERE o."OrderID" < 10400 ORDER BY o."OrderDate" NULLS FIRST LIMIT @__p_2 -) AS t0 ON t."CustomerID" = t0."CustomerID" -WHERE t0."OrderID" > 10300 -GROUP BY t0."CustomerID" +) AS o0 ON c0."CustomerID" = o0."CustomerID" +WHERE o0."OrderID" > 10300 +GROUP BY o0."CustomerID" """); } @@ -1431,7 +1431,7 @@ public override async Task Union_simple_groupby(bool async) AssertSql( """ -SELECT t."City" AS "Key", count(*)::int AS "Total" +SELECT u."City" AS "Key", count(*)::int AS "Total" FROM ( SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region" FROM "Customers" AS c @@ -1440,8 +1440,8 @@ public override async Task Union_simple_groupby(bool async) SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" FROM "Customers" AS c0 WHERE c0."City" = 'México D.F.' -) AS t -GROUP BY t."City" +) AS u +GROUP BY u."City" """); } @@ -1477,12 +1477,12 @@ public override async Task GroupBy_after_anonymous_projection_and_distinct_follo AssertSql( """ -SELECT t."CustomerID" AS "Key", count(*)::int AS "Count" +SELECT o0."CustomerID" AS "Key", count(*)::int AS "Count" FROM ( SELECT DISTINCT o."CustomerID", o."OrderID" FROM "Orders" AS o -) AS t -GROUP BY t."CustomerID" +) AS o0 +GROUP BY o0."CustomerID" """); } @@ -1492,13 +1492,13 @@ public override async Task GroupBy_complex_key_aggregate(bool async) AssertSql( """ -SELECT t."Key", count(*)::int AS "Count" +SELECT s."Key", count(*)::int AS "Count" FROM ( SELECT substring(c."CustomerID", 1, 1) AS "Key" FROM "Orders" AS o LEFT JOIN "Customers" AS c ON o."CustomerID" = c."CustomerID" -) AS t -GROUP BY t."Key" +) AS s +GROUP BY s."Key" """); } @@ -1508,15 +1508,15 @@ public override async Task GroupBy_complex_key_aggregate_2(bool async) AssertSql( """ -SELECT t."Key" AS "Month", COALESCE(sum(t."OrderID"), 0)::int AS "Total", ( - SELECT COALESCE(sum(o0."OrderID"), 0)::int - FROM "Orders" AS o0 - WHERE date_part('month', o0."OrderDate")::int = t."Key" OR (o0."OrderDate" IS NULL AND t."Key" IS NULL)) AS "Payment" +SELECT o0."Key" AS "Month", COALESCE(sum(o0."OrderID"), 0)::int AS "Total", ( + SELECT COALESCE(sum(o1."OrderID"), 0)::int + FROM "Orders" AS o1 + WHERE date_part('month', o1."OrderDate")::int = o0."Key" OR (o1."OrderDate" IS NULL AND o0."Key" IS NULL)) AS "Payment" FROM ( SELECT o."OrderID", date_part('month', o."OrderDate")::int AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -1596,7 +1596,7 @@ public override async Task GroupBy_aggregate_Pushdown(bool async) @__p_0='20' @__p_1='4' -SELECT t."CustomerID" +SELECT o0."CustomerID" FROM ( SELECT o."CustomerID" FROM "Orders" AS o @@ -1604,8 +1604,8 @@ GROUP BY o."CustomerID" HAVING count(*)::int > 10 ORDER BY o."CustomerID" NULLS FIRST LIMIT @__p_0 -) AS t -ORDER BY t."CustomerID" NULLS FIRST +) AS o0 +ORDER BY o0."CustomerID" NULLS FIRST OFFSET @__p_1 """); } @@ -1619,7 +1619,7 @@ public override async Task GroupBy_aggregate_using_grouping_key_Pushdown(bool as @__p_0='20' @__p_1='4' -SELECT t."Key", t."Max" +SELECT o0."Key", o0."Max" FROM ( SELECT o."CustomerID" AS "Key", max(o."CustomerID") AS "Max" FROM "Orders" AS o @@ -1627,8 +1627,8 @@ GROUP BY o."CustomerID" HAVING count(*)::int > 10 ORDER BY o."CustomerID" NULLS FIRST LIMIT @__p_0 -) AS t -ORDER BY t."Key" NULLS FIRST +) AS o0 +ORDER BY o0."Key" NULLS FIRST OFFSET @__p_1 """); } @@ -1642,7 +1642,7 @@ public override async Task GroupBy_aggregate_Pushdown_followed_by_projecting_Len @__p_0='20' @__p_1='4' -SELECT length(t."CustomerID")::int +SELECT length(o0."CustomerID")::int FROM ( SELECT o."CustomerID" FROM "Orders" AS o @@ -1650,8 +1650,8 @@ GROUP BY o."CustomerID" HAVING count(*)::int > 10 ORDER BY o."CustomerID" NULLS FIRST LIMIT @__p_0 -) AS t -ORDER BY t."CustomerID" NULLS FIRST +) AS o0 +ORDER BY o0."CustomerID" NULLS FIRST OFFSET @__p_1 """); } @@ -1673,8 +1673,8 @@ GROUP BY o."CustomerID" HAVING count(*)::int > 10 ORDER BY o."CustomerID" NULLS FIRST LIMIT @__p_0 -) AS t -ORDER BY t."CustomerID" NULLS FIRST +) AS o0 +ORDER BY o0."CustomerID" NULLS FIRST OFFSET @__p_1 """); } @@ -1711,12 +1711,12 @@ public override async Task GroupBy_count_filter(bool async) AssertSql( """ -SELECT t."Key" AS "Name", count(*)::int AS "Count" +SELECT o0."Key" AS "Name", count(*)::int AS "Count" FROM ( SELECT 'Order' AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" HAVING count(*)::int > 0 """); } @@ -1741,15 +1741,15 @@ public override async Task GroupBy_Aggregate_Join(bool async) AssertSql( """ -SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", o0."OrderID", o0."CustomerID", o0."EmployeeID", o0."OrderDate" +SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", o1."OrderID", o1."CustomerID", o1."EmployeeID", o1."OrderDate" FROM ( SELECT o."CustomerID", max(o."OrderID") AS "LastOrderID" FROM "Orders" AS o GROUP BY o."CustomerID" HAVING count(*)::int > 5 -) AS t -INNER JOIN "Customers" AS c ON t."CustomerID" = c."CustomerID" -INNER JOIN "Orders" AS o0 ON t."LastOrderID" = o0."OrderID" +) AS o0 +INNER JOIN "Customers" AS c ON o0."CustomerID" = c."CustomerID" +INNER JOIN "Orders" AS o1 ON o0."LastOrderID" = o1."OrderID" """); } @@ -1762,11 +1762,11 @@ public override async Task GroupBy_Aggregate_Join_converted_from_SelectMany(bool SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region" FROM "Customers" AS c INNER JOIN ( - SELECT o."CustomerID", max(o."OrderID") AS "LastOrderID" + SELECT o."CustomerID" FROM "Orders" AS o GROUP BY o."CustomerID" HAVING count(*)::int > 5 -) AS t ON c."CustomerID" = t."CustomerID" +) AS o0 ON c."CustomerID" = o0."CustomerID" """); } @@ -1779,11 +1779,11 @@ public override async Task GroupBy_Aggregate_LeftJoin_converted_from_SelectMany( SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region" FROM "Customers" AS c LEFT JOIN ( - SELECT o."CustomerID", max(o."OrderID") AS "LastOrderID" + SELECT o."CustomerID" FROM "Orders" AS o GROUP BY o."CustomerID" HAVING count(*)::int > 5 -) AS t ON c."CustomerID" = t."CustomerID" +) AS o0 ON c."CustomerID" = o0."CustomerID" """); } @@ -1793,15 +1793,15 @@ public override async Task Join_GroupBy_Aggregate_multijoins(bool async) AssertSql( """ -SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", o0."OrderID", o0."CustomerID", o0."EmployeeID", o0."OrderDate" +SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", o1."OrderID", o1."CustomerID", o1."EmployeeID", o1."OrderDate" FROM "Customers" AS c INNER JOIN ( SELECT o."CustomerID", max(o."OrderID") AS "LastOrderID" FROM "Orders" AS o GROUP BY o."CustomerID" HAVING count(*)::int > 5 -) AS t ON c."CustomerID" = t."CustomerID" -INNER JOIN "Orders" AS o0 ON t."LastOrderID" = o0."OrderID" +) AS o0 ON c."CustomerID" = o0."CustomerID" +INNER JOIN "Orders" AS o1 ON o0."LastOrderID" = o1."OrderID" """); } @@ -1811,14 +1811,14 @@ public override async Task Join_GroupBy_Aggregate_single_join(bool async) AssertSql( """ -SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", t."LastOrderID" +SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", o0."LastOrderID" FROM "Customers" AS c INNER JOIN ( SELECT o."CustomerID", max(o."OrderID") AS "LastOrderID" FROM "Orders" AS o GROUP BY o."CustomerID" HAVING count(*)::int > 5 -) AS t ON c."CustomerID" = t."CustomerID" +) AS o0 ON c."CustomerID" = o0."CustomerID" """); } @@ -1828,15 +1828,15 @@ public override async Task Join_GroupBy_Aggregate_with_another_join(bool async) AssertSql( """ -SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", t."LastOrderID", o0."OrderID" +SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", o0."LastOrderID", o1."OrderID" FROM "Customers" AS c INNER JOIN ( SELECT o."CustomerID", max(o."OrderID") AS "LastOrderID" FROM "Orders" AS o GROUP BY o."CustomerID" HAVING count(*)::int > 5 -) AS t ON c."CustomerID" = t."CustomerID" -INNER JOIN "Orders" AS o0 ON c."CustomerID" = o0."CustomerID" +) AS o0 ON c."CustomerID" = o0."CustomerID" +INNER JOIN "Orders" AS o1 ON c."CustomerID" = o1."CustomerID" """); } @@ -1846,17 +1846,17 @@ public override async Task Join_GroupBy_Aggregate_distinct_single_join(bool asyn AssertSql( """ -SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", t0."LastOrderID" +SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", o1."LastOrderID" FROM "Customers" AS c INNER JOIN ( - SELECT DISTINCT t."CustomerID", max(t."OrderID") AS "LastOrderID" + SELECT DISTINCT o0."CustomerID", max(o0."OrderID") AS "LastOrderID" FROM ( SELECT o."OrderID", o."CustomerID", date_part('year', o."OrderDate")::int AS "Year" FROM "Orders" AS o - ) AS t - GROUP BY t."CustomerID", t."Year" + ) AS o0 + GROUP BY o0."CustomerID", o0."Year" HAVING count(*)::int > 5 -) AS t0 ON c."CustomerID" = t0."CustomerID" +) AS o1 ON c."CustomerID" = o1."CustomerID" """); } @@ -1866,14 +1866,14 @@ public override async Task Join_GroupBy_Aggregate_with_left_join(bool async) AssertSql( """ -SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", t."LastOrderID" +SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", o0."LastOrderID" FROM "Customers" AS c LEFT JOIN ( SELECT o."CustomerID", max(o."OrderID") AS "LastOrderID" FROM "Orders" AS o GROUP BY o."CustomerID" HAVING count(*)::int > 5 -) AS t ON c."CustomerID" = t."CustomerID" +) AS o0 ON c."CustomerID" = o0."CustomerID" WHERE c."CustomerID" LIKE 'A%' """); } @@ -1884,18 +1884,18 @@ public override async Task Join_GroupBy_Aggregate_in_subquery(bool async) AssertSql( """ -SELECT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate", t0."CustomerID", t0."Address", t0."City", t0."CompanyName", t0."ContactName", t0."ContactTitle", t0."Country", t0."Fax", t0."Phone", t0."PostalCode", t0."Region" +SELECT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate", s."CustomerID", s."Address", s."City", s."CompanyName", s."ContactName", s."ContactTitle", s."Country", s."Fax", s."Phone", s."PostalCode", s."Region" FROM "Orders" AS o INNER JOIN ( SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region" FROM "Customers" AS c INNER JOIN ( - SELECT o0."CustomerID", max(o0."OrderID") AS "LastOrderID" + SELECT o0."CustomerID" FROM "Orders" AS o0 GROUP BY o0."CustomerID" HAVING count(*)::int > 5 - ) AS t ON c."CustomerID" = t."CustomerID" -) AS t0 ON o."CustomerID" = t0."CustomerID" + ) AS o1 ON c."CustomerID" = o1."CustomerID" +) AS s ON o."CustomerID" = s."CustomerID" WHERE o."OrderID" < 10400 """); } @@ -1906,14 +1906,14 @@ public override async Task Join_GroupBy_Aggregate_on_key(bool async) AssertSql( """ -SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", t."LastOrderID" +SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", o0."LastOrderID" FROM "Customers" AS c INNER JOIN ( SELECT o."CustomerID" AS "Key", max(o."OrderID") AS "LastOrderID" FROM "Orders" AS o GROUP BY o."CustomerID" HAVING count(*)::int > 5 -) AS t ON c."CustomerID" = t."Key" +) AS o0 ON c."CustomerID" = o0."Key" """); } @@ -1959,13 +1959,13 @@ public override async Task Distinct_GroupBy_OrderBy_key(bool async) AssertSql( """ -SELECT t."CustomerID" AS "Key", count(*)::int AS c +SELECT o0."CustomerID" AS "Key", count(*)::int AS c FROM ( SELECT DISTINCT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate" FROM "Orders" AS o -) AS t -GROUP BY t."CustomerID" -ORDER BY t."CustomerID" NULLS FIRST +) AS o0 +GROUP BY o0."CustomerID" +ORDER BY o0."CustomerID" NULLS FIRST """); } @@ -1998,13 +1998,13 @@ public override async Task Select_uncorrelated_collection_with_groupby_works(boo AssertSql( """ -SELECT c."CustomerID", t."OrderID" +SELECT c."CustomerID", o0."OrderID" FROM "Customers" AS c LEFT JOIN LATERAL ( SELECT o."OrderID" FROM "Orders" AS o GROUP BY o."OrderID" -) AS t ON TRUE +) AS o0 ON TRUE WHERE c."CustomerID" LIKE 'A%' ORDER BY c."CustomerID" NULLS FIRST """); @@ -2016,20 +2016,20 @@ public override async Task Select_uncorrelated_collection_with_groupby_multiple_ AssertSql( """ -SELECT o."OrderID", t."ProductID", t0.c, t0."ProductID" +SELECT o."OrderID", p1."ProductID", p2.c, p2."ProductID" FROM "Orders" AS o LEFT JOIN LATERAL ( SELECT p."ProductID" FROM "Products" AS p GROUP BY p."ProductID" -) AS t ON TRUE +) AS p1 ON TRUE LEFT JOIN LATERAL ( SELECT count(*)::int AS c, p0."ProductID" FROM "Products" AS p0 GROUP BY p0."ProductID" -) AS t0 ON TRUE +) AS p2 ON TRUE WHERE o."CustomerID" LIKE 'A%' -ORDER BY o."OrderID" NULLS FIRST, t."ProductID" NULLS FIRST +ORDER BY o."OrderID" NULLS FIRST, p1."ProductID" NULLS FIRST """); } @@ -2293,22 +2293,22 @@ public override async Task GroupBy_Shadow2(bool async) AssertSql( """ -SELECT t0."EmployeeID", t0."City", t0."Country", t0."FirstName", t0."ReportsTo", t0."Title" +SELECT e3."EmployeeID", e3."City", e3."Country", e3."FirstName", e3."ReportsTo", e3."Title" FROM ( SELECT e."Title" FROM "Employees" AS e WHERE e."Title" = 'Sales Representative' AND e."EmployeeID" = 1 GROUP BY e."Title" -) AS t +) AS e1 LEFT JOIN ( - SELECT t1."EmployeeID", t1."City", t1."Country", t1."FirstName", t1."ReportsTo", t1."Title" + SELECT e2."EmployeeID", e2."City", e2."Country", e2."FirstName", e2."ReportsTo", e2."Title" FROM ( SELECT e0."EmployeeID", e0."City", e0."Country", e0."FirstName", e0."ReportsTo", e0."Title", ROW_NUMBER() OVER(PARTITION BY e0."Title" ORDER BY e0."EmployeeID" NULLS FIRST) AS row FROM "Employees" AS e0 WHERE e0."Title" = 'Sales Representative' AND e0."EmployeeID" = 1 - ) AS t1 - WHERE t1.row <= 1 -) AS t0 ON t."Title" = t0."Title" + ) AS e2 + WHERE e2.row <= 1 +) AS e3 ON e1."Title" = e3."Title" """); } @@ -2335,14 +2335,14 @@ public override async Task GroupBy_select_grouping_list(bool async) AssertSql( """ -SELECT t."City", c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" +SELECT c1."City", c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" FROM ( SELECT c."City" FROM "Customers" AS c GROUP BY c."City" -) AS t -LEFT JOIN "Customers" AS c0 ON t."City" = c0."City" -ORDER BY t."City" NULLS FIRST +) AS c1 +LEFT JOIN "Customers" AS c0 ON c1."City" = c0."City" +ORDER BY c1."City" NULLS FIRST """); } @@ -2352,14 +2352,14 @@ public override async Task GroupBy_select_grouping_array(bool async) AssertSql( """ -SELECT t."City", c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" +SELECT c1."City", c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" FROM ( SELECT c."City" FROM "Customers" AS c GROUP BY c."City" -) AS t -LEFT JOIN "Customers" AS c0 ON t."City" = c0."City" -ORDER BY t."City" NULLS FIRST +) AS c1 +LEFT JOIN "Customers" AS c0 ON c1."City" = c0."City" +ORDER BY c1."City" NULLS FIRST """); } @@ -2369,18 +2369,18 @@ public override async Task GroupBy_select_grouping_composed_list(bool async) AssertSql( """ -SELECT t."City", t0."CustomerID", t0."Address", t0."City", t0."CompanyName", t0."ContactName", t0."ContactTitle", t0."Country", t0."Fax", t0."Phone", t0."PostalCode", t0."Region" +SELECT c1."City", c2."CustomerID", c2."Address", c2."City", c2."CompanyName", c2."ContactName", c2."ContactTitle", c2."Country", c2."Fax", c2."Phone", c2."PostalCode", c2."Region" FROM ( SELECT c."City" FROM "Customers" AS c GROUP BY c."City" -) AS t +) AS c1 LEFT JOIN ( SELECT c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" FROM "Customers" AS c0 WHERE c0."CustomerID" LIKE 'A%' -) AS t0 ON t."City" = t0."City" -ORDER BY t."City" NULLS FIRST +) AS c2 ON c1."City" = c2."City" +ORDER BY c1."City" NULLS FIRST """); } @@ -2390,14 +2390,14 @@ public override async Task GroupBy_select_grouping_composed_list_2(bool async) AssertSql( """ -SELECT t."City", c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" +SELECT c1."City", c0."CustomerID", c0."Address", c0."City", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" FROM ( SELECT c."City" FROM "Customers" AS c GROUP BY c."City" -) AS t -LEFT JOIN "Customers" AS c0 ON t."City" = c0."City" -ORDER BY t."City" NULLS FIRST, c0."CustomerID" NULLS FIRST +) AS c1 +LEFT JOIN "Customers" AS c0 ON c1."City" = c0."City" +ORDER BY c1."City" NULLS FIRST, c0."CustomerID" NULLS FIRST """); } @@ -2416,10 +2416,10 @@ public override async Task Count_after_GroupBy_aggregate(bool async) """ SELECT count(*)::int FROM ( - SELECT o."CustomerID" + SELECT 1 FROM "Orders" AS o GROUP BY o."CustomerID" -) AS t +) AS o0 """); } @@ -2431,10 +2431,10 @@ public override async Task LongCount_after_GroupBy_aggregate(bool async) """ SELECT count(*) FROM ( - SELECT o."CustomerID" + SELECT 1 FROM "Orders" AS o GROUP BY o."CustomerID" -) AS t +) AS o0 """); } @@ -2480,21 +2480,21 @@ public override async Task MinMax_after_GroupBy_aggregate(bool async) AssertSql( """ -SELECT min(t.c) +SELECT min(o0.c) FROM ( SELECT COALESCE(sum(o."OrderID"), 0)::int AS c FROM "Orders" AS o GROUP BY o."CustomerID" -) AS t +) AS o0 """, // """ -SELECT max(t.c) +SELECT max(o0.c) FROM ( SELECT COALESCE(sum(o."OrderID"), 0)::int AS c FROM "Orders" AS o GROUP BY o."CustomerID" -) AS t +) AS o0 """); } @@ -2547,10 +2547,10 @@ public override async Task Count_after_GroupBy_without_aggregate(bool async) """ SELECT count(*)::int FROM ( - SELECT o."CustomerID" + SELECT 1 FROM "Orders" AS o GROUP BY o."CustomerID" -) AS t +) AS o0 """); } @@ -2562,11 +2562,11 @@ public override async Task Count_with_predicate_after_GroupBy_without_aggregate( """ SELECT count(*)::int FROM ( - SELECT o."CustomerID" + SELECT 1 FROM "Orders" AS o GROUP BY o."CustomerID" HAVING count(*)::int > 1 -) AS t +) AS o0 """); } @@ -2578,10 +2578,10 @@ public override async Task LongCount_after_GroupBy_without_aggregate(bool async) """ SELECT count(*) FROM ( - SELECT o."CustomerID" + SELECT 1 FROM "Orders" AS o GROUP BY o."CustomerID" -) AS t +) AS o0 """); } @@ -2593,11 +2593,11 @@ public override async Task LongCount_with_predicate_after_GroupBy_without_aggreg """ SELECT count(*) FROM ( - SELECT o."CustomerID" + SELECT 1 FROM "Orders" AS o GROUP BY o."CustomerID" HAVING count(*)::int > 1 -) AS t +) AS o0 """); } @@ -2648,16 +2648,16 @@ public override async Task GroupBy_aggregate_followed_by_another_GroupBy_aggrega AssertSql( """ -SELECT t0."Key0" AS "Key", COALESCE(sum(t0."Count"), 0)::int AS "Count" +SELECT o1."Key0" AS "Key", COALESCE(sum(o1."Count"), 0)::int AS "Count" FROM ( - SELECT t."Count", 1 AS "Key0" + SELECT o0."Count", 1 AS "Key0" FROM ( SELECT count(*)::int AS "Count" FROM "Orders" AS o GROUP BY o."CustomerID" - ) AS t -) AS t0 -GROUP BY t0."Key0" + ) AS o0 +) AS o1 +GROUP BY o1."Key0" """); } @@ -2673,12 +2673,12 @@ SELECT 1 WHERE o."OrderID" = o0."OrderID" AND o0."ProductID" < 25) AS "HasOrderDetails", ( SELECT count(*)::int FROM ( - SELECT p."ProductName" + SELECT 1 FROM "Order Details" AS o1 INNER JOIN "Products" AS p ON o1."ProductID" = p."ProductID" WHERE o."OrderID" = o1."OrderID" AND o1."ProductID" < 25 GROUP BY p."ProductName" - ) AS t) > 1 AS "HasMultipleProducts" + ) AS s) > 1 AS "HasMultipleProducts" FROM "Orders" AS o WHERE o."OrderDate" IS NOT NULL """); @@ -2692,10 +2692,10 @@ public override async Task GroupBy_nominal_type_count(bool async) """ SELECT count(*)::int FROM ( - SELECT o."CustomerID" + SELECT 1 FROM "Orders" AS o GROUP BY o."CustomerID" -) AS t +) AS o0 """); } @@ -2717,12 +2717,12 @@ public override async Task GroupBy_based_on_renamed_property_complex(bool async) AssertSql( """ -SELECT t."Renamed" AS "Key", count(*)::int AS "Count" +SELECT c0."Renamed" AS "Key", count(*)::int AS "Count" FROM ( SELECT DISTINCT c."City" AS "Renamed", c."CustomerID" FROM "Customers" AS c -) AS t -GROUP BY t."Renamed" +) AS c0 +GROUP BY c0."Renamed" """); } @@ -2746,12 +2746,12 @@ public override async Task Odata_groupby_empty_key(bool async) AssertSql( """ -SELECT 'TotalAmount' AS "Name", COALESCE(sum(t."OrderID"::numeric), 0.0) AS "Value" +SELECT 'TotalAmount' AS "Name", COALESCE(sum(o0."OrderID"::numeric), 0.0) AS "Value" FROM ( SELECT o."OrderID", 1 AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -2837,14 +2837,14 @@ public override async Task GroupBy_with_order_by_skip_and_another_order_by(bool """ @__p_0='80' -SELECT COALESCE(sum(t."OrderID"), 0)::int +SELECT COALESCE(sum(o0."OrderID"), 0)::int FROM ( SELECT o."OrderID", o."CustomerID" FROM "Orders" AS o ORDER BY o."CustomerID" NULLS FIRST, o."OrderID" NULLS FIRST OFFSET @__p_0 -) AS t -GROUP BY t."CustomerID" +) AS o0 +GROUP BY o0."CustomerID" """); } @@ -2941,13 +2941,13 @@ public override async Task GroupBy_aggregate_join_with_grouping_key(bool async) AssertSql( """ -SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", t."Count" +SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", o0."Count" FROM ( SELECT o."CustomerID" AS "Key", count(*)::int AS "Count" FROM "Orders" AS o GROUP BY o."CustomerID" -) AS t -INNER JOIN "Customers" AS c ON t."Key" = c."CustomerID" +) AS o0 +INNER JOIN "Customers" AS c ON o0."Key" = c."CustomerID" """); } @@ -2962,8 +2962,8 @@ public override async Task GroupBy_aggregate_join_with_group_result(bool async) SELECT o."CustomerID" AS "Key", max(o."OrderDate") AS "LastOrderDate" FROM "Orders" AS o GROUP BY o."CustomerID" -) AS t -INNER JOIN "Orders" AS o0 ON (t."Key" = o0."CustomerID" OR (t."Key" IS NULL AND o0."CustomerID" IS NULL)) AND (t."LastOrderDate" = o0."OrderDate" OR (t."LastOrderDate" IS NULL AND o0."OrderDate" IS NULL)) +) AS o1 +INNER JOIN "Orders" AS o0 ON (o1."Key" = o0."CustomerID" OR (o1."Key" IS NULL AND o0."CustomerID" IS NULL)) AND (o1."LastOrderDate" = o0."OrderDate" OR (o1."LastOrderDate" IS NULL AND o0."OrderDate" IS NULL)) """); } @@ -2975,14 +2975,14 @@ public override async Task GroupBy_aggregate_from_right_side_of_join(bool async) """ @__p_0='10' -SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", t."Max" +SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", o0."Max" FROM "Customers" AS c INNER JOIN ( SELECT o."CustomerID" AS "Key", max(o."OrderDate") AS "Max" FROM "Orders" AS o GROUP BY o."CustomerID" -) AS t ON c."CustomerID" = t."Key" -ORDER BY t."Max" NULLS FIRST, c."CustomerID" NULLS FIRST +) AS o0 ON c."CustomerID" = o0."Key" +ORDER BY o0."Max" NULLS FIRST, c."CustomerID" NULLS FIRST LIMIT @__p_0 OFFSET @__p_0 """); } @@ -2993,18 +2993,18 @@ public override async Task GroupBy_aggregate_join_another_GroupBy_aggregate(bool AssertSql( """ -SELECT t."Key", t."Total", t0."ThatYear" +SELECT o1."Key", o1."Total", o2."ThatYear" FROM ( SELECT o."CustomerID" AS "Key", count(*)::int AS "Total" FROM "Orders" AS o GROUP BY o."CustomerID" -) AS t +) AS o1 INNER JOIN ( SELECT o0."CustomerID" AS "Key", count(*)::int AS "ThatYear" FROM "Orders" AS o0 WHERE date_part('year', o0."OrderDate")::int = 1997 GROUP BY o0."CustomerID" -) AS t0 ON t."Key" = t0."Key" +) AS o2 ON o1."Key" = o2."Key" """); } @@ -3016,13 +3016,13 @@ public override async Task GroupBy_aggregate_after_skip_0_take_0(bool async) """ @__p_0='0' -SELECT t."CustomerID" AS "Key", count(*)::int AS "Total" +SELECT o0."CustomerID" AS "Key", count(*)::int AS "Total" FROM ( SELECT o."CustomerID" FROM "Orders" AS o LIMIT @__p_0 OFFSET @__p_0 -) AS t -GROUP BY t."CustomerID" +) AS o0 +GROUP BY o0."CustomerID" """); } @@ -3048,16 +3048,16 @@ public override async Task GroupBy_aggregate_followed_another_GroupBy_aggregate( AssertSql( """ -SELECT t0."CustomerID" AS "Key", count(*)::int AS "Count" +SELECT o1."CustomerID" AS "Key", count(*)::int AS "Count" FROM ( - SELECT t."CustomerID" + SELECT o0."CustomerID" FROM ( SELECT o."CustomerID", date_part('year', o."OrderDate")::int AS "Year" FROM "Orders" AS o - ) AS t - GROUP BY t."CustomerID", t."Year" -) AS t0 -GROUP BY t0."CustomerID" + ) AS o0 + GROUP BY o0."CustomerID", o0."Year" +) AS o1 +GROUP BY o1."CustomerID" """); } @@ -3072,9 +3072,9 @@ public override async Task GroupBy_aggregate_without_selectMany_selecting_first( SELECT min(o."OrderID") AS c FROM "Orders" AS o GROUP BY o."CustomerID" -) AS t +) AS o1 CROSS JOIN "Orders" AS o0 -WHERE o0."OrderID" = t.c +WHERE o0."OrderID" = o1.c """); } @@ -3101,14 +3101,14 @@ public override async Task GroupBy_selecting_grouping_key_list(bool async) AssertSql( """ -SELECT t."CustomerID", o0."CustomerID", o0."OrderID" +SELECT o1."CustomerID", o0."CustomerID", o0."OrderID" FROM ( SELECT o."CustomerID" FROM "Orders" AS o GROUP BY o."CustomerID" -) AS t -LEFT JOIN "Orders" AS o0 ON t."CustomerID" = o0."CustomerID" -ORDER BY t."CustomerID" NULLS FIRST +) AS o1 +LEFT JOIN "Orders" AS o0 ON o1."CustomerID" = o0."CustomerID" +ORDER BY o1."CustomerID" NULLS FIRST """); } @@ -3118,12 +3118,12 @@ public override async Task GroupBy_with_grouping_key_using_Like(bool async) AssertSql( """ -SELECT t."Key", count(*)::int AS "Count" +SELECT o0."Key", count(*)::int AS "Count" FROM ( SELECT o."CustomerID" LIKE 'A%' AND o."CustomerID" IS NOT NULL AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -3133,12 +3133,12 @@ public override async Task GroupBy_with_grouping_key_DateTime_Day(bool async) AssertSql( """ -SELECT t."Key", count(*)::int AS "Count" +SELECT o0."Key", count(*)::int AS "Count" FROM ( SELECT date_part('day', o."OrderDate")::int AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -3160,14 +3160,14 @@ public override async Task Complex_query_with_groupBy_in_subquery1(bool async) AssertSql( """ -SELECT c."CustomerID", t."Sum", t."CustomerID" +SELECT c."CustomerID", o0."Sum", o0."CustomerID" FROM "Customers" AS c LEFT JOIN LATERAL ( SELECT COALESCE(sum(o."OrderID"), 0)::int AS "Sum", o."CustomerID" FROM "Orders" AS o WHERE c."CustomerID" = o."CustomerID" GROUP BY o."CustomerID" -) AS t ON TRUE +) AS o0 ON TRUE ORDER BY c."CustomerID" NULLS FIRST """); } @@ -3178,14 +3178,14 @@ public override async Task Complex_query_with_groupBy_in_subquery2(bool async) AssertSql( """ -SELECT c."CustomerID", t."Max", t."Sum", t."CustomerID" +SELECT c."CustomerID", o0."Max", o0."Sum", o0."CustomerID" FROM "Customers" AS c LEFT JOIN LATERAL ( SELECT max(length(o."CustomerID")::int) AS "Max", COALESCE(sum(o."OrderID"), 0)::int AS "Sum", o."CustomerID" FROM "Orders" AS o WHERE c."CustomerID" = o."CustomerID" GROUP BY o."CustomerID" -) AS t ON TRUE +) AS o0 ON TRUE ORDER BY c."CustomerID" NULLS FIRST """); } @@ -3196,13 +3196,13 @@ public override async Task Complex_query_with_groupBy_in_subquery3(bool async) AssertSql( """ -SELECT c."CustomerID", t."Max", t."Sum", t."CustomerID" +SELECT c."CustomerID", o0."Max", o0."Sum", o0."CustomerID" FROM "Customers" AS c LEFT JOIN LATERAL ( SELECT max(length(o."CustomerID")::int) AS "Max", COALESCE(sum(o."OrderID"), 0)::int AS "Sum", o."CustomerID" FROM "Orders" AS o GROUP BY o."CustomerID" -) AS t ON TRUE +) AS o0 ON TRUE ORDER BY c."CustomerID" NULLS FIRST """); } @@ -3282,7 +3282,7 @@ public override async Task GroupBy_scalar_subquery(bool async) AssertSql( """ -SELECT t."Key", count(*)::int AS "Count" +SELECT o0."Key", count(*)::int AS "Count" FROM ( SELECT ( SELECT c."ContactName" @@ -3290,8 +3290,8 @@ SELECT c."ContactName" WHERE c."CustomerID" = o."CustomerID" LIMIT 1) AS "Key" FROM "Orders" AS o -) AS t -GROUP BY t."Key" +) AS o0 +GROUP BY o0."Key" """); } @@ -3301,28 +3301,28 @@ public override async Task AsEnumerable_in_subquery_for_GroupBy(bool async) AssertSql( """ -SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", t2."OrderID", t2."CustomerID", t2."EmployeeID", t2."OrderDate", t2."CustomerID0" +SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", s."OrderID", s."CustomerID", s."EmployeeID", s."OrderDate", s."CustomerID0" FROM "Customers" AS c LEFT JOIN LATERAL ( - SELECT t0."OrderID", t0."CustomerID", t0."EmployeeID", t0."OrderDate", t."CustomerID" AS "CustomerID0" + SELECT o3."OrderID", o3."CustomerID", o3."EmployeeID", o3."OrderDate", o1."CustomerID" AS "CustomerID0" FROM ( SELECT o."CustomerID" FROM "Orders" AS o WHERE o."CustomerID" = c."CustomerID" GROUP BY o."CustomerID" - ) AS t + ) AS o1 LEFT JOIN ( - SELECT t1."OrderID", t1."CustomerID", t1."EmployeeID", t1."OrderDate" + SELECT o2."OrderID", o2."CustomerID", o2."EmployeeID", o2."OrderDate" FROM ( SELECT o0."OrderID", o0."CustomerID", o0."EmployeeID", o0."OrderDate", ROW_NUMBER() OVER(PARTITION BY o0."CustomerID" ORDER BY o0."OrderDate" DESC NULLS LAST) AS row FROM "Orders" AS o0 WHERE o0."CustomerID" = c."CustomerID" - ) AS t1 - WHERE t1.row <= 1 - ) AS t0 ON t."CustomerID" = t0."CustomerID" -) AS t2 ON TRUE + ) AS o2 + WHERE o2.row <= 1 + ) AS o3 ON o1."CustomerID" = o3."CustomerID" +) AS s ON TRUE WHERE c."CustomerID" LIKE 'F%' -ORDER BY c."CustomerID" NULLS FIRST, t2."CustomerID0" NULLS FIRST +ORDER BY c."CustomerID" NULLS FIRST, s."CustomerID0" NULLS FIRST """); } @@ -3414,24 +3414,24 @@ public override async Task Select_uncorrelated_collection_with_groupby_when_oute AssertSql( """ -SELECT t."City", t0."ProductID", t1.c, t1."ProductID" +SELECT s."City", p1."ProductID", p2.c, p2."ProductID" FROM ( SELECT DISTINCT c."City" FROM "Orders" AS o LEFT JOIN "Customers" AS c ON o."CustomerID" = c."CustomerID" WHERE o."CustomerID" LIKE 'A%' -) AS t +) AS s LEFT JOIN LATERAL ( SELECT p."ProductID" FROM "Products" AS p GROUP BY p."ProductID" -) AS t0 ON TRUE +) AS p1 ON TRUE LEFT JOIN LATERAL ( SELECT count(*)::int AS c, p0."ProductID" FROM "Products" AS p0 GROUP BY p0."ProductID" -) AS t1 ON TRUE -ORDER BY t."City" NULLS FIRST, t0."ProductID" NULLS FIRST +) AS p2 ON TRUE +ORDER BY s."City" NULLS FIRST, p1."ProductID" NULLS FIRST """); } @@ -3441,15 +3441,15 @@ public override async Task Select_correlated_collection_after_GroupBy_aggregate_ AssertSql( """ -SELECT t."CustomerID", o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate" +SELECT c0."CustomerID", o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate" FROM ( SELECT c."CustomerID" FROM "Customers" AS c GROUP BY c."CustomerID" HAVING c."CustomerID" LIKE 'F%' -) AS t -LEFT JOIN "Orders" AS o ON t."CustomerID" = o."CustomerID" -ORDER BY t."CustomerID" NULLS FIRST +) AS c0 +LEFT JOIN "Orders" AS o ON c0."CustomerID" = o."CustomerID" +ORDER BY c0."CustomerID" NULLS FIRST """); } @@ -3459,15 +3459,15 @@ public override async Task Select_correlated_collection_after_GroupBy_aggregate_ AssertSql( """ -SELECT t."CustomerID", o0."OrderID", o0."CustomerID", o0."EmployeeID", o0."OrderDate" +SELECT o1."CustomerID", o0."OrderID", o0."CustomerID", o0."EmployeeID", o0."OrderDate" FROM ( SELECT o."CustomerID" FROM "Orders" AS o GROUP BY o."CustomerID" HAVING o."CustomerID" LIKE 'F%' -) AS t -LEFT JOIN "Orders" AS o0 ON t."CustomerID" = o0."CustomerID" -ORDER BY t."CustomerID" NULLS FIRST +) AS o1 +LEFT JOIN "Orders" AS o0 ON o1."CustomerID" = o0."CustomerID" +ORDER BY o1."CustomerID" NULLS FIRST """); } @@ -3481,7 +3481,7 @@ public override async Task Complex_query_with_group_by_in_subquery5(bool async) AssertSql( """ -SELECT t.c, t."ProductID", t0."CustomerID", t0."City" +SELECT s.c, s."ProductID", c1."CustomerID", c1."City" FROM ( SELECT COALESCE(sum(o."ProductID" + o."OrderID" * 1000), 0)::int AS c, o."ProductID", min(o."OrderID" / 100) AS c0 FROM "Order Details" AS o @@ -3489,13 +3489,13 @@ SELECT COALESCE(sum(o."ProductID" + o."OrderID" * 1000), 0)::int AS c, o."Produc LEFT JOIN "Customers" AS c ON o0."CustomerID" = c."CustomerID" WHERE c."CustomerID" = 'ALFKI' GROUP BY o."ProductID" -) AS t +) AS s LEFT JOIN LATERAL ( SELECT c0."CustomerID", c0."City" FROM "Customers" AS c0 - WHERE length(c0."CustomerID")::int < t.c0 -) AS t0 ON TRUE -ORDER BY t."ProductID" NULLS FIRST, t0."CustomerID" NULLS FIRST + WHERE length(c0."CustomerID")::int < s.c0 +) AS c1 ON TRUE +ORDER BY s."ProductID" NULLS FIRST, c1."CustomerID" NULLS FIRST """); } @@ -3505,27 +3505,27 @@ public override async Task Complex_query_with_groupBy_in_subquery4(bool async) AssertSql( """ -SELECT c."CustomerID", t1."Sum", t1."Count", t1."Key" +SELECT c."CustomerID", s1."Sum", s1."Count", s1."Key" FROM "Customers" AS c LEFT JOIN LATERAL ( - SELECT COALESCE(sum(t."OrderID"), 0)::int AS "Sum", ( + SELECT COALESCE(sum(s."OrderID"), 0)::int AS "Sum", ( SELECT count(*)::int FROM ( - SELECT o0."OrderID", o0."CustomerID", o0."EmployeeID", o0."OrderDate", c1."CustomerID" AS "CustomerID0", c1."Address", c1."City", c1."CompanyName", c1."ContactName", c1."ContactTitle", c1."Country", c1."Fax", c1."Phone", c1."PostalCode", c1."Region", COALESCE(c1."City", '') || COALESCE(o0."CustomerID", '') AS "Key" + SELECT o0."CustomerID", COALESCE(c1."City", '') || COALESCE(o0."CustomerID", '') AS "Key" FROM "Orders" AS o0 LEFT JOIN "Customers" AS c1 ON o0."CustomerID" = c1."CustomerID" WHERE c."CustomerID" = o0."CustomerID" - ) AS t0 - LEFT JOIN "Customers" AS c0 ON t0."CustomerID" = c0."CustomerID" - WHERE (t."Key" = t0."Key" OR (t."Key" IS NULL AND t0."Key" IS NULL)) AND COALESCE(c0."City", '') || COALESCE(t0."CustomerID", '') LIKE 'Lon%') AS "Count", t."Key" + ) AS s0 + LEFT JOIN "Customers" AS c2 ON s0."CustomerID" = c2."CustomerID" + WHERE (s."Key" = s0."Key" OR (s."Key" IS NULL AND s0."Key" IS NULL)) AND COALESCE(c2."City", '') || COALESCE(s0."CustomerID", '') LIKE 'Lon%') AS "Count", s."Key" FROM ( - SELECT o."OrderID", COALESCE(c2."City", '') || COALESCE(o."CustomerID", '') AS "Key" + SELECT o."OrderID", COALESCE(c0."City", '') || COALESCE(o."CustomerID", '') AS "Key" FROM "Orders" AS o - LEFT JOIN "Customers" AS c2 ON o."CustomerID" = c2."CustomerID" + LEFT JOIN "Customers" AS c0 ON o."CustomerID" = c0."CustomerID" WHERE c."CustomerID" = o."CustomerID" - ) AS t - GROUP BY t."Key" -) AS t1 ON TRUE + ) AS s + GROUP BY s."Key" +) AS s1 ON TRUE ORDER BY c."CustomerID" NULLS FIRST """); } @@ -3606,12 +3606,12 @@ public override async Task Final_GroupBy_complex_key_entity(bool async) AssertSql( """ -SELECT t."City", t."Region", t."Constant", t."CustomerID", t."Address", t."CompanyName", t."ContactName", t."ContactTitle", t."Country", t."Fax", t."Phone", t."PostalCode" +SELECT c0."City", c0."Region", c0."Constant", c0."CustomerID", c0."Address", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode" FROM ( SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", 1 AS "Constant" FROM "Customers" AS c -) AS t -ORDER BY t."City" NULLS FIRST, t."Region" NULLS FIRST, t."Constant" NULLS FIRST +) AS c0 +ORDER BY c0."City" NULLS FIRST, c0."Region" NULLS FIRST, c0."Constant" NULLS FIRST """); } @@ -3621,12 +3621,12 @@ public override async Task Final_GroupBy_nominal_type_entity(bool async) AssertSql( """ -SELECT t."City", t."Constant", t."CustomerID", t."Address", t."CompanyName", t."ContactName", t."ContactTitle", t."Country", t."Fax", t."Phone", t."PostalCode", t."Region" +SELECT c0."City", c0."Constant", c0."CustomerID", c0."Address", c0."CompanyName", c0."ContactName", c0."ContactTitle", c0."Country", c0."Fax", c0."Phone", c0."PostalCode", c0."Region" FROM ( SELECT c."CustomerID", c."Address", c."City", c."CompanyName", c."ContactName", c."ContactTitle", c."Country", c."Fax", c."Phone", c."PostalCode", c."Region", 1 AS "Constant" FROM "Customers" AS c -) AS t -ORDER BY t."City" NULLS FIRST, t."Constant" NULLS FIRST +) AS c0 +ORDER BY c0."City" NULLS FIRST, c0."Constant" NULLS FIRST """); } @@ -3676,13 +3676,13 @@ public override async Task Final_GroupBy_property_entity_projecting_collection_c AssertSql( """ -SELECT c."City", c."CustomerID", t."OrderID", t."CustomerID", t."EmployeeID", t."OrderDate" +SELECT c."City", c."CustomerID", o0."OrderID", o0."CustomerID", o0."EmployeeID", o0."OrderDate" FROM "Customers" AS c LEFT JOIN ( SELECT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate" FROM "Orders" AS o WHERE o."OrderID" < 11000 -) AS t ON c."CustomerID" = t."CustomerID" +) AS o0 ON c."CustomerID" = o0."CustomerID" WHERE c."Country" = 'USA' ORDER BY c."City" NULLS FIRST, c."CustomerID" NULLS FIRST """); @@ -3694,21 +3694,21 @@ public override async Task Final_GroupBy_property_entity_projecting_collection_a AssertSql( """ -SELECT c."City", c."CustomerID", t."OrderID", t."CustomerID", t."EmployeeID", t."OrderDate", t0."OrderID", t0."CustomerID", t0."EmployeeID", t0."OrderDate" +SELECT c."City", c."CustomerID", o1."OrderID", o1."CustomerID", o1."EmployeeID", o1."OrderDate", o3."OrderID", o3."CustomerID", o3."EmployeeID", o3."OrderDate" FROM "Customers" AS c LEFT JOIN ( SELECT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate" FROM "Orders" AS o WHERE o."OrderID" < 11000 -) AS t ON c."CustomerID" = t."CustomerID" +) AS o1 ON c."CustomerID" = o1."CustomerID" LEFT JOIN ( - SELECT t1."OrderID", t1."CustomerID", t1."EmployeeID", t1."OrderDate" + SELECT o2."OrderID", o2."CustomerID", o2."EmployeeID", o2."OrderDate" FROM ( SELECT o0."OrderID", o0."CustomerID", o0."EmployeeID", o0."OrderDate", ROW_NUMBER() OVER(PARTITION BY o0."CustomerID" ORDER BY o0."OrderDate" DESC NULLS LAST) AS row FROM "Orders" AS o0 - ) AS t1 - WHERE t1.row <= 1 -) AS t0 ON c."CustomerID" = t0."CustomerID" + ) AS o2 + WHERE o2.row <= 1 +) AS o3 ON c."CustomerID" = o3."CustomerID" WHERE c."Country" = 'USA' ORDER BY c."City" NULLS FIRST, c."CustomerID" NULLS FIRST """); @@ -3769,29 +3769,29 @@ public override async Task GroupBy_complex_key_without_aggregate(bool async) AssertSql( """ -SELECT t0."Key", t1."OrderID", t1."CustomerID", t1."EmployeeID", t1."OrderDate", t1."CustomerID0" +SELECT s1."Key", s3."OrderID", s3."CustomerID", s3."EmployeeID", s3."OrderDate", s3."CustomerID0" FROM ( - SELECT t."Key" + SELECT s."Key" FROM ( SELECT substring(c."CustomerID", 1, 1) AS "Key" FROM "Orders" AS o LEFT JOIN "Customers" AS c ON o."CustomerID" = c."CustomerID" - ) AS t - GROUP BY t."Key" -) AS t0 + ) AS s + GROUP BY s."Key" +) AS s1 LEFT JOIN ( - SELECT t2."OrderID", t2."CustomerID", t2."EmployeeID", t2."OrderDate", t2."CustomerID0", t2."Key" + SELECT s2."OrderID", s2."CustomerID", s2."EmployeeID", s2."OrderDate", s2."CustomerID0", s2."Key" FROM ( - SELECT t3."OrderID", t3."CustomerID", t3."EmployeeID", t3."OrderDate", t3."CustomerID0", t3."Key", ROW_NUMBER() OVER(PARTITION BY t3."Key" ORDER BY t3."OrderID" NULLS FIRST, t3."CustomerID0" NULLS FIRST) AS row + SELECT s0."OrderID", s0."CustomerID", s0."EmployeeID", s0."OrderDate", s0."CustomerID0", s0."Key", ROW_NUMBER() OVER(PARTITION BY s0."Key" ORDER BY s0."OrderID" NULLS FIRST, s0."CustomerID0" NULLS FIRST) AS row FROM ( SELECT o0."OrderID", o0."CustomerID", o0."EmployeeID", o0."OrderDate", c0."CustomerID" AS "CustomerID0", substring(c0."CustomerID", 1, 1) AS "Key" FROM "Orders" AS o0 LEFT JOIN "Customers" AS c0 ON o0."CustomerID" = c0."CustomerID" - ) AS t3 - ) AS t2 - WHERE 1 < t2.row AND t2.row <= 3 -) AS t1 ON t0."Key" = t1."Key" -ORDER BY t0."Key" NULLS FIRST, t1."OrderID" NULLS FIRST + ) AS s0 + ) AS s2 + WHERE 1 < s2.row AND s2.row <= 3 +) AS s3 ON s1."Key" = s3."Key" +ORDER BY s1."Key" NULLS FIRST, s3."OrderID" NULLS FIRST """); } diff --git a/test/EFCore.PG.FunctionalTests/Query/NorthwindMiscellaneousQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/NorthwindMiscellaneousQueryNpgsqlTest.cs index 6fec39611..188c1a88a 100644 --- a/test/EFCore.PG.FunctionalTests/Query/NorthwindMiscellaneousQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/NorthwindMiscellaneousQueryNpgsqlTest.cs @@ -188,14 +188,14 @@ await Assert.ThrowsAsync( AssertSql( """ -SELECT t."CustomerID", o0."OrderID", o0."CustomerID", o0."EmployeeID", o0."OrderDate" +SELECT o0."CustomerID", o1."OrderID", o1."CustomerID", o1."EmployeeID", o1."OrderDate" FROM ( SELECT DISTINCT o."CustomerID" FROM "Orders" AS o WHERE o."OrderID" < 10300 -) AS t -LEFT JOIN "Orders" AS o0 ON t."CustomerID" = o0."CustomerID" -ORDER BY t."CustomerID" NULLS FIRST +) AS o0 +LEFT JOIN "Orders" AS o1 ON o0."CustomerID" = o1."CustomerID" +ORDER BY o0."CustomerID" NULLS FIRST """); } diff --git a/test/EFCore.PG.FunctionalTests/Query/NorthwindSetOperationsQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/NorthwindSetOperationsQueryNpgsqlTest.cs index 543082d04..316ffb4a9 100644 --- a/test/EFCore.PG.FunctionalTests/Query/NorthwindSetOperationsQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/NorthwindSetOperationsQueryNpgsqlTest.cs @@ -135,7 +135,7 @@ await AssertQuery( AssertSql( """ -SELECT t0."OrderID", t0."CustomerID" +SELECT u0."OrderID", u0."CustomerID" FROM ( SELECT NULL::int AS "OrderID", o."CustomerID" FROM "Orders" AS o @@ -145,9 +145,9 @@ await AssertQuery( UNION SELECT o1."OrderID", o1."CustomerID" FROM "Orders" AS o1 -) AS t0 -WHERE t0."CustomerID" = ( - SELECT t1."CustomerID" +) AS u0 +WHERE u0."CustomerID" = ( + SELECT u2."CustomerID" FROM ( SELECT NULL::int AS "OrderID", o2."CustomerID" FROM "Orders" AS o2 @@ -157,10 +157,10 @@ SELECT t1."CustomerID" UNION SELECT o4."OrderID", o4."CustomerID" FROM "Orders" AS o4 - ) AS t1 - ORDER BY t1."CustomerID" NULLS FIRST - LIMIT 1) OR (t0."CustomerID" IS NULL AND ( - SELECT t1."CustomerID" + ) AS u2 + ORDER BY u2."CustomerID" NULLS FIRST + LIMIT 1) OR (u0."CustomerID" IS NULL AND ( + SELECT u2."CustomerID" FROM ( SELECT NULL::int AS "OrderID", o2."CustomerID" FROM "Orders" AS o2 @@ -170,8 +170,8 @@ SELECT t1."CustomerID" UNION SELECT o4."OrderID", o4."CustomerID" FROM "Orders" AS o4 - ) AS t1 - ORDER BY t1."CustomerID" NULLS FIRST + ) AS u2 + ORDER BY u2."CustomerID" NULLS FIRST LIMIT 1) IS NULL) """); } diff --git a/test/EFCore.PG.FunctionalTests/Query/NorthwindSqlQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/NorthwindSqlQueryNpgsqlTest.cs index 122773d93..d9f1bdd92 100644 --- a/test/EFCore.PG.FunctionalTests/Query/NorthwindSqlQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/NorthwindSqlQueryNpgsqlTest.cs @@ -29,10 +29,10 @@ public override async Task SqlQuery_composed_Contains(bool async) SELECT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate" FROM "Orders" AS o WHERE o."OrderID" IN ( - SELECT t."Value" + SELECT s."Value" FROM ( SELECT "ProductID" AS "Value" FROM "Products" - ) AS t + ) AS s ) """); } @@ -43,11 +43,11 @@ public override async Task SqlQuery_composed_Join(bool async) AssertSql( """ -SELECT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate", t."Value"::int AS p +SELECT o."OrderID", o."CustomerID", o."EmployeeID", o."OrderDate", s."Value"::int AS p FROM "Orders" AS o INNER JOIN ( SELECT "ProductID" AS "Value" FROM "Products" -) AS t ON o."OrderID" = t."Value"::int +) AS s ON o."OrderID" = s."Value"::int """); } diff --git a/test/EFCore.PG.FunctionalTests/Query/PrimitiveCollectionsQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/PrimitiveCollectionsQueryNpgsqlTest.cs index 7700cb224..145973cee 100644 --- a/test/EFCore.PG.FunctionalTests/Query/PrimitiveCollectionsQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/PrimitiveCollectionsQueryNpgsqlTest.cs @@ -48,10 +48,12 @@ public override async Task Inline_collection_of_nullable_ints_Contains_null(bool """); } - public override Task Inline_collection_Count_with_zero_values(bool async) - => AssertTranslationFailedWithDetails( - () => base.Inline_collection_Count_with_zero_values(async), - RelationalStrings.EmptyCollectionNotSupportedAsInlineQueryRoot); + public override async Task Inline_collection_Count_with_zero_values(bool async) + { + await base.Inline_collection_Count_with_zero_values(async); + + AssertSql(); + } public override async Task Inline_collection_Count_with_one_value(bool async) { @@ -98,10 +100,17 @@ SELECT count(*)::int """); } - public override Task Inline_collection_Contains_with_zero_values(bool async) - => AssertTranslationFailedWithDetails( - () => base.Inline_collection_Contains_with_zero_values(async), - RelationalStrings.EmptyCollectionNotSupportedAsInlineQueryRoot); + public override async Task Inline_collection_Contains_with_zero_values(bool async) + { + await base.Inline_collection_Contains_with_zero_values(async); + + AssertSql( + """ +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE FALSE +"""); + } public override async Task Inline_collection_Contains_with_one_value(bool async) { @@ -139,6 +148,18 @@ public override async Task Inline_collection_Contains_with_three_values(bool asy """); } + public override async Task Inline_collection_Contains_with_EF_Constant(bool async) + { + await base.Inline_collection_Contains_with_EF_Constant(async); + + AssertSql( + """ +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE p."Id" IN (2, 999, 1000) +"""); + } + public override async Task Inline_collection_Contains_with_all_parameters(bool async) { await base.Inline_collection_Contains_with_all_parameters(async); @@ -206,6 +227,58 @@ public override async Task Inline_collection_negated_Contains_as_All(bool async) """); } + public override async Task Inline_collection_Min_with_two_values(bool async) + { + await base.Inline_collection_Min_with_two_values(async); + + AssertSql( + """ +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE LEAST(30, p."Int") = 30 +"""); + } + + public override async Task Inline_collection_Max_with_two_values(bool async) + { + await base.Inline_collection_Max_with_two_values(async); + + AssertSql( + """ +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE GREATEST(30, p."Int") = 30 +"""); + } + + public override async Task Inline_collection_Min_with_three_values(bool async) + { + await base.Inline_collection_Min_with_three_values(async); + + AssertSql( + """ +@__i_0='25' + +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE LEAST(30, p."Int", @__i_0) = 25 +"""); + } + + public override async Task Inline_collection_Max_with_three_values(bool async) + { + await base.Inline_collection_Max_with_three_values(async); + + AssertSql( + """ +@__i_0='35' + +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE GREATEST(30, p."Int", @__i_0) = 35 +"""); + } + public override async Task Parameter_collection_Count(bool async) { await base.Parameter_collection_Count(async); @@ -223,9 +296,9 @@ FROM unnest(@__ids_0) AS i(value) """); } - public override async Task Parameter_collection_of_ints_Contains(bool async) + public override async Task Parameter_collection_of_ints_Contains_int(bool async) { - await base.Parameter_collection_of_ints_Contains(async); + await base.Parameter_collection_of_ints_Contains_int(async); AssertSql( """ @@ -234,6 +307,36 @@ public override async Task Parameter_collection_of_ints_Contains(bool async) SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" FROM "PrimitiveCollectionsEntity" AS p WHERE p."Int" = ANY (@__ints_0) +""", + // + """ +@__ints_0={ '10', '999' } (DbType = Object) + +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE NOT (p."Int" = ANY (@__ints_0) AND p."Int" = ANY (@__ints_0) IS NOT NULL) +"""); + } + + public override async Task Parameter_collection_of_ints_Contains_nullable_int(bool async) + { + await base.Parameter_collection_of_ints_Contains_nullable_int(async); + + AssertSql( + """ +@__ints_0={ '10', '999' } (DbType = Object) + +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE p."NullableInt" = ANY (@__ints_0) OR (p."NullableInt" IS NULL AND array_position(@__ints_0, NULL) IS NOT NULL) +""", + // + """ +@__ints_0={ '10', '999' } (DbType = Object) + +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE NOT (p."NullableInt" = ANY (@__ints_0) AND p."NullableInt" = ANY (@__ints_0) IS NOT NULL) AND (p."NullableInt" IS NOT NULL OR array_position(@__ints_0, NULL) IS NULL) """); } @@ -248,6 +351,14 @@ public override async Task Parameter_collection_of_nullable_ints_Contains_int(bo SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" FROM "PrimitiveCollectionsEntity" AS p WHERE p."Int" = ANY (@__nullableInts_0) +""", + // + """ +@__nullableInts_0={ '10', '999' } (DbType = Object) + +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE NOT (p."Int" = ANY (@__nullableInts_0) AND p."Int" = ANY (@__nullableInts_0) IS NOT NULL) """); } @@ -262,6 +373,36 @@ public override async Task Parameter_collection_of_nullable_ints_Contains_nullab SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" FROM "PrimitiveCollectionsEntity" AS p WHERE p."NullableInt" = ANY (@__nullableInts_0) OR (p."NullableInt" IS NULL AND array_position(@__nullableInts_0, NULL) IS NOT NULL) +""", + // + """ +@__nullableInts_0={ NULL, '999' } (DbType = Object) + +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE NOT (p."NullableInt" = ANY (@__nullableInts_0) AND p."NullableInt" = ANY (@__nullableInts_0) IS NOT NULL) AND (p."NullableInt" IS NOT NULL OR array_position(@__nullableInts_0, NULL) IS NULL) +"""); + } + + public override async Task Parameter_collection_of_strings_Contains_string(bool async) + { + await base.Parameter_collection_of_strings_Contains_string(async); + + AssertSql( + """ +@__strings_0={ '10', '999' } (DbType = Object) + +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE p."String" = ANY (@__strings_0) +""", + // + """ +@__strings_0={ '10', '999' } (DbType = Object) + +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE NOT (p."String" = ANY (@__strings_0) AND p."String" = ANY (@__strings_0) IS NOT NULL) """); } @@ -271,25 +412,63 @@ public override async Task Parameter_collection_of_strings_Contains_nullable_str AssertSql( """ -@__strings_0={ '999', NULL } (DbType = Object) +@__strings_0={ '10', '999' } (DbType = Object) SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" FROM "PrimitiveCollectionsEntity" AS p WHERE p."NullableString" = ANY (@__strings_0) OR (p."NullableString" IS NULL AND array_position(@__strings_0, NULL) IS NOT NULL) +""", + // + """ +@__strings_0={ '10', '999' } (DbType = Object) + +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE NOT (p."NullableString" = ANY (@__strings_0) AND p."NullableString" = ANY (@__strings_0) IS NOT NULL) AND (p."NullableString" IS NOT NULL OR array_position(@__strings_0, NULL) IS NULL) """); } - public override async Task Parameter_collection_of_strings_Contains_non_nullable_string(bool async) + public override async Task Parameter_collection_of_nullable_strings_Contains_string(bool async) { - await base.Parameter_collection_of_strings_Contains_non_nullable_string(async); + await base.Parameter_collection_of_nullable_strings_Contains_string(async); AssertSql( """ -@__strings_0={ '10', '999' } (DbType = Object) +@__strings_0={ '10', NULL } (DbType = Object) SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" FROM "PrimitiveCollectionsEntity" AS p WHERE p."String" = ANY (@__strings_0) +""", + // + """ +@__strings_0={ '10', NULL } (DbType = Object) + +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE NOT (p."String" = ANY (@__strings_0) AND p."String" = ANY (@__strings_0) IS NOT NULL) +"""); + } + + public override async Task Parameter_collection_of_nullable_strings_Contains_nullable_string(bool async) + { + await base.Parameter_collection_of_nullable_strings_Contains_nullable_string(async); + + AssertSql( + """ +@__strings_0={ '999', NULL } (DbType = Object) + +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE p."NullableString" = ANY (@__strings_0) OR (p."NullableString" IS NULL AND array_position(@__strings_0, NULL) IS NOT NULL) +""", + // + """ +@__strings_0={ '999', NULL } (DbType = Object) + +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE NOT (p."NullableString" = ANY (@__strings_0) AND p."NullableString" = ANY (@__strings_0) IS NOT NULL) AND (p."NullableString" IS NOT NULL OR array_position(@__strings_0, NULL) IS NULL) """); } @@ -674,7 +853,19 @@ SELECT count(*)::int FROM ( SELECT DISTINCT i.value FROM unnest(p."Ints") AS i(value) - ) AS t) = 3 + ) AS i0) = 3 +"""); + } + + public override async Task Column_collection_SelectMany(bool async) + { + await base.Column_collection_SelectMany(async); + + AssertSql( + """ +SELECT i.value +FROM "PrimitiveCollectionsEntity" AS p +JOIN LATERAL unnest(p."Ints") AS i(value) ON TRUE """); } @@ -754,7 +945,7 @@ FROM unnest(p."Ints") AS i(value) UNION SELECT i0.value FROM unnest(@__ints_0) AS i0(value) - ) AS t) = 2 + ) AS u) = 2 """); } @@ -773,7 +964,7 @@ SELECT i.value FROM unnest(p."Ints") AS i(value) INTERSECT VALUES (11::int), (111) - ) AS t) = 2 + ) AS i0) = 2 """); } @@ -813,8 +1004,8 @@ SELECT v."Value" EXCEPT SELECT i.value AS "Value" FROM unnest(p."Ints") AS i(value) - ) AS t - WHERE t."Value" % 2 = 1) = 2 + ) AS e + WHERE e."Value" % 2 = 1) = 2 """); } @@ -911,7 +1102,7 @@ FROM unnest(@__ints[2:]) AS i(value) UNION SELECT i0.value FROM unnest(p."Ints") AS i0(value) - ) AS t) = 3 + ) AS u) = 3 """); } @@ -933,7 +1124,7 @@ FROM unnest(@__Skip_0) AS s(value) UNION SELECT i.value FROM unnest(p."Ints") AS i(value) - ) AS t) = 3 + ) AS u) = 3 """); } @@ -953,22 +1144,22 @@ SELECT count(*)::int SELECT s.value FROM unnest(@__Skip_0) AS s(value) UNION - SELECT t1.value + SELECT i2.value FROM ( - SELECT t0.value + SELECT i1.value FROM ( - SELECT DISTINCT t2.value + SELECT DISTINCT i0.value FROM ( - SELECT i.value, i.ordinality - FROM unnest(p."Ints") WITH ORDINALITY AS i(value) + SELECT i.value + FROM unnest(p."Ints") AS i(value) ORDER BY i.value NULLS FIRST OFFSET 1 - ) AS t2 - ) AS t0 - ORDER BY t0.value DESC NULLS LAST + ) AS i0 + ) AS i1 + ORDER BY i1.value DESC NULLS LAST LIMIT 20 - ) AS t1 - ) AS t) = 3 + ) AS i2 + ) AS u) = 3 """); } @@ -1021,7 +1212,7 @@ FROM unnest(p."Ints"[2:]) AS i(value) UNION SELECT i0.value FROM unnest(@__ints_0) AS i0(value) - ) AS t) = 3 + ) AS u) = 3 """); } @@ -1056,13 +1247,13 @@ public override async Task Project_collection_of_datetimes_filtered(bool async) AssertSql( """ -SELECT p."Id", t.value, t.ordinality +SELECT p."Id", d0.value, d0.ordinality FROM "PrimitiveCollectionsEntity" AS p LEFT JOIN LATERAL ( SELECT d.value, d.ordinality FROM unnest(p."DateTimes") WITH ORDINALITY AS d(value) WHERE date_part('day', d.value AT TIME ZONE 'UTC')::int <> 1 OR d.value AT TIME ZONE 'UTC' IS NULL -) AS t ON TRUE +) AS d0 ON TRUE ORDER BY p."Id" NULLS FIRST """); } @@ -1086,15 +1277,15 @@ public override async Task Project_collection_of_nullable_ints_with_paging2(bool AssertSql( """ -SELECT p."Id", t.value, t.ordinality +SELECT p."Id", n0.value, n0.ordinality FROM "PrimitiveCollectionsEntity" AS p LEFT JOIN LATERAL ( SELECT n.value, n.ordinality FROM unnest(p."NullableInts") WITH ORDINALITY AS n(value) ORDER BY n.value NULLS FIRST OFFSET 1 -) AS t ON TRUE -ORDER BY p."Id" NULLS FIRST, t.value NULLS FIRST +) AS n0 ON TRUE +ORDER BY p."Id" NULLS FIRST, n0.value NULLS FIRST """); } @@ -1117,12 +1308,12 @@ public override async Task Project_collection_of_ints_with_distinct(bool async) AssertSql( """ -SELECT p."Id", t.value +SELECT p."Id", i0.value FROM "PrimitiveCollectionsEntity" AS p LEFT JOIN LATERAL ( SELECT DISTINCT i.value - FROM unnest(p."Ints") AS i(value) -) AS t ON TRUE + FROM unnest(p."Ints") WITH ORDINALITY AS i(value) +) AS i0 ON TRUE ORDER BY p."Id" NULLS FIRST """); } @@ -1134,25 +1325,43 @@ public override async Task Project_collection_of_nullable_ints_with_distinct(boo AssertSql(); } + public override async Task Project_collection_of_ints_with_ToList_and_FirstOrDefault(bool async) + { + await base.Project_collection_of_ints_with_ToList_and_FirstOrDefault(async); + + AssertSql( + """ +SELECT p0."Id", i.value, i.ordinality +FROM ( + SELECT p."Id", p."Ints" + FROM "PrimitiveCollectionsEntity" AS p + ORDER BY p."Id" NULLS FIRST + LIMIT 1 +) AS p0 +LEFT JOIN LATERAL unnest(p0."Ints") WITH ORDINALITY AS i(value) ON TRUE +ORDER BY p0."Id" NULLS FIRST +"""); + } + public override async Task Project_empty_collection_of_nullables_and_collection_only_containing_nulls(bool async) { await base.Project_empty_collection_of_nullables_and_collection_only_containing_nulls(async); AssertSql( """ -SELECT p."Id", t.value, t.ordinality, t0.value, t0.ordinality +SELECT p."Id", n1.value, n1.ordinality, n2.value, n2.ordinality FROM "PrimitiveCollectionsEntity" AS p LEFT JOIN LATERAL ( SELECT n.value, n.ordinality FROM unnest(p."NullableInts") WITH ORDINALITY AS n(value) WHERE FALSE -) AS t ON TRUE +) AS n1 ON TRUE LEFT JOIN LATERAL ( SELECT n0.value, n0.ordinality FROM unnest(p."NullableInts") WITH ORDINALITY AS n0(value) WHERE n0.value IS NULL -) AS t0 ON TRUE -ORDER BY p."Id" NULLS FIRST, t.ordinality NULLS FIRST +) AS n2 ON TRUE +ORDER BY p."Id" NULLS FIRST, n1.ordinality NULLS FIRST """); } @@ -1180,7 +1389,7 @@ await AssertQuery( AssertSql( """ -SELECT p."Id", i.value, i.ordinality, i0.value, i0.ordinality, t.value, t.ordinality, t0.value, t0.ordinality +SELECT p."Id", i.value, i.ordinality, i0.value, i0.ordinality, d1.value, d1.ordinality, d2.value, d2.ordinality FROM "PrimitiveCollectionsEntity" AS p LEFT JOIN LATERAL unnest(p."Ints") WITH ORDINALITY AS i(value) ON TRUE LEFT JOIN LATERAL unnest(p."Ints") WITH ORDINALITY AS i0(value) ON TRUE @@ -1188,13 +1397,13 @@ LEFT JOIN LATERAL ( SELECT d.value, d.ordinality FROM unnest(p."DateTimes") WITH ORDINALITY AS d(value) WHERE date_part('day', d.value AT TIME ZONE 'UTC')::int <> 1 OR d.value AT TIME ZONE 'UTC' IS NULL -) AS t ON TRUE +) AS d1 ON TRUE LEFT JOIN LATERAL ( SELECT d0.value, d0.ordinality FROM unnest(p."DateTimes") WITH ORDINALITY AS d0(value) WHERE d0.value > TIMESTAMPTZ '2000-01-01T00:00:00Z' -) AS t0 ON TRUE -ORDER BY p."Id" NULLS FIRST, i.ordinality NULLS FIRST, i0.value DESC NULLS LAST, i0.ordinality NULLS FIRST, t.ordinality NULLS FIRST +) AS d2 ON TRUE +ORDER BY p."Id" NULLS FIRST, i.ordinality NULLS FIRST, i0.value DESC NULLS LAST, i0.ordinality NULLS FIRST, d1.ordinality NULLS FIRST """); } @@ -1211,6 +1420,42 @@ ORDER BY p."Id" NULLS FIRST """); } + public override async Task Nested_contains_with_Lists_and_no_inferred_type_mapping(bool async) + { + await base.Nested_contains_with_Lists_and_no_inferred_type_mapping(async); + + AssertSql( + """ +@__ints_1={ '1', '2', '3' } (DbType = Object) +@__strings_0={ 'one', 'two', 'three' } (DbType = Object) + +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE CASE + WHEN p."Int" = ANY (@__ints_1) THEN 'one' + ELSE 'two' +END = ANY (@__strings_0) +"""); + } + + public override async Task Nested_contains_with_arrays_and_no_inferred_type_mapping(bool async) + { + await base.Nested_contains_with_arrays_and_no_inferred_type_mapping(async); + + AssertSql( + """ +@__ints_1={ '1', '2', '3' } (DbType = Object) +@__strings_0={ 'one', 'two', 'three' } (DbType = Object) + +SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings" +FROM "PrimitiveCollectionsEntity" AS p +WHERE CASE + WHEN p."Int" = ANY (@__ints_1) THEN 'one' + ELSE 'two' +END = ANY (@__strings_0) +"""); + } + [ConditionalFact] public virtual void Check_all_tests_overridden() => TestHelpers.AssertAllMethodsOverridden(GetType()); diff --git a/test/EFCore.PG.FunctionalTests/Query/RangeQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/RangeQueryNpgsqlTest.cs index 764a1a636..7021a6497 100644 --- a/test/EFCore.PG.FunctionalTests/Query/RangeQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/RangeQueryNpgsqlTest.cs @@ -263,13 +263,13 @@ public void Union_aggregate() AssertSql( """ -SELECT range_agg(t."IntRange") +SELECT range_agg(r0."IntRange") FROM ( SELECT r."IntRange", TRUE AS "Key" FROM "RangeTestEntities" AS r WHERE r."Id" IN (1, 2) -) AS t -GROUP BY t."Key" +) AS r0 +GROUP BY r0."Key" LIMIT 2 """); } @@ -309,13 +309,13 @@ public void Intersect_aggregate() AssertSql( """ -SELECT range_intersect_agg(t."IntRange") +SELECT range_intersect_agg(r0."IntRange") FROM ( SELECT r."IntRange", TRUE AS "Key" FROM "RangeTestEntities" AS r WHERE r."Id" IN (1, 2) -) AS t -GROUP BY t."Key" +) AS r0 +GROUP BY r0."Key" LIMIT 2 """); } diff --git a/test/EFCore.PG.FunctionalTests/Query/SimpleQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/SimpleQueryNpgsqlTest.cs deleted file mode 100644 index 1861efae3..000000000 --- a/test/EFCore.PG.FunctionalTests/Query/SimpleQueryNpgsqlTest.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities; - -namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query; - -public class SimpleQueryNpgsqlTest : SimpleQueryRelationalTestBase -{ - protected override ITestStoreFactory TestStoreFactory - => NpgsqlTestStoreFactory.Instance; - - // Writes DateTime with Kind=Unspecified to timestamptz - public override Task SelectMany_where_Select(bool async) - => Task.CompletedTask; - - // Writes DateTime with Kind=Unspecified to timestamptz - public override Task Subquery_first_member_compared_to_null(bool async) - => Task.CompletedTask; - - [ConditionalTheory(Skip = "https://github.com/dotnet/efcore/pull/27995/files#r874038747")] - public override Task StoreType_for_UDF_used(bool async) - => base.StoreType_for_UDF_used(async); -} diff --git a/test/EFCore.PG.FunctionalTests/Scaffolding/CompiledModelNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Scaffolding/CompiledModelNpgsqlTest.cs new file mode 100644 index 000000000..f2ad5e6ac --- /dev/null +++ b/test/EFCore.PG.FunctionalTests/Scaffolding/CompiledModelNpgsqlTest.cs @@ -0,0 +1,59 @@ +// using System.Runtime.CompilerServices; +// using Npgsql.EntityFrameworkCore.PostgreSQL.Design.Internal; +// using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure; +// using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities; +// +// namespace Npgsql.EntityFrameworkCore.PostgreSQL.Scaffolding; +// +// public class CompiledModelNpgsqlTest : CompiledModelRelationalTestBase +// { +// protected override TestHelpers TestHelpers => NpgsqlTestHelpers.Instance; +// protected override ITestStoreFactory TestStoreFactory => NpgsqlTestStoreFactory.Instance; +// +// // #3087 +// public override void BigModel() +// => Assert.Throws(() => base.BigModel()); +// +// // #3087 +// public override void BigModel_with_JSON_columns() +// => Assert.Throws(() => base.BigModel()); +// +// // #3087 +// public override void CheckConstraints() +// => Assert.Throws(() => base.BigModel()); +// +// // #3087 +// public override void DbFunctions() +// => Assert.Throws(() => base.BigModel()); +// +// // #3087 +// public override void Triggers() +// => Assert.Throws(() => base.BigModel()); +// +// // https://github.com/dotnet/efcore/pull/32341/files#r1485603038 +// public override void Tpc() +// => Assert.Throws(() => base.Tpc()); +// +// // https://github.com/dotnet/efcore/pull/32341/files#r1485603038 +// public override void ComplexTypes() +// => Assert.Throws(() => base.ComplexTypes()); +// +// protected override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) +// { +// new NpgsqlDbContextOptionsBuilder(builder).UseNetTopologySuite(); +// return builder; +// } +// +// protected override void AddDesignTimeServices(IServiceCollection services) +// => new NpgsqlNetTopologySuiteDesignTimeServices().ConfigureDesignTimeServices(services); +// +// protected override BuildSource AddReferences(BuildSource build, [CallerFilePath] string filePath = "") +// { +// base.AddReferences(build); +// build.References.Add(BuildReference.ByName("Npgsql.EntityFrameworkCore.PostgreSQL")); +// build.References.Add(BuildReference.ByName("Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite")); +// build.References.Add(BuildReference.ByName("Npgsql")); +// build.References.Add(BuildReference.ByName("NetTopologySuite")); +// return build; +// } +// } diff --git a/test/EFCore.PG.FunctionalTests/Scaffolding/NpgsqlDatabaseModelFactoryTest.cs b/test/EFCore.PG.FunctionalTests/Scaffolding/NpgsqlDatabaseModelFactoryTest.cs index 35b749fb0..c26bcc273 100644 --- a/test/EFCore.PG.FunctionalTests/Scaffolding/NpgsqlDatabaseModelFactoryTest.cs +++ b/test/EFCore.PG.FunctionalTests/Scaffolding/NpgsqlDatabaseModelFactoryTest.cs @@ -1886,7 +1886,7 @@ public void Index_covering() // Assert.Equal(new[] { "b", "c" }, indexWith.FindAnnotation(NpgsqlAnnotationNames.IndexInclude).Value); var indexWithout = table.Indexes.Single(i => i.Name == "ix_without"); - Assert.Equal(["a", "b", "c"], indexWithout.Columns.Select(i => i.Name).ToArray()); + Assert.Equal(new[] { "a", "b", "c" }, indexWithout.Columns.Select(i => i.Name).ToArray()); Assert.Null(indexWithout.FindAnnotation(NpgsqlAnnotationNames.IndexInclude)); }, @"DROP TABLE ""IndexCovering"""); @@ -1979,6 +1979,7 @@ public void Dropped_columns() public void Postgres_extensions() => Test( """ +DROP EXTENSION IF EXISTS postgis; CREATE EXTENSION hstore; CREATE EXTENSION pgcrypto SCHEMA db2; """, @@ -2124,13 +2125,13 @@ line line [RequiresPostgis] public void System_tables_are_ignored() => Test( - "CREATE EXTENSION postgis", + """ +DROP EXTENSION IF EXISTS postgis; +CREATE EXTENSION postgis; +""", Enumerable.Empty(), Enumerable.Empty(), - dbModel => - { - Assert.Empty(dbModel.Tables); - }, + dbModel => Assert.Empty(dbModel.Tables), "DROP EXTENSION postgis"); #endregion diff --git a/test/EFCore.PG.FunctionalTests/TestUtilities/NpgsqlTestStoreFactory.cs b/test/EFCore.PG.FunctionalTests/TestUtilities/NpgsqlTestStoreFactory.cs index 1f6858fbb..95c16a849 100644 --- a/test/EFCore.PG.FunctionalTests/TestUtilities/NpgsqlTestStoreFactory.cs +++ b/test/EFCore.PG.FunctionalTests/TestUtilities/NpgsqlTestStoreFactory.cs @@ -22,4 +22,5 @@ public override TestStore GetOrCreate(string storeName) public override IServiceCollection AddProviderServices(IServiceCollection serviceCollection) => serviceCollection.AddEntityFrameworkNpgsql(); + // .AddEntityFrameworkNpgsqlNetTopologySuite(); } diff --git a/test/EFCore.PG.FunctionalTests/Update/JsonUpdateNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Update/JsonUpdateNpgsqlTest.cs index 7a555425c..cd67af7b5 100644 --- a/test/EFCore.PG.FunctionalTests/Update/JsonUpdateNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Update/JsonUpdateNpgsqlTest.cs @@ -18,7 +18,7 @@ public override async Task Add_element_to_json_collection_branch() AssertSql( """ -@p0='[{"Date":"2101-01-01T00:00:00","Enum":1,"Enums":[0,-1,1],"Fraction":10.1,"NullableEnum":0,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_c1_c1"},{"SomethingSomething":"e1_r_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_c1_r"}},{"Date":"2102-01-01T00:00:00","Enum":2,"Enums":[0,-1,1],"Fraction":10.2,"NullableEnum":1,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_c2_c1"},{"SomethingSomething":"e1_r_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_c2_r"}},{"Date":"2010-10-10T00:00:00","Enum":2,"Enums":null,"Fraction":42.42,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":[{"SomethingSomething":"ss1"},{"SomethingSomething":"ss2"}],"OwnedReferenceLeaf":{"SomethingSomething":"ss3"}}]' (Nullable = false) (DbType = Object) +@p0='[{"Date":"2101-01-01T00:00:00","Enum":2,"Enums":[-1,-1,2],"Fraction":10.1,"NullableEnum":-1,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_c1_c1"},{"SomethingSomething":"e1_r_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_c1_r"}},{"Date":"2102-01-01T00:00:00","Enum":-3,"Enums":[-1,-1,2],"Fraction":10.2,"NullableEnum":2,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_c2_c1"},{"SomethingSomething":"e1_r_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_c2_r"}},{"Date":"2010-10-10T00:00:00","Enum":-3,"Enums":null,"Fraction":42.42,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":[{"SomethingSomething":"ss1"},{"SomethingSomething":"ss2"}],"OwnedReferenceLeaf":{"SomethingSomething":"ss3"}}]' (Nullable = false) (DbType = Object) @p1='1' UPDATE "JsonEntitiesBasic" SET "OwnedReferenceRoot" = jsonb_set("OwnedReferenceRoot", '{OwnedCollectionBranch}', @p0) @@ -58,7 +58,7 @@ public override async Task Add_element_to_json_collection_on_derived() AssertSql( """ -@p0='[{"Date":"2221-01-01T00:00:00","Enum":1,"Enums":[0,-1,1],"Fraction":221.1,"NullableEnum":0,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"d2_r_c1"},{"SomethingSomething":"d2_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"d2_r_r"}},{"Date":"2222-01-01T00:00:00","Enum":2,"Enums":[0,-1,1],"Fraction":222.1,"NullableEnum":1,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"d2_r_c1"},{"SomethingSomething":"d2_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"d2_r_r"}},{"Date":"2010-10-10T00:00:00","Enum":2,"Enums":null,"Fraction":42.42,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":[{"SomethingSomething":"ss1"},{"SomethingSomething":"ss2"}],"OwnedReferenceLeaf":{"SomethingSomething":"ss3"}}]' (Nullable = false) (DbType = Object) +@p0='[{"Date":"2221-01-01T00:00:00","Enum":2,"Enums":[-1,-1,2],"Fraction":221.1,"NullableEnum":-1,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"d2_r_c1"},{"SomethingSomething":"d2_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"d2_r_r"}},{"Date":"2222-01-01T00:00:00","Enum":-3,"Enums":[-1,-1,2],"Fraction":222.1,"NullableEnum":2,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"d2_r_c1"},{"SomethingSomething":"d2_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"d2_r_r"}},{"Date":"2010-10-10T00:00:00","Enum":-3,"Enums":null,"Fraction":42.42,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":[{"SomethingSomething":"ss1"},{"SomethingSomething":"ss2"}],"OwnedReferenceLeaf":{"SomethingSomething":"ss3"}}]' (Nullable = false) (DbType = Object) @p1='2' UPDATE "JsonEntitiesInheritance" SET "CollectionOnDerived" = @p0 @@ -79,7 +79,7 @@ public override async Task Add_element_to_json_collection_root() AssertSql( """ -@p0='[{"Name":"e1_c1","Names":["e1_c11","e1_c12"],"Number":11,"Numbers":[-1000,0,1000],"OwnedCollectionBranch":[{"Date":"2111-01-01T00:00:00","Enum":1,"Enums":[0,-1,1],"Fraction":11.1,"NullableEnum":0,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_c1_c1"},{"SomethingSomething":"e1_c1_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c1_r"}},{"Date":"2112-01-01T00:00:00","Enum":2,"Enums":[0,-1,1],"Fraction":11.2,"NullableEnum":1,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_c2_c1"},{"SomethingSomething":"e1_c1_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c2_r"}}],"OwnedReferenceBranch":{"Date":"2110-01-01T00:00:00","Enum":0,"Enums":[0,-1,1],"Fraction":11.0,"NullableEnum":null,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_r_c1"},{"SomethingSomething":"e1_c1_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_r_r"}}},{"Name":"e1_c2","Names":["e1_c21","e1_c22"],"Number":12,"Numbers":[-1001,0,1001],"OwnedCollectionBranch":[{"Date":"2121-01-01T00:00:00","Enum":1,"Enums":[0,-1,1],"Fraction":12.1,"NullableEnum":0,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_c1_c1"},{"SomethingSomething":"e1_c2_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_c1_r"}},{"Date":"2122-01-01T00:00:00","Enum":0,"Enums":[0,-1,1],"Fraction":12.2,"NullableEnum":null,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_c2_c1"},{"SomethingSomething":"e1_c2_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_c2_r"}}],"OwnedReferenceBranch":{"Date":"2120-01-01T00:00:00","Enum":2,"Enums":[0,-1,1],"Fraction":12.0,"NullableEnum":1,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_r_c1"},{"SomethingSomething":"e1_c2_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_r_r"}}},{"Name":"new Name","Names":null,"Number":142,"Numbers":null,"OwnedCollectionBranch":[],"OwnedReferenceBranch":{"Date":"2010-10-10T00:00:00","Enum":2,"Enums":null,"Fraction":42.42,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":[{"SomethingSomething":"ss1"},{"SomethingSomething":"ss2"}],"OwnedReferenceLeaf":{"SomethingSomething":"ss3"}}}]' (Nullable = false) (DbType = Object) +@p0='[{"Name":"e1_c1","Names":["e1_c11","e1_c12"],"Number":11,"Numbers":[-1000,0,1000],"OwnedCollectionBranch":[{"Date":"2111-01-01T00:00:00","Enum":2,"Enums":[-1,-1,2],"Fraction":11.1,"NullableEnum":-1,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_c1_c1"},{"SomethingSomething":"e1_c1_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c1_r"}},{"Date":"2112-01-01T00:00:00","Enum":-3,"Enums":[-1,-1,2],"Fraction":11.2,"NullableEnum":2,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_c2_c1"},{"SomethingSomething":"e1_c1_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c2_r"}}],"OwnedReferenceBranch":{"Date":"2110-01-01T00:00:00","Enum":-1,"Enums":[-1,-1,2],"Fraction":11.0,"NullableEnum":null,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_r_c1"},{"SomethingSomething":"e1_c1_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_r_r"}}},{"Name":"e1_c2","Names":["e1_c21","e1_c22"],"Number":12,"Numbers":[-1001,0,1001],"OwnedCollectionBranch":[{"Date":"2121-01-01T00:00:00","Enum":2,"Enums":[-1,-1,2],"Fraction":12.1,"NullableEnum":-1,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_c1_c1"},{"SomethingSomething":"e1_c2_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_c1_r"}},{"Date":"2122-01-01T00:00:00","Enum":-1,"Enums":[-1,-1,2],"Fraction":12.2,"NullableEnum":null,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_c2_c1"},{"SomethingSomething":"e1_c2_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_c2_r"}}],"OwnedReferenceBranch":{"Date":"2120-01-01T00:00:00","Enum":-3,"Enums":[-1,-1,2],"Fraction":12.0,"NullableEnum":2,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_r_c1"},{"SomethingSomething":"e1_c2_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_r_r"}}},{"Name":"new Name","Names":null,"Number":142,"Numbers":null,"OwnedCollectionBranch":[],"OwnedReferenceBranch":{"Date":"2010-10-10T00:00:00","Enum":-3,"Enums":null,"Fraction":42.42,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":[{"SomethingSomething":"ss1"},{"SomethingSomething":"ss2"}],"OwnedReferenceLeaf":{"SomethingSomething":"ss3"}}}]' (Nullable = false) (DbType = Object) @p1='1' UPDATE "JsonEntitiesBasic" SET "OwnedCollectionRoot" = @p0 @@ -99,7 +99,7 @@ public override async Task Add_element_to_json_collection_root_null_navigations( AssertSql( """ -@p0='[{"Name":"e1_c1","Names":["e1_c11","e1_c12"],"Number":11,"Numbers":[-1000,0,1000],"OwnedCollectionBranch":[{"Date":"2111-01-01T00:00:00","Enum":1,"Enums":[0,-1,1],"Fraction":11.1,"NullableEnum":0,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_c1_c1"},{"SomethingSomething":"e1_c1_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c1_r"}},{"Date":"2112-01-01T00:00:00","Enum":2,"Enums":[0,-1,1],"Fraction":11.2,"NullableEnum":1,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_c2_c1"},{"SomethingSomething":"e1_c1_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c2_r"}}],"OwnedReferenceBranch":{"Date":"2110-01-01T00:00:00","Enum":0,"Enums":[0,-1,1],"Fraction":11.0,"NullableEnum":null,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_r_c1"},{"SomethingSomething":"e1_c1_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_r_r"}}},{"Name":"e1_c2","Names":["e1_c21","e1_c22"],"Number":12,"Numbers":[-1001,0,1001],"OwnedCollectionBranch":[{"Date":"2121-01-01T00:00:00","Enum":1,"Enums":[0,-1,1],"Fraction":12.1,"NullableEnum":0,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_c1_c1"},{"SomethingSomething":"e1_c2_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_c1_r"}},{"Date":"2122-01-01T00:00:00","Enum":0,"Enums":[0,-1,1],"Fraction":12.2,"NullableEnum":null,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_c2_c1"},{"SomethingSomething":"e1_c2_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_c2_r"}}],"OwnedReferenceBranch":{"Date":"2120-01-01T00:00:00","Enum":2,"Enums":[0,-1,1],"Fraction":12.0,"NullableEnum":1,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_r_c1"},{"SomethingSomething":"e1_c2_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_r_r"}}},{"Name":"new Name","Names":null,"Number":142,"Numbers":null,"OwnedCollectionBranch":null,"OwnedReferenceBranch":{"Date":"2010-10-10T00:00:00","Enum":2,"Enums":null,"Fraction":42.42,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":null,"OwnedReferenceLeaf":null}}]' (Nullable = false) (DbType = Object) +@p0='[{"Name":"e1_c1","Names":["e1_c11","e1_c12"],"Number":11,"Numbers":[-1000,0,1000],"OwnedCollectionBranch":[{"Date":"2111-01-01T00:00:00","Enum":2,"Enums":[-1,-1,2],"Fraction":11.1,"NullableEnum":-1,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_c1_c1"},{"SomethingSomething":"e1_c1_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c1_r"}},{"Date":"2112-01-01T00:00:00","Enum":-3,"Enums":[-1,-1,2],"Fraction":11.2,"NullableEnum":2,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_c2_c1"},{"SomethingSomething":"e1_c1_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c2_r"}}],"OwnedReferenceBranch":{"Date":"2110-01-01T00:00:00","Enum":-1,"Enums":[-1,-1,2],"Fraction":11.0,"NullableEnum":null,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_r_c1"},{"SomethingSomething":"e1_c1_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_r_r"}}},{"Name":"e1_c2","Names":["e1_c21","e1_c22"],"Number":12,"Numbers":[-1001,0,1001],"OwnedCollectionBranch":[{"Date":"2121-01-01T00:00:00","Enum":2,"Enums":[-1,-1,2],"Fraction":12.1,"NullableEnum":-1,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_c1_c1"},{"SomethingSomething":"e1_c2_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_c1_r"}},{"Date":"2122-01-01T00:00:00","Enum":-1,"Enums":[-1,-1,2],"Fraction":12.2,"NullableEnum":null,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_c2_c1"},{"SomethingSomething":"e1_c2_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_c2_r"}}],"OwnedReferenceBranch":{"Date":"2120-01-01T00:00:00","Enum":-3,"Enums":[-1,-1,2],"Fraction":12.0,"NullableEnum":2,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_r_c1"},{"SomethingSomething":"e1_c2_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_r_r"}}},{"Name":"new Name","Names":null,"Number":142,"Numbers":null,"OwnedCollectionBranch":null,"OwnedReferenceBranch":{"Date":"2010-10-10T00:00:00","Enum":-3,"Enums":null,"Fraction":42.42,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":null,"OwnedReferenceLeaf":null}}]' (Nullable = false) (DbType = Object) @p1='1' UPDATE "JsonEntitiesBasic" SET "OwnedCollectionRoot" = @p0 @@ -119,7 +119,7 @@ public override async Task Add_entity_with_json() AssertSql( """ -@p0='{"Name":"RootName","Names":null,"Number":42,"Numbers":null,"OwnedCollectionBranch":[],"OwnedReferenceBranch":{"Date":"2010-10-10T00:00:00","Enum":2,"Enums":null,"Fraction":42.42,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":[{"SomethingSomething":"ss1"},{"SomethingSomething":"ss2"}],"OwnedReferenceLeaf":{"SomethingSomething":"ss3"}}}' (Nullable = false) (DbType = Object) +@p0='{"Name":"RootName","Names":null,"Number":42,"Numbers":null,"OwnedCollectionBranch":[],"OwnedReferenceBranch":{"Date":"2010-10-10T00:00:00","Enum":-3,"Enums":null,"Fraction":42.42,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":[{"SomethingSomething":"ss1"},{"SomethingSomething":"ss2"}],"OwnedReferenceLeaf":{"SomethingSomething":"ss3"}}}' (Nullable = false) (DbType = Object) @p1='[]' (Nullable = false) (DbType = Object) @p2='2' @p3=NULL (DbType = Int32) @@ -141,7 +141,7 @@ public override async Task Add_entity_with_json_null_navigations() AssertSql( """ -@p0='{"Name":"RootName","Names":null,"Number":42,"Numbers":null,"OwnedCollectionBranch":null,"OwnedReferenceBranch":{"Date":"2010-10-10T00:00:00","Enum":2,"Enums":null,"Fraction":42.42,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":[{"SomethingSomething":"ss1"},{"SomethingSomething":"ss2"}],"OwnedReferenceLeaf":null}}' (Nullable = false) (DbType = Object) +@p0='{"Name":"RootName","Names":null,"Number":42,"Numbers":null,"OwnedCollectionBranch":null,"OwnedReferenceBranch":{"Date":"2010-10-10T00:00:00","Enum":-3,"Enums":null,"Fraction":42.42,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":[{"SomethingSomething":"ss1"},{"SomethingSomething":"ss2"}],"OwnedReferenceLeaf":null}}' (Nullable = false) (DbType = Object) @p1='2' @p2=NULL (DbType = Int32) @p3='NewEntity' @@ -182,7 +182,7 @@ public override async Task Add_json_reference_root() AssertSql( """ -@p0='{"Name":"RootName","Names":null,"Number":42,"Numbers":null,"OwnedCollectionBranch":[],"OwnedReferenceBranch":{"Date":"2010-10-10T00:00:00","Enum":2,"Enums":null,"Fraction":42.42,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":[{"SomethingSomething":"ss1"},{"SomethingSomething":"ss2"}],"OwnedReferenceLeaf":{"SomethingSomething":"ss3"}}}' (Nullable = false) (DbType = Object) +@p0='{"Name":"RootName","Names":null,"Number":42,"Numbers":null,"OwnedCollectionBranch":[],"OwnedReferenceBranch":{"Date":"2010-10-10T00:00:00","Enum":-3,"Enums":null,"Fraction":42.42,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":[{"SomethingSomething":"ss1"},{"SomethingSomething":"ss2"}],"OwnedReferenceLeaf":{"SomethingSomething":"ss3"}}}' (Nullable = false) (DbType = Object) @p1='1' UPDATE "JsonEntitiesBasic" SET "OwnedReferenceRoot" = @p0 @@ -360,8 +360,8 @@ public override async Task Edit_element_in_json_multiple_levels_partial_update() AssertSql( """ -@p0='[{"Date":"2111-01-01T00:00:00","Enum":1,"Enums":[0,-1,1],"Fraction":11.1,"NullableEnum":0,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"...and another"},{"SomethingSomething":"e1_c1_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c1_r"}},{"Date":"2112-01-01T00:00:00","Enum":2,"Enums":[0,-1,1],"Fraction":11.2,"NullableEnum":1,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"yet another change"},{"SomethingSomething":"and another"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c2_r"}}]' (Nullable = false) (DbType = Object) -@p1='{"Name":"edit","Names":["e1_r1","e1_r2"],"Number":10,"Numbers":[-2147483648,-1,0,1,2147483647],"OwnedCollectionBranch":[{"Date":"2101-01-01T00:00:00","Enum":1,"Enums":[0,-1,1],"Fraction":10.1,"NullableEnum":0,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_c1_c1"},{"SomethingSomething":"e1_r_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_c1_r"}},{"Date":"2102-01-01T00:00:00","Enum":2,"Enums":[0,-1,1],"Fraction":10.2,"NullableEnum":1,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_c2_c1"},{"SomethingSomething":"e1_r_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_c2_r"}}],"OwnedReferenceBranch":{"Date":"2111-11-11T00:00:00","Enum":0,"Enums":[0,-1,1],"Fraction":10.0,"NullableEnum":null,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_r_c1"},{"SomethingSomething":"e1_r_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_r_r"}}}' (Nullable = false) (DbType = Object) +@p0='[{"Date":"2111-01-01T00:00:00","Enum":2,"Enums":[-1,-1,2],"Fraction":11.1,"NullableEnum":-1,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"...and another"},{"SomethingSomething":"e1_c1_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c1_r"}},{"Date":"2112-01-01T00:00:00","Enum":-3,"Enums":[-1,-1,2],"Fraction":11.2,"NullableEnum":2,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"yet another change"},{"SomethingSomething":"and another"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c2_r"}}]' (Nullable = false) (DbType = Object) +@p1='{"Name":"edit","Names":["e1_r1","e1_r2"],"Number":10,"Numbers":[-2147483648,-1,0,1,2147483647],"OwnedCollectionBranch":[{"Date":"2101-01-01T00:00:00","Enum":2,"Enums":[-1,-1,2],"Fraction":10.1,"NullableEnum":-1,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_c1_c1"},{"SomethingSomething":"e1_r_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_c1_r"}},{"Date":"2102-01-01T00:00:00","Enum":-3,"Enums":[-1,-1,2],"Fraction":10.2,"NullableEnum":2,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_c2_c1"},{"SomethingSomething":"e1_r_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_c2_r"}}],"OwnedReferenceBranch":{"Date":"2111-11-11T00:00:00","Enum":-1,"Enums":[-1,-1,2],"Fraction":10.0,"NullableEnum":null,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_r_c1"},{"SomethingSomething":"e1_r_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_r_r"}}}' (Nullable = false) (DbType = Object) @p2='1' UPDATE "JsonEntitiesBasic" SET "OwnedCollectionRoot" = jsonb_set("OwnedCollectionRoot", '{0,OwnedCollectionBranch}', @p0), "OwnedReferenceRoot" = @p1 @@ -381,7 +381,7 @@ public override async Task Edit_element_in_json_branch_collection_and_add_elemen AssertSql( """ -@p0='[{"Date":"2101-01-01T00:00:00","Enum":1,"Enums":[0,-1,1],"Fraction":4321.3,"NullableEnum":0,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_c1_c1"},{"SomethingSomething":"e1_r_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_c1_r"}},{"Date":"2102-01-01T00:00:00","Enum":2,"Enums":[0,-1,1],"Fraction":10.2,"NullableEnum":1,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_c2_c1"},{"SomethingSomething":"e1_r_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_c2_r"}},{"Date":"2222-11-11T00:00:00","Enum":2,"Enums":null,"Fraction":45.32,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":null,"OwnedReferenceLeaf":{"SomethingSomething":"cc"}}]' (Nullable = false) (DbType = Object) +@p0='[{"Date":"2101-01-01T00:00:00","Enum":2,"Enums":[-1,-1,2],"Fraction":4321.3,"NullableEnum":-1,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_c1_c1"},{"SomethingSomething":"e1_r_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_c1_r"}},{"Date":"2102-01-01T00:00:00","Enum":-3,"Enums":[-1,-1,2],"Fraction":10.2,"NullableEnum":2,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_c2_c1"},{"SomethingSomething":"e1_r_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_c2_r"}},{"Date":"2222-11-11T00:00:00","Enum":-3,"Enums":null,"Fraction":45.32,"NullableEnum":null,"NullableEnums":null,"OwnedCollectionLeaf":null,"OwnedReferenceLeaf":{"SomethingSomething":"cc"}}]' (Nullable = false) (DbType = Object) @p1='1' UPDATE "JsonEntitiesBasic" SET "OwnedReferenceRoot" = jsonb_set("OwnedReferenceRoot", '{OwnedCollectionBranch}', @p0) @@ -421,7 +421,7 @@ public override async Task Edit_two_elements_in_the_same_json_collection_at_the_ AssertSql( """ -@p0='[{"Name":"edit1","Names":["e1_c11","e1_c12"],"Number":11,"Numbers":[-1000,0,1000],"OwnedCollectionBranch":[{"Date":"2111-01-01T00:00:00","Enum":1,"Enums":[0,-1,1],"Fraction":11.1,"NullableEnum":0,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_c1_c1"},{"SomethingSomething":"e1_c1_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c1_r"}},{"Date":"2112-01-01T00:00:00","Enum":2,"Enums":[0,-1,1],"Fraction":11.2,"NullableEnum":1,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_c2_c1"},{"SomethingSomething":"e1_c1_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c2_r"}}],"OwnedReferenceBranch":{"Date":"2110-01-01T00:00:00","Enum":0,"Enums":[0,-1,1],"Fraction":11.0,"NullableEnum":null,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_r_c1"},{"SomethingSomething":"e1_c1_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_r_r"}}},{"Name":"edit2","Names":["e1_c21","e1_c22"],"Number":12,"Numbers":[-1001,0,1001],"OwnedCollectionBranch":[{"Date":"2121-01-01T00:00:00","Enum":1,"Enums":[0,-1,1],"Fraction":12.1,"NullableEnum":0,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_c1_c1"},{"SomethingSomething":"e1_c2_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_c1_r"}},{"Date":"2122-01-01T00:00:00","Enum":0,"Enums":[0,-1,1],"Fraction":12.2,"NullableEnum":null,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_c2_c1"},{"SomethingSomething":"e1_c2_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_c2_r"}}],"OwnedReferenceBranch":{"Date":"2120-01-01T00:00:00","Enum":2,"Enums":[0,-1,1],"Fraction":12.0,"NullableEnum":1,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_r_c1"},{"SomethingSomething":"e1_c2_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_r_r"}}}]' (Nullable = false) (DbType = Object) +@p0='[{"Name":"edit1","Names":["e1_c11","e1_c12"],"Number":11,"Numbers":[-1000,0,1000],"OwnedCollectionBranch":[{"Date":"2111-01-01T00:00:00","Enum":2,"Enums":[-1,-1,2],"Fraction":11.1,"NullableEnum":-1,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_c1_c1"},{"SomethingSomething":"e1_c1_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c1_r"}},{"Date":"2112-01-01T00:00:00","Enum":-3,"Enums":[-1,-1,2],"Fraction":11.2,"NullableEnum":2,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_c2_c1"},{"SomethingSomething":"e1_c1_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_c2_r"}}],"OwnedReferenceBranch":{"Date":"2110-01-01T00:00:00","Enum":-1,"Enums":[-1,-1,2],"Fraction":11.0,"NullableEnum":null,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c1_r_c1"},{"SomethingSomething":"e1_c1_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c1_r_r"}}},{"Name":"edit2","Names":["e1_c21","e1_c22"],"Number":12,"Numbers":[-1001,0,1001],"OwnedCollectionBranch":[{"Date":"2121-01-01T00:00:00","Enum":2,"Enums":[-1,-1,2],"Fraction":12.1,"NullableEnum":-1,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_c1_c1"},{"SomethingSomething":"e1_c2_c1_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_c1_r"}},{"Date":"2122-01-01T00:00:00","Enum":-1,"Enums":[-1,-1,2],"Fraction":12.2,"NullableEnum":null,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_c2_c1"},{"SomethingSomething":"e1_c2_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_c2_r"}}],"OwnedReferenceBranch":{"Date":"2120-01-01T00:00:00","Enum":-3,"Enums":[-1,-1,2],"Fraction":12.0,"NullableEnum":2,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_c2_r_c1"},{"SomethingSomething":"e1_c2_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_c2_r_r"}}}]' (Nullable = false) (DbType = Object) @p1='1' UPDATE "JsonEntitiesBasic" SET "OwnedCollectionRoot" = @p0 @@ -441,7 +441,7 @@ public override async Task Edit_collection_element_and_reference_at_once() AssertSql( """ -@p0='{"Date":"2102-01-01T00:00:00","Enum":2,"Enums":[0,-1,1],"Fraction":10.2,"NullableEnum":1,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"edit1"},{"SomethingSomething":"e1_r_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"edit2"}}' (Nullable = false) (DbType = Object) +@p0='{"Date":"2102-01-01T00:00:00","Enum":-3,"Enums":[-1,-1,2],"Fraction":10.2,"NullableEnum":2,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"edit1"},{"SomethingSomething":"e1_r_c2_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"edit2"}}' (Nullable = false) (DbType = Object) @p1='1' UPDATE "JsonEntitiesBasic" SET "OwnedReferenceRoot" = jsonb_set("OwnedReferenceRoot", '{OwnedCollectionBranch,1}', @p0) @@ -461,8 +461,8 @@ public override async Task Edit_single_enum_property() AssertSql( """ -@p0='1' (Nullable = false) (DbType = Object) -@p1='1' (Nullable = false) (DbType = Object) +@p0='2' (Nullable = false) (DbType = Object) +@p1='2' (Nullable = false) (DbType = Object) @p2='1' UPDATE "JsonEntitiesBasic" SET "OwnedCollectionRoot" = jsonb_set("OwnedCollectionRoot", '{1,OwnedCollectionBranch,1,Enum}', @p0), "OwnedReferenceRoot" = jsonb_set("OwnedReferenceRoot", '{OwnedReferenceBranch,Enum}', @p1) @@ -920,8 +920,8 @@ public override async Task Edit_single_property_enum() AssertSql( """ -@p0='2' (Nullable = false) (DbType = Object) -@p1='2' (Nullable = false) (DbType = Object) +@p0='-3' (Nullable = false) (DbType = Object) +@p1='-3' (Nullable = false) (DbType = Object) @p2='1' UPDATE "JsonEntitiesAllTypes" SET "Collection" = jsonb_set("Collection", '{0,TestEnum}', @p0), "Reference" = jsonb_set("Reference", '{TestEnum}', @p1) @@ -942,8 +942,8 @@ public override async Task Edit_single_property_enum_with_int_converter() AssertSql( """ -@p0='2' (Nullable = false) (DbType = Object) -@p1='2' (Nullable = false) (DbType = Object) +@p0='-3' (Nullable = false) (DbType = Object) +@p1='-3' (Nullable = false) (DbType = Object) @p2='1' UPDATE "JsonEntitiesAllTypes" SET "Collection" = jsonb_set("Collection", '{0,TestEnumWithIntConverter}', @p0), "Reference" = jsonb_set("Reference", '{TestEnumWithIntConverter}', @p1) @@ -964,8 +964,8 @@ public override async Task Edit_single_property_nullable_enum() AssertSql( """ -@p0='2' (Nullable = false) (DbType = Object) -@p1='2' (Nullable = false) (DbType = Object) +@p0='-3' (Nullable = false) (DbType = Object) +@p1='-3' (Nullable = false) (DbType = Object) @p2='1' UPDATE "JsonEntitiesAllTypes" SET "Collection" = jsonb_set("Collection", '{0,TestEnum}', @p0), "Reference" = jsonb_set("Reference", '{TestEnum}', @p1) @@ -1008,8 +1008,8 @@ public override async Task Edit_single_property_nullable_enum_with_int_converter AssertSql( """ -@p0='0' (Nullable = false) (DbType = Object) -@p1='2' (Nullable = false) (DbType = Object) +@p0='-1' (Nullable = false) (DbType = Object) +@p1='-3' (Nullable = false) (DbType = Object) @p2='1' UPDATE "JsonEntitiesAllTypes" SET "Collection" = jsonb_set("Collection", '{0,TestNullableEnumWithIntConverter}', @p0), "Reference" = jsonb_set("Reference", '{TestNullableEnumWithIntConverter}', @p1) @@ -1096,8 +1096,8 @@ public override async Task Edit_two_properties_on_same_entity_updates_the_entire AssertSql( """ -@p0='{"TestBoolean":false,"TestBooleanCollection":[true,false],"TestByte":25,"TestByteCollection":null,"TestCharacter":"h","TestCharacterCollection":["A","B","\u0022"],"TestDateOnly":"2323-04-03","TestDateOnlyCollection":["3234-01-23","4331-01-21"],"TestDateTime":"2100-11-11T12:34:56","TestDateTimeCollection":["2000-01-01T12:34:56","3000-01-01T12:34:56"],"TestDateTimeOffset":"2200-11-11T12:34:56-05:00","TestDateTimeOffsetCollection":["2000-01-01T12:34:56-08:00"],"TestDecimal":-123450.01,"TestDecimalCollection":[-1234567890.01],"TestDefaultString":"MyDefaultStringInCollection1","TestDefaultStringCollection":["S1","\u0022S2\u0022","S3"],"TestDouble":-1.2345,"TestDoubleCollection":[-1.23456789,1.23456789,0],"TestEnum":0,"TestEnumCollection":[0,2,-7],"TestEnumWithIntConverter":1,"TestEnumWithIntConverterCollection":[0,2,-7],"TestGuid":"00000000-0000-0000-0000-000000000000","TestGuidCollection":["12345678-1234-4321-7777-987654321000"],"TestInt16":-12,"TestInt16Collection":[-32768,0,32767],"TestInt32":32,"TestInt32Collection":[-2147483648,0,2147483647],"TestInt64":64,"TestInt64Collection":[-9223372036854775808,0,9223372036854775807],"TestMaxLengthString":"Baz","TestMaxLengthStringCollection":["S1","S2","S3"],"TestNullableEnum":0,"TestNullableEnumCollection":[0,null,2,-7],"TestNullableEnumWithConverterThatHandlesNulls":"Two","TestNullableEnumWithConverterThatHandlesNullsCollection":[0,null,-7],"TestNullableEnumWithIntConverter":2,"TestNullableEnumWithIntConverterCollection":[0,null,2,-7],"TestNullableInt32":90,"TestNullableInt32Collection":[null,-2147483648,0,null,2147483647,null],"TestSignedByte":-18,"TestSignedByteCollection":[-128,0,127],"TestSingle":-1.4,"TestSingleCollection":[-1.234,0,-1.234],"TestTimeOnly":"05:07:08.0000000","TestTimeOnlyCollection":["13:42:23.0000000","07:17:25.0000000"],"TestTimeSpan":"06:05:04.003","TestTimeSpanCollection":["10:09:08.007","-09:50:51.993"],"TestUnsignedInt16":12,"TestUnsignedInt16Collection":[0,0,65535],"TestUnsignedInt32":12345,"TestUnsignedInt32Collection":[0,0,4294967295],"TestUnsignedInt64":1234567867,"TestUnsignedInt64Collection":[0,0,18446744073709551615]}' (Nullable = false) (DbType = Object) -@p1='{"TestBoolean":true,"TestBooleanCollection":[true,false],"TestByte":255,"TestByteCollection":null,"TestCharacter":"a","TestCharacterCollection":["A","B","\u0022"],"TestDateOnly":"2023-10-10","TestDateOnlyCollection":["1234-01-23","4321-01-21"],"TestDateTime":"2000-01-01T12:34:56","TestDateTimeCollection":["2000-01-01T12:34:56","3000-01-01T12:34:56"],"TestDateTimeOffset":"2000-01-01T12:34:56-08:00","TestDateTimeOffsetCollection":["2000-01-01T12:34:56-08:00"],"TestDecimal":-1234567890.01,"TestDecimalCollection":[-1234567890.01],"TestDefaultString":"MyDefaultStringInReference1","TestDefaultStringCollection":["S1","\u0022S2\u0022","S3"],"TestDouble":-1.23456789,"TestDoubleCollection":[-1.23456789,1.23456789,0],"TestEnum":0,"TestEnumCollection":[0,2,-7],"TestEnumWithIntConverter":1,"TestEnumWithIntConverterCollection":[0,2,-7],"TestGuid":"12345678-1234-4321-7777-987654321000","TestGuidCollection":["12345678-1234-4321-7777-987654321000"],"TestInt16":-1234,"TestInt16Collection":[-32768,0,32767],"TestInt32":32,"TestInt32Collection":[-2147483648,0,2147483647],"TestInt64":64,"TestInt64Collection":[-9223372036854775808,0,9223372036854775807],"TestMaxLengthString":"Foo","TestMaxLengthStringCollection":["S1","S2","S3"],"TestNullableEnum":0,"TestNullableEnumCollection":[0,null,2,-7],"TestNullableEnumWithConverterThatHandlesNulls":"Three","TestNullableEnumWithConverterThatHandlesNullsCollection":[0,null,-7],"TestNullableEnumWithIntConverter":1,"TestNullableEnumWithIntConverterCollection":[0,null,2,-7],"TestNullableInt32":78,"TestNullableInt32Collection":[null,-2147483648,0,null,2147483647,null],"TestSignedByte":-128,"TestSignedByteCollection":[-128,0,127],"TestSingle":-1.234,"TestSingleCollection":[-1.234,0,-1.234],"TestTimeOnly":"11:12:13.0000000","TestTimeOnlyCollection":["11:42:23.0000000","07:17:27.0000000"],"TestTimeSpan":"10:09:08.007","TestTimeSpanCollection":["10:09:08.007","-09:50:51.993"],"TestUnsignedInt16":1234,"TestUnsignedInt16Collection":[0,0,65535],"TestUnsignedInt32":1234565789,"TestUnsignedInt32Collection":[0,0,4294967295],"TestUnsignedInt64":1234567890123456789,"TestUnsignedInt64Collection":[0,0,18446744073709551615]}' (Nullable = false) (DbType = Object) +@p0='{"TestBoolean":false,"TestBooleanCollection":[true,false],"TestByte":25,"TestByteCollection":null,"TestCharacter":"h","TestCharacterCollection":["A","B","\u0022"],"TestDateOnly":"2323-04-03","TestDateOnlyCollection":["3234-01-23","4331-01-21"],"TestDateTime":"2100-11-11T12:34:56","TestDateTimeCollection":["2000-01-01T12:34:56","3000-01-01T12:34:56"],"TestDateTimeOffset":"2200-11-11T12:34:56-05:00","TestDateTimeOffsetCollection":["2000-01-01T12:34:56-08:00"],"TestDecimal":-123450.01,"TestDecimalCollection":[-1234567890.01],"TestDefaultString":"MyDefaultStringInCollection1","TestDefaultStringCollection":["S1","\u0022S2\u0022","S3"],"TestDouble":-1.2345,"TestDoubleCollection":[-1.23456789,1.23456789,0],"TestEnum":-1,"TestEnumCollection":[-1,-3,-7],"TestEnumWithIntConverter":2,"TestEnumWithIntConverterCollection":[-1,-3,-7],"TestGuid":"00000000-0000-0000-0000-000000000000","TestGuidCollection":["12345678-1234-4321-7777-987654321000"],"TestInt16":-12,"TestInt16Collection":[-32768,0,32767],"TestInt32":32,"TestInt32Collection":[-2147483648,0,2147483647],"TestInt64":64,"TestInt64Collection":[-9223372036854775808,0,9223372036854775807],"TestMaxLengthString":"Baz","TestMaxLengthStringCollection":["S1","S2","S3"],"TestNullableEnum":-1,"TestNullableEnumCollection":[-1,null,-3,-7],"TestNullableEnumWithConverterThatHandlesNulls":"Two","TestNullableEnumWithConverterThatHandlesNullsCollection":[-1,null,-7],"TestNullableEnumWithIntConverter":-3,"TestNullableEnumWithIntConverterCollection":[-1,null,-3,-7],"TestNullableInt32":90,"TestNullableInt32Collection":[null,-2147483648,0,null,2147483647,null],"TestSignedByte":-18,"TestSignedByteCollection":[-128,0,127],"TestSingle":-1.4,"TestSingleCollection":[-1.234,0,-1.234],"TestTimeOnly":"05:07:08.0000000","TestTimeOnlyCollection":["13:42:23.0000000","07:17:25.0000000"],"TestTimeSpan":"06:05:04.003","TestTimeSpanCollection":["10:09:08.007","-09:50:51.993"],"TestUnsignedInt16":12,"TestUnsignedInt16Collection":[0,0,65535],"TestUnsignedInt32":12345,"TestUnsignedInt32Collection":[0,0,4294967295],"TestUnsignedInt64":1234567867,"TestUnsignedInt64Collection":[0,0,18446744073709551615]}' (Nullable = false) (DbType = Object) +@p1='{"TestBoolean":true,"TestBooleanCollection":[true,false],"TestByte":255,"TestByteCollection":null,"TestCharacter":"a","TestCharacterCollection":["A","B","\u0022"],"TestDateOnly":"2023-10-10","TestDateOnlyCollection":["1234-01-23","4321-01-21"],"TestDateTime":"2000-01-01T12:34:56","TestDateTimeCollection":["2000-01-01T12:34:56","3000-01-01T12:34:56"],"TestDateTimeOffset":"2000-01-01T12:34:56-08:00","TestDateTimeOffsetCollection":["2000-01-01T12:34:56-08:00"],"TestDecimal":-1234567890.01,"TestDecimalCollection":[-1234567890.01],"TestDefaultString":"MyDefaultStringInReference1","TestDefaultStringCollection":["S1","\u0022S2\u0022","S3"],"TestDouble":-1.23456789,"TestDoubleCollection":[-1.23456789,1.23456789,0],"TestEnum":-1,"TestEnumCollection":[-1,-3,-7],"TestEnumWithIntConverter":2,"TestEnumWithIntConverterCollection":[-1,-3,-7],"TestGuid":"12345678-1234-4321-7777-987654321000","TestGuidCollection":["12345678-1234-4321-7777-987654321000"],"TestInt16":-1234,"TestInt16Collection":[-32768,0,32767],"TestInt32":32,"TestInt32Collection":[-2147483648,0,2147483647],"TestInt64":64,"TestInt64Collection":[-9223372036854775808,0,9223372036854775807],"TestMaxLengthString":"Foo","TestMaxLengthStringCollection":["S1","S2","S3"],"TestNullableEnum":-1,"TestNullableEnumCollection":[-1,null,-3,-7],"TestNullableEnumWithConverterThatHandlesNulls":"Three","TestNullableEnumWithConverterThatHandlesNullsCollection":[-1,null,-7],"TestNullableEnumWithIntConverter":2,"TestNullableEnumWithIntConverterCollection":[-1,null,-3,-7],"TestNullableInt32":78,"TestNullableInt32Collection":[null,-2147483648,0,null,2147483647,null],"TestSignedByte":-128,"TestSignedByteCollection":[-128,0,127],"TestSingle":-1.234,"TestSingleCollection":[-1.234,0,-1.234],"TestTimeOnly":"11:12:13.0000000","TestTimeOnlyCollection":["11:42:23.0000000","07:17:27.0000000"],"TestTimeSpan":"10:09:08.007","TestTimeSpanCollection":["10:09:08.007","-09:50:51.993"],"TestUnsignedInt16":1234,"TestUnsignedInt16Collection":[0,0,65535],"TestUnsignedInt32":1234565789,"TestUnsignedInt32Collection":[0,0,4294967295],"TestUnsignedInt64":1234567890123456789,"TestUnsignedInt64Collection":[0,0,18446744073709551615]}' (Nullable = false) (DbType = Object) @p2='1' UPDATE "JsonEntitiesAllTypes" SET "Collection" = jsonb_set("Collection", '{0}', @p0), "Reference" = @p1 @@ -1118,7 +1118,7 @@ public override async Task Edit_a_scalar_property_and_reference_navigation_on_th AssertSql( """ -@p0='{"Date":"2100-01-01T00:00:00","Enum":0,"Enums":[0,-1,1],"Fraction":523.532,"NullableEnum":null,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_r_c1"},{"SomethingSomething":"e1_r_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"edit"}}' (Nullable = false) (DbType = Object) +@p0='{"Date":"2100-01-01T00:00:00","Enum":-1,"Enums":[-1,-1,2],"Fraction":523.532,"NullableEnum":null,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_r_c1"},{"SomethingSomething":"e1_r_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"edit"}}' (Nullable = false) (DbType = Object) @p1='1' UPDATE "JsonEntitiesBasic" SET "OwnedReferenceRoot" = jsonb_set("OwnedReferenceRoot", '{OwnedReferenceBranch}', @p0) @@ -1138,7 +1138,7 @@ public override async Task Edit_a_scalar_property_and_collection_navigation_on_t AssertSql( """ -@p0='{"Date":"2100-01-01T00:00:00","Enum":0,"Enums":[0,-1,1],"Fraction":523.532,"NullableEnum":null,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"edit"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_r_r"}}' (Nullable = false) (DbType = Object) +@p0='{"Date":"2100-01-01T00:00:00","Enum":-1,"Enums":[-1,-1,2],"Fraction":523.532,"NullableEnum":null,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"edit"}],"OwnedReferenceLeaf":{"SomethingSomething":"e1_r_r_r"}}' (Nullable = false) (DbType = Object) @p1='1' UPDATE "JsonEntitiesBasic" SET "OwnedReferenceRoot" = jsonb_set("OwnedReferenceRoot", '{OwnedReferenceBranch}', @p0) @@ -1158,7 +1158,7 @@ public override async Task Edit_a_scalar_property_and_another_property_behind_re AssertSql( """ -@p0='{"Date":"2100-01-01T00:00:00","Enum":0,"Enums":[0,-1,1],"Fraction":523.532,"NullableEnum":null,"NullableEnums":[null,-1,1],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_r_c1"},{"SomethingSomething":"e1_r_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"edit"}}' (Nullable = false) (DbType = Object) +@p0='{"Date":"2100-01-01T00:00:00","Enum":-1,"Enums":[-1,-1,2],"Fraction":523.532,"NullableEnum":null,"NullableEnums":[null,-1,2],"OwnedCollectionLeaf":[{"SomethingSomething":"e1_r_r_c1"},{"SomethingSomething":"e1_r_r_c2"}],"OwnedReferenceLeaf":{"SomethingSomething":"edit"}}' (Nullable = false) (DbType = Object) @p1='1' UPDATE "JsonEntitiesBasic" SET "OwnedReferenceRoot" = jsonb_set("OwnedReferenceRoot", '{OwnedReferenceBranch}', @p0) @@ -1775,8 +1775,8 @@ public override async Task Edit_single_property_collection_of_enum() AssertSql( """ -@p0='[2]' (Nullable = false) (DbType = Object) -@p1='[2]' (Nullable = false) (DbType = Object) +@p0='[-3]' (Nullable = false) (DbType = Object) +@p1='[-3]' (Nullable = false) (DbType = Object) @p2='1' UPDATE "JsonEntitiesAllTypes" SET "Collection" = jsonb_set("Collection", '{0,TestEnumCollection}', @p0), "Reference" = jsonb_set("Reference", '{TestEnumCollection}', @p1) @@ -1797,8 +1797,8 @@ public override async Task Edit_single_property_collection_of_enum_with_int_conv AssertSql( """ -@p0='[2]' (Nullable = false) (DbType = Object) -@p1='[2]' (Nullable = false) (DbType = Object) +@p0='[-3]' (Nullable = false) (DbType = Object) +@p1='[-3]' (Nullable = false) (DbType = Object) @p2='1' UPDATE "JsonEntitiesAllTypes" SET "Collection" = jsonb_set("Collection", '{0,TestEnumWithIntConverterCollection}', @p0), "Reference" = jsonb_set("Reference", '{TestEnumWithIntConverterCollection}', @p1) @@ -1819,8 +1819,8 @@ public override async Task Edit_single_property_collection_of_nullable_enum() AssertSql( """ -@p0='[2]' (Nullable = false) (DbType = Object) -@p1='[2]' (Nullable = false) (DbType = Object) +@p0='[-3]' (Nullable = false) (DbType = Object) +@p1='[-3]' (Nullable = false) (DbType = Object) @p2='1' UPDATE "JsonEntitiesAllTypes" SET "Collection" = jsonb_set("Collection", '{0,TestEnumCollection}', @p0), "Reference" = jsonb_set("Reference", '{TestEnumCollection}', @p1) @@ -1863,8 +1863,8 @@ public override async Task Edit_single_property_collection_of_nullable_enum_with AssertSql( """ -@p0='[0,null,-7,1]' (Nullable = false) (DbType = Object) -@p1='[0,2,-7,1]' (Nullable = false) (DbType = Object) +@p0='[-1,null,-7,2]' (Nullable = false) (DbType = Object) +@p1='[-1,-3,-7,2]' (Nullable = false) (DbType = Object) @p2='1' UPDATE "JsonEntitiesAllTypes" SET "Collection" = jsonb_set("Collection", '{0,TestNullableEnumWithIntConverterCollection}', @p0), "Reference" = jsonb_set("Reference", '{TestNullableEnumWithIntConverterCollection}', @p1) @@ -1907,8 +1907,8 @@ public override async Task Edit_single_property_collection_of_nullable_enum_with AssertSql( """ -@p0='[2]' (Nullable = false) (DbType = Object) -@p1='[0]' (Nullable = false) (DbType = Object) +@p0='[-3]' (Nullable = false) (DbType = Object) +@p1='[-1]' (Nullable = false) (DbType = Object) @p2='1' UPDATE "JsonEntitiesAllTypes" SET "Collection" = jsonb_set("Collection", '{0,TestNullableEnumWithConverterThatHandlesNullsCollection}', @p0), "Reference" = jsonb_set("Reference", '{TestNullableEnumWithConverterThatHandlesNullsCollection}', @p1) diff --git a/test/EFCore.PG.NodaTime.FunctionalTests/NodaTimeQueryNpgsqlTest.cs b/test/EFCore.PG.NodaTime.FunctionalTests/NodaTimeQueryNpgsqlTest.cs index f59bcf5ef..7841a2a3c 100644 --- a/test/EFCore.PG.NodaTime.FunctionalTests/NodaTimeQueryNpgsqlTest.cs +++ b/test/EFCore.PG.NodaTime.FunctionalTests/NodaTimeQueryNpgsqlTest.cs @@ -1212,12 +1212,12 @@ public async Task Interval_RangeAgg(bool async) AssertSql( """ -SELECT range_agg(t."Interval") +SELECT range_agg(n0."Interval") FROM ( SELECT n."Interval", TRUE AS "Key" FROM "NodaTimeTypes" AS n -) AS t -GROUP BY t."Key" +) AS n0 +GROUP BY n0."Key" LIMIT 2 """); } @@ -1242,12 +1242,12 @@ public async Task Interval_Intersect_aggregate(bool async) AssertSql( """ -SELECT range_intersect_agg(t."Interval") +SELECT range_intersect_agg(n0."Interval") FROM ( SELECT n."Interval", TRUE AS "Key" FROM "NodaTimeTypes" AS n -) AS t -GROUP BY t."Key" +) AS n0 +GROUP BY n0."Key" LIMIT 2 """); } @@ -1420,12 +1420,12 @@ public async Task DateInterval_RangeAgg(bool async) AssertSql( """ -SELECT range_agg(t."DateInterval") +SELECT range_agg(n0."DateInterval") FROM ( SELECT n."DateInterval", TRUE AS "Key" FROM "NodaTimeTypes" AS n -) AS t -GROUP BY t."Key" +) AS n0 +GROUP BY n0."Key" LIMIT 2 """); } @@ -1449,12 +1449,12 @@ public async Task DateInterval_Intersect_aggregate(bool async) AssertSql( """ -SELECT range_intersect_agg(t."DateInterval") +SELECT range_intersect_agg(n0."DateInterval") FROM ( SELECT n."DateInterval", TRUE AS "Key" FROM "NodaTimeTypes" AS n -) AS t -GROUP BY t."Key" +) AS n0 +GROUP BY n0."Key" LIMIT 2 """); } diff --git a/test/EFCore.PG.Tests/Storage/NpgsqlArrayValueConverterTest.cs b/test/EFCore.PG.Tests/Storage/NpgsqlArrayValueConverterTest.cs index 0f16dd6b2..65c1be941 100644 --- a/test/EFCore.PG.Tests/Storage/NpgsqlArrayValueConverterTest.cs +++ b/test/EFCore.PG.Tests/Storage/NpgsqlArrayValueConverterTest.cs @@ -12,12 +12,12 @@ public void Can_convert_enum_arrays_to_number_arrays() { var converter = EnumArrayToNumberArray.ConvertToProviderExpression.Compile(); - Assert.Equal([7], converter([Beatles.John])); - Assert.Equal([4], converter([Beatles.Paul])); - Assert.Equal([1], converter([Beatles.George])); - Assert.Equal([-1], converter([Beatles.Ringo])); - Assert.Equal([77], converter([(Beatles)77])); - Assert.Equal([0], converter([default(Beatles)])); + Assert.Equal(new[] { 7 }, converter([Beatles.John])); + Assert.Equal(new[] { 4 }, converter([Beatles.Paul])); + Assert.Equal(new[] { 1 }, converter([Beatles.George])); + Assert.Equal(new[] { -1 }, converter([Beatles.Ringo])); + Assert.Equal(new[] { 77 }, converter([(Beatles)77])); + Assert.Equal(new[] { 0 }, converter([default(Beatles)])); Assert.Null(converter(null)); }