/// <summary> /// Determines whether a typed data can do certain operation with another typed data /// </summary> /// <param name="operation">the operation</param> /// <param name="sourceType">the type of data to operation on</param> /// <param name="otherType">the other type</param> /// <returns>Value <c>true</c> if operation can be performed; otherwise, <c>false</c>.</returns> public virtual bool Supports(QueryBinaryOperation operation, QueryScalarType sourceType, QueryScalarType otherType) { var sourceQueryClrType = (IQueryClrType)sourceType; var otherQueryClrType = (IQueryClrType)otherType; var sourceClrType = sourceQueryClrType.ClrType; var otherClrType = otherQueryClrType.ClrType; switch (operation) { case QueryBinaryOperation.Add: case QueryBinaryOperation.Divide: case QueryBinaryOperation.Modulo: case QueryBinaryOperation.Multiply: case QueryBinaryOperation.Subtract: return(LinqTypeSemantics.IsNumeric(sourceClrType) && LinqTypeSemantics.IsNumeric(otherClrType) && this.HaveCommonType(sourceClrType, otherClrType)); case QueryBinaryOperation.BitwiseAnd: case QueryBinaryOperation.BitwiseExclusiveOr: case QueryBinaryOperation.BitwiseOr: return(LinqTypeSemantics.IsIntegralType(sourceClrType) && LinqTypeSemantics.IsIntegralType(otherClrType) && this.HaveCommonType(sourceClrType, otherClrType)); case QueryBinaryOperation.LogicalAnd: case QueryBinaryOperation.LogicalOr: return(sourceClrType == typeof(bool) && otherClrType == typeof(bool)); case QueryBinaryOperation.EqualTo: case QueryBinaryOperation.NotEqualTo: return(this.HaveCommonType(sourceClrType, otherClrType)); case QueryBinaryOperation.LessThan: case QueryBinaryOperation.LessThanOrEqualTo: case QueryBinaryOperation.GreaterThan: case QueryBinaryOperation.GreaterThanOrEqualTo: if (sourceClrType == typeof(byte[]) || otherClrType == typeof(byte[]) || sourceClrType == typeof(string) || otherClrType == typeof(string) || sourceClrType == typeof(bool) || otherClrType == typeof(bool) || sourceClrType == typeof(bool?) || otherClrType == typeof(bool?) || this.IsSpatialType(sourceQueryClrType) || this.IsSpatialType(otherQueryClrType)) { return(false); } else { return(this.HaveCommonType(sourceClrType, otherClrType)); } case QueryBinaryOperation.Concat: return(sourceClrType == typeof(string) || otherClrType == typeof(string)); default: throw new TaupoNotSupportedException("Unsupported query binary operation."); } }
private bool HaveCommonType(Type t1, Type t2) { Type commonClrType; return(LinqTypeSemantics.TryGetCommonType(t1, t2, out commonClrType)); }
/// <summary> /// Gets the common type to which both types can be promoted. /// </summary> /// <param name="leftType">First type.</param> /// <param name="rightType">Second type.</param> /// <returns> /// Common type to which both types can be promoted. Throws if unable to find a common type. /// </returns> public QueryScalarType GetCommonType(QueryScalarType leftType, QueryScalarType rightType) { Type commonClrType = LinqTypeSemantics.GetCommonType(((QueryClrPrimitiveType)leftType).ClrType, ((QueryClrPrimitiveType)rightType).ClrType); return(new QueryClrPrimitiveType(commonClrType, this)); }
/// <summary> /// Compares the primitive value to another value and returns their relative ordering. /// </summary> /// <param name="value">First value.</param> /// <param name="otherValue">Second value.</param> /// <returns> /// Integer which is less than zero if this value is less than the other value, 0 if they are equal, /// greater than zero if this value is greater than the other value /// </returns> public int Compare(QueryScalarValue value, QueryScalarValue otherValue) { var t1 = (QueryClrPrimitiveType)value.Type; var t2 = (QueryClrPrimitiveType)otherValue.Type; object v1 = value.Value; object v2 = otherValue.Value; if (this.IsSpatialType(t1)) { ExceptionUtilities.Assert(this.IsSpatialType(t2), "Because CLR types match, both values should both be spatial. Type was '{0}'", t2); ExceptionUtilities.CheckObjectNotNull(this.SpatialEqualityComparer, "Cannot compare spatial values without a spatial equality-comparer"); return(this.SpatialEqualityComparer.Equals(v1, v2) ? 0 : 2); } if (t1.ClrType != t2.ClrType) { Type commonClrType = LinqTypeSemantics.GetCommonType(t1.ClrType, t2.ClrType); commonClrType = Nullable.GetUnderlyingType(commonClrType) ?? commonClrType; if (v1 != null) { v1 = ArithmeticEvaluationHelper.ChangeType(v1, commonClrType); } if (v2 != null) { v2 = ArithmeticEvaluationHelper.ChangeType(v2, commonClrType); } } if (v1 == null) { if (v2 == null) { // both null - are equal return(0); } else { // first null, second not-null return(-1); } } else { if (v2 == null) { // first not null, second null return(1); } } var bytes1 = v1 as byte[]; if (bytes1 != null) { var bytes2 = (byte[])v2; return(CompareByteArrays(bytes1, bytes2)); } IComparable cv1 = (IComparable)v1; return(cv1.CompareTo(v2)); }