Skip to content

Commit

Permalink
Merge branch 'hotfix/5.0.5' into stable
Browse files Browse the repository at this point in the history
  • Loading branch information
roji committed Apr 16, 2021
2 parents 6b0b62c + 98b5106 commit 68ae233
Show file tree
Hide file tree
Showing 27 changed files with 326 additions and 139 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<Copyright>Copyright 2020 © The Npgsql Development Team</Copyright>
<Company>Npgsql</Company>
<VersionPrefix>5.0.2</VersionPrefix>
<VersionPrefix>5.0.5</VersionPrefix>
<TargetFrameworks>netstandard2.1</TargetFrameworks>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<PackageLicenseExpression>PostgreSQL</PackageLicenseExpression>
Expand Down
4 changes: 2 additions & 2 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project>
<PropertyGroup>
<EFCoreVersion>5.0.2</EFCoreVersion>
<EFCoreVersion>5.0.5</EFCoreVersion>
<MicrosoftExtensionsVersion>5.0.0</MicrosoftExtensionsVersion>
<NpgsqlVersion>5.0.2</NpgsqlVersion>
<NpgsqlVersion>5.0.4</NpgsqlVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
73 changes: 73 additions & 0 deletions src/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Code analysis rules and configuration

root = false

# Code files
[*.cs]

# Design rules

# CA1001: Types that own disposable fields should be disposable
dotnet_diagnostic.CA1001.severity = error

# Globalization rules

# CA1303: Do not pass literals as localized parameters
dotnet_diagnostic.CA1303.severity = none

# CA1304: Specify CultureInfo
dotnet_diagnostic.CA1304.severity = error

# CA1305: Specify IFormatProvider
dotnet_diagnostic.CA1305.severity = none

# CA1307: Specify StringComparison for clarity
dotnet_diagnostic.CA1307.severity = none

# CA1308: Normalize strings to uppercase
dotnet_diagnostic.CA1308.severity = none

# CA1309: Use ordinal stringcomparison
dotnet_diagnostic.CA1309.severity = error

# CA1310: Specify StringComparison for correctness
dotnet_diagnostic.CA1310.severity = error

# CA2101: Specify marshaling for P/Invoke string arguments
dotnet_diagnostic.CA2101.severity = error

# Reliability Rules

# CA2000: Dispose objects before losing scope
# Not reliable enough - false positives
dotnet_diagnostic.CA2000.severity = suggestion

# CA2002: Do not lock on objects with weak identity
dotnet_diagnostic.CA2002.severity = error

# CA2007: Consider calling ConfigureAwait on the awaited task
dotnet_diagnostic.CA2007.severity = error

# CA2008: Do not create tasks without passing a TaskScheduler
dotnet_diagnostic.CA2008.severity = error

# CA2009: Do not call ToImmutableCollection on an ImmutableCollection value
dotnet_diagnostic.CA2009.severity = error

# CA2011: Avoid infinite recursion
dotnet_diagnostic.CA2011.severity = error

# CA2012: Use ValueTasks correctly
dotnet_diagnostic.CA2012.severity = error

# CA2013: Do not use ReferenceEquals with value types
dotnet_diagnostic.CA2013.severity = error

# CA2014: Do not use stackalloc in loops
dotnet_diagnostic.CA2014.severity = error

# CA2015: Do not define finalizers for types derived from MemoryManager<T>
dotnet_diagnostic.CA2015.severity = error

# CA2016: Forward the 'CancellationToken' parameter to methods that take one
dotnet_diagnostic.CA2016.severity = error
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Storage;
using NetTopologySuite.Geometries;
Expand Down Expand Up @@ -110,26 +110,26 @@ public static bool TryParseStoreTypeName(
return false;
}

subtypeName = subtypeName.ToUpper();
subtypeName = subtypeName.ToUpper(CultureInfo.InvariantCulture);

// We have geometry(subtype, srid), parse the subtype (POINT, POINTZ, POINTM, POINTZM...)

if (TryGetClrType(subtypeName, out clrType))
return true;

if (subtypeName.EndsWith("ZM") && TryGetClrType(subtypeName[0..^2], out clrType))
if (subtypeName.EndsWith("ZM", StringComparison.Ordinal) && TryGetClrType(subtypeName[0..^2], out clrType))
{
ordinates = Ordinates.XYZM;
return true;
}

if (subtypeName.EndsWith("M") && TryGetClrType(subtypeName[0..^1], out clrType))
if (subtypeName.EndsWith("M", StringComparison.Ordinal) && TryGetClrType(subtypeName[0..^1], out clrType))
{
ordinates = Ordinates.XYM;
return true;
}

if (subtypeName.EndsWith("Z") && TryGetClrType(subtypeName[0..^1], out clrType))
if (subtypeName.EndsWith("Z", StringComparison.Ordinal) && TryGetClrType(subtypeName[0..^1], out clrType))
{
ordinates = Ordinates.XYZ;
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ protected virtual RelationalTypeMapping FindArrayMapping(in RelationalTypeMappin
if (storeType != null)
{
// PostgreSQL array type names are the element plus []
if (!storeType.EndsWith("[]"))
if (!storeType.EndsWith("[]", StringComparison.Ordinal))
return null;

var elementStoreType = storeType.Substring(0, storeType.Length - 2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ protected override bool IsHandledByConvention(IModel model, IAnnotation annotati
Check.NotNull(annotation, nameof(annotation));

if (annotation.Name == RelationalAnnotationNames.DefaultSchema
&& string.Equals("public", (string)annotation.Value))
&& (string)annotation.Value == "public")
{
return true;
}
Expand All @@ -38,7 +38,7 @@ protected override bool IsHandledByConvention(IIndex index, IAnnotation annotati
Check.NotNull(annotation, nameof(annotation));

if (annotation.Name == NpgsqlAnnotationNames.IndexMethod
&& string.Equals("btree", (string)annotation.Value))
&& (string)annotation.Value == "btree")
{
return true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
Expand All @@ -18,7 +19,7 @@ public static class NpgsqlEntityTypeExtensions

public static Dictionary<string, object> GetStorageParameters([NotNull] this IEntityType entityType)
=> entityType.GetAnnotations()
.Where(a => a.Name.StartsWith(NpgsqlAnnotationNames.StorageParameterPrefix))
.Where(a => a.Name.StartsWith(NpgsqlAnnotationNames.StorageParameterPrefix, StringComparison.Ordinal))
.ToDictionary(
a => a.Name.Substring(NpgsqlAnnotationNames.StorageParameterPrefix.Length),
a => a.Value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public override IEnumerable<IAnnotation> For(ITable table)
if (entityType[CockroachDbAnnotationNames.InterleaveInParent] != null)
yield return new Annotation(CockroachDbAnnotationNames.InterleaveInParent, entityType[CockroachDbAnnotationNames.InterleaveInParent]);
foreach (var storageParamAnnotation in entityType.GetAnnotations()
.Where(a => a.Name.StartsWith(NpgsqlAnnotationNames.StorageParameterPrefix)))
.Where(a => a.Name.StartsWith(NpgsqlAnnotationNames.StorageParameterPrefix, StringComparison.Ordinal)))
{
yield return storageParamAnnotation;
}
Expand Down
4 changes: 2 additions & 2 deletions src/EFCore.PG/Migrations/NpgsqlMigrationsSqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1648,7 +1648,7 @@ public virtual void Transfer(

Dictionary<string, string> GetStorageParameters(Annotatable annotatable)
=> annotatable.GetAnnotations()
.Where(a => a.Name.StartsWith(NpgsqlAnnotationNames.StorageParameterPrefix))
.Where(a => a.Name.StartsWith(NpgsqlAnnotationNames.StorageParameterPrefix, StringComparison.Ordinal))
.ToDictionary(
a => a.Name.Substring(NpgsqlAnnotationNames.StorageParameterPrefix.Length),
a => GenerateStorageParameterValue(a.Value)
Expand Down Expand Up @@ -1703,7 +1703,7 @@ string IndexColumnList(IndexColumn[] columns, string method)

// Of the built-in access methods, only btree (the default) supports
// sorting, thus we only want to emit sort options for btree indexes.
if (method == null || string.Equals(method, "btree"))
if (method == null || method == "btree")
{
if (column.SortOrder == SortOrder.Descending)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,15 @@ arrayOrList.TypeMapping is NpgsqlArrayTypeMapping
case SqlConstantExpression:
return null;

// Similar to ParameterExpression below, but when a bare subquery is present inside ANY(), PostgreSQL just compares
// against each of its resulting rows (just like IN). To "extract" the array result of the scalar subquery, we need to
// add an explicit cast (see #1803).
case ScalarSubqueryExpression subqueryExpression:
return _sqlExpressionFactory.Any(
item,
_sqlExpressionFactory.Convert(subqueryExpression, subqueryExpression.Type, subqueryExpression.TypeMapping),
PostgresAnyOperatorType.Equal);

// For ParameterExpression, and for all other cases - e.g. array returned from some function -
// translate to e.SomeText = ANY (@p). This is superior to the general solution which will expand
// parameters to constants, since non-PG SQL does not support arrays.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public virtual SqlExpression Translate(
typeof(int));
}

if (method.Name.StartsWith("TryGet") && arguments.Count == 0)
if (method.Name.StartsWith("TryGet", StringComparison.Ordinal) && arguments.Count == 0)
throw new InvalidOperationException($"The TryGet* methods on {nameof(JsonElement)} aren't translated yet, use Get* instead.'");

return null;
Expand Down
7 changes: 4 additions & 3 deletions src/EFCore.PG/Query/Internal/NpgsqlQuerySqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -317,9 +317,10 @@ protected override Expression VisitSqlUnary(SqlUnaryExpression sqlUnaryExpressio
// where there's no precedence issues
switch (sqlUnaryExpression.Operand)
{
case SqlConstantExpression _:
case SqlParameterExpression _:
case SqlFunctionExpression _:
case SqlConstantExpression:
case SqlParameterExpression:
case SqlFunctionExpression:
case ScalarSubqueryExpression:
var storeType = sqlUnaryExpression.TypeMapping.StoreType;
if (storeType == "integer")
storeType = "INT"; // Shorthand that looks better in SQL
Expand Down
47 changes: 22 additions & 25 deletions src/EFCore.PG/Query/NpgsqlSqlExpressionFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ public virtual PostgresBinaryExpression AtTimeZone(
RelationalTypeMapping FlipTimestampTypeMapping(RelationalTypeMapping mapping)
{
var storeType = mapping.StoreType;
if (storeType.StartsWith("timestamp with time zone") || storeType.StartsWith("timestamptz"))
if (storeType.StartsWith("timestamp with time zone", StringComparison.Ordinal) || storeType.StartsWith("timestamptz", StringComparison.Ordinal))
return _typeMappingSource.FindMapping("timestamp without time zone");
if (storeType.StartsWith("timestamp without time zone") || storeType.StartsWith("timestamp"))
if (storeType.StartsWith("timestamp without time zone", StringComparison.Ordinal) || storeType.StartsWith("timestamp", StringComparison.Ordinal))
return _typeMappingSource.FindMapping("timestamp with time zone");
throw new ArgumentException($"timestamp argument to AtTimeZone had unknown store type {storeType}", nameof(timestamp));
}
Expand Down Expand Up @@ -279,34 +279,29 @@ SqlExpression ApplyTypeMappingOnSqlBinary(SqlBinaryExpression binary, Relational
var leftType = left.Type.UnwrapNullableType();
var rightType = right.Type.UnwrapNullableType();

if (binary.OperatorType == ExpressionType.Add)
// Note that we apply the given type mapping from above to the left operand (which has the same CLR type as
// the binary expression's)

// DateTime + TimeSpan => DateTime
// DateTimeOffset + TimeSpan => DateTimeOffset
if (rightType == typeof(TimeSpan) && (
leftType == typeof(DateTime) ||
leftType == typeof(DateTimeOffset)) ||
rightType.FullName == "NodaTime.Period" && (
leftType.FullName == "NodaTime.LocalDateTime" ||
leftType.FullName == "NodaTime.LocalDate" ||
leftType.FullName == "NodaTime.LocalTime") ||
rightType.FullName == "NodaTime.Duration" && (
leftType.FullName == "NodaTime.Instant" ||
leftType.FullName == "NodaTime.ZonedDateTime"))
{
// Note that we apply the given type mapping from above to the left operand (which has the same CLR type as
// the binary expression's)

// DateTime + TimeSpan => DateTime
// DateTimeOffset + TimeSpan => DateTimeOffset
if (rightType == typeof(TimeSpan) && (
leftType == typeof(DateTime) ||
leftType == typeof(DateTimeOffset)) ||
rightType.FullName == "NodaTime.Period" && (
leftType.FullName == "NodaTime.LocalDateTime" ||
leftType.FullName == "NodaTime.LocalDate" ||
leftType.FullName == "NodaTime.LocalTime") ||
rightType.FullName == "NodaTime.Duration" && (
leftType.FullName == "NodaTime.Instant" ||
leftType.FullName == "NodaTime.ZonedDateTime"))
{
var newLeft = ApplyTypeMapping(left, typeMapping);
var newRight = ApplyDefaultTypeMapping(right);
return new SqlBinaryExpression(binary.OperatorType, newLeft, newRight, binary.Type, newLeft.TypeMapping);
}
var newLeft = ApplyTypeMapping(left, typeMapping);
var newRight = ApplyDefaultTypeMapping(right);
return new SqlBinaryExpression(binary.OperatorType, newLeft, newRight, binary.Type, newLeft.TypeMapping);
}

if (binary.OperatorType == ExpressionType.Subtract)
{
var inferredTypeMapping = typeMapping ?? ExpressionExtensions.InferTypeMapping(left, right);

// DateTime - DateTime => TimeSpan
// DateTimeOffset - DateTimeOffset => TimeSpan
// Instant - Instant => Duration
Expand All @@ -319,6 +314,8 @@ SqlExpression ApplyTypeMappingOnSqlBinary(SqlBinaryExpression binary, Relational
leftType.FullName == "NodaTime.LocalDate" && rightType.FullName == "NodaTime.LocalDate" ||
leftType.FullName == "NodaTime.LocalTime" && rightType.FullName == "NodaTime.LocalTime")
{
var inferredTypeMapping = typeMapping ?? ExpressionExtensions.InferTypeMapping(left, right);

return new SqlBinaryExpression(
ExpressionType.Subtract,
ApplyTypeMapping(left, inferredTypeMapping),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ NOT indisprimary AND

var columnCollations = record
.GetValueOrDefault<uint[]>("indcollation")
.Select(oid => collations.TryGetValue(oid, out var collation) && !string.Equals(collation, "default") ? collation : null)
.Select(oid => collations.TryGetValue(oid, out var collation) && collation != "default" ? collation : null)
.ToArray();

if (columnCollations.Any(coll => coll != null))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using Microsoft.EntityFrameworkCore.Storage;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Storage;

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal
{
public interface INpgsqlRelationalConnection : IRelationalConnection
{
INpgsqlRelationalConnection CreateMasterConnection();

NpgsqlRelationalConnection CloneWith([NotNull] string connectionString);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ protected NpgsqlTimestampTypeMapping(RelationalTypeMappingParameters parameters)
protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters)
=> new NpgsqlTimestampTypeMapping(parameters);

protected override string ProcessStoreType(RelationalTypeMappingParameters parameters, string storeType, string _)
=> parameters.Precision is null ? storeType : $"timestamp({parameters.Precision}) without time zone";

protected override string GenerateNonNullSqlLiteral(object value)
=> FormattableString.Invariant($"TIMESTAMP '{(DateTime)value:yyyy-MM-dd HH:mm:ss.FFFFFF}'");
}
Expand All @@ -30,6 +33,9 @@ protected NpgsqlTimestampTzTypeMapping(RelationalTypeMappingParameters parameter
protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters)
=> new NpgsqlTimestampTzTypeMapping(parameters);

protected override string ProcessStoreType(RelationalTypeMappingParameters parameters, string storeType, string _)
=> parameters.Precision is null ? storeType : $"timestamp({parameters.Precision}) with time zone";

protected override string GenerateNonNullSqlLiteral(object value)
{
switch (value)
Expand Down Expand Up @@ -109,6 +115,9 @@ protected NpgsqlIntervalTypeMapping(RelationalTypeMappingParameters parameters)
protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters)
=> new NpgsqlIntervalTypeMapping(parameters);

protected override string ProcessStoreType(RelationalTypeMappingParameters parameters, string storeType, string _)
=> parameters.Precision is null ? storeType : $"interval({parameters.Precision})";

protected override string GenerateNonNullSqlLiteral(object value)
=> FormatTimeSpanAsInterval((TimeSpan)value);

Expand Down
24 changes: 24 additions & 0 deletions src/EFCore.PG/Storage/Internal/Mapping/NpgsqlDecimalTypeMapping.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Microsoft.EntityFrameworkCore.Storage;

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.Mapping
{
public class NpgsqlDecimalTypeMapping : DecimalTypeMapping
{
public NpgsqlDecimalTypeMapping() : base("numeric", System.Data.DbType.Decimal) {}

protected NpgsqlDecimalTypeMapping(RelationalTypeMappingParameters parameters)
: base(parameters)
{
}

protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters)
=> new NpgsqlDecimalTypeMapping(parameters);

protected override string ProcessStoreType(RelationalTypeMappingParameters parameters, string storeType, string _)
=> parameters.Precision is null
? storeType
: parameters.Scale is null
? $"numeric({parameters.Precision})"
: $"numeric({parameters.Precision},{parameters.Scale})";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ protected NpgsqlMoneyTypeMapping(RelationalTypeMappingParameters parameters)
}

protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters)
=> new NpgsqlMoneyTypeMapping();
=> new NpgsqlMoneyTypeMapping(parameters);

protected override string GenerateNonNullSqlLiteral(object value)
=> base.GenerateNonNullSqlLiteral(value) + "::money";
Expand Down
Loading

0 comments on commit 68ae233

Please sign in to comment.