internal override SqlExpression VisitSearchedCase(SqlSearchedCase c)
		{
			for(int i = 0, n = c.Whens.Count; i < n; i++)
			{
				SqlWhen when = c.Whens[i];
				when.Match = this.VisitPredicate(when.Match);
				when.Value = this.VisitExpression(when.Value);
			}
			c.Else = this.VisitExpression(c.Else);
			return c;
		}
		private Type GenerateSearchedCase(SqlSearchedCase ssc)
		{
			Label labNext = gen.DefineLabel();
			Label labEnd = gen.DefineLabel();
			for(int i = 0, n = ssc.Whens.Count; i < n; i++)
			{
				if(i > 0)
				{
					gen.MarkLabel(labNext);
					labNext = gen.DefineLabel();
				}
				SqlWhen when = ssc.Whens[i];
				if(when.Match != null)
				{
					this.GenerateExpressionForType(when.Match, typeof(bool)); // test
					this.GenerateConstInt(0);
					gen.Emit(OpCodes.Ceq);
					gen.Emit(OpCodes.Brtrue, labNext);
				}
				this.GenerateExpressionForType(when.Value, ssc.ClrType);
				gen.Emit(OpCodes.Br, labEnd);
			}
			gen.MarkLabel(labNext);
			if(ssc.Else != null)
			{
				this.GenerateExpressionForType(ssc.Else, ssc.ClrType);
			}
			gen.MarkLabel(labEnd);
			return ssc.ClrType;
		}
		internal override SqlExpression VisitSearchedCase(SqlSearchedCase c)
		{
			_depth++;
			this.NewLine();
			_commandStringBuilder.Append("(CASE ");
			_depth++;
			for(int i = 0, n = c.Whens.Count; i < n; i++)
			{
				SqlWhen when = c.Whens[i];
				this.NewLine();
				_commandStringBuilder.Append("WHEN ");
				this.Visit(when.Match);
				_commandStringBuilder.Append(" THEN ");
				this.Visit(when.Value);
			}
			if(c.Else != null)
			{
				this.NewLine();
				_commandStringBuilder.Append("ELSE ");
				this.Visit(c.Else);
			}
			_depth--;
			this.NewLine();
			_commandStringBuilder.Append(" END)");
			_depth--;
			return c;
		}
		internal override SqlExpression VisitSearchedCase(SqlSearchedCase c)
		{
			SqlExpression @else = this.VisitExpression(c.Else);
			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 SqlSearchedCase(c.ClrType, whens, @else, c.SourceExpression);
		}
Example #5
0
		internal override SqlExpression VisitSearchedCase(SqlSearchedCase c)
		{
			base.VisitSearchedCase(c);

			// determine the best common type for all the when and else 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);
			}
			if(c.Else != null)
			{
				ProviderType elseType = c.Else.SqlType;
				type = typeProvider.GetBestType(type, elseType);
			}

			// 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);
			}

			if(c.Else != null && c.Else.SqlType != type && !c.Else.SqlType.IsRuntimeOnlyType)
			{
				c.Else = sql.UnaryConvert(c.Else.ClrType, type, c.Else, c.Else.SourceExpression);
			}

			return c;
		}
		internal override SqlExpression VisitSearchedCase(SqlSearchedCase c)
		{
			bool saveCanJoin = this.canJoin;
			this.canJoin = false;
			try
			{
				return base.VisitSearchedCase(c);
			}
			finally
			{
				this.canJoin = saveCanJoin;
			}
		}
		internal override SqlExpression VisitUnaryOperator(SqlUnary uo) {
			uo.Operand = this.VisitExpression(uo.Operand);
			// ------------------------------------------------------------
			// PHASE 1: If possible, evaluate without fetching the operand.
			// This is preferred because fetching LINKs causes them to not
			// be deferred.
			// ------------------------------------------------------------
			if (uo.NodeType == SqlNodeType.IsNull || uo.NodeType == SqlNodeType.IsNotNull) {
				SqlExpression translated = this.translator.TranslateLinkIsNull(uo);
				if (translated != uo) {
					return this.VisitExpression(translated);
				}
				if (uo.Operand.NodeType==SqlNodeType.OuterJoinedValue) {
					SqlUnary ojv = uo.Operand as SqlUnary;
					if (ojv.Operand.NodeType == SqlNodeType.OptionalValue) {
						SqlOptionalValue ov = (SqlOptionalValue)ojv.Operand;
						return this.VisitUnaryOperator(
													   new SqlUnary(uo.NodeType, uo.ClrType, uo.SqlType,
														   new SqlUnary(SqlNodeType.OuterJoinedValue, ov.ClrType, ov.SqlType, ov.HasValue, ov.SourceExpression)
														   , uo.SourceExpression)
							);
					}
					else if (ojv.Operand.NodeType == SqlNodeType.TypeCase) {
						SqlTypeCase tc = (SqlTypeCase)ojv.Operand;
						return new SqlUnary(uo.NodeType, uo.ClrType, uo.SqlType,
							new SqlUnary(SqlNodeType.OuterJoinedValue, tc.Discriminator.ClrType, tc.Discriminator.SqlType, tc.Discriminator, tc.SourceExpression),
							uo.SourceExpression
							);
					}
				}
			}

			// Fetch the expression.
			uo.Operand = this.ConvertToFetchedExpression(uo.Operand);

			// ------------------------------------------------------------
			// PHASE 2: Evaluate operator on fetched expression.
			// ------------------------------------------------------------
			if ((uo.NodeType == SqlNodeType.Not || uo.NodeType == SqlNodeType.Not2V) && uo.Operand.NodeType == SqlNodeType.Value) {
				SqlValue val = (SqlValue)uo.Operand;
				return sql.Value(typeof(bool), val.SqlType, !(bool)val.Value, val.IsClientSpecified, val.SourceExpression);
			}
			else if (uo.NodeType == SqlNodeType.Not2V) {
				if (SqlExpressionNullability.CanBeNull(uo.Operand) != false) {
					SqlSearchedCase c = new SqlSearchedCase(
						typeof(int),
						new [] { new SqlWhen(uo.Operand, sql.ValueFromObject(1, false, uo.SourceExpression)) },
						sql.ValueFromObject(0, false, uo.SourceExpression),
						uo.SourceExpression
						);
					return sql.Binary(SqlNodeType.EQ, c, sql.ValueFromObject(0, false, uo.SourceExpression));
				}
				else {
					return sql.Unary(SqlNodeType.Not, uo.Operand);
				}
			}
			// push converts of client-expressions inside the client-expression (to be evaluated client side) 
			else if (uo.NodeType == SqlNodeType.Convert && uo.Operand.NodeType == SqlNodeType.Value) {
				SqlValue val = (SqlValue)uo.Operand;
				return sql.Value(uo.ClrType, uo.SqlType, DBConvert.ChangeType(val.Value, uo.ClrType), val.IsClientSpecified, val.SourceExpression);
			}
			else if (uo.NodeType == SqlNodeType.IsNull || uo.NodeType == SqlNodeType.IsNotNull) {
				bool? canBeNull = SqlExpressionNullability.CanBeNull(uo.Operand);
				if (canBeNull == false) {
					return sql.ValueFromObject(uo.NodeType == SqlNodeType.IsNotNull, false, uo.SourceExpression);
				}
				SqlExpression exp = uo.Operand;
				switch (exp.NodeType) {
					case SqlNodeType.Element:
						exp = sql.SubSelect(SqlNodeType.Exists, ((SqlSubSelect)exp).Select);
						if (uo.NodeType == SqlNodeType.IsNull) {
							exp = sql.Unary(SqlNodeType.Not, exp, exp.SourceExpression);
						}
						return exp;
					case SqlNodeType.ClientQuery: {
						SqlClientQuery cq = (SqlClientQuery)exp;
						if (cq.Query.NodeType == SqlNodeType.Element) {
							exp = sql.SubSelect(SqlNodeType.Exists, cq.Query.Select);
							if (uo.NodeType == SqlNodeType.IsNull) {
								exp = sql.Unary(SqlNodeType.Not, exp, exp.SourceExpression);
							}
							return exp;
						}
						return sql.ValueFromObject(uo.NodeType == SqlNodeType.IsNotNull, false, uo.SourceExpression);
					}
					case SqlNodeType.OptionalValue:
						uo.Operand = ((SqlOptionalValue)exp).HasValue;
						return uo;

					case SqlNodeType.ClientCase: {
						// Distribute unary into simple case.
						SqlClientCase sc = (SqlClientCase)uo.Operand;
						List<SqlExpression> matches = new List<SqlExpression>();
						List<SqlExpression> values = new List<SqlExpression>();
						foreach (SqlClientWhen when in sc.Whens) {
							matches.Add(when.Match);
							values.Add(VisitUnaryOperator(sql.Unary(uo.NodeType, when.Value, when.Value.SourceExpression)));
						}
						return sql.Case(sc.ClrType, sc.Expression, matches, values, sc.SourceExpression);
					}
					case SqlNodeType.TypeCase: {
						// Distribute unary into type case. In the process, convert to simple case.
						SqlTypeCase tc = (SqlTypeCase)uo.Operand;
						List<SqlExpression> newMatches = new List<SqlExpression>();
						List<SqlExpression> newValues = new List<SqlExpression>();
						foreach (SqlTypeCaseWhen when in tc.Whens) {
							SqlUnary un = new SqlUnary(uo.NodeType, uo.ClrType, uo.SqlType, when.TypeBinding, when.TypeBinding.SourceExpression);
							SqlExpression expr = VisitUnaryOperator(un);
							if (expr is SqlNew) {
								throw Error.DidNotExpectTypeBinding();
							}
							newMatches.Add(when.Match);
							newValues.Add(expr);
						}
						return sql.Case(uo.ClrType, tc.Discriminator, newMatches, newValues, tc.SourceExpression);
					}
					case SqlNodeType.Value: {
						SqlValue val = (SqlValue)uo.Operand;
						return sql.Value(typeof(bool), this.typeProvider.From(typeof(int)), (val.Value == null) == (uo.NodeType == SqlNodeType.IsNull), val.IsClientSpecified, uo.SourceExpression);
					}
				}
			}
			else if (uo.NodeType == SqlNodeType.Treat) {
				return ApplyTreat(VisitExpression(uo.Operand), uo.ClrType);
			}

			return uo;
		}
		internal override SqlExpression VisitSearchedCase(SqlSearchedCase c) {
			if ((c.ClrType == typeof(bool) || c.ClrType == typeof(bool?)) &&
				c.Whens.Count == 1 && c.Else != null) {
					SqlValue litElse = c.Else as SqlValue;
					SqlValue litWhen = c.Whens[0].Value as SqlValue;

					if (litElse != null && litElse.Value != null && !(bool)litElse.Value) {
						return this.VisitExpression(sql.Binary(SqlNodeType.And, c.Whens[0].Match, c.Whens[0].Value));
					}
					else if (litWhen != null && litWhen.Value != null && (bool)litWhen.Value) {
						return this.VisitExpression(sql.Binary(SqlNodeType.Or, c.Whens[0].Match, c.Else));
					}
				}
			return base.VisitSearchedCase(c);
		}