Skip to content

Commit f818704

Browse files
committed
Bump dependency versions
1 parent bab35a7 commit f818704

9 files changed

+281
-121
lines changed

Directory.Packages.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<Project>
22
<PropertyGroup>
3-
<EFCoreVersion>8.0.0</EFCoreVersion>
3+
<EFCoreVersion>8.0.2</EFCoreVersion>
44
<MicrosoftExtensionsVersion>8.0.0</MicrosoftExtensionsVersion>
5-
<NpgsqlVersion>8.0.0</NpgsqlVersion>
5+
<NpgsqlVersion>8.0.2</NpgsqlVersion>
66
</PropertyGroup>
77

88
<ItemGroup>

src/EFCore.PG/Query/Internal/NpgsqlQuerySqlGenerator.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,11 @@ protected override Expression VisitValues(ValuesExpression valuesExpression)
760760
/// </summary>
761761
protected override void GenerateValues(ValuesExpression valuesExpression)
762762
{
763+
if (valuesExpression.RowValues.Count == 0)
764+
{
765+
throw new InvalidOperationException(RelationalStrings.EmptyCollectionNotSupportedAsInlineQueryRoot);
766+
}
767+
763768
// PostgreSQL supports providing the names of columns projected out of VALUES: (VALUES (1, 3), (2, 4)) AS x(a, b).
764769
// But since other databases sometimes don't, the default relational implementation is complex, involving a SELECT for the first row
765770
// and a UNION All on the rest. Override to do the nice simple thing.

src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitor.cs

Lines changed: 37 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -267,14 +267,15 @@ protected override Expression ApplyInferredTypeMappings(
267267
{
268268
if (source.QueryExpression is SelectExpression
269269
{
270-
Tables: [(PgUnnestExpression or ValuesExpression { ColumnNames: ["_ord", "Value"] }) and var sourceTable],
270+
Tables: [var sourceTable],
271271
Predicate: null,
272272
GroupBy: [],
273273
Having: null,
274274
IsDistinct: false,
275275
Limit: null,
276276
Offset: null
277277
}
278+
&& TryGetArray(sourceTable, out var array)
278279
&& TranslateLambdaExpression(source, predicate) is { } translatedPredicate)
279280
{
280281
switch (translatedPredicate)
@@ -291,7 +292,7 @@ protected override Expression ApplyInferredTypeMappings(
291292
{
292293
return BuildSimplifiedShapedQuery(
293294
source,
294-
_sqlExpressionFactory.All(match, GetArray(sourceTable), PgAllOperatorType.Like));
295+
_sqlExpressionFactory.All(match, array, PgAllOperatorType.Like));
295296
}
296297

297298
// Pattern match for: new[] { "a", "b", "c" }.All(p => EF.Functions.Like(e.SomeText, p)),
@@ -306,7 +307,7 @@ protected override Expression ApplyInferredTypeMappings(
306307
{
307308
return BuildSimplifiedShapedQuery(
308309
source,
309-
_sqlExpressionFactory.All(match, GetArray(sourceTable), PgAllOperatorType.ILike));
310+
_sqlExpressionFactory.All(match, array, PgAllOperatorType.ILike));
310311
}
311312

312313
// Pattern match for: e.SomeArray.All(p => ints.Contains(p)) over non-column,
@@ -318,7 +319,7 @@ protected override Expression ApplyInferredTypeMappings(
318319
}
319320
when sourceColumn.Table == sourceTable:
320321
{
321-
return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.ContainedBy(GetArray(sourceTable), otherArray));
322+
return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.ContainedBy(array, otherArray));
322323
}
323324

324325
// Pattern match for: new[] { 4, 5 }.All(p => e.SomeArray.Contains(p)) over column,
@@ -331,7 +332,7 @@ protected override Expression ApplyInferredTypeMappings(
331332
}
332333
when sourceColumn.Table == sourceTable:
333334
{
334-
return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.ContainedBy(GetArray(sourceTable), otherArray));
335+
return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.ContainedBy(array, otherArray));
335336
}
336337
}
337338
}
@@ -349,14 +350,15 @@ protected override Expression ApplyInferredTypeMappings(
349350
{
350351
if (source.QueryExpression is SelectExpression
351352
{
352-
Tables: [(PgUnnestExpression or ValuesExpression { ColumnNames: ["_ord", "Value"] }) and var sourceTable],
353+
Tables: [var sourceTable],
353354
Predicate: null,
354355
GroupBy: [],
355356
Having: null,
356357
IsDistinct: false,
357358
Limit: null,
358359
Offset: null
359-
})
360+
}
361+
&& TryGetArray(sourceTable, out var array))
360362
{
361363
// Pattern match: x.Array.Any()
362364
// Translation: cardinality(x.array) > 0 instead of EXISTS (SELECT 1 FROM FROM unnest(x.Array))
@@ -367,7 +369,7 @@ protected override Expression ApplyInferredTypeMappings(
367369
_sqlExpressionFactory.GreaterThan(
368370
_sqlExpressionFactory.Function(
369371
"cardinality",
370-
new[] { GetArray(sourceTable) },
372+
new[] { array },
371373
nullable: true,
372374
argumentsPropagateNullability: TrueArrays[1],
373375
typeof(int)),
@@ -392,7 +394,7 @@ protected override Expression ApplyInferredTypeMappings(
392394
when pattern.Table == sourceTable:
393395
{
394396
return BuildSimplifiedShapedQuery(
395-
source, _sqlExpressionFactory.Any(match, GetArray(sourceTable), PgAnyOperatorType.Like));
397+
source, _sqlExpressionFactory.Any(match, array, PgAnyOperatorType.Like));
396398
}
397399

398400
// Pattern match: new[] { "a", "b", "c" }.Any(p => EF.Functions.Like(e.SomeText, p))
@@ -406,7 +408,7 @@ protected override Expression ApplyInferredTypeMappings(
406408
when pattern.Table == sourceTable:
407409
{
408410
return BuildSimplifiedShapedQuery(
409-
source, _sqlExpressionFactory.Any(match, GetArray(sourceTable), PgAnyOperatorType.ILike));
411+
source, _sqlExpressionFactory.Any(match, array, PgAnyOperatorType.ILike));
410412
}
411413

412414
// Array overlap over non-column
@@ -419,7 +421,7 @@ protected override Expression ApplyInferredTypeMappings(
419421
}
420422
when sourceColumn.Table == sourceTable:
421423
{
422-
return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.Overlaps(GetArray(sourceTable), otherArray));
424+
return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.Overlaps(array, otherArray));
423425
}
424426

425427
// Array overlap over column
@@ -433,7 +435,7 @@ protected override Expression ApplyInferredTypeMappings(
433435
}
434436
when sourceColumn.Table == sourceTable:
435437
{
436-
return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.Overlaps(GetArray(sourceTable), otherArray));
438+
return BuildSimplifiedShapedQuery(source, _sqlExpressionFactory.Overlaps(array, otherArray));
437439
}
438440

439441
#region LTree translations
@@ -453,7 +455,7 @@ protected override Expression ApplyInferredTypeMappings(
453455
new PgBinaryExpression(
454456
PgExpressionType.LTreeMatchesAny,
455457
ltree,
456-
_sqlExpressionFactory.ApplyTypeMapping(GetArray(sourceTable), _typeMappingSource.FindMapping("lquery[]")),
458+
_sqlExpressionFactory.ApplyTypeMapping(array, _typeMappingSource.FindMapping("lquery[]")),
457459
typeof(bool),
458460
typeMapping: _typeMappingSource.FindMapping(typeof(bool))));
459461
}
@@ -475,7 +477,7 @@ protected override Expression ApplyInferredTypeMappings(
475477
source,
476478
new PgBinaryExpression(
477479
operatorType,
478-
_sqlExpressionFactory.ApplyDefaultTypeMapping(GetArray(sourceTable)),
480+
_sqlExpressionFactory.ApplyDefaultTypeMapping(array),
479481
ltree,
480482
typeof(bool),
481483
typeMapping: _typeMappingSource.FindMapping(typeof(bool))));
@@ -497,7 +499,7 @@ protected override Expression ApplyInferredTypeMappings(
497499
source,
498500
new PgBinaryExpression(
499501
PgExpressionType.LTreeMatches,
500-
_sqlExpressionFactory.ApplyDefaultTypeMapping(GetArray(sourceTable)),
502+
_sqlExpressionFactory.ApplyDefaultTypeMapping(array),
501503
lquery,
502504
typeof(bool),
503505
typeMapping: _typeMappingSource.FindMapping(typeof(bool))));
@@ -518,7 +520,7 @@ protected override Expression ApplyInferredTypeMappings(
518520
source,
519521
new PgBinaryExpression(
520522
PgExpressionType.LTreeMatchesAny,
521-
_sqlExpressionFactory.ApplyDefaultTypeMapping(GetArray(sourceTable)),
523+
_sqlExpressionFactory.ApplyDefaultTypeMapping(array),
522524
lqueries,
523525
typeof(bool),
524526
typeMapping: _typeMappingSource.FindMapping(typeof(bool))));
@@ -578,26 +580,20 @@ protected override Expression ApplyInferredTypeMappings(
578580
/// </summary>
579581
protected override ShapedQueryExpression? TranslateContains(ShapedQueryExpression source, Expression item)
580582
{
583+
// Note that most other simplifications convert ValuesExpression to unnest over array constructor, but we avoid doing that
584+
// here for Contains, since the relational translation for ValuesExpression is better.
581585
if (source.QueryExpression is SelectExpression
582586
{
583-
Tables: [(PgUnnestExpression or ValuesExpression { ColumnNames: ["_ord", "Value"] }) and var sourceTable],
587+
Tables: [PgUnnestExpression { Array: var array }],
584588
Predicate: null,
585589
GroupBy: [],
586590
Having: null,
587591
IsDistinct: false,
588592
Limit: null,
589593
Offset: null
590-
})
591-
{
592-
if (TranslateExpression(item, applyDefaultTypeMapping: false) is not SqlExpression translatedItem)
593-
{
594-
return null;
595594
}
596-
597-
// Note that most other simplifications here convert ValuesExpression to unnest over array constructor, but we avoid doing that
598-
// here, since the relational translation for ValuesExpression is better.
599-
var array = GetArray(sourceTable);
600-
595+
&& TranslateExpression(item, applyDefaultTypeMapping: false) is SqlExpression translatedItem)
596+
{
601597
(translatedItem, array) = _sqlExpressionFactory.ApplyTypeMappingsOnItemAndArray(translatedItem, array);
602598

603599
// When the array is a column, we translate Contains to array @> ARRAY[item]. GIN indexes on array are used, but null
@@ -823,7 +819,7 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s
823819
// select expression should already contain our predicate.
824820
if (source.QueryExpression is SelectExpression
825821
{
826-
Tables: [(PgUnnestExpression or ValuesExpression { ColumnNames: ["_ord", "Value"] }) and var sourceTable],
822+
Tables: [var sourceTable],
827823
Predicate: var translatedPredicate,
828824
GroupBy: [],
829825
Having: null,
@@ -832,6 +828,7 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s
832828
Offset: null,
833829
Orderings: []
834830
}
831+
&& TryGetArray(sourceTable, out var array)
835832
&& translatedPredicate is null ^ predicate is null)
836833
{
837834
if (translatedPredicate is null)
@@ -864,7 +861,7 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s
864861
operatorType == PgExpressionType.Contains
865862
? PgExpressionType.LTreeFirstAncestor
866863
: PgExpressionType.LTreeFirstDescendent,
867-
_sqlExpressionFactory.ApplyDefaultTypeMapping(GetArray(sourceTable)),
864+
_sqlExpressionFactory.ApplyDefaultTypeMapping(array),
868865
ltree,
869866
typeof(LTree),
870867
_typeMappingSource.FindMapping(typeof(LTree))));
@@ -886,7 +883,7 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s
886883
source,
887884
new PgBinaryExpression(
888885
PgExpressionType.LTreeFirstMatches,
889-
_sqlExpressionFactory.ApplyDefaultTypeMapping(GetArray(sourceTable)),
886+
_sqlExpressionFactory.ApplyDefaultTypeMapping(array),
890887
lquery,
891888
typeof(LTree),
892889
_typeMappingSource.FindMapping(typeof(LTree))));
@@ -1226,18 +1223,17 @@ private ShapedQueryExpression BuildSimplifiedShapedQuery(ShapedQueryExpression s
12261223
/// Extracts the <see cref="PgUnnestExpression.Array" /> out of <see cref="PgUnnestExpression" />.
12271224
/// If a <see cref="ValuesExpression" /> is given, converts its literal values into a <see cref="PgNewArrayExpression" />.
12281225
/// </summary>
1229-
private SqlExpression GetArray(TableExpressionBase tableExpression)
1226+
private bool TryGetArray(TableExpressionBase tableExpression, [NotNullWhen(true)] out SqlExpression? array)
12301227
{
1231-
Check.DebugAssert(
1232-
tableExpression is PgUnnestExpression or ValuesExpression { ColumnNames: ["_ord", "Value"] },
1233-
"Bad tableExpression");
1234-
12351228
switch (tableExpression)
12361229
{
12371230
case PgUnnestExpression unnest:
1238-
return unnest.Array;
1231+
array = unnest.Array;
1232+
return true;
12391233

1240-
case ValuesExpression valuesExpression:
1234+
// TODO: We currently don't have information type information on empty ValuesExpression, so we can't transform that into an
1235+
// array.
1236+
case ValuesExpression { ColumnNames: ["_ord", "Value"], RowValues.Count: > 0 } valuesExpression:
12411237
{
12421238
// The source table was a constant collection, so translated by default to ValuesExpression. Convert it to an unnest over
12431239
// an array constructor.
@@ -1249,12 +1245,14 @@ private SqlExpression GetArray(TableExpressionBase tableExpression)
12491245
elements[i] = valuesExpression.RowValues[i].Values[1];
12501246
}
12511247

1252-
return new PgNewArrayExpression(
1248+
array = new PgNewArrayExpression(
12531249
elements, valuesExpression.RowValues[0].Values[1].Type.MakeArrayType(), typeMapping: null);
1250+
return true;
12541251
}
12551252

12561253
default:
1257-
throw new ArgumentException(nameof(tableExpression));
1254+
array = null;
1255+
return false;
12581256
}
12591257
}
12601258

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#nullable enable
2+
3+
namespace Npgsql.EntityFrameworkCore.PostgreSQL;
4+
5+
public class BadDataJsonDeserializationNpgsqlTest : BadDataJsonDeserializationTestBase
6+
{
7+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
8+
=> base.OnConfiguring(optionsBuilder.UseNpgsql(b => b.UseNetTopologySuite()));
9+
}

test/EFCore.PG.FunctionalTests/Query/FunkyDataQueryNpgsqlTest.cs

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -35,30 +35,6 @@ await AssertQuery(
3535
ss => ss.Set<FunkyCustomer>().Where(c => c.FirstName != null && c.FirstName.StartsWith(param)));
3636
}
3737

38-
[ConditionalTheory] // TODO: Remove, test was introduced upstream
39-
[MemberData(nameof(IsAsyncData))]
40-
public virtual async Task String_Contains_and_StartsWith_with_same_parameter(bool async)
41-
{
42-
var s = "B";
43-
44-
await AssertQuery(
45-
async,
46-
ss => ss.Set<FunkyCustomer>().Where(
47-
c => c.FirstName.Contains(s) || c.LastName.StartsWith(s)),
48-
ss => ss.Set<FunkyCustomer>().Where(
49-
c => c.FirstName.MaybeScalar(f => f.Contains(s)) == true || c.LastName.MaybeScalar(l => l.StartsWith(s)) == true));
50-
51-
AssertSql(
52-
"""
53-
@__s_0_contains='%B%'
54-
@__s_0_startswith='B%'
55-
56-
SELECT f."Id", f."FirstName", f."LastName", f."NullableBool"
57-
FROM "FunkyCustomers" AS f
58-
WHERE f."FirstName" LIKE @__s_0_contains ESCAPE '\' OR f."LastName" LIKE @__s_0_startswith ESCAPE '\'
59-
""");
60-
}
61-
6238
private void AssertSql(params string[] expected)
6339
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected);
6440

test/EFCore.PG.FunctionalTests/Query/JsonQueryAdHocNpgsqlTest.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,14 @@ protected override void SeedJunkInJson(MyContextJunkInJson ctx)
232232
'{{"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"}}}}',
233233
'{{"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"}}}}',
234234
1)
235+
""");
236+
237+
protected override void SeedTrickyBuffering(MyContextTrickyBuffering ctx)
238+
=> ctx.Database.ExecuteSqlRaw(
239+
"""
240+
INSERT INTO "Entities" ("Reference", "Id")
241+
VALUES(
242+
'{{"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)
235243
""");
236244

237245
protected override void SeedShadowProperties(MyContextShadowProperties ctx)

0 commit comments

Comments
 (0)