internal override ProviderType GetBestType(ProviderType typeA, ProviderType typeB) { // first determine the type precedence SqlType bestType = (SqlType)(typeA.ComparePrecedenceTo(typeB) > 0 ? typeA : typeB); // if one of the types is a not a server type, return // that type if(typeA.IsApplicationType || typeA.IsRuntimeOnlyType) { return typeA; } if(typeB.IsApplicationType || typeB.IsRuntimeOnlyType) { return typeB; } SqlType sqlTypeA = (SqlType)typeA; SqlType sqlTypeB = (SqlType)typeB; if(sqlTypeA.HasPrecisionAndScale && sqlTypeB.HasPrecisionAndScale && bestType.SqlDbType == SqlDbType.Decimal) { int p0 = sqlTypeA.Precision; int s0 = sqlTypeA.Scale; int p1 = sqlTypeB.Precision; int s1 = sqlTypeB.Scale; // precision and scale may be zero if this is an unsized type. if(p0 == 0 && s0 == 0 && p1 == 0 && s1 == 0) { return SqlTypeSystem.Create(bestType.SqlDbType); } else if(p0 == 0 && s0 == 0) { return SqlTypeSystem.Create(bestType.SqlDbType, p1, s1); } else if(p1 == 0 && s1 == 0) { return SqlTypeSystem.Create(bestType.SqlDbType, p0, s0); } // determine best scale/precision int bestLeft = Math.Max(p0 - s0, p1 - s1); int bestRight = Math.Max(s0, s1); int precision = Math.Min(bestLeft + bestRight, 38); return SqlTypeSystem.Create(bestType.SqlDbType, precision, /*scale*/bestRight); } else { // determine the best size int? bestSize = null; if(sqlTypeA.Size.HasValue && sqlTypeB.Size.HasValue) { bestSize = (sqlTypeB.Size > sqlTypeA.Size) ? sqlTypeB.Size : sqlTypeA.Size; } if(sqlTypeB.Size.HasValue && sqlTypeB.Size.Value == ProviderConstants.LargeTypeSizeIndicator || sqlTypeA.Size.HasValue && sqlTypeA.Size.Value == ProviderConstants.LargeTypeSizeIndicator) { // the large type size trumps all bestSize = ProviderConstants.LargeTypeSizeIndicator; } bestType = new SqlType(bestType.SqlDbType, bestSize); } return bestType; }
internal override ProviderType GetBestType(ProviderType typeA, ProviderType typeB) { // first determine the type precedence SqlType bestType = (SqlType)(typeA.ComparePrecedenceTo(typeB) > 0 ? typeA : typeB); // if one of the types is a not a server type, return // that type if (typeA.IsApplicationType || typeA.IsRuntimeOnlyType) { return(typeA); } if (typeB.IsApplicationType || typeB.IsRuntimeOnlyType) { return(typeB); } SqlType sqlTypeA = (SqlType)typeA; SqlType sqlTypeB = (SqlType)typeB; if (sqlTypeA.HasPrecisionAndScale && sqlTypeB.HasPrecisionAndScale && bestType.SqlDbType == SqlDbType.Decimal) { int p0 = sqlTypeA.Precision; int s0 = sqlTypeA.Scale; int p1 = sqlTypeB.Precision; int s1 = sqlTypeB.Scale; // precision and scale may be zero if this is an unsized type. if (p0 == 0 && s0 == 0 && p1 == 0 && s1 == 0) { return(SqlTypeSystem.Create(bestType.SqlDbType)); } else if (p0 == 0 && s0 == 0) { return(SqlTypeSystem.Create(bestType.SqlDbType, p1, s1)); } else if (p1 == 0 && s1 == 0) { return(SqlTypeSystem.Create(bestType.SqlDbType, p0, s0)); } // determine best scale/precision int bestLeft = Math.Max(p0 - s0, p1 - s1); int bestRight = Math.Max(s0, s1); int precision = Math.Min(bestLeft + bestRight, 38); return(SqlTypeSystem.Create(bestType.SqlDbType, precision, /*scale*/ bestRight)); } else { // determine the best size int?bestSize = null; if (sqlTypeA.Size.HasValue && sqlTypeB.Size.HasValue) { bestSize = (sqlTypeB.Size > sqlTypeA.Size) ? sqlTypeB.Size : sqlTypeA.Size; } if (sqlTypeB.Size.HasValue && sqlTypeB.Size.Value == ProviderConstants.LargeTypeSizeIndicator || sqlTypeA.Size.HasValue && sqlTypeA.Size.Value == ProviderConstants.LargeTypeSizeIndicator) { // the large type size trumps all bestSize = ProviderConstants.LargeTypeSizeIndicator; } bestType = new SqlType(bestType.SqlDbType, bestSize); } return(bestType); }
internal override ProviderType PredictTypeForBinary(SqlNodeType binaryOp, ProviderType leftType, ProviderType rightType) { SqlType highest; if(leftType.IsSameTypeFamily(this.From(typeof(string))) && rightType.IsSameTypeFamily(this.From(typeof(string)))) { highest = (SqlType)this.GetBestType(leftType, rightType); } else { int coercionPrecedence = leftType.ComparePrecedenceTo(rightType); highest = (SqlType)(coercionPrecedence > 0 ? leftType : rightType); } switch(binaryOp) { case SqlNodeType.Add: case SqlNodeType.Sub: case SqlNodeType.Mul: case SqlNodeType.Div: case SqlNodeType.BitAnd: case SqlNodeType.BitOr: case SqlNodeType.BitXor: case SqlNodeType.Mod: case SqlNodeType.Coalesce: return highest; case SqlNodeType.Concat: // When concatenating two types with size, the result type after // concatenation must have a size equal to the sum of the two sizes. if(highest.HasSizeOrIsLarge) { // get the best type, specifying null for size so we get // the maximum allowable size ProviderType concatType = this.GetBestType(highest.SqlDbType, null); if((!leftType.IsLargeType && leftType.Size.HasValue) && (!rightType.IsLargeType && rightType.Size.HasValue)) { // If both types are not large types and have size, and the // size is less than the default size, return the shortened type. int concatSize = leftType.Size.Value + rightType.Size.Value; if((concatSize < concatType.Size) || concatType.IsLargeType) { return GetBestType(highest.SqlDbType, concatSize); } } return concatType; } return highest; case SqlNodeType.And: case SqlNodeType.Or: case SqlNodeType.LT: case SqlNodeType.LE: case SqlNodeType.GT: case SqlNodeType.GE: case SqlNodeType.EQ: case SqlNodeType.NE: case SqlNodeType.EQ2V: case SqlNodeType.NE2V: return ProviderConstants.IntType; default: throw Error.UnexpectedNode(binaryOp); } }
internal override ProviderType PredictTypeForBinary(SqlNodeType binaryOp, ProviderType leftType, ProviderType rightType) { SqlType highest; if (leftType.IsSameTypeFamily(this.From(typeof(string))) && rightType.IsSameTypeFamily(this.From(typeof(string)))) { highest = (SqlType)this.GetBestType(leftType, rightType); } else { int coercionPrecedence = leftType.ComparePrecedenceTo(rightType); highest = (SqlType)(coercionPrecedence > 0 ? leftType : rightType); } switch (binaryOp) { case SqlNodeType.Add: case SqlNodeType.Sub: case SqlNodeType.Mul: case SqlNodeType.Div: case SqlNodeType.BitAnd: case SqlNodeType.BitOr: case SqlNodeType.BitXor: case SqlNodeType.Mod: case SqlNodeType.Coalesce: return(highest); case SqlNodeType.Concat: // When concatenating two types with size, the result type after // concatenation must have a size equal to the sum of the two sizes. if (highest.HasSizeOrIsLarge) { // get the best type, specifying null for size so we get // the maximum allowable size ProviderType concatType = this.GetBestType(highest.SqlDbType, null); if ((!leftType.IsLargeType && leftType.Size.HasValue) && (!rightType.IsLargeType && rightType.Size.HasValue)) { // If both types are not large types and have size, and the // size is less than the default size, return the shortened type. int concatSize = leftType.Size.Value + rightType.Size.Value; if ((concatSize < concatType.Size) || concatType.IsLargeType) { return(GetBestType(highest.SqlDbType, concatSize)); } } return(concatType); } return(highest); case SqlNodeType.And: case SqlNodeType.Or: case SqlNodeType.LT: case SqlNodeType.LE: case SqlNodeType.GT: case SqlNodeType.GE: case SqlNodeType.EQ: case SqlNodeType.NE: case SqlNodeType.EQ2V: case SqlNodeType.NE2V: return(ProviderConstants.IntType); default: throw Error.UnexpectedNode(binaryOp); } }