From ae41afcb77df69d6af861a486c1619d9f61461f8 Mon Sep 17 00:00:00 2001 From: Austin Drenski Date: Tue, 24 Jul 2018 22:37:20 -0400 Subject: [PATCH] Refactor SQL generator for 541 --- .../Sql/Internal/NpgsqlQuerySqlGenerator.cs | 137 ++++++++++-------- 1 file changed, 78 insertions(+), 59 deletions(-) diff --git a/src/EFCore.PG/Query/Sql/Internal/NpgsqlQuerySqlGenerator.cs b/src/EFCore.PG/Query/Sql/Internal/NpgsqlQuerySqlGenerator.cs index f9728bfe2..409320efc 100644 --- a/src/EFCore.PG/Query/Sql/Internal/NpgsqlQuerySqlGenerator.cs +++ b/src/EFCore.PG/Query/Sql/Internal/NpgsqlQuerySqlGenerator.cs @@ -37,28 +37,33 @@ namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.Sql.Internal { + /// + /// The default query SQL generator for Npgsql. + /// public class NpgsqlQuerySqlGenerator : DefaultQuerySqlGenerator { + /// + /// True if null ordering is reversed; otherwise false. + /// readonly bool _reverseNullOrderingEnabled; + /// protected override string TypedTrueLiteral { get; } = "TRUE::bool"; + /// protected override string TypedFalseLiteral { get; } = "FALSE::bool"; + /// public NpgsqlQuerySqlGenerator( [NotNull] QuerySqlGeneratorDependencies dependencies, [NotNull] SelectExpression selectExpression, bool reverseNullOrderingEnabled) : base(dependencies, selectExpression) - { - _reverseNullOrderingEnabled = reverseNullOrderingEnabled; - } + => _reverseNullOrderingEnabled = reverseNullOrderingEnabled; - protected override void GenerateTop(SelectExpression selectExpression) - { - // No TOP() in PostgreSQL, see GenerateLimitOffset - } + #region Generators + /// protected override void GenerateLimitOffset(SelectExpression selectExpression) { Check.NotNull(selectExpression, nameof(selectExpression)); @@ -81,6 +86,60 @@ protected override void GenerateLimitOffset(SelectExpression selectExpression) } } + /// + /// PostgreSQL array indexing is 1-based. If the index happens to be a constant, + /// just increment it. Otherwise, append a +1 in the SQL. + /// + protected virtual Expression GenerateOneBasedIndexExpression([NotNull] Expression expression) + => expression is ConstantExpression constantExpression + ? Expression.Constant(Convert.ToInt32(constantExpression.Value) + 1) + : (Expression)Expression.Add(expression, Expression.Constant(1)); + + /// + protected override string GenerateOperator(Expression expression) + { + switch (expression.NodeType) + { + case ExpressionType.Add: + if (expression.Type == typeof(string)) + return " || "; + goto default; + + case ExpressionType.And: + if (expression.Type == typeof(bool)) + return " AND "; + goto default; + + case ExpressionType.Or: + if (expression.Type == typeof(bool)) + return " OR "; + goto default; + + default: + return base.GenerateOperator(expression); + } + } + + /// + protected override void GenerateOrdering(Ordering ordering) + { + base.GenerateOrdering(ordering); + + if (_reverseNullOrderingEnabled) + Sql.Append(ordering.OrderingDirection == OrderingDirection.Asc ? " NULLS FIRST" : " NULLS LAST"); + } + + /// + protected override void GenerateTop(SelectExpression selectExpression) + { + // No TOP() in PostgreSQL, see GenerateLimitOffset + } + + #endregion + + #region Visitors + + /// public override Expression VisitSqlFunction(SqlFunctionExpression sqlFunctionExpression) { var expr = base.VisitSqlFunction(sqlFunctionExpression); @@ -108,6 +167,7 @@ public override Expression VisitSqlFunction(SqlFunctionExpression sqlFunctionExp return expr; } + /// protected override Expression VisitBinary(BinaryExpression expression) { switch (expression.NodeType) @@ -137,6 +197,7 @@ protected override Expression VisitBinary(BinaryExpression expression) return base.VisitBinary(expression); } + /// protected override Expression VisitUnary(UnaryExpression expression) { if (expression.NodeType == ExpressionType.ArrayLength) @@ -180,7 +241,7 @@ protected virtual void VisitArrayIndex([NotNull] BinaryExpression expression) /// /// Produces expressions like: 1 = ANY ('{0,1,2}') or 'cat' LIKE ANY ('{a%,b%,c%}'). /// - public Expression VisitArrayAnyAll(ArrayAnyAllExpression arrayAnyAllExpression) + public virtual Expression VisitArrayAnyAll([NotNull] ArrayAnyAllExpression arrayAnyAllExpression) { Visit(arrayAnyAllExpression.Operand); Sql.Append(' '); @@ -193,19 +254,10 @@ public Expression VisitArrayAnyAll(ArrayAnyAllExpression arrayAnyAllExpression) return arrayAnyAllExpression; } - /// - /// PostgreSQL array indexing is 1-based. If the index happens to be a constant, - /// just increment it. Otherwise, append a +1 in the SQL. - /// - static Expression GenerateOneBasedIndexExpression(Expression expression) - => expression is ConstantExpression constantExpression - ? Expression.Constant(Convert.ToInt32(constantExpression.Value) + 1) - : (Expression)Expression.Add(expression, Expression.Constant(1)); - /// /// See: http://www.postgresql.org/docs/current/static/functions-matching.html /// - public Expression VisitRegexMatch([NotNull] RegexMatchExpression regexMatchExpression) + public virtual Expression VisitRegexMatch([NotNull] RegexMatchExpression regexMatchExpression) { Check.NotNull(regexMatchExpression, nameof(regexMatchExpression)); var options = regexMatchExpression.Options; @@ -240,7 +292,7 @@ public Expression VisitRegexMatch([NotNull] RegexMatchExpression regexMatchExpre return regexMatchExpression; } - public Expression VisitAtTimeZone([NotNull] AtTimeZoneExpression atTimeZoneExpression) + public virtual Expression VisitAtTimeZone([NotNull] AtTimeZoneExpression atTimeZoneExpression) { Check.NotNull(atTimeZoneExpression, nameof(atTimeZoneExpression)); @@ -253,7 +305,7 @@ public Expression VisitAtTimeZone([NotNull] AtTimeZoneExpression atTimeZoneExpre return atTimeZoneExpression; } - public virtual Expression VisitILike(ILikeExpression iLikeExpression) + public virtual Expression VisitILike([NotNull] ILikeExpression iLikeExpression) { Check.NotNull(iLikeExpression, nameof(iLikeExpression)); @@ -277,7 +329,7 @@ public virtual Expression VisitILike(ILikeExpression iLikeExpression) return iLikeExpression; } - public Expression VisitExplicitStoreTypeCast([NotNull] ExplicitStoreTypeCastExpression castExpression) + public virtual Expression VisitExplicitStoreTypeCast([NotNull] ExplicitStoreTypeCastExpression castExpression) { Sql.Append("CAST("); @@ -295,42 +347,7 @@ public Expression VisitExplicitStoreTypeCast([NotNull] ExplicitStoreTypeCastExpr return castExpression; } - protected override string GenerateOperator(Expression expression) - { - switch (expression.NodeType) - { - case ExpressionType.Add: - if (expression.Type == typeof(string)) - return " || "; - goto default; - - case ExpressionType.And: - if (expression.Type == typeof(bool)) - return " AND "; - goto default; - - case ExpressionType.Or: - if (expression.Type == typeof(bool)) - return " OR "; - goto default; - - default: - return base.GenerateOperator(expression); - } - } - - protected override void GenerateOrdering(Ordering ordering) - { - base.GenerateOrdering(ordering); - - if (_reverseNullOrderingEnabled) - Sql.Append( - ordering.OrderingDirection == OrderingDirection.Asc - ? " NULLS FIRST" - : " NULLS LAST"); - } - - public virtual Expression VisitCustomBinary(CustomBinaryExpression expression) + public virtual Expression VisitCustomBinary([NotNull] CustomBinaryExpression expression) { Check.NotNull(expression, nameof(expression)); @@ -345,7 +362,7 @@ public virtual Expression VisitCustomBinary(CustomBinaryExpression expression) return expression; } - public virtual Expression VisitCustomUnary(CustomUnaryExpression expression) + public virtual Expression VisitCustomUnary([NotNull] CustomUnaryExpression expression) { Check.NotNull(expression, nameof(expression)); @@ -363,7 +380,7 @@ public virtual Expression VisitCustomUnary(CustomUnaryExpression expression) return expression; } - public virtual Expression VisitPgFunction(PgFunctionExpression e) + public virtual Expression VisitPgFunction([NotNull] PgFunctionExpression e) { //var parentTypeMapping = _typeMapping; @@ -416,5 +433,7 @@ public virtual Expression VisitPgFunction(PgFunctionExpression e) return e; } + + #endregion } }