Ejemplo n.º 1
0
            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);
                }
                else if (treatType.IsAssignableFrom(originalType))
                {
                    t.Operand.SetClrType(treatType);
                    return(t.Operand);
                }
                else 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);
            }
        /// <summary>
        /// Get a MetaType that represents the dynamic type of the given node.
        /// </summary>
        internal static MetaType GetSourceMetaType(SqlNode node, MetaModel model)
        {
            Visitor v = new Visitor();

            v.Visit(node);
            Type type = v.sourceType;

            type = TypeSystem.GetNonNullableType(type); // Emulate CLR's behavior: strip nullability from type.
            return(model.GetMetaType(type));
        }
Ejemplo n.º 3
0
 internal override SqlRow VisitRow(SqlRow row)
 {
     for (int i = 0, n = row.Columns.Count; i < n; i++)
     {
         SqlColumn     col  = row.Columns[i];
         SqlExpression expr = this.VisitExpression(col.Expression);
         if (expr != null)
         {
             if (TypeSystem.GetNonNullableType(col.ClrType) != TypeSystem.GetNonNullableType(expr.ClrType))
             {
                 throw Error.ColumnClrTypeDoesNotAgreeWithExpressionsClrType();
             }
         }
     }
     return(row);
 }
        internal SqlUnary UnaryValueOf(SqlExpression expression, Expression sourceExpression)
        {
            Type valueType = TypeSystem.GetNonNullableType(expression.ClrType);

            return(new SqlUnary(SqlNodeType.ValueOf, valueType, expression.SqlType, expression, null, sourceExpression));
        }
            internal override SqlNode Visit(SqlNode node)
            {
                if (node == null)
                {
                    return(null);
                }

                sourceExpression = node as SqlExpression;
                if (sourceExpression != null)
                {
                    Type        type   = sourceExpression.ClrType;
                    UnwrapStack unwrap = this.UnwrapSequences;
                    while (unwrap != null)
                    {
                        if (unwrap.Unwrap)
                        {
                            type = TypeSystem.GetElementType(type);
                        }
                        unwrap = unwrap.Last;
                    }
                    sourceType = type;
                }
                if (sourceType != null && TypeSystem.GetNonNullableType(sourceType).IsValueType)
                {
                    return(node); // Value types can't also have a dynamic type.
                }
                if (sourceType != null && TypeSystem.HasIEnumerable(sourceType))
                {
                    return(node); // Sequences can't be polymorphic.
                }

                switch (node.NodeType)
                {
                case SqlNodeType.ScalarSubSelect:
                case SqlNodeType.Multiset:
                case SqlNodeType.Element:
                case SqlNodeType.SearchedCase:
                case SqlNodeType.ClientCase:
                case SqlNodeType.SimpleCase:
                case SqlNodeType.Member:
                case SqlNodeType.DiscriminatedType:
                case SqlNodeType.New:
                case SqlNodeType.FunctionCall:
                case SqlNodeType.MethodCall:
                case SqlNodeType.Convert:     // Object identity does not survive convert. It does survive Cast.
                    // Dig no further.
                    return(node);

                case SqlNodeType.TypeCase:
                    sourceType = ((SqlTypeCase)node).RowType.Type;
                    return(node);

                case SqlNodeType.Link:
                    sourceType = ((SqlLink)node).RowType.Type;
                    return(node);

                case SqlNodeType.Table:
                    sourceType = ((SqlTable)node).RowType.Type;
                    return(node);

                case SqlNodeType.Value:
                    SqlValue val = (SqlValue)node;
                    if (val.Value != null)
                    {
                        // In some cases the ClrType of a Value node may
                        // differ from the actual runtime type of the value.
                        // Therefore, we ensure here that the correct type is set.
                        sourceType = val.Value.GetType();
                    }
                    return(node);
                }
                return(base.Visit(node));
            }
Ejemplo n.º 6
0
        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));
                }
                else if (oldClrType == typeof(bool))
                {
                    // use 'true' or 'false' if it was a bool in the CLR expression
                    return(ConvertBitToString(uo.Operand, uo.ClrType));
                }
                else 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);
        }