349 lines
16 KiB
C#
349 lines
16 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Linq.Expressions;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace SqlSugar
|
|
{
|
|
public class BinaryExpressionResolve : BaseResolve
|
|
{
|
|
public BinaryExpressionResolve(ExpressionParameter parameter) : base(parameter)
|
|
{
|
|
switch (parameter.Context.ResolveType)
|
|
{
|
|
case ResolveExpressType.FieldSingle:
|
|
case ResolveExpressType.FieldMultiple:
|
|
var sql = base.GetNewExpressionValue(this.Expression);
|
|
this.Context.Result.Append(sql);
|
|
break;
|
|
default:
|
|
Other(parameter);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void Other(ExpressionParameter parameter)
|
|
{
|
|
var expression = this.Expression as BinaryExpression;
|
|
if (expression.NodeType == ExpressionType.ArrayIndex)
|
|
{
|
|
var parameterName = AppendParameter(ExpressionTool.DynamicInvoke(expression));
|
|
if (this.BaseParameter?.IsLeft==true)
|
|
{
|
|
base.Context.Result.Append($" {BaseParameter.BaseParameter.OperatorValue} {parameterName} ");
|
|
}
|
|
else
|
|
{
|
|
base.Context.Result.Append($" {parameterName} ");
|
|
}
|
|
return;
|
|
}
|
|
var operatorValue = parameter.OperatorValue = ExpressionTool.GetOperator(expression.NodeType);
|
|
var isSubGroup = IsGroupSubquery(expression.Right, operatorValue);
|
|
if (isSubGroup)
|
|
{
|
|
SubGroup(expression, operatorValue);
|
|
}
|
|
else if (IsJoinString(expression, operatorValue))
|
|
{
|
|
JoinString(parameter, expression);
|
|
}
|
|
else if (IsUpdateJson(parameter,expression, operatorValue))
|
|
{
|
|
parameter.CommonTempData = "IsJson=true";
|
|
DefaultBinary(parameter, expression, operatorValue);
|
|
parameter.CommonTempData = null;
|
|
}
|
|
else if (IsUpdateArray(parameter, expression, operatorValue))
|
|
{
|
|
parameter.CommonTempData = "IsArray=true";
|
|
DefaultBinary(parameter, expression, operatorValue);
|
|
parameter.CommonTempData = null;
|
|
}
|
|
else
|
|
{
|
|
DefaultBinary(parameter, expression, operatorValue);
|
|
}
|
|
}
|
|
private bool IsUpdateArray(ExpressionParameter parameter, BinaryExpression expression, string operatorValue)
|
|
{
|
|
var isOk = parameter.Context.ResolveType == ResolveExpressType.WhereSingle && operatorValue == "=" && (expression.Left is MemberExpression) && expression.Left.Type.IsClass();
|
|
if (isOk && this.Context.SugarContext != null)
|
|
{
|
|
var member = (expression.Left as MemberExpression);
|
|
if (member.Expression != null)
|
|
{
|
|
var entity = this.Context.SugarContext.Context.EntityMaintenance.GetEntityInfo(member.Expression.Type);
|
|
var jsonColumn = entity.Columns.FirstOrDefault(it => it.IsArray && it.PropertyName == ExpressionTool.GetMemberName(expression.Left));
|
|
if (jsonColumn != null)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool IsUpdateJson(ExpressionParameter parameter,BinaryExpression expression, string operatorValue)
|
|
{
|
|
var isOk= parameter.Context.ResolveType==ResolveExpressType.WhereSingle&&operatorValue == "=" && (expression.Left is MemberExpression) && expression.Left.Type.IsClass();
|
|
if (isOk&&this.Context.SugarContext != null)
|
|
{
|
|
var member = (expression.Left as MemberExpression);
|
|
if (member.Expression != null)
|
|
{
|
|
var entity = this.Context.SugarContext.Context.EntityMaintenance.GetEntityInfo(member.Expression.Type);
|
|
var jsonColumn = entity.Columns.FirstOrDefault(it => it.IsJson && it.PropertyName == ExpressionTool.GetMemberName(expression.Left));
|
|
if (jsonColumn != null)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void JoinString(ExpressionParameter parameter, BinaryExpression expression)
|
|
{
|
|
var leftString = GetNewExpressionValue(expression.Left);
|
|
var RightString = GetNewExpressionValue(expression.Right);
|
|
var joinString = this.Context.DbMehtods.MergeString(leftString, RightString);
|
|
if (this.Context.Result.Contains(ExpressionConst.FormatSymbol))
|
|
{
|
|
base.Context.Result.Replace("{0}", $" {joinString} ");
|
|
base.Context.Result.Append(" " + ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index + " ");
|
|
}
|
|
else
|
|
{
|
|
base.Context.Result.Append($" {joinString} ");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void DefaultBinary(ExpressionParameter parameter, BinaryExpression expression, string operatorValue)
|
|
{
|
|
var isEqual = expression.NodeType == ExpressionType.Equal;
|
|
var isComparisonOperator = ExpressionTool.IsComparisonOperator(expression);
|
|
base.ExactExpression = expression;
|
|
var leftExpression = expression.Left;
|
|
var rightExpression = expression.Right;
|
|
if (operatorValue == "="&& ExpressionTool.RemoveConvert(leftExpression) is ConstantExpression)
|
|
{
|
|
leftExpression = expression.Right;
|
|
rightExpression = expression.Left;
|
|
}
|
|
if (RightIsHasValue(leftExpression, rightExpression,ExpressionTool.IsLogicOperator(expression)))
|
|
{
|
|
Expression trueValue = Expression.Constant(true);
|
|
rightExpression = ExpressionBuilderHelper.CreateExpression(rightExpression, trueValue, ExpressionType.Equal);
|
|
}
|
|
var leftIsBinary = leftExpression is BinaryExpression;
|
|
var rightBinary = rightExpression is BinaryExpression;
|
|
var lbrs = leftIsBinary && !rightBinary;
|
|
var lsrb = !leftIsBinary && rightBinary;
|
|
var lbrb = rightBinary && leftIsBinary;
|
|
var lsbs = !leftIsBinary && !rightBinary;
|
|
var isAppend = !base.Context.Result.Contains(ExpressionConst.FormatSymbol);
|
|
ConvertExpression(ref leftExpression, ref rightExpression, isAppend);
|
|
parameter.LeftExpression = leftExpression;
|
|
parameter.RightExpression = rightExpression;
|
|
Left(expression, leftExpression);
|
|
Right(parameter, operatorValue, isEqual, rightExpression, lsbs);
|
|
}
|
|
|
|
private void SubGroup(BinaryExpression expression, string operatorValue)
|
|
{
|
|
if (ExpressionTool.IsUnConvertExpress(expression.Right))
|
|
{
|
|
InSubGroupByConvertExpress(expression);
|
|
}
|
|
else
|
|
{
|
|
InSubGroupBy(expression, operatorValue == "<>" ? "NOT" : "");
|
|
}
|
|
}
|
|
|
|
private void ConvertExpression(ref Expression leftExpression, ref Expression rightExpression, bool isAppend)
|
|
{
|
|
if (isAppend)
|
|
{
|
|
base.Context.Result.Append(ExpressionConst.LeftParenthesis);
|
|
base.Context.Result.Append(ExpressionConst.FormatSymbol);
|
|
}
|
|
else
|
|
{
|
|
base.Context.Result.Replace(ExpressionConst.FormatSymbol, ExpressionConst.LeftParenthesis + ExpressionConst.FormatSymbol);
|
|
}
|
|
if (leftExpression is UnaryExpression && (leftExpression as UnaryExpression).Operand is UnaryExpression && (leftExpression as UnaryExpression).NodeType == ExpressionType.Convert)
|
|
{
|
|
leftExpression = (leftExpression as UnaryExpression).Operand;
|
|
}
|
|
if (leftExpression is UnaryExpression && (leftExpression as UnaryExpression).Operand.Type == UtilConstants.BoolType && (leftExpression as UnaryExpression).NodeType == ExpressionType.Convert && rightExpression.Type == UtilConstants.BoolTypeNull)
|
|
{
|
|
leftExpression = (leftExpression as UnaryExpression).Operand;
|
|
}
|
|
if (rightExpression is UnaryExpression && (rightExpression as UnaryExpression).NodeType == ExpressionType.Convert)
|
|
{
|
|
rightExpression = (rightExpression as UnaryExpression).Operand;
|
|
}
|
|
}
|
|
|
|
private void Right(ExpressionParameter parameter, string operatorValue, bool isEqual, Expression rightExpression, bool lsbs)
|
|
{
|
|
base.IsLeft = false;
|
|
base.Expression = rightExpression;
|
|
base.Start();
|
|
base.IsLeft = null;
|
|
if (lsbs && parameter.ValueIsNull)
|
|
{
|
|
base.Context.Result.Replace(ExpressionConst.ExpressionReplace + parameter.Index, isEqual ? "IS" : "IS NOT");
|
|
base.Context.Result.Replace(ExpressionConst.ExpressionReplace + (parameter.Index + 1), isEqual ? "IS" : "IS NOT");
|
|
}
|
|
else
|
|
{
|
|
base.Context.Result.Replace(ExpressionConst.ExpressionReplace + parameter.Index, operatorValue);
|
|
base.Context.Result.Replace(ExpressionConst.ExpressionReplace + (parameter.Index + 1), operatorValue);
|
|
}
|
|
base.Context.Result.Append(ExpressionConst.RightParenthesis);
|
|
if (parameter.BaseExpression is BinaryExpression && parameter.IsLeft == true)
|
|
{
|
|
base.Context.Result.Append(" " + ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index + " ");
|
|
}
|
|
}
|
|
|
|
private void Left(BinaryExpression expression, Expression leftExpression)
|
|
{
|
|
base.Expression = leftExpression;
|
|
base.IsLeft = true;
|
|
base.Start();
|
|
if (leftExpression is UnaryExpression && leftExpression.Type == UtilConstants.BoolType && !this.Context.Result.Contains(ExpressionConst.ExpressionReplace))
|
|
{
|
|
this.Context.Result.AppendFormat(" {0} ", ExpressionTool.GetOperator(expression.NodeType));
|
|
}
|
|
else if (leftExpression is UnaryExpression && ExpressionTool.RemoveConvert(leftExpression) is BinaryExpression && !this.Context.Result.Contains(ExpressionConst.ExpressionReplace))
|
|
{
|
|
this.Context.Result.AppendFormat(" {0} ", ExpressionTool.GetOperator(expression.NodeType));
|
|
}
|
|
}
|
|
|
|
private void InSubGroupByConvertExpress(BinaryExpression expression)
|
|
{
|
|
var leftSql = GetNewExpressionValue(expression.Left);
|
|
var rightExpression = (expression.Right as UnaryExpression).Operand as MethodCallExpression;
|
|
var selector = GetNewExpressionValue(rightExpression.Arguments[0]);
|
|
var rightSql = GetNewExpressionValue(rightExpression.Object).Replace("SELECT FROM", $"SELECT {selector} FROM");
|
|
if (this.Context.IsSingle && this.Context.SingleTableNameSubqueryShortName == null)
|
|
{
|
|
var leftExp = expression.Left;
|
|
if (leftExp is UnaryExpression)
|
|
{
|
|
leftExp = (leftExp as UnaryExpression).Operand;
|
|
}
|
|
var p = (leftExp as MemberExpression);
|
|
this.Context.SingleTableNameSubqueryShortName = p.Expression.ToString();
|
|
}
|
|
base.Context.Result.Append($" {leftSql} in ({rightSql}) ");
|
|
}
|
|
private void InSubGroupBy(BinaryExpression expression,string not)
|
|
{
|
|
var leftSql = GetNewExpressionValue(expression.Left);
|
|
var rightExpression = expression.Right as MethodCallExpression;
|
|
if (rightExpression.Arguments[0] is LambdaExpression)
|
|
{
|
|
if ((rightExpression.Arguments[0] as LambdaExpression).Parameters?.Count > 0)
|
|
{
|
|
foreach (var item in (rightExpression.Arguments[0] as LambdaExpression).Parameters)
|
|
{
|
|
if (this.Context.InitMappingInfo != null)
|
|
{
|
|
this.Context.InitMappingInfo(item.Type);
|
|
this.Context.RefreshMapping();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
var selector = GetNewExpressionValue(rightExpression.Arguments[0]);
|
|
var selectorExp = rightExpression.Arguments[0];
|
|
if (selector.Contains(".") && selectorExp is LambdaExpression)
|
|
{
|
|
var selectorExpLam = (selectorExp as LambdaExpression);
|
|
var name=(selectorExpLam.Parameters[0] as ParameterExpression).Name;
|
|
selector= selector.Replace(this.Context.GetTranslationColumnName(name)+ ".", "");
|
|
}
|
|
var rightSql = GetNewExpressionValue(rightExpression.Object).Replace("SELECT FROM", $"SELECT {selector} FROM");
|
|
if (this.Context.IsSingle&&this.Context.SingleTableNameSubqueryShortName==null)
|
|
{
|
|
var leftExp = expression.Left;
|
|
if (leftExp is UnaryExpression)
|
|
{
|
|
leftExp = (leftExp as UnaryExpression).Operand;
|
|
}
|
|
var p = (leftExp as MemberExpression);
|
|
this.Context.SingleTableNameSubqueryShortName=p.Expression.ToString();
|
|
}
|
|
if (UtilMethods.IsParentheses(rightSql+""))
|
|
{
|
|
base.Context.Result.Append($" {leftSql} {not} in {rightSql} ");
|
|
}
|
|
else
|
|
{
|
|
base.Context.Result.Append($" {leftSql} {not} in ({rightSql}) ");
|
|
}
|
|
}
|
|
|
|
private bool IsGroupSubquery(Expression rightExpression, string operatorValue)
|
|
{
|
|
if (operatorValue != "="&& operatorValue != "<>")
|
|
{
|
|
return false;
|
|
}
|
|
if (rightExpression == null)
|
|
{
|
|
return false;
|
|
}
|
|
if (ExpressionTool.IsUnConvertExpress(rightExpression))
|
|
{
|
|
rightExpression = (rightExpression as UnaryExpression).Operand;
|
|
}
|
|
if ((rightExpression is MethodCallExpression) == false)
|
|
{
|
|
return false;
|
|
}
|
|
var method = (rightExpression as MethodCallExpression);
|
|
if (method.Method.Name != "Select")
|
|
{
|
|
return false;
|
|
}
|
|
var methodString = method.ToString();
|
|
if (methodString.IndexOf("GroupBy(")<=0)
|
|
{
|
|
return false;
|
|
}
|
|
if (Regex.Matches(methodString, @"Subqueryable\(").Count!=1)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
private static bool IsJoinString(BinaryExpression expression, string operatorValue)
|
|
{
|
|
return operatorValue == "+"
|
|
&& expression.Right.Type == UtilConstants.StringType
|
|
&& expression.Left.Type==UtilConstants.StringType;
|
|
}
|
|
private static bool RightIsHasValue(Expression leftExpression, Expression rightExpression,bool isLogic)
|
|
{
|
|
return isLogic&&
|
|
leftExpression.Type == UtilConstants.BoolType &&
|
|
rightExpression.Type == UtilConstants.BoolType &&
|
|
rightExpression is MethodCallExpression &&
|
|
(rightExpression as MethodCallExpression).Method.Name == "HasValue";
|
|
}
|
|
|
|
}
|
|
}
|