internal override SqlExpression VisitSimpleCase(SqlSimpleCase c) {
			c.Expression = this.VisitExpression(c.Expression);
			for (int i = 0, n = c.Whens.Count; i < n; i++) {
				// Don't walk down the match side. This can't be a column.
				c.Whens[i].Value = this.VisitExpression(c.Whens[i].Value);
			}
			return c;
		}
Example #2
0
		internal bool AreCaseWhenValuesConstant(SqlSimpleCase sc)
		{
			foreach(SqlWhen when in sc.Whens)
			{
				if(when.Value.NodeType != SqlNodeType.Value)
				{
					return false;
				}
			}
			return true;
		}
Example #3
0
		/// <summary>
		/// Helper for VisitBinaryOperator. Builds the new case with distributed valueds.
		/// </summary>
		private SqlExpression DistributeOperatorIntoCase(SqlNodeType nt, SqlSimpleCase sc, SqlExpression expr)
		{
			if(nt != SqlNodeType.EQ && nt != SqlNodeType.NE && nt != SqlNodeType.EQ2V && nt != SqlNodeType.NE2V)
				throw Error.ArgumentOutOfRange("nt");
			object val = Eval(expr);
			List<SqlExpression> values = new List<SqlExpression>();
			List<SqlExpression> matches = new List<SqlExpression>();
			foreach(SqlWhen when in sc.Whens)
			{
				matches.Add(when.Match);
				object whenVal = Eval(when.Value);
				bool eq = when.Value.SqlType.AreValuesEqual(whenVal, val);
				values.Add(_sql.ValueFromObject((nt == SqlNodeType.EQ || nt == SqlNodeType.EQ2V) == eq, false, sc.SourceExpression));
			}
			return this.VisitExpression(_sql.Case(typeof(bool), sc.Expression, matches, values, sc.SourceExpression));
		}
Example #4
0
 internal virtual SqlExpression VisitSimpleCase(SqlSimpleCase c) {
     c.Expression = this.VisitExpression(c.Expression);
     for (int i = 0, n = c.Whens.Count; i < n; i++) {
         SqlWhen when = c.Whens[i];
         when.Match = this.VisitExpression(when.Match);
         when.Value = this.VisitExpression(when.Value);
     }
     return c;
 }
		internal override SqlExpression VisitSimpleCase(SqlSimpleCase c)
		{
			_depth++;
			this.NewLine();
			_commandStringBuilder.Append("(CASE");
			_depth++;
			if(c.Expression != null)
			{
				_commandStringBuilder.Append(" ");
				this.Visit(c.Expression);
			}
			for(int i = 0, n = c.Whens.Count; i < n; i++)
			{
				SqlWhen when = c.Whens[i];
				if(i == n - 1 && when.Match == null)
				{
					this.NewLine();
					_commandStringBuilder.Append("ELSE ");
					this.Visit(when.Value);
				}
				else
				{
					this.NewLine();
					_commandStringBuilder.Append("WHEN ");
					this.Visit(when.Match);
					_commandStringBuilder.Append(" THEN ");
					this.Visit(when.Value);
				}
			}
			_depth--;
			this.NewLine();
			_commandStringBuilder.Append(" END)");
			_depth--;
			return c;
		}
		internal override SqlExpression VisitSimpleCase(SqlSimpleCase c)
		{
			SqlExpression expr = this.VisitExpression(c.Expression);
			SqlWhen[] whens = new SqlWhen[c.Whens.Count];
			for(int i = 0, n = whens.Length; i < n; i++)
			{
				SqlWhen when = c.Whens[i];
				whens[i] = new SqlWhen(this.VisitExpression(when.Match), this.VisitExpression(when.Value));
			}
			return new SqlSimpleCase(c.ClrType, expr, whens, c.SourceExpression);
		}
Example #7
0
		internal override SqlExpression VisitSimpleCase(SqlSimpleCase c)
		{
			c.Expression = this.VisitExpression(c.Expression);
			int compareWhen = 0;

			// Find the ELSE if it exists.
			for(int i = 0, n = c.Whens.Count; i < n; i++)
			{
				if(c.Whens[i].Match == null)
				{
					compareWhen = i;
					break;
				}
			}

			c.Whens[compareWhen].Match = VisitExpression(c.Whens[compareWhen].Match);
			c.Whens[compareWhen].Value = VisitExpression(c.Whens[compareWhen].Value);

			// Compare each other when value to the compare when
			List<SqlWhen> newWhens = new List<SqlWhen>();
			bool allValuesLiteral = true;
			for(int i = 0, n = c.Whens.Count; i < n; i++)
			{
				if(compareWhen != i)
				{
					SqlWhen when = c.Whens[i];
					when.Match = this.VisitExpression(when.Match);
					when.Value = this.VisitExpression(when.Value);
					if(!SqlComparer.AreEqual(c.Whens[compareWhen].Value, when.Value))
					{
						newWhens.Add(when);
					}
					allValuesLiteral = allValuesLiteral && when.Value.NodeType == SqlNodeType.Value;
				}
			}
			newWhens.Add(c.Whens[compareWhen]);

			// Did everything reduce to a single CASE?
			SqlExpression rewrite = TryToConsolidateAllValueExpressions(newWhens.Count, c.Whens[compareWhen].Value);
			if(rewrite != null)
				return rewrite;

			// Can it be a conjuction (or disjunction) of clauses?
			rewrite = TryToWriteAsSimpleBooleanExpression(c.ClrType, c.Expression, newWhens, allValuesLiteral);
			if(rewrite != null)
				return rewrite;

			// Can any WHEN clauses be reduced to fall into the ELSE clause? 
			rewrite = TryToWriteAsReducedCase(c.ClrType, c.Expression, newWhens, c.Whens[compareWhen].Match, c.Whens.Count);
			if(rewrite != null)
				return rewrite;

			return c;
		}
Example #8
0
		internal override SqlExpression VisitSimpleCase(SqlSimpleCase c)
		{
			base.VisitSimpleCase(c);

			// determine the best common type for all the when values
			ProviderType type = c.Whens[0].Value.SqlType;
			for(int i = 1; i < c.Whens.Count; i++)
			{
				ProviderType whenType = c.Whens[i].Value.SqlType;
				type = typeProvider.GetBestType(type, whenType);
			}

			// coerce each one          
			foreach(SqlWhen when in c.Whens.Where(w => w.Value.SqlType != type && !w.Value.SqlType.IsRuntimeOnlyType))
			{
				when.Value = sql.UnaryConvert(when.Value.ClrType, type, when.Value, when.Value.SourceExpression);
			}

			return c;
		}
Example #9
0
		private static SqlExpression UnwrapTrivialCaseExpression(SqlSimpleCase sc)
		{
			if(sc.Whens.Count != 1)
			{
				return sc;
			}
			if(!SqlComparer.AreEqual(sc.Expression, sc.Whens[0].Match))
			{
				return sc;
			}
			SqlExpression result = sc.Whens[0].Value;
			if(result.NodeType == SqlNodeType.SimpleCase)
			{
				return UnwrapTrivialCaseExpression((SqlSimpleCase)result);
			}
			return result;
		}
		internal override SqlExpression VisitSimpleCase(SqlSimpleCase c)
		{
			bool saveCanJoin = this.canJoin;
			this.canJoin = false;
			try
			{
				return base.VisitSimpleCase(c);
			}
			finally
			{
				this.canJoin = saveCanJoin;
			}
		}