Example #1
0
        private Predicate ImplementEquality(Predicate left, Predicate right, EqualsPattern pattern)
        {
            switch (left.PredicateType)
            {
            case PredicateType.Constant:
                switch (right.PredicateType)
                {
                case PredicateType.Constant:         // constant EQ constant
                    return(left.Equal(right));

                case PredicateType.Null:         // null EQ constant --> false
                    return(PredicateBuilder.False);

                default:
                    return(ImplementEqualityConstantAndUnknown((ConstantPredicate)left, right, pattern));
                }

            case PredicateType.Null:
                switch (right.PredicateType)
                {
                case PredicateType.Constant:
                    return(PredicateBuilder.False);

                case PredicateType.Null:
                    return(PredicateBuilder.True);

                default:
                    return(right.IsNull());
                }

            default:
                switch (right.PredicateType)
                {
                case PredicateType.Constant:
                    return(ImplementEqualityConstantAndUnknown((ConstantPredicate)right, left, pattern));

                case PredicateType.Null:
                    return(left.IsNull());

                default:
                    return(ImplementEqualityUnknownArguments(left, right, pattern));
                }
            }
        }
Example #2
0
        private Predicate ImplementEqualityUnknownArguments(Predicate left, Predicate right, EqualsPattern pattern)
        {
            switch (pattern)
            {
            case EqualsPattern.Store:
                return(left.Equal(right));

            case EqualsPattern.PositiveNullEqualityNonComposable:     // for Joins
                return(left.Equal(right).Or(left.IsNull().And(right.IsNull())));

            case EqualsPattern.PositiveNullEqualityComposable:
            {
                var bothNotNull  = left.Equal(right);
                var bothNull     = left.IsNull().And(right.IsNull());
                var anyOneIsNull = left.IsNull().Or(right.IsNull());
                return((bothNotNull.And(anyOneIsNull.Not())).Or(bothNull));
            }

            default:
                return(null);
            }
        }
Example #3
0
        private Predicate ImplementEqualityConstantAndUnknown(ConstantPredicate constant, Predicate unknown, EqualsPattern pattern)
        {
            switch (pattern)
            {
            case EqualsPattern.Store:
            case EqualsPattern.PositiveNullEqualityNonComposable:     // for Joins
                return(constant.Equal(unknown));

            case EqualsPattern.PositiveNullEqualityComposable:
                return(constant.Equal(unknown).And(unknown.IsNull().Not()));

            default:
                return(null);
            }
        }
Example #4
0
        private Predicate RecursivelyRewriteEqualsExpression(Predicate left, Predicate right, EqualsPattern pattern)
        {
            var leftType  = left.ResultType.EdmType as RowType;
            var rightType = right.ResultType.EdmType as RowType;

            if (null != leftType || null != rightType)
            {
                if (null != leftType && null != rightType)
                {
                    Predicate shreddedEquals = null;
                    foreach (var property in leftType.Properties)
                    {
                        var leftElement    = left.Property(property);
                        var rightElement   = right.Property(property);
                        var elementsEquals = RecursivelyRewriteEqualsExpression(leftElement, rightElement, pattern);

                        if (null == shreddedEquals)
                        {
                            shreddedEquals = elementsEquals;
                        }
                        else
                        {
                            shreddedEquals = shreddedEquals.And(elementsEquals);
                        }
                    }
                    return(shreddedEquals);
                }
                else
                {
                    return(PredicateBuilder.False);
                }
            }
            else
            {
                return(ImplementEquality(left, right, pattern));
            }
        }
 // Generate an equality expression where the values of the left and right operands are completely unknown 
 private DbExpression ImplementEqualityUnknownArguments(DbExpression left, DbExpression right, EqualsPattern pattern)
 {
     switch (pattern)
     {
         case EqualsPattern.Store: // left EQ right
             return left.Equal(right);
         case EqualsPattern.PositiveNullEqualityNonComposable: // for Joins
             return left.Equal(right).Or(left.IsNull().And(right.IsNull()));
         case EqualsPattern.PositiveNullEqualityComposable:
             {
                 var bothNotNull = left.Equal(right);
                 var bothNull = left.IsNull().And(right.IsNull());
                 if (!_funcletizer.RootContext.ContextOptions.UseCSharpNullComparisonBehavior)
                 {
                     return bothNotNull.Or(bothNull); // same as EqualsPattern.PositiveNullEqualityNonComposable
                 }
                 // add more logic to avoid undefined result for true clr semantics, ensuring composability
                 // (left EQ right AND NOT (left IS NULL OR right IS NULL)) OR (left IS NULL AND right IS NULL)
                 var anyOneIsNull = left.IsNull().Or(right.IsNull());
                 return (bothNotNull.And(anyOneIsNull.Not())).Or(bothNull);
             }
         default:
             Debug.Fail("unexpected pattern");
             return null;
     }
 }
Example #6
0
 internal Predicate CreateEqualsExpression(Predicate left, Predicate right, EqualsPattern pattern, Type leftClrType, Type rightClrType)
 {
     return(RecursivelyRewriteEqualsExpression(left, right, pattern));
 }
 // Generate an equality expression with one unknown operator and 
 private DbExpression ImplementEqualityConstantAndUnknown(
     DbConstantExpression constant, DbExpression unknown, EqualsPattern pattern)
 {
     switch (pattern)
     {
         case EqualsPattern.Store:
         case EqualsPattern.PositiveNullEqualityNonComposable: // for Joins                    
             return constant.Equal(unknown); // either both are non-null, or one is null and the predicate result is undefined
         case EqualsPattern.PositiveNullEqualityComposable:
             if (!_funcletizer.RootContext.ContextOptions.UseCSharpNullComparisonBehavior)
             {
                 return constant.Equal(unknown); // same as EqualsPattern.PositiveNullEqualityNonComposable
             }
             return constant.Equal(unknown).And(unknown.IsNull().Not());
         // add more logic to avoid undefined result for true clr semantics
         default:
             Debug.Fail("unknown pattern");
             return null;
     }
 }
 // For comparisons, where the left and right side are nullable or not nullable, 
 // here are the (compositionally safe) null equality predicates:
 // -- x NOT NULL, y NULL
 // x = y AND  NOT (y IS NULL)
 // -- x NULL, y NULL
 // (x = y AND  (NOT (x IS NULL OR y IS NULL))) OR (x IS NULL AND y IS NULL)
 // -- x NOT NULL, y NOT NULL
 // x = y
 // -- x NULL, y NOT NULL
 // x = y AND  NOT (x IS NULL)
 private DbExpression ImplementEquality(DbExpression left, DbExpression right, EqualsPattern pattern)
 {
     switch (left.ExpressionKind)
     {
         case DbExpressionKind.Constant:
             switch (right.ExpressionKind)
             {
                 case DbExpressionKind.Constant: // constant EQ constant
                     return left.Equal(right);
                 case DbExpressionKind.Null: // null EQ constant --> false
                     return DbExpressionBuilder.False;
                 default:
                     return ImplementEqualityConstantAndUnknown((DbConstantExpression)left, right, pattern);
             }
         case DbExpressionKind.Null:
             switch (right.ExpressionKind)
             {
                 case DbExpressionKind.Constant: // null EQ constant --> false
                     return DbExpressionBuilder.False;
                 case DbExpressionKind.Null: // null EQ null --> true
                     return DbExpressionBuilder.True;
                 default: // null EQ right --> right IS NULL
                     return right.IsNull();
             }
         default: // unknown
             switch (right.ExpressionKind)
             {
                 case DbExpressionKind.Constant:
                     return ImplementEqualityConstantAndUnknown((DbConstantExpression)right, left, pattern);
                 case DbExpressionKind.Null: //  left EQ null --> left IS NULL
                     return left.IsNull();
                 default:
                     return ImplementEqualityUnknownArguments(left, right, pattern);
             }
     }
 }
        private DbExpression RecursivelyRewriteEqualsExpression(DbExpression left, DbExpression right, EqualsPattern pattern)
        {
            // check if either side is an initializer type
            var leftType = left.ResultType.EdmType as RowType;
            var rightType = right.ResultType.EdmType as RowType;

            if (null != leftType
                || null != rightType)
            {
                if (null != leftType && null != rightType)
                {
                    DbExpression shreddedEquals = null;
                    // if the types are the same, use struct equivalence semantics
                    foreach (var property in leftType.Properties)
                    {
                        var leftElement = left.Property(property);
                        var rightElement = right.Property(property);
                        var elementsEquals = RecursivelyRewriteEqualsExpression(
                            leftElement, rightElement, pattern);

                        // build up and expression
                        if (null == shreddedEquals)
                        {
                            shreddedEquals = elementsEquals;
                        }
                        else
                        {
                            shreddedEquals = shreddedEquals.And(elementsEquals);
                        }
                    }
                    return shreddedEquals;
                }
                else
                {
                    // if one or both sides is an initializer and the types are not the same,
                    // "equals" always evaluates to false
                    return DbExpressionBuilder.False;
                }
            }
            else
            {
                return
                    _funcletizer.RootContext.ContextOptions.UseCSharpNullComparisonBehavior
                        ? ImplementEquality(left, right, EqualsPattern.Store)
                        : ImplementEquality(left, right, pattern);
            }
        }
Example #10
0
        // <summary>
        // Creates an implementation of equals using the given pattern. Throws exception when argument types
        // are not supported for equals comparison.
        // </summary>
        private DbExpression CreateEqualsExpression(
            DbExpression left, DbExpression right, EqualsPattern pattern, Type leftClrType, Type rightClrType)
        {
            VerifyTypeSupportedForComparison(leftClrType, left.ResultType, null);
            VerifyTypeSupportedForComparison(rightClrType, right.ResultType, null);

            //For Ref Type comparison, check whether they refer to compatible Entity Types.
            var leftType = left.ResultType;
            var rightType = right.ResultType;
            if (leftType.EdmType.BuiltInTypeKind == BuiltInTypeKind.RefType
                && rightType.EdmType.BuiltInTypeKind == BuiltInTypeKind.RefType)
            {
                TypeUsage commonType;
                if (!TypeSemantics.TryGetCommonType(leftType, rightType, out commonType))
                {
                    var leftRefType = left.ResultType.EdmType as RefType;
                    var rightRefType = right.ResultType.EdmType as RefType;
                    throw new NotSupportedException(
                        Strings.ELinq_UnsupportedRefComparison(leftRefType.ElementType.FullName, rightRefType.ElementType.FullName));
                }
            }

            return RecursivelyRewriteEqualsExpression(left, right, pattern);
        }
        private DbExpression RecursivelyRewriteEqualsExpression(DbExpression left, DbExpression right, EqualsPattern pattern)
        {
            // check if either side is an initializer type
            RowType leftType = left.ResultType.EdmType as RowType;
            RowType rightType = left.ResultType.EdmType as RowType;

            if (null != leftType || null != rightType)
            {
                if ((null != leftType && null != rightType) && leftType.EdmEquals(rightType))
                {
                    DbExpression shreddedEquals = null;
                    // if the types are the same, use struct equivalence semantics
                    foreach (EdmProperty property in leftType.Properties)
                    {
                        DbPropertyExpression leftElement = left.Property(property);
                        DbPropertyExpression rightElement = right.Property(property);
                        DbExpression elementsEquals = RecursivelyRewriteEqualsExpression(
                            leftElement, rightElement, pattern);

                        // build up and expression
                        if (null == shreddedEquals) { shreddedEquals = elementsEquals; }
                        else { shreddedEquals = shreddedEquals.And(elementsEquals); }
                    }
                    return shreddedEquals;
                }
                else
                {
                    // if one or both sides is an initializer and the types are not the same,
                    // "equals" always evaluates to false
                    return DbExpressionBuilder.False;
                }
            }
            else
            {
                return ImplementEquality(left, right, pattern);
            }
        }