/// <summary>
        /// For CASE statements which represent boolean values:
        ///
        ///  CASE XXX
        ///    WHEN AAA THEN true        ===>        (XXX==AAA) || (XXX==BBB)
        ///    WHEN BBB THEN true
        ///    ELSE false
        ///    etc.
        ///  END
        ///
        /// Also,
        ///
        ///  CASE XXX
        ///    WHEN AAA THEN false        ===>        (XXX!=AAA) && (XXX!=BBB)
        ///    WHEN BBB THEN false
        ///    ELSE true
        ///    etc.
        ///  END
        ///
        /// The reduce to a conjunction or disjunction of equality or inequality.
        /// The possibility of NULL in XXX is taken into account.
        /// </summary>
        private SqlExpression TryToWriteAsSimpleBooleanExpression(Type caseType, SqlExpression discriminator, List <SqlWhen> newWhens, bool allValuesLiteral)
        {
            SqlExpression rewrite = null;

            if (caseType == typeof(bool) && allValuesLiteral)
            {
                bool?holdsNull = SqlExpressionNullability.CanBeNull(discriminator);
                // The discriminator can't hold a NULL.
                // In this case, we don't need the special fallback that CASE-ELSE gives.
                // We can just construct a boolean operation.
                bool?whenValue = null;
                for (int i = 0; i < newWhens.Count; ++i)
                {
                    SqlValue lit   = (SqlValue)newWhens[i].Value; // Must be SqlValue because of allValuesLiteral.
                    bool     value = (bool)lit.Value;             // Must be bool because of caseType==typeof(bool).
                    if (newWhens[i].Match != null)
                    {                                             // Skip the ELSE
                        if (value)
                        {
                            rewrite = _sql.OrAccumulate(rewrite, _sql.Binary(SqlNodeType.EQ, discriminator, newWhens[i].Match));
                        }
                        else
                        {
                            rewrite = _sql.AndAccumulate(rewrite, _sql.Binary(SqlNodeType.NE, discriminator, newWhens[i].Match));
                        }
                    }
                    else
                    {
                        whenValue = value;
                    }
                }
                // If it could possibly hold null values.
                if (holdsNull != false && whenValue != null)
                {
                    if (whenValue == true)
                    {
                        rewrite = _sql.OrAccumulate(rewrite, _sql.Unary(SqlNodeType.IsNull, discriminator, discriminator.SourceExpression));
                    }
                    else
                    {
                        rewrite = _sql.AndAccumulate(rewrite, _sql.Unary(SqlNodeType.IsNotNull, discriminator, discriminator.SourceExpression));
                    }
                }
            }
            return(rewrite);
        }
        internal override SqlExpression ConvertPredicateToValue(SqlExpression predicateExpression)
        {
            // Transform the 'Predicate' expression into a 'Bit' by forming the
            // following operation:
            //   CASE
            //    WHEN predicateExpression THEN 1
            //    ELSE NOT(predicateExpression) THEN 0
            //    ELSE NULL
            //   END

            // Possible simplification to the generated SQL would be to detect when 'predicateExpression'
            // is SqlUnary(NOT) and use its operand with the literal 1 and 0 below swapped.
            SqlExpression valueTrue  = sql.ValueFromObject(true, false, predicateExpression.SourceExpression);
            SqlExpression valueFalse = sql.ValueFromObject(false, false, predicateExpression.SourceExpression);

            if (SqlExpressionNullability.CanBeNull(predicateExpression) != false)
            {
                SqlExpression valueNull = sql.Value(valueTrue.ClrType, valueTrue.SqlType, null, false, predicateExpression.SourceExpression);
                return(new SqlSearchedCase(
                           predicateExpression.ClrType,
                           new SqlWhen[] {
                    new SqlWhen(predicateExpression, valueTrue),
                    new SqlWhen(new SqlUnary(SqlNodeType.Not, predicateExpression.ClrType, predicateExpression.SqlType, predicateExpression, predicateExpression.SourceExpression), valueFalse)
                },
                           valueNull,
                           predicateExpression.SourceExpression
                           ));
            }
            else
            {
                return(new SqlSearchedCase(
                           predicateExpression.ClrType,
                           new SqlWhen[] { new SqlWhen(predicateExpression, valueTrue) },
                           valueFalse,
                           predicateExpression.SourceExpression
                           ));
            }
        }