diff --git a/src/EFCore.PG/Query/Expressions/Internal/ArrayAnyAllExpression.cs b/src/EFCore.PG/Query/Expressions/Internal/ArrayAnyAllExpression.cs
index f7d15efc9..66d3338f3 100644
--- a/src/EFCore.PG/Query/Expressions/Internal/ArrayAnyAllExpression.cs
+++ b/src/EFCore.PG/Query/Expressions/Internal/ArrayAnyAllExpression.cs
@@ -93,23 +93,20 @@ public ArrayAnyAllExpression(
///
protected override Expression Accept(ExpressionVisitor visitor)
- => visitor is NpgsqlQuerySqlGenerator npsgqlGenerator
- ? npsgqlGenerator.VisitArrayAnyAll(this)
+ => visitor is NpgsqlQuerySqlGenerator npgsqlGenerator
+ ? npgsqlGenerator.VisitArrayAnyAll(this)
: base.Accept(visitor);
///
protected override Expression VisitChildren(ExpressionVisitor visitor)
{
- if (!(visitor.Visit(Operand) is Expression operand))
- throw new ArgumentException($"The {nameof(operand)} of a {nameof(ArrayAnyAllExpression)} cannot be null.");
-
- if (!(visitor.Visit(Array) is Expression collection))
- throw new ArgumentException($"The {nameof(collection)} of a {nameof(ArrayAnyAllExpression)} cannot be null.");
+ var operand = visitor.Visit(Operand) ?? Operand;
+ var array = visitor.Visit(Array) ?? Array;
return
- operand == Operand && collection == Array
- ? this
- : new ArrayAnyAllExpression(ArrayComparisonType, Operator, operand, collection);
+ operand != Operand || array != Array
+ ? new ArrayAnyAllExpression(ArrayComparisonType, Operator, operand, array)
+ : this;
}
///
@@ -131,8 +128,7 @@ public override int GetHashCode()
(397 * Array.GetHashCode()));
///
- public override string ToString()
- => $"{Operand} {Operator} {ArrayComparisonType.ToString()} ({Array})";
+ public override string ToString() => $"{Operand} {Operator} {ArrayComparisonType.ToString()} ({Array})";
}
///
diff --git a/src/EFCore.PG/Query/Expressions/Internal/AtTimeZoneExpression.cs b/src/EFCore.PG/Query/Expressions/Internal/AtTimeZoneExpression.cs
index e0021edb9..8528e8e05 100644
--- a/src/EFCore.PG/Query/Expressions/Internal/AtTimeZoneExpression.cs
+++ b/src/EFCore.PG/Query/Expressions/Internal/AtTimeZoneExpression.cs
@@ -1,4 +1,5 @@
#region License
+
// The PostgreSQL License
//
// Copyright (C) 2016 The Npgsql Development Team
@@ -19,6 +20,7 @@
// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
// ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
#endregion
using System;
@@ -29,42 +31,59 @@
namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.Expressions.Internal
{
+ ///
+ /// Represents a PostgreSQL AT TIME ZONE expression.
+ ///
public class AtTimeZoneExpression : Expression
{
- public AtTimeZoneExpression([NotNull] Expression timestampExpression, [NotNull] string timeZone)
- {
- Check.NotNull(timestampExpression, nameof(timestampExpression));
- Check.NotNull(timeZone, nameof(timeZone));
-
- TimestampExpression = timestampExpression;
- TimeZone = timeZone;
- }
-
- public Expression TimestampExpression { get; }
- public string TimeZone { get; }
-
+ ///
public override ExpressionType NodeType => ExpressionType.Extension;
+ ///
public override Type Type => typeof(DateTime);
- protected override Expression Accept([NotNull] ExpressionVisitor visitor)
+ ///
+ /// The timestamp.
+ ///
+ [NotNull]
+ public Expression Timestamp { get; }
+
+ ///
+ /// The time zone.
+ ///
+ [NotNull]
+ public string TimeZone { get; }
+
+ ///
+ /// Constructs an .
+ ///
+ /// The timestamp.
+ /// The time zone.
+ ///
+ public AtTimeZoneExpression([NotNull] Expression timestamp, [NotNull] string timeZone)
{
- Check.NotNull(visitor, nameof(visitor));
+ Timestamp = Check.NotNull(timestamp, nameof(timestamp));
+ TimeZone = Check.NotNull(timeZone, nameof(timeZone));
+ }
- return visitor is NpgsqlQuerySqlGenerator npgsqlGenerator
+ ///
+ protected override Expression Accept(ExpressionVisitor visitor)
+ => visitor is NpgsqlQuerySqlGenerator npgsqlGenerator
? npgsqlGenerator.VisitAtTimeZone(this)
: base.Accept(visitor);
- }
+ ///
protected override Expression VisitChildren(ExpressionVisitor visitor)
{
- var newTimestampExpression = visitor.Visit(TimestampExpression);
+ var timestamp = visitor.Visit(Timestamp) ?? Timestamp;
- return newTimestampExpression != TimestampExpression
- ? new AtTimeZoneExpression(newTimestampExpression, TimeZone)
- : this;
+ return
+ timestamp != Timestamp
+ ? new AtTimeZoneExpression(timestamp, TimeZone)
+ : this;
}
- public override string ToString() => $"{TimestampExpression} AT TIME ZONE {TimeZone}";
+ ///
+ public override string ToString() => $"{Timestamp} AT TIME ZONE {TimeZone}";
}
}
diff --git a/src/EFCore.PG/Query/Expressions/Internal/CustomBinaryExpression.cs b/src/EFCore.PG/Query/Expressions/Internal/CustomBinaryExpression.cs
index 617dbf1d6..17999c558 100644
--- a/src/EFCore.PG/Query/Expressions/Internal/CustomBinaryExpression.cs
+++ b/src/EFCore.PG/Query/Expressions/Internal/CustomBinaryExpression.cs
@@ -1,10 +1,8 @@
using System;
-using System.Linq;
using System.Linq.Expressions;
using JetBrains.Annotations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Query.Sql.Internal;
using Npgsql.EntityFrameworkCore.PostgreSQL.Utilities;
-using NpgsqlTypes;
namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.Expressions.Internal
{
@@ -14,49 +12,69 @@ namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.Expressions.Internal
///
public class CustomBinaryExpression : Expression
{
+ ///
+ public override ExpressionType NodeType => ExpressionType.Extension;
+
+ ///
+ public override Type Type { get; }
+
+ ///
+ /// The left-hand expression.
+ ///
+ [NotNull]
+ public Expression Left { get; }
+
+ ///
+ /// The right-hand expression.
+ ///
+ [NotNull]
+ public Expression Right { get; }
+
+ ///
+ /// The operator.
+ ///
+ [NotNull]
+ public string Operator { get; }
+
+ ///
+ /// Constructs a .
+ ///
+ /// The left-hand expression.
+ /// The right-hand expression.
+ /// The operator symbol acting on the expression.
+ /// The result type.
+ ///
public CustomBinaryExpression(
[NotNull] Expression left,
[NotNull] Expression right,
[NotNull] string binaryOperator,
[NotNull] Type type)
{
- Check.NotNull(right, nameof(right));
- Check.NotNull(left, nameof(left));
- Check.NotEmpty(binaryOperator, nameof(binaryOperator));
- Check.NotNull(type, nameof(type));
-
- Left = left;
- Right = right;
- Operator = binaryOperator;
- Type = type;
+ Left = Check.NotNull(left, nameof(left));
+ Right = Check.NotNull(right, nameof(right));
+ Operator = Check.NotEmpty(binaryOperator, nameof(binaryOperator));
+ Type = Check.NotNull(type, nameof(type));
}
- public Expression Left { get; }
- public Expression Right { get; }
- public string Operator { get; }
- public override Type Type { get; }
-
- public override ExpressionType NodeType => ExpressionType.Extension;
-
+ ///
protected override Expression Accept(ExpressionVisitor visitor)
- {
- Check.NotNull(visitor, nameof(visitor));
-
- return visitor is NpgsqlQuerySqlGenerator npgsqlGenerator
+ => visitor is NpgsqlQuerySqlGenerator npgsqlGenerator
? npgsqlGenerator.VisitCustomBinary(this)
: base.Accept(visitor);
- }
+ ///
protected override Expression VisitChildren(ExpressionVisitor visitor)
{
- var newLeft = visitor.Visit(Left);
- var newRight = visitor.Visit(Right);
+ var left = visitor.Visit(Left) ?? Left;
+ var right = visitor.Visit(Right) ?? Right;
- return newLeft != Left || newRight != Right
- ? new CustomBinaryExpression(newLeft, newRight, Operator, Type)
- : this;
+ return
+ left != Left || right != Right
+ ? new CustomBinaryExpression(left, right, Operator, Type)
+ : this;
}
+ ///
public override string ToString() => $"{Left} {Operator} {Right}";
}
}
diff --git a/src/EFCore.PG/Query/Expressions/Internal/CustomUnaryExpression.cs b/src/EFCore.PG/Query/Expressions/Internal/CustomUnaryExpression.cs
index 5a3bd7d46..b2bb7b8b2 100644
--- a/src/EFCore.PG/Query/Expressions/Internal/CustomUnaryExpression.cs
+++ b/src/EFCore.PG/Query/Expressions/Internal/CustomUnaryExpression.cs
@@ -1,10 +1,8 @@
using System;
-using System.Linq;
using System.Linq.Expressions;
using JetBrains.Annotations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Query.Sql.Internal;
using Npgsql.EntityFrameworkCore.PostgreSQL.Utilities;
-using NpgsqlTypes;
namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.Expressions.Internal
{
@@ -14,49 +12,67 @@ namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.Expressions.Internal
///
public class CustomUnaryExpression : Expression
{
- public CustomUnaryExpression(
- [NotNull] Expression operand,
- [NotNull] string @operator,
- [NotNull] Type type,
- bool postfix=false)
- {
- Check.NotNull(operand, nameof(operand));
- Check.NotEmpty(@operator, nameof(@operator));
- Check.NotNull(type, nameof(type));
+ ///
+ public override ExpressionType NodeType => ExpressionType.Extension;
- Operand = operand;
- Operator = @operator;
- Type = type;
- Postfix = postfix;
- }
+ ///
+ public override Type Type { get; }
+ ///
+ /// The expression acted on by the operator.
+ ///
+ [NotNull]
public Expression Operand { get; }
+
+ ///
+ /// The operator.
+ ///
+ [NotNull]
public string Operator { get; }
- public override Type Type { get; }
- public bool Postfix { get; }
- public override ExpressionType NodeType => ExpressionType.Extension;
+ ///
+ /// True if the operator follows the operand; otherwise, false.
+ ///
+ public bool Postfix { get; }
- protected override Expression Accept(ExpressionVisitor visitor)
+ ///
+ /// Constructs a .
+ ///
+ /// The expression acted on by the .
+ /// The operator symbol acting on the expression.
+ /// The result type.
+ /// True if the follows the operand; otherwise, false.
+ ///
+ public CustomUnaryExpression(
+ [NotNull] Expression operand,
+ [NotNull] string unaryOperator,
+ [NotNull] Type type,
+ bool postfix = false)
{
- Check.NotNull(visitor, nameof(visitor));
+ Operand = Check.NotNull(operand, nameof(operand));
+ Operator = Check.NotEmpty(unaryOperator, nameof(unaryOperator));
+ Type = Check.NotNull(type, nameof(type));
+ Postfix = postfix;
+ }
- return visitor is NpgsqlQuerySqlGenerator npgsqlGenerator
+ ///
+ protected override Expression Accept(ExpressionVisitor visitor)
+ => visitor is NpgsqlQuerySqlGenerator npgsqlGenerator
? npgsqlGenerator.VisitCustomUnary(this)
: base.Accept(visitor);
- }
+ ///
protected override Expression VisitChildren(ExpressionVisitor visitor)
{
- var newOperand = visitor.Visit(Operand);
+ var operand = visitor.Visit(Operand) ?? Operand;
- return newOperand != Operand
- ? new CustomUnaryExpression(newOperand, Operator, Type)
- : this;
+ return
+ operand != Operand
+ ? new CustomUnaryExpression(operand, Operator, Type)
+ : this;
}
- public override string ToString() => Postfix
- ? $"{Operator}{Operand}"
- : $"{Operand}{Operator}";
+ ///
+ public override string ToString() => Postfix ? $"{Operator}{Operand}" : $"{Operand}{Operator}";
}
}
diff --git a/src/EFCore.PG/Query/Expressions/Internal/ExplicitStoreTypeCastExpression.cs b/src/EFCore.PG/Query/Expressions/Internal/ExplicitStoreTypeCastExpression.cs
index 68e2352bb..73e631d6b 100644
--- a/src/EFCore.PG/Query/Expressions/Internal/ExplicitStoreTypeCastExpression.cs
+++ b/src/EFCore.PG/Query/Expressions/Internal/ExplicitStoreTypeCastExpression.cs
@@ -1,4 +1,5 @@
#region License
+
// The PostgreSQL License
//
// Copyright (C) 2016 The Npgsql Development Team
@@ -19,6 +20,7 @@
// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
// ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
#endregion
using System;
@@ -30,132 +32,77 @@
namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.Expressions.Internal
{
///
- /// Represents a SQL CAST expression to a store type specified as a string rather than a CLR type.
+ /// Represents a SQL CAST expression to a store type specified as a string rather than a CLR type.
///
- public class ExplicitStoreTypeCastExpression : Expression
+ public class ExplicitStoreTypeCastExpression : Expression, IEquatable
{
- readonly Type _type;
- readonly string _storeType;
-
- ///
- /// Creates a new instance of a ExplicitCastExpression..
- ///
- /// The operand.
- /// The target type.
- /// The store type name.
- public ExplicitStoreTypeCastExpression(
- [NotNull] Expression operand,
- [NotNull] Type type,
- [NotNull] string storeType)
- {
- Check.NotNull(operand, nameof(operand));
- Check.NotNull(type, nameof(type));
- Check.NotNull(storeType, nameof(storeType));
+ ///
+ public override ExpressionType NodeType => ExpressionType.Extension;
- Operand = operand;
- _type = type;
- _storeType = storeType;
- }
+ ///
+ public override Type Type { get; }
///
- /// Gets the operand.
+ /// The operand.
///
- ///
- /// The operand.
- ///
+ [NotNull]
public virtual Expression Operand { get; }
///
- /// Returns the node type of this . (Inherited from .)
- ///
- /// The that represents this expression.
- public override ExpressionType NodeType => ExpressionType.Extension;
-
- ///
- /// Gets the static type of the expression that this represents. (Inherited from .)
+ /// The store type name.
///
- /// The that represents the static type of the expression.
- public override Type Type => _type;
-
- public string StoreType=> _storeType;
+ [NotNull]
+ public string StoreType { get; }
///
- /// Dispatches to the specific visit method for this node type.
+ /// Constructs a .
///
- protected override Expression Accept(ExpressionVisitor visitor)
+ /// The operand.
+ /// The target type.
+ /// The store type name.
+ public ExplicitStoreTypeCastExpression(
+ [NotNull] Expression operand,
+ [NotNull] Type type,
+ [NotNull] string storeType)
{
- Check.NotNull(visitor, nameof(visitor));
+ Operand = Check.NotNull(operand, nameof(operand));
+ Type = Check.NotNull(type, nameof(type));
+ StoreType = Check.NotNull(storeType, nameof(storeType));
+ }
- return visitor is NpgsqlQuerySqlGenerator npgsqlVisitor
- ? npgsqlVisitor.VisitExplicitStoreTypeCast(this)
+ ///
+ protected override Expression Accept(ExpressionVisitor visitor)
+ => visitor is NpgsqlQuerySqlGenerator npgsqlGenerator
+ ? npgsqlGenerator.VisitExplicitStoreTypeCast(this)
: base.Accept(visitor);
- }
- ///
- /// Reduces the node and then calls the method passing the
- /// reduced expression.
- /// Throws an exception if the node isn't reducible.
- ///
- /// An instance of .
- /// The expression being visited, or an expression which should replace it in the tree.
- ///
- /// Override this method to provide logic to walk the node's children.
- /// A typical implementation will call visitor.Visit on each of its
- /// children, and if any of them change, should return a new copy of
- /// itself with the modified children.
- ///
+ ///
protected override Expression VisitChildren(ExpressionVisitor visitor)
{
- var newOperand = visitor.Visit(Operand);
+ var operand = visitor.Visit(Operand) ?? Operand;
- return newOperand != Operand
- ? new ExplicitStoreTypeCastExpression(newOperand, _type, _storeType)
- : this;
+ return
+ operand != Operand
+ ? new ExplicitStoreTypeCastExpression(operand, Type, StoreType)
+ : this;
}
- ///
- /// Tests if this object is considered equal to another.
- ///
- /// The object to compare with the current object.
- ///
- /// true if the objects are considered equal, false if they are not.
- ///
+ ///
public override bool Equals(object obj)
- {
- if (obj is null)
- {
- return false;
- }
+ => obj is ExplicitStoreTypeCastExpression other && Equals(other);
- if (ReferenceEquals(this, obj))
- {
- return true;
- }
+ ///
+ public bool Equals(ExplicitStoreTypeCastExpression other)
+ => other != null &&
+ Type == other.Type &&
+ StoreType == other.StoreType &&
+ Equals(Operand, other.Operand);
- return obj.GetType() == GetType() && Equals((ExplicitStoreTypeCastExpression)obj);
- }
-
- private bool Equals(ExplicitStoreTypeCastExpression other)
- => _type == other._type && _storeType == other._storeType && Equals(Operand, other.Operand);
-
- ///
- /// Returns a hash code for this object.
- ///
- ///
- /// A hash code for this object.
- ///
+ ///
public override int GetHashCode()
- {
- unchecked
- {
- return (_type.GetHashCode() * 397) ^ (_storeType.GetHashCode() * 397) ^ Operand.GetHashCode();
- }
- }
+ => unchecked((Type.GetHashCode() * 397) ^ (StoreType.GetHashCode() * 397) ^ Operand.GetHashCode());
- ///
- /// Creates a representation of the Expression.
- ///
- /// A representation of the Expression.
- public override string ToString() => "CAST(" + Operand + " AS " + _storeType + ")";
+ ///
+ public override string ToString() => $"CAST({Operand} AS {StoreType})";
}
}
diff --git a/src/EFCore.PG/Query/Expressions/Internal/ILikeExpression.cs b/src/EFCore.PG/Query/Expressions/Internal/ILikeExpression.cs
index 78fa7777d..2f5c4b64c 100644
--- a/src/EFCore.PG/Query/Expressions/Internal/ILikeExpression.cs
+++ b/src/EFCore.PG/Query/Expressions/Internal/ILikeExpression.cs
@@ -1,4 +1,5 @@
#region License
+
// The PostgreSQL License
//
// Copyright (C) 2016 The Npgsql Development Team
@@ -19,162 +20,103 @@
// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
// ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
#endregion
using System;
using System.Linq.Expressions;
using JetBrains.Annotations;
-using Microsoft.EntityFrameworkCore.Query.Expressions;
using Npgsql.EntityFrameworkCore.PostgreSQL.Query.Sql.Internal;
using Npgsql.EntityFrameworkCore.PostgreSQL.Utilities;
namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.Expressions.Internal
{
///
- /// Represents a SQL ILIKE expression.
+ /// Represents a PostgreSQL ILIKE expression.
///
- public class ILikeExpression : Expression
+ // ReSharper disable once InconsistentNaming
+ public class ILikeExpression : Expression, IEquatable
{
- ///
- /// Creates a new instance of LikeExpression.
- ///
- /// The expression to match.
- /// The pattern to match.
- public ILikeExpression([NotNull] Expression match, [NotNull] Expression pattern)
- {
- Check.NotNull(match, nameof(match));
- Check.NotNull(pattern, nameof(pattern));
-
- Match = match;
- Pattern = pattern;
- }
-
- ///
- /// Creates a new instance of LikeExpression.
- ///
- /// The expression to match.
- /// The pattern to match.
- /// The escape character to use in .
- public ILikeExpression([NotNull] Expression match, [NotNull] Expression pattern, [CanBeNull] Expression escapeChar)
- {
- Check.NotNull(match, nameof(match));
- Check.NotNull(pattern, nameof(pattern));
+ ///
+ public override ExpressionType NodeType => ExpressionType.Extension;
- Match = match;
- Pattern = pattern;
- EscapeChar = escapeChar;
- }
+ ///
+ public override Type Type => typeof(bool);
///
- /// Gets the match expression.
+ /// The match expression.
///
- ///
- /// The match expression.
- ///
+ [NotNull]
public virtual Expression Match { get; }
///
- /// Gets the pattern to match.
+ /// The pattern to match.
///
- ///
- /// The pattern to match.
- ///
+ [NotNull]
public virtual Expression Pattern { get; }
///
- /// Gets the escape character to use in .
+ /// The escape character to use in .
///
- ///
- /// The escape character to use. If null, no escape character is used.
- ///
[CanBeNull]
public virtual Expression EscapeChar { get; }
///
- /// Returns the node type of this . (Inherited from .)
- ///
- /// The that represents this expression.
- public override ExpressionType NodeType => ExpressionType.Extension;
-
- ///
- /// Gets the static type of the expression that this represents. (Inherited from .)
+ /// Constructs a .
///
- /// The that represents the static type of the expression.
- public override Type Type => typeof(bool);
+ /// The expression to match.
+ /// The pattern to match.
+ ///
+ public ILikeExpression([NotNull] Expression match, [NotNull] Expression pattern)
+ {
+ Match = Check.NotNull(match, nameof(match));
+ Pattern = Check.NotNull(pattern, nameof(pattern));
+ }
///
- /// Dispatches to the specific visit method for this node type.
+ /// Constructs a .
///
- protected override Expression Accept(ExpressionVisitor visitor)
+ /// The expression to match.
+ /// The pattern to match.
+ /// The escape character to use in .
+ ///
+ public ILikeExpression([NotNull] Expression match, [NotNull] Expression pattern, [CanBeNull] Expression escapeChar)
{
- Check.NotNull(visitor, nameof(visitor));
-
- var specificVisitor = visitor as NpgsqlQuerySqlGenerator;
+ Match = Check.NotNull(match, nameof(match));
+ Pattern = Check.NotNull(pattern, nameof(pattern));
+ EscapeChar = escapeChar;
+ }
- return specificVisitor != null
- ? specificVisitor.VisitILike(this)
+ ///
+ protected override Expression Accept(ExpressionVisitor visitor)
+ => visitor is NpgsqlQuerySqlGenerator npgsqlGenerator
+ ? npgsqlGenerator.VisitILike(this)
: base.Accept(visitor);
- }
- ///
- /// Reduces the node and then calls the method passing the
- /// reduced expression.
- /// Throws an exception if the node isn't reducible.
- ///
- /// An instance of .
- /// The expression being visited, or an expression which should replace it in the tree.
- ///
- /// Override this method to provide logic to walk the node's children.
- /// A typical implementation will call visitor.Visit on each of its
- /// children, and if any of them change, should return a new copy of
- /// itself with the modified children.
- ///
+ ///
protected override Expression VisitChildren(ExpressionVisitor visitor)
{
- var newMatchExpression = visitor.Visit(Match);
- var newPatternExpression = visitor.Visit(Pattern);
- var newEscapeCharExpression = EscapeChar == null ? null : visitor.Visit(EscapeChar);
-
- return newMatchExpression != Match
- || newPatternExpression != Pattern
- || newEscapeCharExpression != EscapeChar
- ? new ILikeExpression(newMatchExpression, newPatternExpression, newEscapeCharExpression)
- : this;
+ var match = visitor.Visit(Match) ?? Match;
+ var pattern = visitor.Visit(Pattern) ?? Pattern;
+ var escapeChar = visitor.Visit(EscapeChar);
+
+ return
+ match != Match || pattern != Pattern || escapeChar != EscapeChar
+ ? new ILikeExpression(match, pattern, escapeChar)
+ : this;
}
- ///
- /// Tests if this object is considered equal to another.
- ///
- /// The object to compare with the current object.
- ///
- /// true if the objects are considered equal, false if they are not.
- ///
- public override bool Equals(object obj)
- {
- if (ReferenceEquals(null, obj))
- {
- return false;
- }
-
- if (ReferenceEquals(this, obj))
- {
- return true;
- }
-
- return obj.GetType() == GetType() && Equals((ILikeExpression)obj);
- }
+ ///
+ public override bool Equals(object obj) => obj is ILikeExpression other && Equals(other);
- bool Equals(ILikeExpression other)
- => Equals(Match, other.Match)
- && Equals(Pattern, other.Pattern)
- && Equals(EscapeChar, other.EscapeChar);
+ ///
+ public bool Equals(ILikeExpression other)
+ => other != null &&
+ Equals(Match, other.Match) &&
+ Equals(Pattern, other.Pattern) &&
+ Equals(EscapeChar, other.EscapeChar);
- ///
- /// Returns a hash code for this object.
- ///
- ///
- /// A hash code for this object.
- ///
+ ///
public override int GetHashCode()
{
unchecked
@@ -182,15 +124,11 @@ public override int GetHashCode()
var hashCode = Match.GetHashCode();
hashCode = (hashCode * 397) ^ Pattern.GetHashCode();
hashCode = (hashCode * 397) ^ (EscapeChar?.GetHashCode() ?? 0);
-
return hashCode;
}
}
- ///
- /// Creates a representation of the Expression.
- ///
- /// A representation of the Expression.
+ ///
public override string ToString() => $"{Match} ILIKE {Pattern}{(EscapeChar == null ? "" : $" ESCAPE {EscapeChar}")}";
}
}
diff --git a/src/EFCore.PG/Query/Expressions/Internal/PgFunctionExpression.cs b/src/EFCore.PG/Query/Expressions/Internal/PgFunctionExpression.cs
index ccb1fc548..1698c28b4 100644
--- a/src/EFCore.PG/Query/Expressions/Internal/PgFunctionExpression.cs
+++ b/src/EFCore.PG/Query/Expressions/Internal/PgFunctionExpression.cs
@@ -29,11 +29,11 @@
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
-using System.Text;
using JetBrains.Annotations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Query.Sql.Internal;
using Npgsql.EntityFrameworkCore.PostgreSQL.Utilities;
+// ReSharper disable ArgumentsStyleLiteral
namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.Expressions.Internal
{
///
@@ -242,35 +242,30 @@ internal PgFunctionExpression(
///
protected override Expression Accept(ExpressionVisitor visitor)
- {
- Check.NotNull(visitor, nameof(visitor));
-
- return visitor is NpgsqlQuerySqlGenerator specificVisitor
- ? specificVisitor.VisitPgFunction(this)
+ => visitor is NpgsqlQuerySqlGenerator npgsqlGenerator
+ ? npgsqlGenerator.VisitPgFunction(this)
: base.Accept(visitor);
- }
///
protected override Expression VisitChildren(ExpressionVisitor visitor)
{
- var newInstance = visitor.Visit(Instance);
- var newPositionalArguments = visitor.VisitAndConvert(_positionalArguments, nameof(VisitChildren));
+ var instance = visitor.Visit(Instance) ?? Instance;
+ var positionalArguments = visitor.VisitAndConvert(_positionalArguments, nameof(VisitChildren));
- var newNamedArguments = new Dictionary(_namedArguments.Count);
+ var namedArguments = new Dictionary(_namedArguments.Count);
var namedArgumentsChanged = false;
foreach (var kv in _namedArguments)
{
var newExpression = visitor.Visit(kv.Value);
if (newExpression != kv.Value)
namedArgumentsChanged = true;
- newNamedArguments[kv.Key] = newExpression;
+ namedArguments[kv.Key] = newExpression;
}
- return newInstance != Instance ||
- newPositionalArguments != _positionalArguments ||
- namedArgumentsChanged
- ? new PgFunctionExpression(newInstance, FunctionName, Schema, Type, newPositionalArguments, newNamedArguments)
- : this;
+ return
+ instance != Instance || positionalArguments != _positionalArguments || namedArgumentsChanged
+ ? new PgFunctionExpression(instance, FunctionName, Schema, Type, positionalArguments, namedArguments)
+ : this;
}
///
diff --git a/src/EFCore.PG/Query/Expressions/Internal/RegexMatchExpression.cs b/src/EFCore.PG/Query/Expressions/Internal/RegexMatchExpression.cs
index 69c052323..03cb4d85d 100644
--- a/src/EFCore.PG/Query/Expressions/Internal/RegexMatchExpression.cs
+++ b/src/EFCore.PG/Query/Expressions/Internal/RegexMatchExpression.cs
@@ -1,4 +1,5 @@
#region License
+
// The PostgreSQL License
//
// Copyright (C) 2016 The Npgsql Development Team
@@ -19,12 +20,14 @@
// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
// ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
#endregion
using System;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
using JetBrains.Annotations;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Query.ExpressionVisitors;
using Npgsql.EntityFrameworkCore.PostgreSQL.Query.Sql.Internal;
using Npgsql.EntityFrameworkCore.PostgreSQL.Utilities;
@@ -32,44 +35,62 @@ namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.Expressions.Internal
{
public class RegexMatchExpression : Expression
{
- public RegexMatchExpression([NotNull] Expression match, [NotNull] Expression pattern, RegexOptions options)
- {
- Check.NotNull(match, nameof(match));
- Check.NotNull(pattern, nameof(pattern));
+ ///
+ public override ExpressionType NodeType => ExpressionType.Extension;
- Match = match;
- Pattern = pattern;
- Options = options;
- }
+ ///
+ public override Type Type => typeof(bool);
- public Expression Match { get; }
- public Expression Pattern { get; }
- public RegexOptions Options { get; }
+ ///
+ /// The match expression.
+ ///
+ [NotNull]
+ public virtual Expression Match { get; }
- public override ExpressionType NodeType => ExpressionType.Extension;
+ ///
+ /// The pattern to match.
+ ///
+ [NotNull]
+ public virtual Expression Pattern { get; }
- public override Type Type => typeof(bool);
+ ///
+ /// The options for regular expression evaluation.
+ ///
+ public RegexOptions Options { get; }
- protected override Expression Accept([NotNull] ExpressionVisitor visitor)
+ ///
+ /// Constructs a .
+ ///
+ /// The expression to match.
+ /// The pattern to match.
+ /// The options for regular expression evaluation.
+ ///
+ public RegexMatchExpression([NotNull] Expression match, [NotNull] Expression pattern, RegexOptions options)
{
- Check.NotNull(visitor, nameof(visitor));
+ Match = Check.NotNull(match, nameof(match));
+ Pattern = Check.NotNull(pattern, nameof(pattern));
+ Options = options;
+ }
- return visitor is NpgsqlQuerySqlGenerator npsgqlGenerator
- ? npsgqlGenerator.VisitRegexMatch(this)
+ ///
+ protected override Expression Accept(ExpressionVisitor visitor)
+ => visitor is NpgsqlQuerySqlGenerator npgsqlGenerator
+ ? npgsqlGenerator.VisitRegexMatch(this)
: base.Accept(visitor);
- }
+ ///
protected override Expression VisitChildren(ExpressionVisitor visitor)
{
- var newMatchExpression = visitor.Visit(Match);
- var newPatternExpression = visitor.Visit(Pattern);
+ var match = visitor.Visit(Match) ?? Match;
+ var pattern = visitor.Visit(Pattern) ?? Pattern;
- return newMatchExpression != Match
- || newPatternExpression != Pattern
- ? new RegexMatchExpression(newMatchExpression, newPatternExpression, Options)
- : this;
+ return
+ match != Match || pattern != Pattern
+ ? new RegexMatchExpression(match, pattern, Options)
+ : this;
}
+ ///
public override string ToString() => $"{Match} ~ {Pattern}";
}
}
diff --git a/src/EFCore.PG/Query/Sql/Internal/NpgsqlQuerySqlGenerator.cs b/src/EFCore.PG/Query/Sql/Internal/NpgsqlQuerySqlGenerator.cs
index 409320efc..6971349c1 100644
--- a/src/EFCore.PG/Query/Sql/Internal/NpgsqlQuerySqlGenerator.cs
+++ b/src/EFCore.PG/Query/Sql/Internal/NpgsqlQuerySqlGenerator.cs
@@ -186,15 +186,16 @@ protected override Expression VisitBinary(BinaryExpression expression)
return exp;
}
- break;
+ goto default;
}
case ExpressionType.ArrayIndex:
VisitArrayIndex(expression);
return expression;
- }
- return base.VisitBinary(expression);
+ default:
+ return base.VisitBinary(expression);
+ }
}
///
@@ -241,35 +242,42 @@ protected virtual void VisitArrayIndex([NotNull] BinaryExpression expression)
///
/// Produces expressions like: 1 = ANY ('{0,1,2}') or 'cat' LIKE ANY ('{a%,b%,c%}').
///
- public virtual Expression VisitArrayAnyAll([NotNull] ArrayAnyAllExpression arrayAnyAllExpression)
+ public virtual Expression VisitArrayAnyAll([NotNull] ArrayAnyAllExpression expression)
{
- Visit(arrayAnyAllExpression.Operand);
+ Visit(expression.Operand);
Sql.Append(' ');
- Sql.Append(arrayAnyAllExpression.Operator);
+ Sql.Append(expression.Operator);
Sql.Append(' ');
- Sql.Append(arrayAnyAllExpression.ArrayComparisonType.ToString());
+ Sql.Append(expression.ArrayComparisonType.ToString());
Sql.Append(" (");
- Visit(arrayAnyAllExpression.Array);
+ Visit(expression.Array);
Sql.Append(')');
- return arrayAnyAllExpression;
+ return expression;
}
///
- /// See: http://www.postgresql.org/docs/current/static/functions-matching.html
+ /// Visits the children of a .
///
- public virtual Expression VisitRegexMatch([NotNull] RegexMatchExpression regexMatchExpression)
+ /// The expression.
+ ///
+ /// An .
+ ///
+ ///
+ /// See: http://www.postgresql.org/docs/current/static/functions-matching.html
+ ///
+ [NotNull]
+ public virtual Expression VisitRegexMatch([NotNull] RegexMatchExpression expression)
{
- Check.NotNull(regexMatchExpression, nameof(regexMatchExpression));
- var options = regexMatchExpression.Options;
+ var options = expression.Options;
- Visit(regexMatchExpression.Match);
+ Visit(expression.Match);
Sql.Append(" ~ ");
// PG regexps are singleline by default
if (options == RegexOptions.Singleline)
{
- Visit(regexMatchExpression.Pattern);
- return regexMatchExpression;
+ Visit(expression.Pattern);
+ return expression;
}
Sql.Append("('(?");
@@ -286,71 +294,97 @@ public virtual Expression VisitRegexMatch([NotNull] RegexMatchExpression regexMa
Sql.Append('x');
Sql.Append(")' || ");
- Visit(regexMatchExpression.Pattern);
+ Visit(expression.Pattern);
Sql.Append(')');
- return regexMatchExpression;
+ return expression;
}
- public virtual Expression VisitAtTimeZone([NotNull] AtTimeZoneExpression atTimeZoneExpression)
+ ///
+ /// Visits the children of an .
+ ///
+ /// The expression.
+ ///
+ /// An .
+ ///
+ [NotNull]
+ public virtual Expression VisitAtTimeZone([NotNull] AtTimeZoneExpression expression)
{
- Check.NotNull(atTimeZoneExpression, nameof(atTimeZoneExpression));
-
- Visit(atTimeZoneExpression.TimestampExpression);
+ Visit(expression.Timestamp);
Sql.Append(" AT TIME ZONE '");
- Sql.Append(atTimeZoneExpression.TimeZone);
+ Sql.Append(expression.TimeZone);
Sql.Append('\'');
- return atTimeZoneExpression;
+ return expression;
}
- public virtual Expression VisitILike([NotNull] ILikeExpression iLikeExpression)
+ ///
+ /// Visits the children of an .
+ ///
+ /// The expression.
+ ///
+ /// An .
+ ///
+ [NotNull]
+ public virtual Expression VisitILike([NotNull] ILikeExpression expression)
{
- Check.NotNull(iLikeExpression, nameof(iLikeExpression));
-
//var parentTypeMapping = _typeMapping;
- //_typeMapping = InferTypeMappingFromColumn(iLikeExpression.Match) ?? parentTypeMapping;
+ //_typeMapping = InferTypeMappingFromColumn(expression.Match) ?? parentTypeMapping;
- Visit(iLikeExpression.Match);
+ Visit(expression.Match);
Sql.Append(" ILIKE ");
- Visit(iLikeExpression.Pattern);
+ Visit(expression.Pattern);
- if (iLikeExpression.EscapeChar != null)
+ if (expression.EscapeChar != null)
{
Sql.Append(" ESCAPE ");
- Visit(iLikeExpression.EscapeChar);
+ Visit(expression.EscapeChar);
}
//_typeMapping = parentTypeMapping;
- return iLikeExpression;
+ return expression;
}
- public virtual Expression VisitExplicitStoreTypeCast([NotNull] ExplicitStoreTypeCastExpression castExpression)
+ ///
+ /// Visits the children of an .
+ ///
+ /// The expression.
+ ///
+ /// An .
+ ///
+ [NotNull]
+ public virtual Expression VisitExplicitStoreTypeCast([NotNull] ExplicitStoreTypeCastExpression expression)
{
Sql.Append("CAST(");
//var parentTypeMapping = _typeMapping;
- //_typeMapping = InferTypeMappingFromColumn(castExpression.Operand);
+ //_typeMapping = InferTypeMappingFromColumn(expression.Operand);
- Visit(castExpression.Operand);
+ Visit(expression.Operand);
Sql.Append(" AS ")
- .Append(castExpression.StoreType)
+ .Append(expression.StoreType)
.Append(")");
//_typeMapping = parentTypeMapping;
- return castExpression;
+ return expression;
}
+ ///
+ /// Visits the children of a .
+ ///
+ /// The expression.
+ ///
+ /// An .
+ ///
+ [NotNull]
public virtual Expression VisitCustomBinary([NotNull] CustomBinaryExpression expression)
{
- Check.NotNull(expression, nameof(expression));
-
Sql.Append('(');
Visit(expression.Left);
Sql.Append(' ');
@@ -362,10 +396,16 @@ public virtual Expression VisitCustomBinary([NotNull] CustomBinaryExpression exp
return expression;
}
+ ///
+ /// Visits the children of a .
+ ///
+ /// The expression.
+ ///
+ /// An .
+ ///
+ [NotNull]
public virtual Expression VisitCustomUnary([NotNull] CustomUnaryExpression expression)
{
- Check.NotNull(expression, nameof(expression));
-
if (expression.Postfix)
{
Visit(expression.Operand);
@@ -380,7 +420,15 @@ public virtual Expression VisitCustomUnary([NotNull] CustomUnaryExpression expre
return expression;
}
- public virtual Expression VisitPgFunction([NotNull] PgFunctionExpression e)
+ ///
+ /// Visits the children of a .
+ ///
+ /// The expression.
+ ///
+ /// An .
+ ///
+ [NotNull]
+ public virtual Expression VisitPgFunction([NotNull] PgFunctionExpression expression)
{
//var parentTypeMapping = _typeMapping;
@@ -388,15 +436,15 @@ public virtual Expression VisitPgFunction([NotNull] PgFunctionExpression e)
var wroteSchema = false;
- if (e.Instance != null)
+ if (expression.Instance != null)
{
- Visit(e.Instance);
+ Visit(expression.Instance);
Sql.Append(".");
}
- else if (!string.IsNullOrWhiteSpace(e.Schema))
+ else if (!string.IsNullOrWhiteSpace(expression.Schema))
{
- Sql.Append(SqlGenerator.DelimitIdentifier(e.Schema))
+ Sql.Append(SqlGenerator.DelimitIdentifier(expression.Schema))
.Append(".");
wroteSchema = true;
@@ -404,18 +452,18 @@ public virtual Expression VisitPgFunction([NotNull] PgFunctionExpression e)
Sql.Append(
wroteSchema
- ? SqlGenerator.DelimitIdentifier(e.FunctionName)
- : e.FunctionName);
+ ? SqlGenerator.DelimitIdentifier(expression.FunctionName)
+ : expression.FunctionName);
Sql.Append("(");
//_typeMapping = null;
- GenerateList(e.PositionalArguments);
+ GenerateList(expression.PositionalArguments);
- bool hasArguments = e.PositionalArguments.Count > 0 && e.NamedArguments.Count > 0;
+ bool hasArguments = expression.PositionalArguments.Count > 0 && expression.NamedArguments.Count > 0;
- foreach (var kv in e.NamedArguments)
+ foreach (var kv in expression.NamedArguments)
{
if (hasArguments)
Sql.Append(", ");
@@ -431,7 +479,7 @@ public virtual Expression VisitPgFunction([NotNull] PgFunctionExpression e)
Sql.Append(")");
//_typeMapping = parentTypeMapping;
- return e;
+ return expression;
}
#endregion