Skip to content

Commit

Permalink
added support for DateTime.UtcNow and DateTime.Now
Browse files Browse the repository at this point in the history
  • Loading branch information
win7user10 committed Jan 25, 2024
1 parent 3fa2cfb commit 80691fa
Show file tree
Hide file tree
Showing 33 changed files with 651 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System;
using System.Linq.Expressions;
using Laraue.EfCoreTriggers.Common.Converters.MethodCall;
using Laraue.EfCoreTriggers.Common.SqlGeneration;
using Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors;

namespace Laraue.EfCoreTriggers.Common.Converters.MemberAccess
{
/// <summary>
/// Base <see cref="IMethodCallVisitor"/>.
/// </summary>
public abstract class BaseMemberAccessVisitor : IMemberAccessVisitor
{
/// <summary>
/// Specifies a method which will be handled by this converter.
/// </summary>
protected abstract string PropertyName { get; }

/// <summary>
/// Specifies a class which methods will be handled by this converter.
/// </summary>
protected abstract Type ReflectedType { get; }

/// <summary>
/// Factory to visit expressions and generate SQL code.
/// </summary>
protected IExpressionVisitorFactory VisitorFactory { get; }

/// <summary>
/// Initialize a new instance of <see cref="BaseMethodCallVisitor"/>.
/// </summary>
/// <param name="visitorFactory"></param>
protected BaseMemberAccessVisitor(IExpressionVisitorFactory visitorFactory)
{
VisitorFactory = visitorFactory;
}

/// <inheritdoc />
public bool IsApplicable(MemberExpression expression)
{
return expression.Member.ReflectedType == ReflectedType && PropertyName == expression.Member.Name;
}

/// <inheritdoc />
public abstract SqlBuilder Visit(MemberExpression expression);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors;

namespace Laraue.EfCoreTriggers.Common.Converters.MemberAccess.DateTime
{
/// <summary>
/// Base visitor for <see cref="System.Math"/> methods.
/// </summary>
public abstract class BaseDateTimeVisitor : BaseMemberAccessVisitor
{
/// <inheritdoc />
protected override Type ReflectedType => typeof(System.DateTime);

/// <inheritdoc />
protected BaseDateTimeVisitor(IExpressionVisitorFactory visitorFactory)
: base(visitorFactory)
{
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors;

namespace Laraue.EfCoreTriggers.Common.Converters.MemberAccess.DateTime
{
/// <summary>
/// Visitor for <see cref="System.DateTime.Now"/>.
/// </summary>
public abstract class BaseNowVisitor : BaseDateTimeVisitor
{
/// <inheritdoc />
protected override string PropertyName => nameof(System.DateTime.Now);

/// <inheritdoc />
protected BaseNowVisitor(IExpressionVisitorFactory visitorFactory)
: base(visitorFactory)
{
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors;

namespace Laraue.EfCoreTriggers.Common.Converters.MemberAccess.DateTime
{
/// <summary>
/// Visitor for <see cref="System.DateTime.UtcNow"/>,
/// </summary>
public abstract class BaseUtcNowVisitor : BaseDateTimeVisitor
{
/// <inheritdoc />
protected override string PropertyName => nameof(System.DateTime.UtcNow);

/// <inheritdoc />
protected BaseUtcNowVisitor(IExpressionVisitorFactory visitorFactory)
: base(visitorFactory)
{
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.Linq.Expressions;
using Laraue.EfCoreTriggers.Common.SqlGeneration;

namespace Laraue.EfCoreTriggers.Common.Converters.MemberAccess
{
/// <summary>
/// Converter for <see cref="MethodCallExpression"/>.
/// </summary>
public interface IMemberAccessVisitor
{
/// <summary>
/// Should this converter be used to translate a <see cref="MemberExpression"/> to a SQL.
/// </summary>
/// <param name="expression"></param>
/// <returns></returns>
bool IsApplicable(MemberExpression expression);

/// <summary>
/// Build a SQL for passed <see cref="MethodCallExpression"/>.
/// </summary>
/// <param name="expression">Expression to parse.</param>
/// <returns></returns>
SqlBuilder Visit(MemberExpression expression);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Linq.Expressions;
using Laraue.EfCoreTriggers.Common.Converters.MemberAccess;
using Laraue.EfCoreTriggers.Common.Converters.MethodCall;
using Laraue.EfCoreTriggers.Common.Converters.MethodCall.CSharpMethods;
using Laraue.EfCoreTriggers.Common.Converters.MethodCall.Enumerable.Count;
Expand Down Expand Up @@ -46,6 +47,19 @@ public static IServiceCollection AddMethodCallConverter<TImpl>(this IServiceColl
{
return services.AddScoped<IMethodCallVisitor, TImpl>();
}

/// <summary>
/// Register new <see cref="IMemberAccessVisitor"/> into container.
/// All visitors are applied in reverse order.
/// </summary>
/// <param name="services">Service collection.</param>
/// <typeparam name="TImpl">Implementation of visitor.</typeparam>
/// <returns></returns>
public static IServiceCollection AddMemberAccessConverter<TImpl>(this IServiceCollection services)
where TImpl : class, IMemberAccessVisitor
{
return services.AddScoped<IMemberAccessVisitor, TImpl>();
}

/// <summary>
/// Register new <see cref="IExpressionVisitor{T}"/> into container.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Laraue.EfCoreTriggers.Common.Converters.MemberAccess;
using Laraue.EfCoreTriggers.Common.SqlGeneration;
using Laraue.EfCoreTriggers.Common.TriggerBuilders;
using Laraue.EfCoreTriggers.Common.TriggerBuilders.TableRefs;

namespace Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors
{
/// <inheritdoc />
public sealed class MemberExpressionVisitor : BaseExpressionVisitor<MemberExpression>
public sealed class MemberExpressionVisitor
: BaseExpressionVisitor<MemberExpression>
{
private readonly ISqlGenerator _generator;
private readonly IEnumerable<IMemberAccessVisitor> _staticMembersVisitors;

/// <inheritdoc />
public MemberExpressionVisitor(ISqlGenerator generator)
public MemberExpressionVisitor(ISqlGenerator generator, IEnumerable<IMemberAccessVisitor> staticMembersVisitors)
{
_generator = generator;
_staticMembersVisitors = staticMembersVisitors.Reverse().ToArray();
}

/// <inheritdoc />
Expand All @@ -35,16 +41,18 @@ public override SqlBuilder Visit(MemberExpression expression, VisitedMembers vis
/// <returns></returns>
private string Visit(MemberExpression memberExpression, ArgumentType argumentType, VisitedMembers visitedMembers)
{
if (memberExpression.Expression is MemberExpression nestedMemberExpression)
switch (memberExpression.Expression)
{
return GetColumnSql(nestedMemberExpression, memberExpression.Member, visitedMembers);
// Static member
case null:
return Visit(memberExpression);

// Column
case MemberExpression nestedMemberExpression:
return GetColumnSql(nestedMemberExpression, memberExpression.Member, visitedMembers);
}

return GetTableSql(memberExpression, argumentType);
}

private string GetTableSql(MemberExpression memberExpression, ArgumentType argumentType)
{
// Table
if (memberExpression.Member.TryGetNewTableRef(out _))
{
return _generator.NewEntityPrefix;
Expand Down Expand Up @@ -94,5 +102,18 @@ private string GetColumnSql(Type? tableType, MemberInfo columnMember, ArgumentTy
columnMember,
argumentType);
}

private SqlBuilder Visit(MemberExpression expression)
{
foreach (var converter in _staticMembersVisitors)
{
if (converter.IsApplicable(expression))
{
return converter.Visit(expression);
}
}

throw new NotSupportedException($"Member expression {expression.Member.DeclaringType}.{expression.Member.Name} is not supported");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Linq.Expressions;
using Laraue.EfCoreTriggers.Common.Converters.MemberAccess.DateTime;
using Laraue.EfCoreTriggers.Common.SqlGeneration;
using Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors;

namespace Laraue.EfCoreTriggers.MySql.Converters.MemberAccess.DateTime
{
/// <inheritdoc />
public class NowVisitor : BaseNowVisitor
{
/// <inheritdoc />
public NowVisitor(IExpressionVisitorFactory visitorFactory)
: base(visitorFactory)
{
}

/// <inheritdoc />
public override SqlBuilder Visit(MemberExpression expression)
{
return SqlBuilder.FromString("LOCALTIME()");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Linq.Expressions;
using Laraue.EfCoreTriggers.Common.Converters.MemberAccess.DateTime;
using Laraue.EfCoreTriggers.Common.SqlGeneration;
using Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors;

namespace Laraue.EfCoreTriggers.MySql.Converters.MemberAccess.DateTime
{
/// <inheritdoc />
public class UtcNowVisitor : BaseUtcNowVisitor
{
/// <inheritdoc />
public UtcNowVisitor(IExpressionVisitorFactory visitorFactory)
: base(visitorFactory)
{
}

/// <inheritdoc />
public override SqlBuilder Visit(MemberExpression expression)
{
return SqlBuilder.FromString("UTC_TIMESTAMP()");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using Laraue.EfCoreTriggers.Common.TriggerBuilders.Actions;
using Laraue.EfCoreTriggers.Common.Visitors.TriggerVisitors;
using Laraue.EfCoreTriggers.Common.Visitors.TriggerVisitors.Statements;
using Laraue.EfCoreTriggers.MySql.Converters.MemberAccess.DateTime;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

Expand Down Expand Up @@ -88,7 +89,9 @@ public static void AddMySqlServices(this IServiceCollection serviceCollection)
.AddMethodCallConverter<MathCeilingVisitor>()
.AddMethodCallConverter<MathCosVisitor>()
.AddMethodCallConverter<MathExpVisitor>()
.AddMethodCallConverter<MathFloorVisitor>();
.AddMethodCallConverter<MathFloorVisitor>()
.AddMemberAccessConverter<UtcNowVisitor>()
.AddMemberAccessConverter<NowVisitor>();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Linq.Expressions;
using Laraue.EfCoreTriggers.Common.Converters.MemberAccess.DateTime;
using Laraue.EfCoreTriggers.Common.SqlGeneration;
using Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors;

namespace Laraue.EfCoreTriggers.PostgreSql.Converters.MemberAccess.DateTime
{
/// <inheritdoc />
public class NowVisitor : BaseNowVisitor
{
/// <inheritdoc />
public NowVisitor(IExpressionVisitorFactory visitorFactory)
: base(visitorFactory)
{
}

/// <inheritdoc />
public override SqlBuilder Visit(MemberExpression expression)
{
return SqlBuilder.FromString("NOW()");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Linq.Expressions;
using Laraue.EfCoreTriggers.Common.Converters.MemberAccess.DateTime;
using Laraue.EfCoreTriggers.Common.SqlGeneration;
using Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors;

namespace Laraue.EfCoreTriggers.PostgreSql.Converters.MemberAccess.DateTime
{
/// <inheritdoc />
public class UtcNowVisitor : BaseUtcNowVisitor
{
/// <inheritdoc />
public UtcNowVisitor(IExpressionVisitorFactory visitorFactory)
: base(visitorFactory)
{
}

/// <inheritdoc />
public override SqlBuilder Visit(MemberExpression expression)
{
return SqlBuilder.FromString("CURRENT_TIMESTAMP");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using Laraue.EfCoreTriggers.Common.TriggerBuilders.Actions;
using Laraue.EfCoreTriggers.Common.Visitors.TriggerVisitors;
using Laraue.EfCoreTriggers.Common.Visitors.TriggerVisitors.Statements;
using Laraue.EfCoreTriggers.PostgreSql.Converters.MemberAccess.DateTime;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

Expand Down Expand Up @@ -85,7 +86,9 @@ public static void AddPostgreSqlServices(this IServiceCollection services)
.AddMethodCallConverter<MathCeilingVisitor>()
.AddMethodCallConverter<MathCosVisitor>()
.AddMethodCallConverter<MathExpVisitor>()
.AddMethodCallConverter<MathFloorVisitor>();
.AddMethodCallConverter<MathFloorVisitor>()
.AddMemberAccessConverter<UtcNowVisitor>()
.AddMemberAccessConverter<NowVisitor>();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Linq.Expressions;
using Laraue.EfCoreTriggers.Common.Converters.MemberAccess.DateTime;
using Laraue.EfCoreTriggers.Common.SqlGeneration;
using Laraue.EfCoreTriggers.Common.Visitors.ExpressionVisitors;

namespace Laraue.EfCoreTriggers.SqlLite.Converters.MemberAccess.DateTime
{
/// <inheritdoc />
public class NowVisitor : BaseNowVisitor
{
/// <inheritdoc />
public NowVisitor(IExpressionVisitorFactory visitorFactory)
: base(visitorFactory)
{
}

/// <inheritdoc />
public override SqlBuilder Visit(MemberExpression expression)
{
return SqlBuilder.FromString("DATETIME('now', 'localtime')");
}
}
}
Loading

0 comments on commit 80691fa

Please sign in to comment.