protected override Expression VisitBinaryExpression (BinaryExpression expression)
{
ArgumentUtility.CheckNotNull ("expression", expression);
var childContext = BooleanUtility.IsBooleanType (expression.Type)
? GetChildSemanticsForBinaryBoolExpression (expression.NodeType)
: SqlExpressionContext.SingleValueRequired;
var left = ApplySqlExpressionContext (expression.Left, childContext);
var right = ApplySqlExpressionContext (expression.Right, childContext);
if (BooleanUtility.IsBooleanType (expression.Type) && expression.NodeType == ExpressionType.Coalesce)
{
// In predicate context, we can ignore coalesces towards false, treat like a conversion to bool instead. (SQL treats NULL values in a falsey
// way in predicate contexts.)
if (_currentContext == SqlExpressionContext.PredicateRequired
&& expression.Right is ConstantExpression
&& Equals (((ConstantExpression) expression.Right).Value, false))
{
return VisitExpression (Expression.Convert (expression.Left, expression.Type));
}
// We'll pull out the bool conversion marker from the operands of the Coalesce expression and instead put it around the whole expression.
// That way, HandleValueSemantics will not try to convert us back to a value; this avoids double CASE WHENs.
// We know that left and right must be ConvertedBooleanExpressions because Coalesce has single value semantics for its operands, and boolean
// Coalesces must have booleans operands. Applying value semantics to boolean operands results in ConvertedBooleanExpression values.
Assertion.DebugAssert (childContext == SqlExpressionContext.SingleValueRequired);
Assertion.DebugAssert (left is SqlConvertedBooleanExpression);
Assertion.DebugAssert (right is SqlConvertedBooleanExpression);
var newCoalesceExpression = Expression.Coalesce (((SqlConvertedBooleanExpression) left).Expression, ((SqlConvertedBooleanExpression) right).Expression);
return new SqlConvertedBooleanExpression (newCoalesceExpression);
}
if (left != expression.Left || right != expression.Right)
return Expression.MakeBinary (expression.NodeType, left, right, expression.IsLiftedToNull, expression.Method);
return expression;
}