private HqlTreeNode TranslateEqualityComparison(BinaryExpression expression) { var lhs = VisitExpression(expression.Left).ToArithmeticExpression(); var rhs = VisitExpression(expression.Right).ToArithmeticExpression(); // Check for nulls on left or right. if (VisitorUtil.IsNullConstant(expression.Right)) { rhs = null; } if (VisitorUtil.IsNullConstant(expression.Left)) { lhs = null; } if (lhs == null && rhs == null) { return(_hqlTreeBuilder.True()); } if (lhs == null) { return(_hqlTreeBuilder.IsNull(rhs)); } if (rhs == null) { return(_hqlTreeBuilder.IsNull((lhs))); } var lhsNullable = IsNullable(lhs); var rhsNullable = IsNullable(rhs); var equality = _hqlTreeBuilder.Equality(lhs, rhs); if (!lhsNullable || !rhsNullable) { return(equality); } var lhs2 = VisitExpression(expression.Left).ToArithmeticExpression(); var rhs2 = VisitExpression(expression.Right).ToArithmeticExpression(); return(_hqlTreeBuilder.BooleanOr( equality, _hqlTreeBuilder.BooleanAnd( _hqlTreeBuilder.IsNull(lhs2), _hqlTreeBuilder.IsNull(rhs2)))); }
private static bool IsConstructionToNullComparison(Expression expression) { var testExpression = expression as BinaryExpression; if (testExpression != null) { if ((IsConstruction(testExpression.Left) && VisitorUtil.IsNullConstant(testExpression.Right)) || (IsConstruction(testExpression.Right) && VisitorUtil.IsNullConstant(testExpression.Left))) { return(true); } } return(false); }
private void FindNotNullMember(BinaryExpression binaryExpression, List <MemberExpression> notNullMembers) { _equalityNotNullMembers[binaryExpression] = notNullMembers; if (binaryExpression.NodeType != ExpressionType.NotEqual) { return; } MemberExpression memberExpression; if (VisitorUtil.IsNullConstant(binaryExpression.Right) && TryGetMemberAccess(binaryExpression.Left, out memberExpression)) { notNullMembers.Add(memberExpression); } else if (VisitorUtil.IsNullConstant(binaryExpression.Left) && TryGetMemberAccess(binaryExpression.Right, out memberExpression)) { notNullMembers.Add(memberExpression); } }
private HqlTreeNode TranslateEqualityComparison(BinaryExpression expression, HqlExpression lhs, HqlExpression rhs, Func <HqlExpression, HqlTreeNode> applyNullComparison, Func <HqlExpression, HqlExpression, HqlTreeNode> applyRegularComparison) { // Check for nulls on left or right. if (VisitorUtil.IsNullConstant(expression.Right)) { rhs = null; } if (VisitorUtil.IsNullConstant(expression.Left)) { lhs = null; } // Need to check for boolean equality if (lhs is HqlBooleanExpression || rhs is HqlBooleanExpression) { if (lhs != null) { lhs = GetExpressionForBooleanEquality(expression.Left, lhs); } if (rhs != null) { rhs = GetExpressionForBooleanEquality(expression.Right, rhs); } } if (lhs == null) { return(applyNullComparison(rhs)); } if (rhs == null) { return(applyNullComparison(lhs)); } return(applyRegularComparison(lhs, rhs)); }
protected override Expression VisitBinaryExpression(BinaryExpression expression) { var result = base.VisitBinaryExpression(expression); if (expression.NodeType == ExpressionType.AndAlso) { HandleBinaryOperation((a, b) => a.AndAlso(b)); } else if (expression.NodeType == ExpressionType.OrElse) { HandleBinaryOperation((a, b) => a.OrElse(b)); } else if (expression.NodeType == ExpressionType.NotEqual && VisitorUtil.IsNullConstant(expression.Right)) { // Discard result from right null. Left is visited first, so it's below right on the stack. _values.Pop(); HandleUnaryOperation(pvs => pvs.IsNotNull()); } else if (expression.NodeType == ExpressionType.NotEqual && VisitorUtil.IsNullConstant(expression.Left)) { // Discard result from left null. var right = _values.Pop(); _values.Pop(); // Discard left. _values.Push(right); HandleUnaryOperation(pvs => pvs.IsNotNull()); } else if (expression.NodeType == ExpressionType.Equal && VisitorUtil.IsNullConstant(expression.Right)) { // Discard result from right null. Left is visited first, so it's below right on the stack. _values.Pop(); HandleUnaryOperation(pvs => pvs.IsNull()); } else if (expression.NodeType == ExpressionType.Equal && VisitorUtil.IsNullConstant(expression.Left)) { // Discard result from left null. var right = _values.Pop(); _values.Pop(); // Discard left. _values.Push(right); HandleUnaryOperation(pvs => pvs.IsNull()); } else if (expression.NodeType == ExpressionType.Coalesce) { HandleBinaryOperation((a, b) => a.Coalesce(b)); } else if (expression.NodeType == ExpressionType.Add || expression.NodeType == ExpressionType.AddChecked) { HandleBinaryOperation((a, b) => a.Add(b, expression.Type)); } else if (expression.NodeType == ExpressionType.Divide) { HandleBinaryOperation((a, b) => a.Divide(b, expression.Type)); } else if (expression.NodeType == ExpressionType.Modulo) { HandleBinaryOperation((a, b) => a.Modulo(b, expression.Type)); } else if (expression.NodeType == ExpressionType.Multiply || expression.NodeType == ExpressionType.MultiplyChecked) { HandleBinaryOperation((a, b) => a.Multiply(b, expression.Type)); } else if (expression.NodeType == ExpressionType.Power) { HandleBinaryOperation((a, b) => a.Power(b, expression.Type)); } else if (expression.NodeType == ExpressionType.Subtract || expression.NodeType == ExpressionType.SubtractChecked) { HandleBinaryOperation((a, b) => a.Subtract(b, expression.Type)); } else if (expression.NodeType == ExpressionType.And) { HandleBinaryOperation((a, b) => a.And(b, expression.Type)); } else if (expression.NodeType == ExpressionType.Or) { HandleBinaryOperation((a, b) => a.Or(b, expression.Type)); } else if (expression.NodeType == ExpressionType.ExclusiveOr) { HandleBinaryOperation((a, b) => a.ExclusiveOr(b, expression.Type)); } else if (expression.NodeType == ExpressionType.LeftShift) { HandleBinaryOperation((a, b) => a.LeftShift(b, expression.Type)); } else if (expression.NodeType == ExpressionType.RightShift) { HandleBinaryOperation((a, b) => a.RightShift(b, expression.Type)); } else if (expression.NodeType == ExpressionType.Equal) { HandleBinaryOperation((a, b) => a.Equal(b)); } else if (expression.NodeType == ExpressionType.NotEqual) { HandleBinaryOperation((a, b) => a.NotEqual(b)); } else if (expression.NodeType == ExpressionType.GreaterThanOrEqual) { HandleBinaryOperation((a, b) => a.GreaterThanOrEqual(b)); } else if (expression.NodeType == ExpressionType.GreaterThan) { HandleBinaryOperation((a, b) => a.GreaterThan(b)); } else if (expression.NodeType == ExpressionType.LessThan) { HandleBinaryOperation((a, b) => a.LessThan(b)); } else if (expression.NodeType == ExpressionType.LessThanOrEqual) { HandleBinaryOperation((a, b) => a.LessThanOrEqual(b)); } return(result); }
private HqlTreeNode TranslateInequalityComparison(BinaryExpression expression) { var lhs = VisitExpression(expression.Left).ToArithmeticExpression(); var rhs = VisitExpression(expression.Right).ToArithmeticExpression(); // Check for nulls on left or right. if (VisitorUtil.IsNullConstant(expression.Right)) { rhs = null; } if (VisitorUtil.IsNullConstant(expression.Left)) { lhs = null; } if (lhs == null && rhs == null) { return(_hqlTreeBuilder.False()); } if (lhs == null) { return(_hqlTreeBuilder.IsNotNull(rhs)); } if (rhs == null) { return(_hqlTreeBuilder.IsNotNull(lhs)); } var lhsNullable = IsNullable(lhs); var rhsNullable = IsNullable(rhs); var inequality = _hqlTreeBuilder.Inequality(lhs, rhs); if (!lhsNullable && !rhsNullable) { return(inequality); } var lhs2 = VisitExpression(expression.Left).ToArithmeticExpression(); var rhs2 = VisitExpression(expression.Right).ToArithmeticExpression(); HqlBooleanExpression booleanExpression; if (lhsNullable && rhsNullable) { booleanExpression = _hqlTreeBuilder.Inequality( _hqlTreeBuilder.IsNull(lhs2).ToArithmeticExpression(), _hqlTreeBuilder.IsNull(rhs2).ToArithmeticExpression()); } else if (lhsNullable) { booleanExpression = _hqlTreeBuilder.IsNull(lhs2); } else { booleanExpression = _hqlTreeBuilder.IsNull(rhs2); } return(_hqlTreeBuilder.BooleanOr(inequality, booleanExpression)); }
public bool IsNullable(Expression expression, BinaryExpression equalityExpression) { switch (expression.NodeType) { case ExpressionType.Convert: case ExpressionType.ConvertChecked: case ExpressionType.TypeAs: // a cast will not return null if the operand is not null (as long as TypeAs is not translated to // try_convert in SQL). return(IsNullable(((UnaryExpression)expression).Operand, equalityExpression)); case ExpressionType.Not: case ExpressionType.And: case ExpressionType.Or: case ExpressionType.ExclusiveOr: case ExpressionType.LeftShift: case ExpressionType.RightShift: case ExpressionType.AndAlso: case ExpressionType.OrElse: case ExpressionType.Equal: case ExpressionType.NotEqual: case ExpressionType.GreaterThanOrEqual: case ExpressionType.GreaterThan: case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: return(false); case ExpressionType.Add: case ExpressionType.AddChecked: case ExpressionType.Divide: case ExpressionType.Modulo: case ExpressionType.Multiply: case ExpressionType.MultiplyChecked: case ExpressionType.Power: case ExpressionType.Subtract: case ExpressionType.SubtractChecked: var binaryExpression = (BinaryExpression)expression; return(IsNullable(binaryExpression.Left, equalityExpression) || IsNullable(binaryExpression.Right, equalityExpression)); case ExpressionType.ArrayIndex: return(true); // for indexed lists we cannot determine whether the item will be null or not case ExpressionType.Coalesce: return(IsNullable(((BinaryExpression)expression).Right, equalityExpression)); case ExpressionType.Conditional: var conditionalExpression = (ConditionalExpression)expression; return(IsNullable(conditionalExpression.IfTrue, equalityExpression) || IsNullable(conditionalExpression.IfFalse, equalityExpression)); case ExpressionType.Call: var methodInfo = ((MethodCallExpression)expression).Method; return(!_functionRegistry.TryGetGenerator(methodInfo, out var method) || method.AllowsNullableReturnType(methodInfo)); case ExpressionType.MemberAccess: return(IsNullable((MemberExpression)expression, equalityExpression)); case ExpressionType.Extension: return(IsNullableExtension(expression, equalityExpression)); case ExpressionType.TypeIs: // an equal or in operator will be generated and those cannot return null case ExpressionType.NewArrayInit: return(false); case ExpressionType.Constant: return(VisitorUtil.IsNullConstant(expression)); case ExpressionType.Parameter: return(!expression.Type.IsValueType); default: return(true); } }