internal override SqlExpression VisitUnaryOperator(SqlUnary fc)
		{
			// process the arguments
			SqlExpression result = base.VisitUnaryOperator(fc);
			if(result is SqlUnary)
			{
				SqlUnary unary = (SqlUnary)result;

				switch(unary.NodeType)
				{
					case SqlNodeType.ClrLength:
						SqlExpression expr = unary.Operand;

						result = sql.FunctionCallDataLength(expr);

						if(expr.SqlType.IsUnicodeType)
						{
							result = sql.Divide(result, sql.ValueFromObject(2, expr.SourceExpression));
						}

						result = sql.ConvertToInt(result);
						break;
					default:
						break;
				}
			}

			return result;
		}
		internal override SqlExpression VisitUnaryOperator(SqlUnary uo)
		{
			base.VisitUnaryOperator(uo);
			if(uo.NodeType != SqlNodeType.Convert && uo.Operand != null && uo.Operand.SqlType != null)
			{
				uo.SetSqlType(this.typeProvider.PredictTypeForUnary(uo.NodeType, uo.Operand.SqlType));
			}
			return uo;
		}
		internal override SqlExpression VisitUnaryOperator(SqlUnary uo)
		{
			if(uo.NodeType.IsUnaryOperatorExpectingPredicateOperand())
			{
				uo.Operand = this.VisitPredicate(uo.Operand);
			}
			else
			{
				uo.Operand = this.VisitExpression(uo.Operand);
			}
			return uo;
		}
 internal override SqlExpression VisitUnaryOperator(SqlUnary uo) {
     switch (uo.NodeType) {
         case SqlNodeType.Min:
         case SqlNodeType.Max:
         case SqlNodeType.Avg:
         case SqlNodeType.Sum:
         case SqlNodeType.Count:
         case SqlNodeType.LongCount:
             this.hasAggregates = true;
             return uo;
         default:
             return base.VisitUnaryOperator(uo);
     }
 }
Beispiel #5
0
 internal virtual SqlExpression VisitUnaryOperator(SqlUnary uo) {
     uo.Operand = this.VisitExpression(uo.Operand);
     return uo;
 }
		private Type GenerateValueOf(SqlUnary u)
		{
			Diagnostics.Debug.Assert(TypeSystem.IsNullableType(u.Operand.ClrType));
			this.GenerateExpressionForType(u.Operand, u.Operand.ClrType);
			LocalBuilder loc = gen.DeclareLocal(u.Operand.ClrType);
			gen.Emit(OpCodes.Stloc, loc);
			gen.Emit(OpCodes.Ldloca, loc);
			this.GenerateGetValue(u.Operand.ClrType);
			return u.ClrType;
		}
		internal override SqlExpression VisitUnaryOperator(SqlUnary uo)
		{
			switch(uo.NodeType)
			{
				case SqlNodeType.Not:
				case SqlNodeType.Not2V:
					_commandStringBuilder.Append(GetOperator(uo.NodeType));
					_commandStringBuilder.Append(" ");
					this.VisitWithParens(uo.Operand, uo);
					break;
				case SqlNodeType.Negate:
				case SqlNodeType.BitNot:
					_commandStringBuilder.Append(GetOperator(uo.NodeType));
					this.VisitWithParens(uo.Operand, uo);
					break;
				case SqlNodeType.Count:
				case SqlNodeType.LongCount:
				case SqlNodeType.Max:
				case SqlNodeType.Min:
				case SqlNodeType.Sum:
				case SqlNodeType.Avg:
				case SqlNodeType.Stddev:
				case SqlNodeType.ClrLength:
				{
					_commandStringBuilder.Append(GetOperator(uo.NodeType));
					_commandStringBuilder.Append("(");
					if(uo.Operand == null)
					{
						_commandStringBuilder.Append("*");
					}
					else
					{
						this.Visit(uo.Operand);
					}
					_commandStringBuilder.Append(")");
					break;
				}
				case SqlNodeType.IsNull:
				case SqlNodeType.IsNotNull:
				{
					this.VisitWithParens(uo.Operand, uo);
					_commandStringBuilder.Append(" ");
					_commandStringBuilder.Append(GetOperator(uo.NodeType));
					break;
				}
				case SqlNodeType.Convert:
				{
					_commandStringBuilder.Append("CONVERT(");
					QueryFormatOptions options = QueryFormatOptions.None;
					if(uo.Operand.SqlType.CanSuppressSizeForConversionToString)
					{
						options = QueryFormatOptions.SuppressSize;
					}
					_commandStringBuilder.Append(uo.SqlType.ToQueryString(options));
					_commandStringBuilder.Append(",");
					this.Visit(uo.Operand);
					_commandStringBuilder.Append(")");
					break;
				}
				case SqlNodeType.ValueOf:
				case SqlNodeType.OuterJoinedValue:
					this.Visit(uo.Operand); // no op
					break;
				default:
					throw Error.InvalidFormatNode(uo.NodeType);
			}
			return uo;
		}
		internal override SqlExpression VisitTreat(SqlUnary t)
		{
			_commandStringBuilder.Append("TREAT(");
			this.Visit(t.Operand);
			_commandStringBuilder.Append(" AS ");
			this.FormatType(t.SqlType);
			_commandStringBuilder.Append(")");
			return t;
		}
		internal override SqlExpression VisitCast(SqlUnary c)
		{
			_commandStringBuilder.Append("CAST(");
			this.Visit(c.Operand);
			_commandStringBuilder.Append(" AS ");
			QueryFormatOptions options = QueryFormatOptions.None;
			if(c.Operand.SqlType.CanSuppressSizeForConversionToString)
			{
				options = QueryFormatOptions.SuppressSize;
			}
			_commandStringBuilder.Append(c.SqlType.ToQueryString(options));
			_commandStringBuilder.Append(")");
			return c;
		}
		internal override SqlExpression VisitUnaryOperator(SqlUnary uo)
		{
			return new SqlUnary(uo.NodeType, uo.ClrType, uo.SqlType, (SqlExpression)this.Visit(uo.Operand), uo.Method, uo.SourceExpression);
		}
		internal override SqlExpression VisitTreat(SqlUnary t)
		{
			return new SqlUnary(SqlNodeType.Treat, t.ClrType, t.SqlType, (SqlExpression)this.Visit(t.Operand), t.SourceExpression);
		}
		private static bool IsSupportedUnary(SqlUnary uo)
		{
			return uo.NodeType == SqlNodeType.Convert &&
				   uo.ClrType == typeof(char) || uo.Operand.ClrType == typeof(char);
		}
Beispiel #13
0
 internal virtual SqlExpression VisitCast(SqlUnary c) {
     c.Operand = this.VisitExpression(c.Operand);
     return c;
 }
		internal override SqlExpression VisitUnaryOperator(SqlUnary uo)
		{
			uo.Operand = this.VisitExpression(uo.Operand);
			if(uo.NodeType != SqlNodeType.Convert)
			{
				return uo;
			}
			ProviderType oldSqlType = uo.Operand.SqlType;
			ProviderType newSqlType = uo.SqlType;
			Type oldClrType = TypeSystem.GetNonNullableType(uo.Operand.ClrType);
			Type newClrType = TypeSystem.GetNonNullableType(uo.ClrType);

			if(newClrType == typeof(char))
			{
				if(oldClrType == typeof(bool))
				{
					throw Error.ConvertToCharFromBoolNotSupported();
				}

				if(oldSqlType.IsNumeric)
				{
					// numeric --> char
					return sql.FunctionCall(uo.ClrType, "NCHAR", new SqlExpression[] { uo.Operand }, uo.SourceExpression);
				}

				if(StringConversionIsSafe(oldSqlType, newSqlType))
				{
					if(StringConversionIsNeeded(oldSqlType, newSqlType))
					{
						// set the new size to the (potentially smaller) oldSqlType.Size
						uo.SetSqlType(sql.TypeProvider.From(uo.ClrType, oldSqlType.HasSizeOrIsLarge ? oldSqlType.Size : (int?)null));
					}
				}
				else
				{
					throw Error.UnsafeStringConversion(oldSqlType.ToQueryString(), newSqlType.ToQueryString());
				}
			}
			else if(oldClrType == typeof(char) && (oldSqlType.IsChar || oldSqlType.IsString) && newSqlType.IsNumeric)
			{
				// char --> int 
				return sql.FunctionCall(newClrType, sql.TypeProvider.From(typeof(int)), "UNICODE", new SqlExpression[] { uo.Operand }, uo.SourceExpression);
			}
			else if(newClrType == typeof(string))
			{
				if(oldClrType == typeof(double))
				{
					// use longer format if it was a double in the CLR expression
					return ConvertDoubleToString(uo.Operand, uo.ClrType);
				}
				if(oldClrType == typeof(bool))
				{
					// use 'true' or 'false' if it was a bool in the CLR expression
					return ConvertBitToString(uo.Operand, uo.ClrType);
				}
				if(StringConversionIsSafe(oldSqlType, newSqlType))
				{
					if(StringConversionIsNeeded(oldSqlType, newSqlType))
					{
						// set the new size to the (potentially smaller) oldSqlType.Size
						uo.SetSqlType(sql.TypeProvider.From(uo.ClrType, oldSqlType.HasSizeOrIsLarge ? oldSqlType.Size : (int?)null));
					}
				}
				else
				{
					throw Error.UnsafeStringConversion(oldSqlType.ToQueryString(), newSqlType.ToQueryString());
				}
			}
			return uo;
		}
		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 VisitTreat(SqlUnary a) {
			return VisitUnaryOperator(a);
		}
			internal override SqlExpression VisitTreat(SqlUnary t)
			{
				t.Operand = this.VisitExpression(t.Operand);
				Type treatType = t.ClrType;
				Type originalType = model.GetMetaType(t.Operand.ClrType).InheritanceRoot.Type;

				// .NET nullability rules are that typeof(int)==typeof(int?). Let's be consistent with that:
				treatType = TypeSystem.GetNonNullableType(treatType);
				originalType = TypeSystem.GetNonNullableType(originalType);

				if(treatType == originalType)
				{
					return t.Operand;
				}
				if(treatType.IsAssignableFrom(originalType))
				{
					t.Operand.SetClrType(treatType);
					return t.Operand;
				}
				if(!treatType.IsAssignableFrom(originalType) && !originalType.IsAssignableFrom(treatType))
				{
					if(!treatType.IsInterface && !originalType.IsInterface)
					{ // You can't tell when there's an interface involved.
						// We statically know the TREAT will result in NULL.
						return sql.TypedLiteralNull(treatType, t.SourceExpression);
					}
				}

				//return base.VisitTreat(t);
				return t;
			}
			// transform type conversion if necessary
			internal override SqlExpression VisitUnaryOperator(SqlUnary uo)
			{
				if(uo.NodeType == SqlNodeType.Convert)
				{
					Type newType = uo.ClrType;
					SqlExpression expr = uo.Operand;
					if(newType == typeof(char) || expr.ClrType == typeof(char))
					{
						expr = this.VisitExpression(uo.Operand);
						uo.Operand = expr;
						return sql.ConvertTo(newType, uo.SqlType, expr);
					}
				}
				return base.VisitUnaryOperator(uo);
			}
Beispiel #19
0
 internal virtual SqlExpression VisitTreat(SqlUnary t) {
     t.Operand = this.VisitExpression(t.Operand);
     return t;
 }
Beispiel #20
0
        internal SqlExpression TranslateLinkIsNull(SqlUnary expr) {
            System.Diagnostics.Debug.Assert(expr.NodeType == SqlNodeType.IsNull || expr.NodeType == SqlNodeType.IsNotNull);

            SqlLink link = expr.Operand as SqlLink;
            if (!(link != null && link.Member.IsAssociation && link.Member.Association.IsForeignKey)) {
                return expr;
            }

            List<SqlExpression> exprs = link.KeyExpressions;
            System.Diagnostics.Debug.Assert(exprs.Count > 0);

            SqlExpression exp = null;
            SqlNodeType combo = (expr.NodeType == SqlNodeType.IsNull) ? SqlNodeType.Or : SqlNodeType.And;
            for (int i = 0, n = exprs.Count; i < n; i++) {
                SqlExpression compare = sql.Unary(expr.NodeType, sql.DoNotVisitExpression(exprs[i]), expr.SourceExpression);
                if (exp == null) {
                    exp = compare;
                }
                else {
                    exp = sql.Binary(combo, exp, compare);
                }
            }
            return exp;
        }