Example #1
0
		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)
		{
			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;
		}