예제 #1
0
        private bool ReplaceAxisCallback(Expression node, object[] noargs)         // note: internal longhorn name found on www.winfx247.com
        {
            if (node.NodeType == NodeType.Axis)
            {
                Axis axis = (Axis)node;

                // convert the axis into a filter (don't want any axis nodes in final tree)
                Expression filter = new Filter(axis);

                // see if we need to wrap the filter with an exist node
                // note: this is needed when:
                //		1) the source property of the axis is relational
                //		2) the parent of the axis is not already an exists (for future support for the exists keyword)
                //		3) the axis is not in the source of its parent filter
                if (axis.Owner.NodeType != NodeType.Unary || ((Unary)axis.Owner).Operator != UnaryOperator.Exists)
                {
                    // get the source property for this axis
                    Property property;
                    if (axis.Source.NodeType == NodeType.Property)
                    {
                        property = (Property)axis.Source;
                    }
                    else if (axis.Source.NodeType == NodeType.Filter || axis.Source.NodeType == NodeType.Axis)
                    {
                        property = (Property)(axis.Source as Filter).Source;
                    }
                    else                     // source not property, filter, or axis
                    {
                        throw new Exception("Axis source node type of '" + axis.Source.NodeType + "' was not expected.");
                    }

                    if (property.IsRelational)
                    {
                        // find the containing filter for this axis (there has to be one) and track the child
                        Expression child  = axis;
                        Expression parent = axis.Owner;
                        while (parent != null && parent.NodeType != NodeType.Filter)
                        {
                            child  = parent;
                            parent = parent.Owner;
                        }
                        if (parent == null)
                        {
                            throw new Exception("Axis node is not contained in a Filter node.  Assumption failed.");
                        }

                        if (((Filter)parent).Source != child)                          // axis not in source of filter
                        {
                            filter = new Unary(UnaryOperator.Exists, filter);
                        }
                    }
                }

                // do the replacement
                Expression.Replace(axis, filter);
            }
            return(true);
        }
예제 #2
0
        private bool RecomposeBinary(Expression node, object[] noargs)         // note: internal longhorn name found on www.winfx247.com
        {
            if (node.NodeType == NodeType.Binary)
            {
                Binary binary = (Binary)node;

                bool leftIsAxis  = (binary.Left.NodeType == NodeType.Axis);
                bool rightIsAxis = (binary.Right.NodeType == NodeType.Axis);

                // nothing to do if neither branch contains an axis
                if (!leftIsAxis && !rightIsAxis)
                {
                    return(true);
                }

                // don't consider moving the binary node if neither branch is constant (and joined by a logical operator)
                // the binary node should stay above an axis in this case (example: (AAA.BBB = X) && (CCC = Y))
                if (!binary.Left.IsConst && !binary.Right.IsConst && Binary.IsOperatorLogical(binary.Operator))
                {
                    return(true);
                }

                // see if we have an axis on both sides
                if (leftIsAxis && rightIsAxis)
                {
                    throw new NotSupportedException("Relationship traversals on both sides of a binary operator is not currently supported.");
                    // recompose the left and right to put both under one axis
                    //V2: Recompose2Axis(binary);
                    //return true;
                }
                else                 // axis on one side only
                {
                    // get our root axis and find the last (leaf) axis in the chain
                    // the leaf axis will hold the parent binary when moved
                    // (this is to handle multiple dot expressions like: AAA.BBB.CCC = @Value)
                    Axis axis        = (leftIsAxis) ? (Axis)binary.Left : (Axis)binary.Right;
                    Axis leafAxis    = axis;
                    int  parentCount = 1;
                    while (leafAxis.Constraint.NodeType == NodeType.Axis)
                    {
                        leafAxis     = (Axis)leafAxis.Constraint;
                        parentCount += 1;
                    }

                    // now make the binary node the constraint of the the leaf axis
                    //   and move the existing constraint under the other branch of the binary
                    if (leftIsAxis)
                    {
                        Expression newRight = (Expression)binary.Right.Clone();
                        Expression.EnumNodes(newRight, new Expression.EnumNodesCallBack(this.IncreaseParentDepth), null, parentCount);
                        leafAxis.Constraint = new Binary(binary.Operator, leafAxis.Constraint, newRight);
                    }
                    else                     // right is axis
                    {
                        Expression newLeft = (Expression)binary.Left.Clone();
                        Expression.EnumNodes(newLeft, new Expression.EnumNodesCallBack(this.IncreaseParentDepth), null, parentCount);
                        leafAxis.Constraint = new Binary(binary.Operator, newLeft, leafAxis.Constraint);
                    }

                    Expression.Replace(binary, axis);
                }
            }

            return(true);
        }