예제 #1
0
        private void FixTree(Expression expr)
        {
            //Debug.WriteLine("\n\nBefore FixTree:\n" + expr.ToXmlString());

            //V2: This logic does not handle axis nodes in functions correctly.
            //V2: Need to crate a RecomposeFunction to move axis out from inside a function (or just don't let this happen - make them use []'s instead)
            //V2: Be sure to check that all properties in a function are of the same type.
            //	  Mixing relations in a function would be bad (e.g., LEN(BillAddress.Zip + ShipAddress.Zip)

            //V2: Expression.EnumNodes(expr, new Expression.EnumNodesCallBack(this.RecomposeFunction), null, (Function)null);
            //V2: Debug.WriteLine("\n\nAfter RecomposeFunction:\n" + expr.ToXmlString());

            // note: using a post callback to handle binary node chains correctly (found this out the hard way)
            Expression.EnumNodes(expr, null, new Expression.EnumNodesCallBack(this.RecomposeBinary), null);
            //Debug.WriteLine("\n\nAfter RecomposeBinary:\n" + expr.ToXmlString());

            Expression.EnumNodes(expr, new Expression.EnumNodesCallBack(this.ReplaceAxisCallback));
            //Debug.WriteLine("\n\nAfter ReplaceAxisCallback:\n" + expr.ToXmlString());

            Expression.EnumNodes(expr, new Expression.EnumNodesCallBack(this.LinkPropertiesToMap), null, new object[0]);
            //Debug.WriteLine("\n\nAfter LinkPropertiesToMap:\n" + expr.ToXmlString());

            Expression.EnumNodes(expr, new Expression.EnumNodesCallBack(this.ReplaceAddWithConcatenation), null, new object[0]);
            //Debug.WriteLine("\n\nAfter ReplaceAddWithConcatenation:\n" + expr.ToXmlString());

            //Debug.WriteLine("\n\nAfter FixTree:\n" + expr.ToXmlString());
        }
예제 #2
0
 private bool OleDbSetParameterOrder(Expression node, object[] args)
 {
     if (node.NodeType == NodeType.Filter)
     {
         // the parameters in this filter are the next in sequence
         Filter filter = (Filter)node;
         Expression.EnumNodesCallBack callback = new Expression.EnumNodesCallBack(this.OleDbSetParameterOrderInFilter);
         Expression.EnumNodes(filter.Source, callback, null, args);
         Expression.EnumNodes(filter.Constraint, callback, null, args);
     }
     return(true);
 }
예제 #3
0
        private bool LinkPropertiesToMap(Expression node, object[] args)
        {
            if (node.NodeType == NodeType.Filter)
            {
                Filter filter = (Filter)node;
                Expression.EnumNodesCallBack callback = new Expression.EnumNodesCallBack(this.LinkPropertiesToMap);
                if (args.Length > 0)
                {
                    Expression.EnumNodes(filter.Source, callback, null, args);
                }

                // add the new filter to the font of the list
                object[] newArgs = new object[args.Length + 1];
                Array.Copy(args, 0, newArgs, 1, args.Length);
                newArgs[0] = filter;

                Expression.EnumNodes(filter.Constraint, callback, null, newArgs);
                return(false);
            }
            else if (node.NodeType == NodeType.Property)
            {
                Property property = (Property)node;

                // determine the level of the filter to link
                int level = 0;
                if (property.Source.NodeType == NodeType.Parent)
                {
                    level = (property.Source as Parent).Level;
                    // replace the parent source with a new context for linking
                    property.Source = new Context();
                }
                if (level >= args.Length)
                {
                    throw new OPathException("Property '" + property.Name + "' could not be associated to an entity.");
                }

                // set the context link to the source of the filter
                Context context = (Context)property.Source;
                context.Link = (args[level] as Filter).Source;

                // set the property info
                SetPropertyInfo(property);
            }
            return(true);
        }
예제 #4
0
        private void SetParameterOrder(ObjectExpression oe)
        {
            if (oe.ParameterCount == 0)
            {
                return;
            }

            if (_provider.Provider == Provider.Access || _provider.Provider == Provider.OleDb)
            {
                // the OleDb driver expects the order of parameters to be specified in "subquery major" order (which I consider a *major* design flaw).
                // in other words, the order is driven by a post traversal of the select statements (filters), with standard left-to-right order within a given select.
                Expression.EnumNodesCallBack postCallback = new Expression.EnumNodesCallBack(this.OleDbSetParameterOrder);
                Expression.EnumNodes(oe.Expression, null, postCallback, 0);
            }
            else             // not an OleDb provider
            {
                // use standard right-to-left order (which the parameters are already in)
                for (int i = _parameterTable.Count - 1; i >= 0; i--)
                {
                    _parameterTable[i].Ordinal = i;
                }
            }
        }
예제 #5
0
        public static void EnumNodes(Expression root, EnumNodesCallBack callback, EnumNodesCallBack postCallback, params object[] args)
        {
            switch (root.NodeType)
            {
            case NodeType.Literal:
            case NodeType.Parameter:
            case NodeType.Context:
            {
                if (callback != null)
                {
                    callback(root, args);
                }
                if (postCallback != null)
                {
                    postCallback(root, args);
                }
                return;
            }

            case NodeType.Binary:
            {
                if (callback == null || callback(root, args))
                {
                    Binary node = (Binary)root;
                    Expression.EnumNodes(node.Left, callback, postCallback, args);
                    Expression.EnumNodes(node.Right, callback, postCallback, args);

                    if (postCallback != null)
                    {
                        postCallback(root, args);
                    }
                }
                return;
            }

            case NodeType.Unary:
            {
                if (callback == null || callback(root, args))
                {
                    Unary node = (Unary)root;
                    Expression.EnumNodes(node.Operand, callback, postCallback, args);

                    if (postCallback != null)
                    {
                        postCallback(root, args);
                    }
                }
                return;
            }

            case NodeType.Axis:
            case NodeType.Filter:
            {
                if (callback == null || callback(root, args))
                {
                    Filter node = (Filter)root;
                    Expression.EnumNodes(node.Source, callback, postCallback, args);
                    Expression.EnumNodes(node.Constraint, callback, postCallback, args);

                    if (postCallback != null)
                    {
                        postCallback(root, args);
                    }
                }
                return;
            }

            case NodeType.Property:
            {
                if (callback == null || callback(root, args))
                {
                    Property node = (Property)root;
                    Expression.EnumNodes(node.Source, callback, postCallback, args);

                    if (postCallback != null)
                    {
                        postCallback(root, args);
                    }
                }
                return;
            }

            case NodeType.Parent:
            {
                if (callback == null || callback(root, args))
                {
                    Parent node = (Parent)root;
                    Expression.EnumNodes(node.Source, callback, postCallback, args);

                    if (postCallback != null)
                    {
                        postCallback(root, args);
                    }
                }
                return;
            }

            case NodeType.Function:
            {
                if (callback == null || callback(root, args))
                {
                    Function node = (Function)root;
                    for (int i = 0; i < node.Params.Length; i++)
                    {
                        Expression.EnumNodes(node.Params[i], callback, postCallback, args);
                    }

                    if (postCallback != null)
                    {
                        postCallback(root, args);
                    }
                }
                return;
            }

            case NodeType.TypeFilter:
            {
                if (callback == null || callback(root, args))
                {
                    TypeFilter node = (TypeFilter)root;
                    Expression.EnumNodes(node.Source, callback, postCallback, args);

                    if (postCallback != null)
                    {
                        postCallback(root, args);
                    }
                }
                return;
            }

            case NodeType.Empty:
            {
                return;
            }

            case NodeType.OrderBy:
            {
                if (callback == null || callback(root, args))
                {
                    OrderBy node = (OrderBy)root;
                    Expression.EnumNodes(node.Source, callback, postCallback, args);

                    if (postCallback != null)
                    {
                        postCallback(root, args);
                    }
                }
                return;
            }

            default:
            {
                throw new NotSupportedException("Expression type '" + root.GetType() + "' is not currently supported.");
            }
            }
        }
예제 #6
0
        public override void Validate()
        {
            // there is currently no way to support traversals within a function
            Expression.EnumNodes(this, new Expression.EnumNodesCallBack(this.ValidateNoFilters));

            // verify argument types based on function
            switch (_op)
            {
            case FunctionOperator.Trim:
            case FunctionOperator.Len:
            case FunctionOperator.UpperCase:
            case FunctionOperator.LowerCase:
            {
                if (_args.Length != 1)
                {
                    throw new OPathException("Invalid number of parameters passed to " + GetDisplayName(_op) + " function.");
                }
                if (_args[0].NodeType == NodeType.Parameter)
                {
                    (_args[0] as Parameter).inferredType = typeof(string);
                }
                if (_args[0].ValueType != typeof(string))
                {
                    throw new OPathException("Parameter of " + GetDisplayName(_op) + " function must be of type string.");
                }
                break;
            }

            case FunctionOperator.Left:
            case FunctionOperator.Right:
            {
                if (_args.Length != 2)
                {
                    throw new OPathException("Invalid number of parameters passed to " + GetDisplayName(_op) + " function.");
                }
                if (_args[0].NodeType == NodeType.Parameter)
                {
                    (_args[0] as Parameter).inferredType = typeof(string);
                }
                if (_args[1].NodeType == NodeType.Parameter)
                {
                    (_args[1] as Parameter).inferredType = typeof(long);
                }

                if (_args[0].ValueType != typeof(string))
                {
                    throw new OPathException("First parameter of " + GetDisplayName(_op) + " function must be of type string.");
                }
                if (!Binary.IsInteger(_args[1].ValueType))
                {
                    throw new OPathException("Second parameter of " + GetDisplayName(_op) + " function must be of integer type.");
                }
                break;
            }

            case FunctionOperator.Substring:
            {
                if (_args.Length != 3)
                {
                    throw new OPathException("Invalid number of parameters passed to " + GetDisplayName(_op) + " function.");
                }
                if (_args[0].NodeType == NodeType.Parameter)
                {
                    (_args[0] as Parameter).inferredType = typeof(string);
                }
                if (_args[1].NodeType == NodeType.Parameter)
                {
                    (_args[1] as Parameter).inferredType = typeof(long);
                }
                if (_args[2].NodeType == NodeType.Parameter)
                {
                    (_args[2] as Parameter).inferredType = typeof(long);
                }

                if (_args[0].ValueType != typeof(string))
                {
                    throw new OPathException("First parameter of " + GetDisplayName(_op) + " function must be of type string.");
                }
                if (!Binary.IsInteger(_args[1].ValueType))
                {
                    throw new OPathException("First parameter of " + GetDisplayName(_op) + " function must be of integer type.");
                }
                if (!Binary.IsInteger(_args[2].ValueType))
                {
                    throw new OPathException("Second parameter of " + GetDisplayName(_op) + " function must be of integer type.");
                }
                break;
            }

            case FunctionOperator.Like:
            {
                if (_args.Length != 2)
                {
                    throw new OPathException("Invalid number of parameters passed to " + GetDisplayName(_op) + " function.");
                }
                if (_args[0].NodeType == NodeType.Parameter)
                {
                    (_args[0] as Parameter).inferredType = typeof(string);
                }
                if (_args[1].NodeType == NodeType.Parameter)
                {
                    (_args[1] as Parameter).inferredType = typeof(string);
                }

                //NOTE: Until type casting is supported, let's just send the left operand to the database and let it try casting
                //if( _args[0].ValueType != typeof(string) )
                //{
                //	throw new OPathException("Left operand of " + GetDisplayName(_op) + " comparison must be of type string.");
                //}
                if (_args[1].ValueType != typeof(string))
                {
                    throw new OPathException("Right operand of " + GetDisplayName(_op) + " comparison must be of type string.");
                }
                break;
            }

            case FunctionOperator.In:
            {
                if (_args.Length < 2)
                {
                    throw new OPathException("Invalid number of parameters passed to " + GetDisplayName(_op) + " function.");
                }
                break;
            }

            default:
            {
                throw new NotSupportedException("Binary operator '" + _op + "' was not expected.");
            }
            }
        }
예제 #7
0
 private void Validate(Expression expr)
 {
     // validate every node in the tree
     Expression.EnumNodes(expr, new Expression.EnumNodesCallBack(this.ValidateNode));
 }
예제 #8
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);
        }