private bool OldWillFitInNew(ProviderType oldSqlType, ProviderType newSqlType) { bool result = newSqlType.IsLargeType // we can fit into a large type || !newSqlType.HasSizeOrIsLarge // if the type is not large, and doesn't have a size specified, assume OK || (!oldSqlType.IsLargeType // else, if the old type isn't large && oldSqlType.HasSizeOrIsLarge // and both old .. && newSqlType.HasSizeOrIsLarge // .. and new sizes are specified && newSqlType.Size >= oldSqlType.Size); // and if the new size is larger or equal to the old, then OK return result; }
bool StringConversionIsSafe(ProviderType oldSqlType, ProviderType newSqlType) { // if we are dealing with a conversion from a fixed-size string or char if (BothTypesAreStrings(oldSqlType, newSqlType)) { // we assume we can convert to an unknown size // we can do the conversion when both sizes are specified and the destination size is larger return !newSqlType.HasSizeOrIsLarge || OldWillFitInNew(oldSqlType, newSqlType); } // give the benefit of the doubt for conversion from non-string types return true; }
bool StringConversionIsNeeded(ProviderType oldSqlType, ProviderType newSqlType) { if (BothTypesAreStrings(oldSqlType, newSqlType)) { bool stringsFixedSize = oldSqlType.IsFixedSize || newSqlType.IsFixedSize; if (!newSqlType.HasSizeOrIsLarge) { // we assume we can convert to an unknown size return true; } else if (OldWillFitInNew(oldSqlType, newSqlType)) { // we can do the conversion when both sizes are specified and the destination size is larger // but we only need to do it when one is fixed size return stringsFixedSize; } else { return false; } } else { return true; } }
internal SqlBinary Binary(SqlNodeType nodeType, SqlExpression left, SqlExpression right, MethodInfo method, Type clrType) { ProviderType sqlType = null; if (nodeType.IsPredicateBinaryOperator()) { if (clrType == null) { clrType = typeof(bool); } sqlType = typeProvider.From(clrType); } else { ProviderType resultType = this.typeProvider.PredictTypeForBinary(nodeType, left.SqlType, right.SqlType); if (resultType == right.SqlType) { if (clrType == null) { clrType = right.ClrType; } sqlType = right.SqlType; } else if (resultType == left.SqlType) { if (clrType == null) { clrType = left.ClrType; } sqlType = left.SqlType; } else { sqlType = resultType; if (clrType == null) { clrType = resultType.GetClosestRuntimeType(); } } } return(new SqlBinary(nodeType, clrType, sqlType, left, right, method)); }
internal override SqlExpression VisitBinaryOperator(SqlBinary bo) { // // Special case to allow DateTime CLR type to be passed as a paramater where // a SQL type TIME is expected. We do this only for the equality/inequality // comparisons. // switch (bo.NodeType) { case SqlNodeType.EQ: case SqlNodeType.EQ2V: case SqlNodeType.NE: case SqlNodeType.NE2V: { SqlDbType leftSqlDbType = ((SqlTypeSystem.SqlType)(bo.Left.SqlType)).SqlDbType; SqlDbType rightSqlDbType = ((SqlTypeSystem.SqlType)(bo.Right.SqlType)).SqlDbType; if (leftSqlDbType == rightSqlDbType) { break; } bool isLeftColRef = bo.Left is SqlColumnRef; bool isRightColRef = bo.Right is SqlColumnRef; if (isLeftColRef == isRightColRef) { break; } if (isLeftColRef && leftSqlDbType == SqlDbType.Time && bo.Right.ClrType == typeof(DateTime)) { this.timeProviderType = bo.Left.SqlType; } else if (isRightColRef && rightSqlDbType == SqlDbType.Time && bo.Left.ClrType == typeof(DateTime)) { this.timeProviderType = bo.Left.SqlType; } break; } } base.VisitBinaryOperator(bo); return(bo); }
private bool RetypeOutParameter(SqlParameter node) { if (!node.SqlType.IsLargeType) { return(false); } ProviderType newType = this.parameterizer.typeProvider.GetBestLargeType(node.SqlType); if (node.SqlType != newType) { node.SetSqlType(newType); return(true); } // Since we are dealing with a long out parameter that hasn't been // retyped, we need to annotate this.parameterizer.annotations.Add( node, new SqlServerCompatibilityAnnotation( SqlClient.Strings.MaxSizeNotSupported(node.SourceExpression), SqlProvider.ProviderMode.Sql2000)); return(false); }
internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc) { for (int i = 0, n = fc.Arguments.Count; i < n; i++) { fc.Arguments[i] = this.VisitExpression(fc.Arguments[i]); } if (fc.Arguments.Count > 0) { ProviderType oldType = fc.Arguments[0].SqlType; // if this has a real argument (not e.g. the symbol "DAY" in DATEDIFF(DAY,...)) if (oldType != null) { ProviderType newType = this.typeProvider.ReturnTypeOfFunction(fc); if (newType != null) { fc.SetSqlType(newType); } } } return(fc); }
internal override SqlExpression VisitSimpleCase(SqlSimpleCase c) { base.VisitSimpleCase(c); // determine the best common type for all the when 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); } // 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); } return(c); }
private void CoerceTypeFamily(SqlExpression arg1, SqlExpression arg2) { if ((arg1.SqlType.HasPrecisionAndScale && arg2.SqlType.HasPrecisionAndScale && arg1.SqlType != arg2.SqlType) || SqlFactory.IsSqlHighPrecisionDateTimeType(arg1) || SqlFactory.IsSqlHighPrecisionDateTimeType(arg2)) { ProviderType best = typeProvider.GetBestType(arg1.SqlType, arg2.SqlType); SetSqlTypeIfSimpleExpression(arg1, best); SetSqlTypeIfSimpleExpression(arg2, best); return; } // The SQL data type DATE is special, in that it has a higher range but lower // precedence, so we need to account for that here (DevDiv 175229) if (SqlFactory.IsSqlDateType(arg1) && !SqlFactory.IsSqlHighPrecisionDateTimeType(arg2)) { SetSqlTypeIfSimpleExpression(arg2, arg1.SqlType); } else if (SqlFactory.IsSqlDateType(arg2) && !SqlFactory.IsSqlHighPrecisionDateTimeType(arg1)) { SetSqlTypeIfSimpleExpression(arg1, arg2.SqlType); } }
internal SqlUnary Unary(SqlNodeType nodeType, SqlExpression expression, MethodInfo method, Expression sourceExpression) { Type clrType = null; ProviderType sqlType = null; if (nodeType == SqlNodeType.Count) { clrType = typeof(int); sqlType = typeProvider.From(typeof(int)); } else if (nodeType == SqlNodeType.LongCount) { clrType = typeof(long); sqlType = typeProvider.From(typeof(long)); } else if (nodeType == SqlNodeType.ClrLength) { clrType = typeof(int); sqlType = typeProvider.From(typeof(int)); } else { if (nodeType.IsPredicateUnaryOperator()) { // DevDiv 201730 - Do not ignore nullability of bool type clrType = expression.ClrType.Equals(typeof(bool?)) ? typeof(bool?) : typeof(bool); } else { clrType = expression.ClrType; } sqlType = typeProvider.PredictTypeForUnary(nodeType, expression.SqlType); } return(new SqlUnary(nodeType, clrType, sqlType, expression, method, sourceExpression)); }
internal SqlBinary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression left, SqlExpression right) : this(nt, clrType, sqlType, left, right, null) { }
internal abstract ProviderType PredictTypeForBinary(SqlNodeType binaryOp, ProviderType leftType, ProviderType rightType);
internal abstract ProviderType PredictTypeForBinary(SqlNodeType binaryOp, ProviderType leftType, ProviderType rightType);
internal abstract ProviderType PredictTypeForUnary(SqlNodeType unaryOp, ProviderType operandType);
internal SqlMember(Type clrType, ProviderType sqlType, SqlExpression expr, MemberInfo member) : base(SqlNodeType.Member, clrType, sqlType, expr.SourceExpression) { this.member = member; Expression = expr; }
private SqlExpression ConvertToMax(SqlExpression expr, ProviderType newType) { return sql.UnaryConvert(expr.ClrType, newType, expr, expr.SourceExpression); }
internal SqlFunctionCall(Type clrType, ProviderType sqlType, string name, IEnumerable <SqlExpression> args, Expression source) : this(SqlNodeType.FunctionCall, clrType, sqlType, name, args, source) { }
internal SqlExpression ConvertTo(Type clrType, ProviderType sqlType, SqlExpression expr) { return(UnaryConvert(clrType, sqlType, expr, expr.SourceExpression)); }
internal override SqlExpression VisitBinaryOperator(SqlBinary bo) { // // Special case to allow DateTime CLR type to be passed as a paramater where // a SQL type TIME is expected. We do this only for the equality/inequality // comparisons. // switch (bo.NodeType) { case SqlNodeType.EQ: case SqlNodeType.EQ2V: case SqlNodeType.NE: case SqlNodeType.NE2V: { SqlDbType leftSqlDbType = ((SqlTypeSystem.SqlType)(bo.Left.SqlType)).SqlDbType; SqlDbType rightSqlDbType = ((SqlTypeSystem.SqlType)(bo.Right.SqlType)).SqlDbType; if (leftSqlDbType == rightSqlDbType) break; bool isLeftColRef = bo.Left is SqlColumnRef; bool isRightColRef = bo.Right is SqlColumnRef; if (isLeftColRef == isRightColRef) break; if (isLeftColRef && leftSqlDbType == SqlDbType.Time && bo.Right.ClrType == typeof(DateTime)) this.timeProviderType = bo.Left.SqlType; else if (isRightColRef && rightSqlDbType == SqlDbType.Time && bo.Left.ClrType == typeof(DateTime)) this.timeProviderType = bo.Left.SqlType; break; } } base.VisitBinaryOperator(bo); return bo; }
internal abstract void InitializeParameter(ProviderType type, System.Data.Common.DbParameter parameter, object value);
/// <summary> /// Get a type that can hold the same information but belongs to a different type family. /// For example, to represent a SQL NChar as an integer type, we need to use the type int. /// (SQL smallint would not be able to contain characters with unicode >32768) /// </summary> /// <param name="toType">Type of the target type family</param> /// <returns>Smallest type of target type family that can hold equivalent information</returns> internal abstract ProviderType ChangeTypeFamilyTo(ProviderType type, ProviderType typeWithFamily);
/// <summary> /// Returns a type that can be used to hold values for both the current /// type and the specified type without data loss. /// </summary> internal abstract ProviderType GetBestType(ProviderType typeA, ProviderType typeB);
/// <summary> /// For LOB data types that have large type equivalents, this function returns the equivalent large /// data type. If the type is not an LOB or cannot be converted, the function returns the current type. /// For example SqlServer defines the 'Image' LOB type, whose large type equivalent is VarBinary(MAX). /// </summary> internal abstract ProviderType GetBestLargeType(ProviderType type);
/// <summary> /// Returns the most precise type in the family of the type given. /// A family is a group types that serve similar functions. For example, /// in SQL SmallInt and Int are part of one family. /// </summary> internal abstract ProviderType MostPreciseTypeInFamily(ProviderType type);
private bool BothTypesAreStrings(ProviderType oldSqlType, ProviderType newSqlType) { bool result = oldSqlType.IsSameTypeFamily(sql.TypeProvider.From(typeof(string))) && newSqlType.IsSameTypeFamily(sql.TypeProvider.From(typeof(string))); return result; }
/// <summary> /// Determines whether two types are in the same type family. /// A family is a group types that serve similar functions. For example, /// in SQL SmallInt and Int are part of one family. /// </summary> internal abstract bool IsSameTypeFamily(ProviderType type);
internal SqlUnary UnaryConvert(Type targetClrType, ProviderType targetSqlType, SqlExpression expression, Expression sourceExpression) { System.Diagnostics.Debug.Assert(!targetSqlType.IsRuntimeOnlyType, "Attempted coversion to a runtime type: from = " + expression.SqlType.ToQueryString() + "; to = " + targetSqlType.ToQueryString() + "; source = " + sourceExpression.ToString()); return(new SqlUnary(SqlNodeType.Convert, targetClrType, targetSqlType, expression, null, sourceExpression)); }
internal SqlFunctionCall(SqlNodeType nodeType, Type clrType, ProviderType sqlType, string name, IEnumerable <SqlExpression> args, Expression source) : base(nodeType, clrType, sqlType, source) { Name = name; Arguments = new List <SqlExpression>(args); }
internal SqlJoinedCollection(Type clrType, ProviderType sqlType, SqlExpression expression, SqlExpression count, Expression sourceExpression) : base(SqlNodeType.JoinedCollection, clrType, sqlType, sourceExpression) { this.expression = expression; this.count = count; }
private SqlExpression ConvertToMax(SqlExpression expr, ProviderType newType) { return(sql.UnaryConvert(expr.ClrType, newType, expr, expr.SourceExpression)); }
internal SqlFunctionCall FunctionCall(Type clrType, ProviderType sqlType, string name, IEnumerable <SqlExpression> args, Expression source) { return(new SqlFunctionCall(clrType, sqlType, name, args, source)); }
/// <summary> /// Compare implicit type coercion precedence. /// -1 means there is an implicit conversion from this->type. /// 0 means there is a two way implicit conversion from this->type /// 1 means there is an implicit conversion from type->this. /// </summary> internal abstract int ComparePrecedenceTo(ProviderType type);
/// <summary> /// For LOB data types that have large type equivalents, this function returns the equivalent large /// data type. If the type is not an LOB or cannot be converted, the function returns the current type. /// For example SqlServer defines the 'Image' LOB type, whose large type equivalent is VarBinary(MAX). /// </summary> internal abstract ProviderType GetBestLargeType(ProviderType type);
/// <summary> /// Determines whether two types are in the same type family. /// A family is a group types that serve similar functions. For example, /// in SQL SmallInt and Int are part of one family. /// </summary> internal abstract bool IsSameTypeFamily(ProviderType type);
/// <summary> /// Get a type that can hold the same information but belongs to a different type family. /// For example, to represent a SQL NChar as an integer type, we need to use the type int. /// (SQL smallint would not be able to contain characters with unicode >32768) /// </summary> /// <param name="toType">Type of the target type family</param> /// <returns>Smallest type of target type family that can hold equivalent information</returns> internal abstract ProviderType ChangeTypeFamilyTo(ProviderType type, ProviderType typeWithFamily);
/// <summary> /// Returns the most precise type in the family of the type given. /// A family is a group types that serve similar functions. For example, /// in SQL SmallInt and Int are part of one family. /// </summary> internal abstract ProviderType MostPreciseTypeInFamily(ProviderType type);
internal abstract ProviderType PredictTypeForUnary(SqlNodeType unaryOp, ProviderType operandType);
/// <summary> /// Returns a type that can be used to hold values for both the current /// type and the specified type without data loss. /// </summary> internal abstract ProviderType GetBestType(ProviderType typeA, ProviderType typeB);
private void FormatType(ProviderType type) { sb.Append(type.ToQueryString()); }
internal abstract void InitializeParameter(ProviderType type, System.Data.Common.DbParameter parameter, object value);
internal SqlIn(Type clrType, ProviderType sqlType, SqlExpression expression, IEnumerable <SqlExpression> values, Expression sourceExpression) : base(SqlNodeType.In, clrType, sqlType, sourceExpression) { this.expression = expression; this.values = values != null ? new List <SqlExpression>(values) : new List <SqlExpression>(0); }
internal SqlDiscriminatorOf(SqlExpression obj, Type clrType, ProviderType sqlType, Expression sourceExpression) : base(SqlNodeType.DiscriminatorOf, clrType, sqlType, sourceExpression) { this.Object = obj; }
internal SqlFunctionCall FunctionCall(Type clrType, ProviderType sqlType, string name, IEnumerable<SqlExpression> args, Expression source) { return new SqlFunctionCall(clrType, sqlType, name, args, source); }
internal SqlClientParameter(Type clrType, ProviderType sqlType, LambdaExpression accessor, Expression sourceExpression) : base(SqlNodeType.ClientParameter, clrType, sqlType, sourceExpression) { this.accessor = accessor; }
/// <summary> /// Compare implicit type coercion precedence. /// -1 means there is an implicit conversion from this->type. /// 0 means there is a two way implicit conversion from this->type /// 1 means there is an implicit conversion from type->this. /// </summary> internal abstract int ComparePrecedenceTo(ProviderType type);
internal SqlExpression Value(Type clrType, ProviderType sqlType, object value, bool isClientSpecified, Expression sourceExpression) { if (typeof(Type).IsAssignableFrom(clrType) && value != null) { MetaType typeOf = this.model.GetMetaType((Type)value); return StaticType(typeOf, sourceExpression); } return new SqlValue(clrType, sqlType, value, isClientSpecified, sourceExpression); }
internal SqlExpression ConvertTo(Type clrType, ProviderType sqlType, SqlExpression expr) { return UnaryConvert(clrType, sqlType, expr, expr.SourceExpression); }
private static void SetSqlTypeIfSimpleExpression(SqlExpression expression, ProviderType sqlType) { SqlSimpleTypeExpression simpleExpression = expression as SqlSimpleTypeExpression; if (simpleExpression != null) { simpleExpression.SetSqlType(sqlType); } }
internal SqlUnary UnaryConvert(Type targetClrType, ProviderType targetSqlType, SqlExpression expression, Expression sourceExpression) { System.Diagnostics.Debug.Assert(!targetSqlType.IsRuntimeOnlyType, "Attempted coversion to a runtime type: from = " + expression.SqlType.ToQueryString() + "; to = " + targetSqlType.ToQueryString() + "; source = " + sourceExpression.ToString()); return new SqlUnary(SqlNodeType.Convert, targetClrType, targetSqlType, expression, null, sourceExpression); }
private static void SetSqlTypeIfSimpleExpression(SqlExpression expression, ProviderType sqlType) { SqlSimpleTypeExpression simpleExpression = expression as SqlSimpleTypeExpression; if (simpleExpression != null) { simpleExpression.SetSqlType(sqlType); } }
internal SqlNop(Type clrType, ProviderType sqlType, Expression sourceExpression) : base(SqlNodeType.Nop, clrType, sqlType, sourceExpression) { }