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"; } } }