예제 #1
0
        protected override Expression VisitUnary(UnaryExpression node)
        {
#if (DEBUGPRINT)
            System.Diagnostics.Debug.Print("VisitUnary: {0}", node);
#endif

            var expression = base.VisitUnary(node) as UnaryExpression;

            DbExpression operandExpression = GetDbExpressionForExpression(expression.Operand);

            switch (expression.NodeType)
            {
            case ExpressionType.Not:
                MapExpressionToDbExpression(expression, operandExpression.Not());
                break;

            case ExpressionType.Convert:
                MapExpressionToDbExpression(expression, operandExpression.CastTo(TypeUsageForPrimitiveType(expression.Operand.Type)));
                break;

            default:
                throw new NotImplementedException(string.Format("Unhandled NodeType of {0} in LambdaToDbExpressionVisitor.VisitUnary", expression.NodeType));
            }

            return(expression);
        }
        /// <summary>
        /// Maps a comparison of an expression to a "null" constant.
        /// </summary>
        /// <returns></returns>
        private DbExpression MapNullComparison(Expression expression, ExpressionType comparisonType)
        {
            DbExpression dbExpression = GetDbExpressionForExpression(expression).IsNull();

            switch (comparisonType)
            {
            case ExpressionType.Equal:
                return(dbExpression);

            case ExpressionType.NotEqual:
                //  Creates expression: !([expression] is null)
                return(dbExpression.Not());
            }

            throw new NotImplementedException(string.Format("Unhandled comparisonType of {0} in LambdaToDbExpressionVisitor.MapNullComparison", comparisonType));
        }
        private DbExpression TransformIntersectOrExcept(
            DbExpression left,
            DbExpression right,
            DbExpressionKind expressionKind,
            IList <DbPropertyExpression> sortExpressionsOverLeft,
            string sortExpressionsBindingVariableName)
        {
            bool flag1 = expressionKind == DbExpressionKind.Except || expressionKind == DbExpressionKind.Skip;
            bool flag2 = expressionKind == DbExpressionKind.Except || expressionKind == DbExpressionKind.Intersect;
            DbExpressionBinding          input                   = left.Bind();
            DbExpressionBinding          expressionBinding       = right.Bind();
            IList <DbPropertyExpression> propertyExpressionList1 = (IList <DbPropertyExpression>) new List <DbPropertyExpression>();
            IList <DbPropertyExpression> propertyExpressionList2 = (IList <DbPropertyExpression>) new List <DbPropertyExpression>();

            this.FlattenProperties((DbExpression)input.Variable, propertyExpressionList1);
            this.FlattenProperties((DbExpression)expressionBinding.Variable, propertyExpressionList2);
            if (expressionKind == DbExpressionKind.Skip && Sql8ExpressionRewriter.RemoveNonSortProperties(propertyExpressionList1, propertyExpressionList2, sortExpressionsOverLeft, input.VariableName, sortExpressionsBindingVariableName))
            {
                expressionBinding = Sql8ExpressionRewriter.CapWithProject(expressionBinding, propertyExpressionList2);
            }
            DbExpression dbExpression1 = (DbExpression)null;

            for (int index = 0; index < propertyExpressionList1.Count; ++index)
            {
                DbExpression right1 = (DbExpression)propertyExpressionList1[index].Equal((DbExpression)propertyExpressionList2[index]).Or((DbExpression)propertyExpressionList1[index].IsNull().And((DbExpression)propertyExpressionList2[index].IsNull()));
                dbExpression1 = index != 0 ? (DbExpression)dbExpression1.And(right1) : right1;
            }
            DbExpression dbExpression2 = (DbExpression)expressionBinding.Any(dbExpression1);
            DbExpression predicate     = !flag1 ? dbExpression2 : (DbExpression)dbExpression2.Not();
            DbExpression dbExpression3 = (DbExpression)input.Filter(predicate);

            if (flag2)
            {
                dbExpression3 = (DbExpression)dbExpression3.Distinct();
            }
            return(dbExpression3);
        }
        // <summary>
        // This method is used for translating <see cref="DbIntersectExpression" /> and <see cref="DbExceptExpression" />,
        // and for translating the "Except" part of <see cref="DbSkipExpression" />.
        // into the follwoing expression:
        // A INTERSECT B, A EXCEPT B
        // (DISTINCT)
        // |
        // FILTER
        // |
        // | - Input: A
        // | - Predicate:(NOT)
        // |
        // ANY
        // |
        // | - Input: B
        // | - Predicate:  (B.b1 = A.a1 or (B.b1 is null and A.a1 is null))
        // AND (B.b2 = A.a2 or (B.b2 is null and A.a2 is null))
        // AND ...
        // AND (B.bn = A.an or (B.bn is null and A.an is null)))
        // Here, A corresponds to right and B to left.
        // (NOT) is present when transforming Except
        // for the purpose of translating <see cref="DbExceptExpression" /> or <see cref="DbSkipExpression" />.
        // (DISTINCT) is present when transforming for the purpose of translating
        // <see cref="DbExceptExpression" /> or <see cref="DbIntersectExpression" />.
        // For <see cref="DbSkipExpression" />, the input to ANY is caped with project which projects out only
        // the columns represented in the sortExpressionsOverLeft list and only these are used in the predicate.
        // This is because we want to support skip over input with non-equal comarable columns and we have no way to recognize these.
        // </summary>
        // <param name="sortExpressionsOverLeft"> note that this list gets destroyed by this method </param>
        private DbExpression TransformIntersectOrExcept(
            DbExpression left, DbExpression right, DbExpressionKind expressionKind, IList <DbPropertyExpression> sortExpressionsOverLeft,
            string sortExpressionsBindingVariableName)
        {
            var negate   = (expressionKind == DbExpressionKind.Except) || (expressionKind == DbExpressionKind.Skip);
            var distinct = (expressionKind == DbExpressionKind.Except) || (expressionKind == DbExpressionKind.Intersect);

            var leftInputBinding  = left.Bind();
            var rightInputBinding = right.Bind();

            IList <DbPropertyExpression> leftFlattenedProperties  = new List <DbPropertyExpression>();
            IList <DbPropertyExpression> rightFlattenedProperties = new List <DbPropertyExpression>();

            FlattenProperties(leftInputBinding.Variable, leftFlattenedProperties);
            FlattenProperties(rightInputBinding.Variable, rightFlattenedProperties);

            //For Skip, we need to ignore any columns that are not in the original sort list. We can recognize these by comparing the left flattened properties and
            // the properties in the list sortExpressionsOverLeft
            // If any such columns exist, we need to add an additional project, to keep the rest of the columns from being projected, as if any among these
            // are non equal comparable, SQL Server 2000 throws.
            if (expressionKind == DbExpressionKind.Skip)
            {
                if (RemoveNonSortProperties(
                        leftFlattenedProperties, rightFlattenedProperties, sortExpressionsOverLeft, leftInputBinding.VariableName,
                        sortExpressionsBindingVariableName))
                {
                    rightInputBinding = CapWithProject(rightInputBinding, rightFlattenedProperties);
                }
            }

            Debug.Assert(
                leftFlattenedProperties.Count == rightFlattenedProperties.Count,
                "The left and the right input to INTERSECT or EXCEPT have a different number of properties");
            Debug.Assert(leftFlattenedProperties.Count != 0, "The inputs to INTERSECT or EXCEPT have no properties");

            //Build the predicate for the quantifier:
            //   (B.b1 = A.a1 or (B.b1 is null and A.a1 is null))
            //      AND (B.b2 = A.a2 or (B.b2 is null and A.a2 is null))
            //      AND ...
            //      AND (B.bn = A.an or (B.bn is null and A.an is null)))
            DbExpression existsPredicate = null;

            for (var i = 0; i < leftFlattenedProperties.Count; i++)
            {
                //A.ai == B.bi
                DbExpression equalsExpression = leftFlattenedProperties[i].Equal(rightFlattenedProperties[i]);

                //A.ai is null AND B.bi is null
                DbExpression leftIsNullExpression  = leftFlattenedProperties[i].IsNull();
                DbExpression rightIsNullExpression = rightFlattenedProperties[i].IsNull();
                DbExpression bothNullExpression    = leftIsNullExpression.And(rightIsNullExpression);

                DbExpression orExpression = equalsExpression.Or(bothNullExpression);

                if (i == 0)
                {
                    existsPredicate = orExpression;
                }
                else
                {
                    existsPredicate = existsPredicate.And(orExpression);
                }
            }

            //Build the quantifier
            DbExpression quantifierExpression = rightInputBinding.Any(existsPredicate);

            DbExpression filterPredicate;

            //Negate if needed
            if (negate)
            {
                filterPredicate = quantifierExpression.Not();
            }
            else
            {
                filterPredicate = quantifierExpression;
            }

            //Build the filter
            DbExpression result = leftInputBinding.Filter(filterPredicate);

            //Apply distinct in needed
            if (distinct)
            {
                result = result.Distinct();
            }

            return(result);
        }
예제 #5
0
        public static DbCaseWhenExpression ConstructReturnCSharpBooleanCaseWhenExpression(DbExpression exp)
        {
            // case when 1>0 then 1 when not (1>0) then 0 else Null end
            DbCaseWhenExpression.WhenThenExpressionPair        whenThenPair  = new DbCaseWhenExpression.WhenThenExpressionPair(exp, DbConstantExpression.True);
            DbCaseWhenExpression.WhenThenExpressionPair        whenThenPair1 = new DbCaseWhenExpression.WhenThenExpressionPair(DbExpression.Not(exp), DbConstantExpression.False);
            List <DbCaseWhenExpression.WhenThenExpressionPair> whenThenExps  = new List <DbCaseWhenExpression.WhenThenExpressionPair>(2);

            whenThenExps.Add(whenThenPair);
            whenThenExps.Add(whenThenPair1);
            DbCaseWhenExpression caseWhenExpression = DbExpression.CaseWhen(whenThenExps, DbConstantExpression.Null, PublicConstants.TypeOfBoolean);

            return(caseWhenExpression);
        }