- 优化 Enum 位运算 MapType 解析;#1413

This commit is contained in:
2881099 2023-02-08 19:35:19 +08:00
parent af44fdadb0
commit f8773469bc
3 changed files with 163 additions and 9 deletions

View File

@ -800,14 +800,5 @@
<param name="that"></param> <param name="that"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Microsoft.Extensions.DependencyInjection.FreeSqlRepositoryDependencyInjection.AddFreeRepository(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{FreeSql.FluentDataFilter},System.Reflection.Assembly[])">
<summary>
批量注入 Repository可以参考代码自行调整
</summary>
<param name="services"></param>
<param name="globalDataFilter"></param>
<param name="assemblies"></param>
<returns></returns>
</member>
</members> </members>
</doc> </doc>

View File

@ -17,6 +17,80 @@ namespace FreeSql.Tests.MySqlExpression
} }
[Fact]
public void BitEnum()
{
var fsql = g.mysql;
var sql1 = fsql.Select<BitEnum01>().Where(a => a.enum1 == TableAllTypeEnumType1.e5).ToSql();
var enum1 = TableAllTypeEnumType1.e5;
var sql2 = fsql.Select<BitEnum01>().Where(a => a.enum1 == enum1).ToSql();
Assert.Equal(sql1, sql2);
Assert.Equal(@"SELECT a.`id`, a.`enum1`, a.`enum2`, a.`set1`, a.`set2`
FROM `BitEnum01` a
WHERE (a.`enum1` = 'e5')", sql1);
sql1 = fsql.Select<BitEnum01>().Where(a => a.enum2 == TableAllTypeEnumType1.e5).ToSql();
sql2 = fsql.Select<BitEnum01>().Where(a => a.enum2 == enum1).ToSql();
Assert.Equal(sql1, sql2);
Assert.Equal(@"SELECT a.`id`, a.`enum1`, a.`enum2`, a.`set1`, a.`set2`
FROM `BitEnum01` a
WHERE (a.`enum2` = 3)", sql1);
sql1 = fsql.Select<BitEnum01>().Where(a => (a.enum1 & TableAllTypeEnumType1.e2) == TableAllTypeEnumType1.e2).ToSql();
enum1 = TableAllTypeEnumType1.e2;
sql2 = fsql.Select<BitEnum01>().Where(a => (a.enum1 & enum1) == enum1).ToSql();
Assert.Equal(sql1, sql2);
Assert.Equal(@"SELECT a.`id`, a.`enum1`, a.`enum2`, a.`set1`, a.`set2`
FROM `BitEnum01` a
WHERE ((a.`enum1` & 'e2') = 'e2')", sql1);
sql1 = fsql.Select<BitEnum01>().Where(a => (a.enum2 & TableAllTypeEnumType1.e2) == TableAllTypeEnumType1.e2).ToSql();
enum1 = TableAllTypeEnumType1.e2;
sql2 = fsql.Select<BitEnum01>().Where(a => (a.enum2 & enum1) == enum1).ToSql();
Assert.Equal(sql1, sql2);
Assert.Equal(@"SELECT a.`id`, a.`enum1`, a.`enum2`, a.`set1`, a.`set2`
FROM `BitEnum01` a
WHERE ((a.`enum2` & 1) = 1)", sql1);
sql1 = fsql.Select<BitEnum01>().Where(a => a.set1 == TableAllTypeEnumType2.f3).ToSql();
var set1 = TableAllTypeEnumType2.f3;
sql2 = fsql.Select<BitEnum01>().Where(a => a.set1 == set1).ToSql();
Assert.Equal(sql1, sql2);
Assert.Equal(@"SELECT a.`id`, a.`enum1`, a.`enum2`, a.`set1`, a.`set2`
FROM `BitEnum01` a
WHERE (a.`set1` = 'f3')", sql1);
sql1 = fsql.Select<BitEnum01>().Where(a => a.set2 == TableAllTypeEnumType2.f3).ToSql();
sql2 = fsql.Select<BitEnum01>().Where(a => a.set2 == set1).ToSql();
Assert.Equal(sql1, sql2);
Assert.Equal(@"SELECT a.`id`, a.`enum1`, a.`enum2`, a.`set1`, a.`set2`
FROM `BitEnum01` a
WHERE (a.`set2` = 2)", sql1);
sql1 = fsql.Select<BitEnum01>().Where(a => (a.set1 & TableAllTypeEnumType2.f2) == TableAllTypeEnumType2.f2).ToSql();
set1 = TableAllTypeEnumType2.f2;
sql2 = fsql.Select<BitEnum01>().Where(a => (a.set1 & set1) == set1).ToSql();
Assert.Equal(sql1, sql2);
Assert.Equal(@"SELECT a.`id`, a.`enum1`, a.`enum2`, a.`set1`, a.`set2`
FROM `BitEnum01` a
WHERE ((a.`set1` & 'f2') = 'f2')", sql1);
sql1 = fsql.Select<BitEnum01>().Where(a => (a.set2 & TableAllTypeEnumType2.f2) == TableAllTypeEnumType2.f2).ToSql();
set1 = TableAllTypeEnumType2.f2;
sql2 = fsql.Select<BitEnum01>().Where(a => (a.set2 & set1) == set1).ToSql();
Assert.Equal(sql1, sql2);
Assert.Equal(@"SELECT a.`id`, a.`enum1`, a.`enum2`, a.`set1`, a.`set2`
FROM `BitEnum01` a
WHERE ((a.`set2` & 1) = 1)", sql1);
}
class BitEnum01
{
public int id { get; set; }
public TableAllTypeEnumType1 enum1 { get; set; }
[Column(MapType = typeof(int))]
public TableAllTypeEnumType1 enum2 { get; set; }
public TableAllTypeEnumType2 set1 { get; set; }
[Column(MapType = typeof(long))]
public TableAllTypeEnumType2 set2 { get; set; }
}
[Fact] [Fact]
public void ArrayAnyOr() public void ArrayAnyOr()
{ {

View File

@ -2034,8 +2034,97 @@ namespace FreeSql.Internal
if (exp.IsParameter() == false) return formatSql(Expression.Lambda(exp).Compile().DynamicInvoke(), tsc.mapType, tsc.mapColumnTmp, tsc.dbParams); if (exp.IsParameter() == false) return formatSql(Expression.Lambda(exp).Compile().DynamicInvoke(), tsc.mapType, tsc.mapColumnTmp, tsc.dbParams);
return ""; return "";
} }
switch (expBinary.NodeType)
{
case ExpressionType.Equal:
case ExpressionType.NotEqual:
//位运算 + MapType
var bitwiseResult = ExpressionBinaryBitwise(tryoper, expBinary.Left, expBinary.Right, tsc);
if (string.IsNullOrEmpty(bitwiseResult) == false) return bitwiseResult;
break;
}
return ExpressionBinary(tryoper, expBinary.Left, expBinary.Right, tsc); return ExpressionBinary(tryoper, expBinary.Left, expBinary.Right, tsc);
} }
public string ExpressionBinaryBitwise(string oper, Expression leftExp, Expression rightExp, ExpTSC tsc)
{
string LocalSwithBitResult(Expression expBit, string r1, string r2)
{
switch (expBit.NodeType)
{
case ExpressionType.And: return _common.BitAnd(r1, r2);
case ExpressionType.Or: return _common.BitOr(r1, r2);
case ExpressionType.LeftShift: return _common.BitShiftLeft(r1, r2);
case ExpressionType.RightShift: return _common.BitShiftRight(r1, r2);
case ExpressionType.ExclusiveOr: return _common.BitXor(r1, r2);
}
return "";
}
while (leftExp.NodeType == ExpressionType.Convert && leftExp is UnaryExpression leftExpUExp) leftExp = leftExpUExp.Operand;
switch (leftExp.NodeType)
{
case ExpressionType.And:
case ExpressionType.Or:
case ExpressionType.LeftShift:
case ExpressionType.RightShift:
case ExpressionType.ExclusiveOr:
var leftBinary = leftExp as BinaryExpression;
var leftBinaryL = ExpressionLambdaToSql(leftBinary.Left, tsc);
var leftBinaryR = "";
var leftBinaryColumn = SearchColumnByField(tsc._tables, tsc.currentTable, leftBinaryL);
if (leftBinaryColumn != null)
{
var oldMapType = tsc.SetMapTypeReturnOld(leftBinaryColumn.Attribute.MapType);
leftBinaryR = ExpressionLambdaToSql(leftBinary.Right, tsc);
var rightResult = ExpressionLambdaToSql(rightExp, tsc);
tsc.SetMapTypeReturnOld(oldMapType);
return $"{LocalSwithBitResult(leftExp, leftBinaryL, leftBinaryR)} {oper} {rightResult}";
}
leftBinaryR = ExpressionLambdaToSql(leftBinary.Right, tsc);
leftBinaryColumn = SearchColumnByField(tsc._tables, tsc.currentTable, leftBinaryR);
if (leftBinaryColumn != null)
{
var oldMapType = tsc.SetMapTypeReturnOld(leftBinaryColumn.Attribute.MapType);
leftBinaryL = ExpressionLambdaToSql(leftBinary.Left, tsc);
var rightResult = ExpressionLambdaToSql(rightExp, tsc);
tsc.SetMapTypeReturnOld(oldMapType);
return $"{LocalSwithBitResult(leftExp, leftBinaryL, leftBinaryR)} {oper} {rightResult}";
}
break;
}
while (rightExp.NodeType == ExpressionType.Convert && rightExp is UnaryExpression rightExpUExp) rightExp = rightExpUExp.Operand;
switch (rightExp.NodeType)
{
case ExpressionType.And:
case ExpressionType.Or:
case ExpressionType.LeftShift:
case ExpressionType.RightShift:
case ExpressionType.ExclusiveOr:
var rightBinary = rightExp as BinaryExpression;
var rightBinaryL = ExpressionLambdaToSql(rightBinary.Left, tsc);
var rightBinaryR = "";
var rightBinaryColumn = SearchColumnByField(tsc._tables, tsc.currentTable, rightBinaryL);
if (rightBinaryColumn != null)
{
var oldMapType = tsc.SetMapTypeReturnOld(rightBinaryColumn.Attribute.MapType);
rightBinaryR = ExpressionLambdaToSql(rightBinary.Right, tsc);
var leftResult = ExpressionLambdaToSql(leftExp, tsc);
tsc.SetMapTypeReturnOld(oldMapType);
return $"{leftResult} {oper} {LocalSwithBitResult(rightExp, rightBinaryL, rightBinaryR)}";
}
rightBinaryR = ExpressionLambdaToSql(rightBinary.Right, tsc);
rightBinaryColumn = SearchColumnByField(tsc._tables, tsc.currentTable, rightBinaryR);
if (rightBinaryColumn != null)
{
var oldMapType = tsc.SetMapTypeReturnOld(rightBinaryColumn.Attribute.MapType);
rightBinaryL = ExpressionLambdaToSql(rightBinary.Left, tsc);
var leftResult = ExpressionLambdaToSql(leftExp, tsc);
tsc.SetMapTypeReturnOld(oldMapType);
return $"{leftResult} {oper} {LocalSwithBitResult(rightExp, rightBinaryL, rightBinaryR)}";
}
break;
}
return "";
}
public abstract string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc); public abstract string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc);
public abstract string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc); public abstract string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc);