Skip to content

Commit

Permalink
Refactor SQL generator for 541
Browse files Browse the repository at this point in the history
  • Loading branch information
austindrenski committed Jul 25, 2018
1 parent c4a8e30 commit ae41afc
Showing 1 changed file with 78 additions and 59 deletions.
137 changes: 78 additions & 59 deletions src/EFCore.PG/Query/Sql/Internal/NpgsqlQuerySqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,28 +37,33 @@

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.Sql.Internal
{
/// <summary>
/// The default query SQL generator for Npgsql.
/// </summary>
public class NpgsqlQuerySqlGenerator : DefaultQuerySqlGenerator
{
/// <summary>
/// True if null ordering is reversed; otherwise false.
/// </summary>
readonly bool _reverseNullOrderingEnabled;

/// <inheritdoc />
protected override string TypedTrueLiteral { get; } = "TRUE::bool";

/// <inheritdoc />
protected override string TypedFalseLiteral { get; } = "FALSE::bool";

/// <inheritdoc />
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

/// <inheritdoc />
protected override void GenerateLimitOffset(SelectExpression selectExpression)
{
Check.NotNull(selectExpression, nameof(selectExpression));
Expand All @@ -81,6 +86,60 @@ protected override void GenerateLimitOffset(SelectExpression selectExpression)
}
}

/// <summary>
/// PostgreSQL array indexing is 1-based. If the index happens to be a constant,
/// just increment it. Otherwise, append a +1 in the SQL.
/// </summary>
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));

/// <inheritdoc />
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);
}
}

/// <inheritdoc />
protected override void GenerateOrdering(Ordering ordering)
{
base.GenerateOrdering(ordering);

if (_reverseNullOrderingEnabled)
Sql.Append(ordering.OrderingDirection == OrderingDirection.Asc ? " NULLS FIRST" : " NULLS LAST");
}

/// <inheritdoc />
protected override void GenerateTop(SelectExpression selectExpression)
{
// No TOP() in PostgreSQL, see GenerateLimitOffset
}

#endregion

#region Visitors

/// <inheritdoc />
public override Expression VisitSqlFunction(SqlFunctionExpression sqlFunctionExpression)
{
var expr = base.VisitSqlFunction(sqlFunctionExpression);
Expand Down Expand Up @@ -108,6 +167,7 @@ public override Expression VisitSqlFunction(SqlFunctionExpression sqlFunctionExp
return expr;
}

/// <inheritdoc />
protected override Expression VisitBinary(BinaryExpression expression)
{
switch (expression.NodeType)
Expand Down Expand Up @@ -137,6 +197,7 @@ protected override Expression VisitBinary(BinaryExpression expression)
return base.VisitBinary(expression);
}

/// <inheritdoc />
protected override Expression VisitUnary(UnaryExpression expression)
{
if (expression.NodeType == ExpressionType.ArrayLength)
Expand Down Expand Up @@ -180,7 +241,7 @@ protected virtual void VisitArrayIndex([NotNull] BinaryExpression expression)
/// <summary>
/// Produces expressions like: 1 = ANY ('{0,1,2}') or 'cat' LIKE ANY ('{a%,b%,c%}').
/// </summary>
public Expression VisitArrayAnyAll(ArrayAnyAllExpression arrayAnyAllExpression)
public virtual Expression VisitArrayAnyAll([NotNull] ArrayAnyAllExpression arrayAnyAllExpression)
{
Visit(arrayAnyAllExpression.Operand);
Sql.Append(' ');
Expand All @@ -193,19 +254,10 @@ public Expression VisitArrayAnyAll(ArrayAnyAllExpression arrayAnyAllExpression)
return arrayAnyAllExpression;
}

/// <summary>
/// PostgreSQL array indexing is 1-based. If the index happens to be a constant,
/// just increment it. Otherwise, append a +1 in the SQL.
/// </summary>
static Expression GenerateOneBasedIndexExpression(Expression expression)
=> expression is ConstantExpression constantExpression
? Expression.Constant(Convert.ToInt32(constantExpression.Value) + 1)
: (Expression)Expression.Add(expression, Expression.Constant(1));

/// <summary>
/// See: http://www.postgresql.org/docs/current/static/functions-matching.html
/// </summary>
public Expression VisitRegexMatch([NotNull] RegexMatchExpression regexMatchExpression)
public virtual Expression VisitRegexMatch([NotNull] RegexMatchExpression regexMatchExpression)
{
Check.NotNull(regexMatchExpression, nameof(regexMatchExpression));
var options = regexMatchExpression.Options;
Expand Down Expand Up @@ -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));

Expand All @@ -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));

Expand All @@ -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(");

Expand All @@ -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));

Expand All @@ -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));

Expand All @@ -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;

Expand Down Expand Up @@ -416,5 +433,7 @@ public virtual Expression VisitPgFunction(PgFunctionExpression e)

return e;
}

#endregion
}
}

0 comments on commit ae41afc

Please sign in to comment.