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); }
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); }