Skip to content

Commit

Permalink
Merge pull request #17 from zadykian/fix/comparison-macros
Browse files Browse the repository at this point in the history
Comparison Macros
  • Loading branch information
sdcb authored Aug 31, 2023
2 parents cf9a6cf + 5ad6398 commit de91daa
Show file tree
Hide file tree
Showing 6 changed files with 279 additions and 62 deletions.
7 changes: 4 additions & 3 deletions sdmap/src/sdmap.ext.Dapper/sdmap.ext.Dapper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<AssemblyName>sdmap.ext.Dapper</AssemblyName>
<PackageId>sdmap.ext.Dapper</PackageId>
<PackageTags>dynamic sql;sdmap;dapper</PackageTags>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageReleaseNotes>For more information, please view:
https://github.com/sdcb/sdmap/blob/master/ReleaseNotes.md</PackageReleaseNotes>
<PackageLicenseUrl></PackageLicenseUrl>
Expand All @@ -13,13 +14,13 @@ https://github.com/sdcb/sdmap/blob/master/ReleaseNotes.md</PackageReleaseNotes>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Version>0.16.4</Version>
<Version>0.16.5</Version>
<Description>Dapper extensions for sdmap.</Description>
<PackageProjectUrl>https://github.com/sdcb/sdmap</PackageProjectUrl>
<Authors>sdcb</Authors>
<Copyright>MIT</Copyright>
<AssemblyVersion>0.16.4</AssemblyVersion>
<FileVersion>0.16.4</FileVersion>
<AssemblyVersion>0.16.5</AssemblyVersion>
<FileVersion>0.16.5</FileVersion>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
Expand Down
7 changes: 4 additions & 3 deletions sdmap/src/sdmap.ext/sdmap.ext.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<AssemblyName>sdmap.ext</AssemblyName>
<PackageId>sdmap.ext</PackageId>
<PackageTags>dynamic sql;sdmap</PackageTags>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageReleaseNotes>For more information, please view:
https://github.com/sdcb/sdmap/blob/master/ReleaseNotes.md</PackageReleaseNotes>
<PackageLicenseUrl></PackageLicenseUrl>
Expand All @@ -13,13 +14,13 @@ https://github.com/sdcb/sdmap/blob/master/ReleaseNotes.md</PackageReleaseNotes>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Version>0.16.4</Version>
<Version>0.16.5</Version>
<Description>Useful extensions for sdmap/Dapper.</Description>
<PackageProjectUrl>https://github.com/sdcb/sdmap</PackageProjectUrl>
<Authors>sdcb</Authors>
<Copyright>MIT</Copyright>
<AssemblyVersion>0.16.4</AssemblyVersion>
<FileVersion>0.16.4</FileVersion>
<AssemblyVersion>0.16.5</AssemblyVersion>
<FileVersion>0.16.5</FileVersion>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
Expand Down
76 changes: 23 additions & 53 deletions sdmap/src/sdmap/Macros/Implements/RuntimeMacros.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public static Result<string> IsEqual(OneCallContext context,
string syntax = (string)arguments[0];
var val = GetPropValue(self, syntax);
var compare = arguments[1];
if (IsEqual(val, compare))
if (ValueComparer.Compare(val, compare) is ComparisonResult.AreEqual)
return MacroUtil.EvalToString(arguments[2], context, self);

return Empty;
Expand All @@ -197,14 +197,14 @@ public static Result<string> IsNotEqual(OneCallContext context,
string syntax = (string)arguments[0];
var val = GetPropValue(self, syntax);
var compare = arguments[1];
if (!IsEqual(val, compare))
if (ValueComparer.Compare(val, compare) is not ComparisonResult.AreEqual)
return MacroUtil.EvalToString(arguments[2], context, self);

return Empty;
}

[Macro("isLessThan")]
[MacroArguments(SdmapTypes.Syntax, SdmapTypes.Number, SdmapTypes.StringOrSql)]
[MacroArguments(SdmapTypes.Syntax, SdmapTypes.Any, SdmapTypes.StringOrSql)]
public static Result<string> IsLessThan(OneCallContext context,
string ns, object self, object[] arguments)
{
Expand All @@ -214,16 +214,17 @@ public static Result<string> IsLessThan(OneCallContext context,
if (prop == null) return RequirePropNotNull(arguments[0]);

string syntax = (string)arguments[0];
var val = GetPropValue(self, syntax);
var compare = Convert.ToDouble(arguments[1]);
if (Convert.ToDouble(val) < compare)
var left = GetPropValue(self, syntax);
var right = arguments[1];

if (ValueComparer.Compare(left, right) is ComparisonResult.LeftIsLess)
return MacroUtil.EvalToString(arguments[2], context, self);

return Empty;
}

[Macro("isGreaterThan")]
[MacroArguments(SdmapTypes.Syntax, SdmapTypes.Number, SdmapTypes.StringOrSql)]
[MacroArguments(SdmapTypes.Syntax, SdmapTypes.Any, SdmapTypes.StringOrSql)]
public static Result<string> IsGreaterThan(OneCallContext context,
string ns, object self, object[] arguments)
{
Expand All @@ -233,16 +234,17 @@ public static Result<string> IsGreaterThan(OneCallContext context,
if (prop == null) return RequirePropNotNull(arguments[0]);

string syntax = (string)arguments[0];
var val = GetPropValue(self, syntax);
var compare = Convert.ToDouble(arguments[1]);
if (Convert.ToDouble(val) > compare)
var left = GetPropValue(self, syntax);
var right = arguments[1];

if (ValueComparer.Compare(left, right) is ComparisonResult.LeftIsGreater)
return MacroUtil.EvalToString(arguments[2], context, self);

return Empty;
}

[Macro("isLessEqual")]
[MacroArguments(SdmapTypes.Syntax, SdmapTypes.Number, SdmapTypes.StringOrSql)]
[MacroArguments(SdmapTypes.Syntax, SdmapTypes.Any, SdmapTypes.StringOrSql)]
public static Result<string> IsLessEqual(OneCallContext context,
string ns, object self, object[] arguments)
{
Expand All @@ -252,16 +254,17 @@ public static Result<string> IsLessEqual(OneCallContext context,
if (prop == null) return RequirePropNotNull(arguments[0]);

string syntax = (string)arguments[0];
var val = GetPropValue(self, syntax);
var compare = Convert.ToDouble(arguments[1]);
if (Convert.ToDouble(val) <= compare)
var left = GetPropValue(self, syntax);
var right = arguments[1];

if (ValueComparer.Compare(left, right) is ComparisonResult.LeftIsLess or ComparisonResult.AreEqual)
return MacroUtil.EvalToString(arguments[2], context, self);

return Empty;
}

[Macro("isGreaterEqual")]
[MacroArguments(SdmapTypes.Syntax, SdmapTypes.Number, SdmapTypes.StringOrSql)]
[MacroArguments(SdmapTypes.Syntax, SdmapTypes.Any, SdmapTypes.StringOrSql)]
public static Result<string> IsGreaterEqual(OneCallContext context,
string ns, object self, object[] arguments)
{
Expand All @@ -271,9 +274,10 @@ public static Result<string> IsGreaterEqual(OneCallContext context,
if (prop == null) return RequirePropNotNull(arguments[0]);

string syntax = (string)arguments[0];
var val = GetPropValue(self, syntax);
var compare = Convert.ToDouble(arguments[1]);
if (Convert.ToDouble(val) >= compare)
var left = GetPropValue(self, syntax);
var right = arguments[1];

if (ValueComparer.Compare(left, right) is ComparisonResult.LeftIsGreater or ComparisonResult.AreEqual)
return MacroUtil.EvalToString(arguments[2], context, self);

return Empty;
Expand Down Expand Up @@ -477,40 +481,6 @@ public static object GetPropValue(object self, string prop)
}
}

public static bool IsEqual(object v1, object v2)
{
if (v1 is string str)
return str.Equals((string)v2);

if (v1 is bool b)
return b.Equals((bool)v2);

if (v1 is int integer)
return integer.Equals(Convert.ToInt32(v2));

if (v1 is long longValue)
return longValue.Equals(Convert.ToInt64(v2));

if (v1 is double db)
return db.Equals(Convert.ToDouble(v2));

if (v1 is decimal dm)
return dm.Equals(Convert.ToDecimal(v2));

if (v1 is DateTime date)
return date.Equals((DateTime)v2);

if (v1 is Enum @enum)
{
if (v2 is string v2s)
return @enum.ToString() == v2s;
if (v2 is double v2d)
return Convert.ToInt64(@enum) == v2d;
}

return v1 == v2;
}

public static bool IsEmpty(object v)
{
if (v == null)
Expand All @@ -528,4 +498,4 @@ public static bool ArrayEmpty(IEnumerable arr)
return !arr.GetEnumerator().MoveNext();
}
}
}
}
140 changes: 140 additions & 0 deletions sdmap/src/sdmap/Macros/Implements/ValueComparer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
using System;
using System.Linq;
using System.Reflection;
// ReSharper disable SuggestBaseTypeForParameter

namespace sdmap.Macros.Implements;

public enum ComparisonResult : byte
{
Incomparable = 1,
AreEqual,
LeftIsGreater,
LeftIsLess
}

internal static class ValueComparer
{
public static ComparisonResult Compare(object left, object right)
=> CompareImpl(left, right) switch
{
null => ComparisonResult.Incomparable,
0 => ComparisonResult.AreEqual,
> 0 => ComparisonResult.LeftIsGreater,
< 0 => ComparisonResult.LeftIsLess
};

private static int? CompareImpl(object left, object right)
=> left switch
{
null => right is null ? 0 : null,
not null when right is null => null,

byte byteValue => byteValue.CompareTo(Convert.ToByte(right)),
sbyte sByteValue => sByteValue.CompareTo(Convert.ToSByte(right)),
short shortValue => shortValue.CompareTo(Convert.ToInt16(right)),
ushort ushortValue => ushortValue.CompareTo(Convert.ToUInt16(right)),

int intValue => intValue.CompareTo(Convert.ToInt32(right)),
uint uIntValue => uIntValue.CompareTo(Convert.ToUInt32(right)),
long longValue => longValue.CompareTo(Convert.ToInt64(right)),
ulong uLongValue => uLongValue.CompareTo(Convert.ToUInt64(right)),

float floatValue => floatValue.CompareTo(Convert.ToSingle(right)),
double doubleValue => doubleValue.CompareTo(Convert.ToDouble(right)),
decimal decimalValue => decimalValue.CompareTo(Convert.ToDecimal(right)),

Enum enumValue => Compare(enumValue, right),
IComparable comparable => Compare(comparable, right),

_ => null
};

private static int? Compare(Enum leftEnum, object right)
{
if (right is Enum rightEnum)
{
return leftEnum.GetType() == rightEnum.GetType()
? leftEnum.CompareTo(rightEnum)
: null;
}

return EnumParser.TryParse(leftEnum.GetType(), right.ToString(), out var parsed)
? leftEnum.CompareTo(parsed)
: null;
}

private static int? Compare(IComparable comparable, object right)
{
var leftType = comparable.GetType();

if (leftType == right.GetType())
{
return comparable.CompareTo(right);
}

return TryParse(leftType, right.ToString(), out var parsed)
? comparable.CompareTo(parsed)
: null;

static bool TryParse(Type targetType, string input, out object parsed)
{
if (targetType == typeof(Guid))
{
var result = Guid.TryParse(input, out var parsedValue);
parsed = parsedValue;
return result;
}

if (targetType == typeof(TimeSpan))
{
var result = TimeSpan.TryParse(input, out var parsedValue);
parsed = parsedValue;
return result;
}

if (targetType == typeof(DateTime))
{
var result = DateTime.TryParse(input, out var parsedValue);
parsed = parsedValue;
return result;
}

if (targetType == typeof(DateTimeOffset))
{
var result = DateTimeOffset.TryParse(input, out var parsedValue);
parsed = parsedValue;
return result;
}

parsed = null;
return false;
}
}

private static class EnumParser
{
private static readonly MethodInfo TryParseMethod
= typeof(Enum)
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.Single(method =>
method.Name == nameof(Enum.TryParse)
&& method.IsGenericMethodDefinition
&& method.ReturnType == typeof(bool)
&& method.GetParameters().Length == 3
&& method.GetParameters().First().ParameterType == typeof(string)
);

public static bool TryParse(Type enumType, string value, out object parsed)
{
var parameters = new object[] { value, true, null };

var result = TryParseMethod
.MakeGenericMethod(enumType)
.Invoke(obj: null, parameters);

parsed = parameters[2];
return (bool)result;
}
}
}
8 changes: 5 additions & 3 deletions sdmap/src/sdmap/sdmap.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@
<PropertyGroup>
<Description>A template engine for writing dynamic sql.</Description>
<TargetFrameworks>net6;netstandard20</TargetFrameworks>
<LangVersion>latest</LangVersion>
<AssemblyName>sdmap</AssemblyName>
<PackageId>sdmap</PackageId>
<PackageTags>dynamic sql;ibatis</PackageTags>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageReleaseNotes>https://github.com/sdcb/sdmap/blob/master/ReleaseNotes.md</PackageReleaseNotes>
<PackageLicenseUrl></PackageLicenseUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/sdcb/sdmap</RepositoryUrl>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Version>0.16.4</Version>
<AssemblyVersion>0.16.4</AssemblyVersion>
<FileVersion>0.16.4</FileVersion>
<Version>0.16.5</Version>
<AssemblyVersion>0.16.5</AssemblyVersion>
<FileVersion>0.16.5</FileVersion>
<Authors>sdcb</Authors>
<Copyright>MIT</Copyright>
<PackageProjectUrl>https://github.com/sdcb/sdmap</PackageProjectUrl>
Expand Down
Loading

0 comments on commit de91daa

Please sign in to comment.