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