internal override SqlSelect VisitSelect(SqlSelect select)
            {
                Scope save = this.current;

                this.current = new Scope(select.Where, this.current);

                SqlSelect result = base.VisitSelect(select);

                bool stopHoisting =
                    select.IsDistinct ||
                    select.GroupBy.Count > 0 ||
                    this.aggregateChecker.HasAggregates(select) ||
                    select.Top != null ||
                    this.rowNumberChecker.HasRowNumber(select);

                // Shift as much of the current WHERE to the parent as possible.
                if (this.current != null)
                {
                    if (this.current.Parent != null && !stopHoisting)
                    {
                        this.current.Parent.Where = sql.AndAccumulate(this.current.Parent.Where, this.current.Where);
                        this.current.Where        = null;
                    }
                    select.Where = this.current.Where;
                }

                this.current = save;
                return(result);
            }
            /// <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);
            }