Exemplo n.º 1
0
        /// <summary>
        /// Override this method if you want to visit each query node.
        /// </summary>
        /// <remarks>
        /// This method is intended to be called from method overrides in subclasses. This method also supports unit-testing scenarios and is not intended to be called from user code.
        /// Call the Validate method to validate a <see cref="FilterQueryOption"/> instance.
        /// </remarks>
        /// <param name="node"></param>
        /// <param name="settings"></param>
        public virtual void ValidateQueryNode(QueryNode node, ODataValidationSettings settings)
        {
            // Recursion guard to avoid stack overflows
            RuntimeHelpers.EnsureSufficientExecutionStack();

            SingleValueNode singleNode     = node as SingleValueNode;
            CollectionNode  collectionNode = node as CollectionNode;

            IncrementNodeCount(settings);

            if (singleNode != null)
            {
                ValidateSingleValueNode(singleNode, settings);
            }
            else if (collectionNode != null)
            {
                ValidateCollectionNode(collectionNode, settings);
            }
        }
Exemplo n.º 2
0
        private static Stack <SingleValueNode> ReversePropertyPath(SingleValueNode node)
        {
            var result = new Stack <SingleValueNode>();

            do
            {
                result.Push(node);
                if (node.Kind == QueryNodeKind.SingleValuePropertyAccess)
                {
                    node = ((SingleValuePropertyAccessNode)node).Source;
                }
                else if (node.Kind == QueryNodeKind.SingleNavigationNode)
                {
                    node = ((SingleNavigationNode)node).NavigationSource as SingleValueNode;
                }
            }while (node != null && IsPropertyNode(node));

            return(result);
        }
Exemplo n.º 3
0
 private static string GetNodePropertyName(SingleValueNode property)
 {
     if (property.Kind == QueryNodeKind.SingleValuePropertyAccess)
     {
         return(((SingleValuePropertyAccessNode)property).Property.Name);
     }
     else if (property.Kind == QueryNodeKind.SingleComplexNode)
     {
         return(((SingleComplexNode)property).Property.Name);
     }
     else if (property.Kind == QueryNodeKind.SingleNavigationNode)
     {
         return(((SingleNavigationNode)property).NavigationProperty.Name);
     }
     else
     {
         throw new NotSupportedException();
     }
 }
Exemplo n.º 4
0
        /// <summary>
        /// Parse expression into syntaxs token tree, and bind it into semantics node tree.
        /// </summary>
        /// <param name="bindingState">The BindingState.</param>
        /// <param name="aliasValueExpression">The alias value's expression text.</param>
        /// <returns>The semantcs node of the expression text.</returns>
        private SingleValueNode ParseAndBindParameterAliasValueExpression(BindingState bindingState, string aliasValueExpression)
        {
            // Get the syntactic representation of the filter expression
            // TODO: change Settings.FilterLimit to ParameterAliasValueLimit
            UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(bindingState.Configuration.Settings.FilterLimit);
            QueryToken aliasValueToken = expressionParser.ParseExpressionText(aliasValueExpression);

            // Get the semantic node, and check for SingleValueNode
            QueryNode       aliasValueNode = this.bindMethod(aliasValueToken);
            SingleValueNode result         = aliasValueNode as SingleValueNode;

            if (result == null)
            {
                // TODO: add string resource
                throw new ODataException("ODataErrorStrings.MetadataBinder_ParameterAliasValueExpressionNotSingleValue");
            }

            return(result);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Retrieves the type reference associated to a segment.
        /// </summary>
        /// <param name="segment">The node to retrive the type reference from.</param>
        /// <returns>The Type reference of the node (item type reference for collections).</returns>
        internal static IEdmTypeReference GetEdmTypeReference(this QueryNode segment)
        {
            DebugUtils.CheckNoExternalCallers();
            SingleValueNode singleNode = segment as SingleValueNode;

            if (singleNode != null)
            {
                return(singleNode.TypeReference);
            }

            CollectionNode collectionNode = segment as CollectionNode;

            if (collectionNode != null)
            {
                return(collectionNode.ItemType);
            }

            return(null);
        }
Exemplo n.º 6
0
        private string BuildWhereClause(SingleValueNode node)
        {
            string result = string.Empty;

            var operatorNode = node as BinaryOperatorNode;

            if (operatorNode == null)
            {
                if (node is SingleValueFunctionCallNode operatorNode2 &&
                    operatorNode2.Parameters.ToList()[0] is SingleValuePropertyAccessNode prop &&
                    operatorNode2.Parameters.ToList()[1] is ConstantNode val)
                {
                    return($"{prop.Property.Name} LIKE '%{val.LiteralText.Trim(new char[] { (char)39 })}%' ");
                }
                else
                {
                    return(result);
                }
            }
Exemplo n.º 7
0
        /// <summary>
        /// Retrieves <see cref="EdmClrProperty" /> from the given <see cref="SingleValueNode" />.
        /// </summary>
        /// <param name="node">The node to get the property from.</param>
        protected EdmClrProperty GetProperty(SingleValueNode node)
        {
            if (!(node is SingleValuePropertyAccessNode propertyAccessNode))
            {
                throw new ODataException($"The '{node.GetType().Name}' node is not supported.");
            }

            if (!(propertyAccessNode.Property is EdmClrProperty property))
            {
                throw new ODataException($"The '{propertyAccessNode.Property.GetType().Name}' property is not supported.");
            }

            if (!(propertyAccessNode.Source is ResourceRangeVariableReferenceNode))
            {
                throw new ODataException($"Nested properties are not supported.");
            }

            return(property);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Bind the expression of the LambdaToken
        /// </summary>
        /// <param name="queryToken">the expression token</param>
        /// <returns>the bound expression node</returns>
        private SingleValueNode BindExpressionToken(QueryToken queryToken)
        {
            SingleValueNode expression = this.bindMethod(queryToken) as SingleValueNode;

            if (expression == null)
            {
                throw new ODataException(ODataErrorStrings.MetadataBinder_AnyAllExpressionNotSingleValue);
            }

            // type reference is allowed to be null for open properties.
            IEdmTypeReference expressionTypeReference = expression.GetEdmTypeReference();

            if (expressionTypeReference != null && !expressionTypeReference.AsPrimitive().IsBoolean())
            {
                throw new ODataException(ODataErrorStrings.MetadataBinder_AnyAllExpressionNotSingleValue);
            }

            return(expression);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Binds a an end path token into a PropertyAccessToken, OpenPropertyToken, or FunctionCallToken.
        /// </summary>
        /// <param name="endPathToken">The property access token to bind.</param>
        /// <returns>A Query node representing this endpath token, bound to metadata.</returns>
        internal QueryNode BindEndPath(EndPathToken endPathToken)
        {
            ExceptionUtils.CheckArgumentNotNull(endPathToken, "EndPathToken");
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(endPathToken.Identifier, "EndPathToken.Identifier");

            // Set the parent (get the parent type, so you can check whether the Identifier inside EndPathToken really is legit offshoot of the parent type)
            QueryNode parent = this.DetermineParentNode(endPathToken);

            QueryNode boundFunction;

            SingleValueNode singleValueParent = parent as SingleValueNode;

            if (singleValueParent == null)
            {
                if (functionCallBinder.TryBindEndPathAsFunctionCall(endPathToken, parent, state, out boundFunction))
                {
                    return(boundFunction);
                }

                throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyAccessSourceNotSingleValue(endPathToken.Identifier));
            }


            // Now that we have the parent type, can find its corresponding EDM type
            IEdmStructuredTypeReference structuredParentType =
                singleValueParent.TypeReference == null ? null : singleValueParent.TypeReference.AsStructuredOrNull();

            IEdmProperty property =
                structuredParentType == null ? null : this.Resolver.ResolveProperty(structuredParentType.StructuredDefinition(), endPathToken.Identifier);

            if (property != null)
            {
                return(GeneratePropertyAccessQueryNode(singleValueParent, property));
            }

            if (functionCallBinder.TryBindEndPathAsFunctionCall(endPathToken, singleValueParent, state, out boundFunction))
            {
                return(boundFunction);
            }

            return(GeneratePropertyAccessQueryForOpenType(endPathToken, singleValueParent));
        }
Exemplo n.º 10
0
        private Expression BindAccessor(SingleValueNode node)
        {
            switch (node.Kind)
            {
            case QueryNodeKind.ResourceRangeVariableReference:
                return(this._lambdaParameter.Type.IsGenericType && this._lambdaParameter.Type.GetGenericTypeDefinition() == typeof(FlatteningWrapper <>)
                        ? (Expression)Expression.Property(this._lambdaParameter, "Source")
                        : this._lambdaParameter);

            case QueryNodeKind.SingleValuePropertyAccess:
                var propAccessNode = node as SingleValuePropertyAccessNode;
                return(CreatePropertyAccessExpression(BindAccessor(propAccessNode.Source), propAccessNode.Property, GetFullPropertyPath(propAccessNode)));

            case QueryNodeKind.SingleComplexNode:
                var singleComplexNode = node as SingleComplexNode;
                return(CreatePropertyAccessExpression(BindAccessor(singleComplexNode.Source), singleComplexNode.Property, GetFullPropertyPath(singleComplexNode)));

            case QueryNodeKind.SingleValueOpenPropertyAccess:
                var openNode = node as SingleValueOpenPropertyAccessNode;
                return(GetFlattenedPropertyExpression(openNode.Name) ?? Expression.Property(BindAccessor(openNode.Source), openNode.Name));

            case QueryNodeKind.None:
            case QueryNodeKind.SingleNavigationNode:
                var navNode = node as SingleNavigationNode;
                return(CreatePropertyAccessExpression(BindAccessor(navNode.Source), navNode.NavigationProperty));

            case QueryNodeKind.BinaryOperator:
                var binaryNode      = node as BinaryOperatorNode;
                var leftExpression  = BindAccessor(binaryNode.Left);
                var rightExpression = BindAccessor(binaryNode.Right);
                return(CreateBinaryExpression(binaryNode.OperatorKind, leftExpression, rightExpression,
                                              liftToNull: true));

            case QueryNodeKind.Convert:
                var convertNode = node as ConvertNode;
                return(CreateConvertExpression(convertNode, BindAccessor(convertNode.Source)));

            default:
                throw Error.NotSupported(SRResources.QueryNodeBindingNotSupported, node.Kind,
                                         typeof(AggregationBinder).Name);
            }
        }
Exemplo n.º 11
0
        private static Query ProcessBinaryOperatorNode(Query query, BinaryOperatorNode binaryOperatorNode)
        {
            switch (binaryOperatorNode.OperatorKind)
            {
            case BinaryOperatorKind.Equal:
            case BinaryOperatorKind.NotEqual:
            case BinaryOperatorKind.GreaterThan:
            case BinaryOperatorKind.GreaterThanOrEqual:
            case BinaryOperatorKind.LessThan:
            case BinaryOperatorKind.LessThanOrEqual:

                SingleValueNode singleValueNodeLeft  = binaryOperatorNode.Left;
                SingleValueNode singleValueNodeRight = binaryOperatorNode.Right;

                if (singleValueNodeLeft.Kind == QueryNodeKind.Constant &&
                    singleValueNodeRight.Kind == QueryNodeKind.SingleValuePropertyAccess)
                {
                    SingleValuePropertyAccessNode singleValuePropertyAccessNode = (SingleValuePropertyAccessNode)singleValueNodeRight;
                    ConstantNode constantNode = (ConstantNode)singleValueNodeLeft;

                    return(query.Where(singleValuePropertyAccessNode.Property.Name,
                                       _binaryOperatorKindToSymbolDictionary[binaryOperatorNode.OperatorKind],
                                       constantNode.Value));
                }
                else if (singleValueNodeLeft.Kind == QueryNodeKind.SingleValuePropertyAccess &&
                         singleValueNodeRight.Kind == QueryNodeKind.Constant)
                {
                    SingleValuePropertyAccessNode singleValuePropertyAccessNode = (SingleValuePropertyAccessNode)singleValueNodeLeft;
                    ConstantNode constantNode = (ConstantNode)singleValueNodeRight;

                    return(query.Where(singleValuePropertyAccessNode.Property.Name,
                                       _binaryOperatorKindToSymbolDictionary[binaryOperatorNode.OperatorKind],
                                       constantNode.Value));
                }
                else
                {
                    throw new NotImplementedException();
                }
            }

            return(query);
        }
        static string Bind(QueryNode node)
        {
            CollectionNode  collectionNode  = node as CollectionNode;
            SingleValueNode singleValueNode = node as SingleValueNode;

            if (singleValueNode != null)
            {
                switch (singleValueNode.Kind)
                {
                //case QueryNodeKind.:
                //    return BindRangeVariable((node as EntityRangeVariableReferenceNode).RangeVariable);
                case QueryNodeKind.SingleValuePropertyAccess:
                    return(BindPropertyAccessQueryNode(node as SingleValuePropertyAccessNode));

                default:
                    return(string.Empty);
                }
            }
            return(string.Empty);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Checks that all arguments are SingleValueNodes
        /// </summary>
        /// <param name="functionName">The name of the function the arguments are from.</param>
        /// <param name="argumentNodes">The arguments to validate.</param>
        /// <returns>SingleValueNode array</returns>
        internal static SingleValueNode[] ValidateArgumentsAreSingleValue(string functionName, List <QueryNode> argumentNodes)
        {
            ExceptionUtils.CheckArgumentNotNull(functionName, "functionCallToken");
            ExceptionUtils.CheckArgumentNotNull(argumentNodes, "argumentNodes");

            // Right now all functions take a single value for all arguments
            SingleValueNode[] ret = new SingleValueNode[argumentNodes.Count];
            for (int i = 0; i < argumentNodes.Count; i++)
            {
                SingleValueNode argumentNode = argumentNodes[i] as SingleValueNode;
                if (argumentNode == null)
                {
                    throw new ODataException(ODataErrorStrings.MetadataBinder_FunctionArgumentNotSingleValue(functionName));
                }

                ret[i] = argumentNode;
            }

            return(ret);
        }
Exemplo n.º 14
0
        /// <summary>
        /// Retrieves type associated to a segment.
        /// </summary>
        /// <param name="segment">The node to retrive the type from.</param>
        /// <returns>The type of the node, or item type for collections.</returns>
        internal static IEdmType GetEdmType(this QueryNode segment)
        {
            SingleValueNode singleNode = segment as SingleValueNode;

            if (singleNode != null)
            {
                IEdmTypeReference typeRef = singleNode.TypeReference;
                return((typeRef != null) ? typeRef.Definition : null);
            }

            CollectionNode collectionNode = segment as CollectionNode;

            if (collectionNode != null)
            {
                IEdmTypeReference typeRef = collectionNode.ItemType;
                return((typeRef != null) ? typeRef.Definition : null);
            }

            return(null);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Append OData filtering to the FilterExpression.
        /// </summary>
        /// <param name="criteria">Filter container for the QueryExpression.</param>
        /// <param name="expression">An expression containing OData filtering details.</param>
        private void UpdateCriteriaFromExpression(FilterExpression criteria, SingleValueNode expression)
        {
            switch (expression.Kind)
            {
            case QueryNodeKind.BinaryOperator:
                UpdateCriteriaFromBinaryExpression(criteria, (BinaryOperatorNode)expression);
                break;

            case QueryNodeKind.Convert:
                UpdateCriteriaFromExpression(criteria, ((ConvertNode)expression).Source);
                break;

            case QueryNodeKind.SingleValueFunctionCall:
                UpdateCriteriaFromSingleValueFunctionCall(criteria, (SingleValueFunctionCallNode)expression);
                break;

            default:
                throw new NotImplementedException(String.Format("Unsupported expression kind: \'{0}\'.", expression.Kind));
            }
        }
Exemplo n.º 16
0
        private void ValidateSingleValueNode(SingleValueNode node, ValidationSettings settings)
        {
            switch (node.Kind)
            {
            case QueryNodeKind.Convert:
                ValidateQueryNode((node as ConvertNode).Source, settings);
                break;

            case QueryNodeKind.BinaryOperator:
                ValidateBinaryOperatorNode(node as BinaryOperatorNode, settings);
                break;

            case QueryNodeKind.UnaryOperator:
                ValidateUnaryOperatorNode(node as UnaryOperatorNode, settings);
                break;

            case QueryNodeKind.SingleValuePropertyAccess:
                ValidateQueryNode((node as SingleValuePropertyAccessNode).Source, settings);
                break;

            case QueryNodeKind.SingleValueFunctionCall:
                ValidateSingleValueFunctionCallNode(node as SingleValueFunctionCallNode, settings);
                break;

            case QueryNodeKind.Any:
                ValidateAnyNode(node as AnyNode, settings);
                break;

            case QueryNodeKind.SingleResourceCast:
                ValidateQueryNode((node as SingleResourceCastNode).Source, settings);
                break;

            case QueryNodeKind.All:
                ValidateAllNode(node as AllNode, settings);
                break;

            case QueryNodeKind.SingleResourceFunctionCall:
                ValidateSingleResourceFunctionCallNode(node as SingleResourceFunctionCallNode, settings);
                break;
            }
        }
Exemplo n.º 17
0
        /// <summary>
        /// Checks that all arguments are SingleValueNodes
        /// </summary>
        /// <param name="functionName">The name of the function the arguments are from.</param>
        /// <param name="argumentNodes">The arguments to validate.</param>
        /// <returns>Returns the types of the arguments provided.</returns>
        internal static IEdmTypeReference[] EnsureArgumentsAreSingleValue(string functionName, List <QueryNode> argumentNodes)
        {
            DebugUtils.CheckNoExternalCallers();
            ExceptionUtils.CheckArgumentNotNull(functionName, "functionCallToken");
            ExceptionUtils.CheckArgumentNotNull(argumentNodes, "argumentNodes");

            // Right now all functions take a single value for all arguments
            IEdmTypeReference[] argumentTypes = new IEdmTypeReference[argumentNodes.Count];
            for (int i = 0; i < argumentNodes.Count; i++)
            {
                SingleValueNode argumentNode = argumentNodes[i] as SingleValueNode;
                if (argumentNode == null)
                {
                    throw new ODataException(ODataErrorStrings.MetadataBinder_FunctionArgumentNotSingleValue(functionName));
                }

                argumentTypes[i] = argumentNode.TypeReference;
            }

            return(argumentTypes);
        }
Exemplo n.º 18
0
        public static BinaryOperatorNode CreateFilterExpression(SingleValueNode singleValueNode, IEnumerable <KeyValuePair <IEdmStructuralProperty, Object?> > keys)
        {
            BinaryOperatorNode?compositeNode = null;

            foreach (KeyValuePair <IEdmStructuralProperty, Object?> keyValue in keys)
            {
                var left  = new SingleValuePropertyAccessNode(singleValueNode, keyValue.Key);
                var right = new ConstantNode(keyValue.Value, ODataUriUtils.ConvertToUriLiteral(keyValue.Value, ODataVersion.V4));
                var node  = new BinaryOperatorNode(BinaryOperatorKind.Equal, left, right);

                if (compositeNode == null)
                {
                    compositeNode = node;
                }
                else
                {
                    compositeNode = new BinaryOperatorNode(BinaryOperatorKind.And, compositeNode, node);
                }
            }
            return(compositeNode ?? throw new InvalidOperationException("Parameter keys is empty collection"));
        }
Exemplo n.º 19
0
        public override void PromoteBinaryOperandTypes(
            BinaryOperatorKind binaryOperatorKind,
            ref SingleValueNode leftNode,
            ref SingleValueNode rightNode,
            out IEdmTypeReference typeReference)
        {
            if (binaryOperatorKind == BinaryOperatorKind.Multiply &&
                leftNode.TypeReference != null &&
                leftNode.TypeReference.IsString() &&
                rightNode.TypeReference != null &&
                rightNode.TypeReference.IsInt32())
            {
                // The result type should be Edm.String, as it could be nullable or not, we just took the left
                // node's type reference.
                typeReference = leftNode.TypeReference;
                return;
            }

            // fallback
            base.PromoteBinaryOperandTypes(binaryOperatorKind, ref leftNode, ref rightNode, out typeReference);
        }
Exemplo n.º 20
0
        internal static BinaryOperatorNode CreateFilterExpression(SingleValueNode singleValueNode, IEnumerable <KeyValuePair <IEdmStructuralProperty, Object> > keys)
        {
            BinaryOperatorNode compositeNode = null;

            foreach (KeyValuePair <IEdmStructuralProperty, Object> keyValue in keys)
            {
                var left  = new SingleValuePropertyAccessNode(singleValueNode, keyValue.Key);
                var right = new ConstantNode(keyValue.Value, ODataUriUtils.ConvertToUriLiteral(keyValue.Value, ODataVersion.V4));
                var node  = new BinaryOperatorNode(BinaryOperatorKind.Equal, left, right);

                if (compositeNode == null)
                {
                    compositeNode = node;
                }
                else
                {
                    compositeNode = new BinaryOperatorNode(BinaryOperatorKind.And, compositeNode, node);
                }
            }
            return(compositeNode);
        }
Exemplo n.º 21
0
        /// <summary>
        /// Binds a <see cref="QueryNode"/> to create a LINQ <see cref="Expression"/> that represents the semantics
        /// of the <see cref="QueryNode"/>.
        /// </summary>
        /// <param name="node">The node to bind.</param>
        /// <returns>The LINQ <see cref="Expression"/> created.</returns>
        public override Expression Bind(QueryNode node)
        {
            // Recursion guard to avoid stack overflows
            RuntimeHelpers.EnsureSufficientExecutionStack();

            CollectionNode  collectionNode  = node as CollectionNode;
            SingleValueNode singleValueNode = node as SingleValueNode;

            if (collectionNode != null)
            {
                return(BindCollectionNode(collectionNode));
            }
            else if (singleValueNode != null)
            {
                return(BindSingleValueNode(singleValueNode));
            }
            else
            {
                throw Error.NotSupported(SRResources.QueryNodeBindingNotSupported, node.Kind, typeof(FilterBinder).Name);
            }
        }
Exemplo n.º 22
0
        internal Expression GetTuplePropertyByAliasName(Expression source, SingleValueNode singleValueNode)
        {
            String aliasName  = GetAliasName(singleValueNode);
            int    groupCount = 0;

            for (int i = 0; i < _aggProperties.Count; i++)
            {
                if (_aggProperties[i].IsGroup)
                {
                    groupCount++;
                }
                if (String.CompareOrdinal(_aggProperties[i].Name, aliasName) == 0)
                {
                    PropertyInfo propertyInfo;
                    int          itemIndex;
                    if (_aggProperties[i].IsGroup)
                    {
                        propertyInfo = source.Type.GetProperty("Item1") !;
                        source       = Expression.Property(source, propertyInfo);
                        itemIndex    = groupCount;

                        for (; itemIndex > 7; itemIndex -= 7)
                        {
                            propertyInfo = source.Type.GetProperty("Rest") !;
                            source       = Expression.Property(source, propertyInfo);
                        }
                    }
                    else
                    {
                        itemIndex = i - groupCount + 2;
                    }

                    String propertyName = "Item" + itemIndex.ToString(CultureInfo.InvariantCulture);
                    propertyInfo = source.Type.GetProperty(propertyName) !;
                    return(Expression.Property(source, propertyInfo));
                }
            }

            throw new InvalidOperationException("Property " + aliasName + " not found in " + source.Type.FullName);
        }
Exemplo n.º 23
0
        public static void TryNodeValue(SingleValueNode node, IDictionary <string, object> values)
        {
            if (node is BinaryOperatorNode)
            {
                var bon   = (BinaryOperatorNode)node;
                var left  = bon.Left;
                var right = bon.Right;

                if (left is ConvertNode)
                {
                    TryNodeValue(((ConvertNode)left).Source, values);
                }

                if (left is BinaryOperatorNode)
                {
                    TryNodeValue(left, values);
                }

                if (right is ConvertNode)
                {
                    TryNodeValue(((ConvertNode)right).Source, values);
                }

                if (right is BinaryOperatorNode)
                {
                    TryNodeValue(right, values);
                }

                if (left is SingleValuePropertyAccessNode && right is ConstantNode)
                {
                    var p = (SingleValuePropertyAccessNode)left;

                    if (bon.OperatorKind == BinaryOperatorKind.Equal)
                    {
                        var value = ((ConstantNode)right).Value;
                        values.Add(p.Property.Name, value);
                    }
                }
            }
        }
Exemplo n.º 24
0
        internal static SingleValueNode TranslateParameterAlias(
            SingleValueNode node,
            IDictionary <string, SingleValueNode> parameterAliasNodes)
        {
            if (node == null)
            {
                throw Error.ArgumentNull("node");
            }

            if (parameterAliasNodes == null)
            {
                throw Error.ArgumentNull("parameterAliasNodes");
            }

            ParameterAliasNode parameterAliasNode = node as ParameterAliasNode;

            if (parameterAliasNode == null)
            {
                return(node);
            }

            SingleValueNode singleValueNode;

            if (parameterAliasNodes.TryGetValue(parameterAliasNode.Alias, out singleValueNode) &&
                singleValueNode != null)
            {
                if (singleValueNode is ParameterAliasNode)
                {
                    singleValueNode = TranslateParameterAlias(singleValueNode, parameterAliasNodes);
                }

                return(singleValueNode);
            }

            // Parameter alias value is assumed to be null if it is not found.
            // Do not need to translate the parameter alias node from the query string
            // because this method only deals with the parameter alias node mapping from ODL parser.
            return(null);
        }
        /// <summary>
        /// Apply $filter parameter to query.
        /// </summary>
        /// <param name="query">
        /// The OData aware query.
        /// </param>
        /// <param name="filterText">
        /// The $filter parameter text.
        /// </param>
        /// <param name="entitySetName">
        /// The entity set name.
        /// </param>
        /// <typeparam name="T">
        /// The query type param
        /// </typeparam>
        /// <returns>
        /// The <see cref="ODataQuery{T}"/> query with applied filter parameter.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// Argument Null Exception
        /// </exception>
        public static ODataQuery <T> Filter <T>(this ODataQuery <T> query, string filterText, string entitySetName = null)
        {
            if (query == null)
            {
                throw new ArgumentNullException(nameof(query));
            }
            if (filterText == null)
            {
                throw new ArgumentNullException(nameof(filterText));
            }

            IEdmModel edmModel = query.EdmModel;

            ODataQueryOptionParser queryOptionParser = GetParser(
                query,
                entitySetName,
                new Dictionary <string, string> {
                { "$filter", filterText }
            });

            ODataSettings settings = query.ServiceProvider.GetRequiredService <ODataSettings>();

            FilterClause    filterClause     = queryOptionParser.ParseFilter();
            SingleValueNode filterExpression = filterClause.Expression.Accept(
                new ParameterAliasNodeTranslator(queryOptionParser.ParameterAliasNodes)) as SingleValueNode;

            filterExpression = filterExpression ?? new ConstantNode(null);
            filterClause     = new FilterClause(filterExpression, filterClause.RangeVariable);
            Contract.Assert(filterClause != null);

            var validator = new FilterQueryValidator(settings.DefaultQuerySettings);

            validator.Validate(filterClause, settings.ValidationSettings, edmModel);

            Expression filter = FilterBinder.Bind(query, filterClause, typeof(T), query.ServiceProvider);
            var        result = ExpressionHelpers.Where(query, filter, typeof(T));

            return(new ODataQuery <T>(result, query.ServiceProvider));
        }
Exemplo n.º 26
0
        /// <summary>
        /// Promote the left and right operand types, supports enum property and string constant scenario.
        /// </summary>
        /// <param name="binaryOperatorKind">the operator kind</param>
        /// <param name="leftNode">the left operand</param>
        /// <param name="rightNode">the right operand</param>
        /// <param name="typeReference">type reference for the result BinaryOperatorNode.</param>
        public override void PromoteBinaryOperandTypes(
            BinaryOperatorKind binaryOperatorKind,
            ref SingleValueNode leftNode,
            ref SingleValueNode rightNode,
            out IEdmTypeReference typeReference)
        {
            typeReference = null;

            if (leftNode.TypeReference != null && rightNode.TypeReference != null)
            {
                if ((leftNode.TypeReference.IsEnum()) && (rightNode.TypeReference.IsString()) && rightNode is ConstantNode)
                {
                    string            text = ((ConstantNode)rightNode).Value as string;
                    ODataEnumValue    val;
                    IEdmTypeReference typeRef = leftNode.TypeReference;

                    if (TryParseEnum(typeRef.Definition as IEdmEnumType, text, out val))
                    {
                        rightNode = new ConstantNode(val, text, typeRef);
                        return;
                    }
                }
                else if ((rightNode.TypeReference.IsEnum()) && (leftNode.TypeReference.IsString()) && leftNode is ConstantNode)
                {
                    string            text = ((ConstantNode)leftNode).Value as string;
                    ODataEnumValue    val;
                    IEdmTypeReference typeRef = rightNode.TypeReference;
                    if (TryParseEnum(typeRef.Definition as IEdmEnumType, text, out val))
                    {
                        leftNode = new ConstantNode(val, text, typeRef);
                        return;
                    }
                }
            }

            // fallback
            base.PromoteBinaryOperandTypes(binaryOperatorKind, ref leftNode, ref rightNode, out typeReference);
        }
Exemplo n.º 27
0
        private static Expression GetOrderByCall(this Expression expression, OrderByClause orderByClause)
        {
            const string OrderBy           = "OrderBy";
            const string OrderByDescending = "OrderByDescending";

            return(orderByClause.ThenBy == null
                ? GetMethodCall()
                : GetMethodCall().GetThenByCall(orderByClause.ThenBy));

            Expression GetMethodCall()
            {
                SingleValueNode orderByNode = orderByClause.Expression;

                switch (orderByNode)
                {
                case CountNode countNode:
                    return(expression.GetOrderByCountCall
                           (
                               countNode.GetPropertyPath(),
                               orderByClause.Direction == OrderByDirection.Ascending
                                ? OrderBy
                                : OrderByDescending,
                               orderByClause.RangeVariable.Name
                           ));

                default:
                    SingleValuePropertyAccessNode propertyNode = (SingleValuePropertyAccessNode)orderByNode;
                    return(expression.GetOrderByCall
                           (
                               propertyNode.GetPropertyPath(),
                               orderByClause.Direction == OrderByDirection.Ascending
                                ? OrderBy
                                : OrderByDescending,
                               orderByClause.RangeVariable.Name
                           ));
                }
            }
        }
Exemplo n.º 28
0
        internal static string RestorePropertyPath(SingleValueNode expression)
        {
            if (expression == null)
            {
                return(String.Empty);
            }

            string          propertyName = String.Empty;
            SingleValueNode source       = null;

            var accessNode = expression as SingleValuePropertyAccessNode;

            if (accessNode != null)
            {
                propertyName = accessNode.Property.Name;
                source       = accessNode.Source;
            }
            else
            {
                var complexNode = expression as SingleComplexNode;
                if (complexNode != null)
                {
                    propertyName = complexNode.Property.Name;
                    source       = complexNode.Source;
                }
            }

            var parentPath = RestorePropertyPath(source);

            if (String.IsNullOrEmpty(parentPath))
            {
                return(propertyName);
            }
            else
            {
                return(String.Format(CultureInfo.CurrentCulture, "{0}/{1}", parentPath, propertyName));
            }
        }
Exemplo n.º 29
0
        private bool IsLeafNode(SingleValueNode node)
        {
            BinaryOperatorNode expression;

            if (node.Kind == QueryNodeKind.Convert)
            {
                var convertNode = node as ConvertNode;
                expression = (convertNode.Source as BinaryOperatorNode);
            }
            else if (node.Kind == QueryNodeKind.BinaryOperator)
            {
                expression = node as BinaryOperatorNode;
            }
            else
            {
                return(false);
            }

            var leftNode  = expression.Left;
            var rightNode = expression.Right;

            return(leftNode is SingleValuePropertyAccessNode && rightNode is ConstantNode);
        }
        internal string GetFullPropertyPath(SingleValueNode node)
        {
            string          path   = null;
            SingleValueNode parent = null;

            switch (node.Kind)
            {
            case QueryNodeKind.SingleComplexNode:
                var complexNode = (SingleComplexNode)node;
                path   = complexNode.Property.Name;
                parent = complexNode.Source;
                break;

            case QueryNodeKind.SingleValuePropertyAccess:
                var propertyNode = ((SingleValuePropertyAccessNode)node);
                path   = propertyNode.Property.Name;
                parent = propertyNode.Source;
                break;

            case QueryNodeKind.SingleNavigationNode:
                var navNode = ((SingleNavigationNode)node);
                path   = navNode.NavigationProperty.Name;
                parent = navNode.Source;
                break;
            }

            if (parent != null)
            {
                var parentPath = GetFullPropertyPath(parent);
                if (parentPath != null)
                {
                    path = parentPath + "\\" + path;
                }
            }

            return(path);
        }
Exemplo n.º 31
0
        /// <summary>
        /// The recursive method that validate most of the query node type is of SingleValueNode type.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="settings"></param>
        private void ValidateSingleValueNode(SingleValueNode node, ODataValidationSettings settings)
        {
            switch (node.Kind)
            {
                case QueryNodeKind.BinaryOperator:
                    ValidateBinaryOperatorNode(node as BinaryOperatorNode, settings);
                    break;

                case QueryNodeKind.Constant:
                    ValidateConstantNode(node as ConstantNode, settings);
                    break;

                case QueryNodeKind.Convert:
                    ValidateConvertNode(node as ConvertNode, settings);
                    break;

                case QueryNodeKind.EntityRangeVariableReference:
                    ValidateRangeVariable((node as EntityRangeVariableReferenceNode).RangeVariable, settings);
                    break;

                case QueryNodeKind.NonentityRangeVariableReference:
                    ValidateRangeVariable((node as NonentityRangeVariableReferenceNode).RangeVariable, settings);
                    break;

                case QueryNodeKind.SingleValuePropertyAccess:
                    ValidateSingleValuePropertyAccessNode(node as SingleValuePropertyAccessNode, settings);
                    break;

                case QueryNodeKind.UnaryOperator:
                    ValidateUnaryOperatorNode(node as UnaryOperatorNode, settings);
                    break;

                case QueryNodeKind.SingleValueFunctionCall:
                    ValidateSingleValueFunctionCallNode(node as SingleValueFunctionCallNode, settings);
                    break;

                case QueryNodeKind.SingleNavigationNode:
                    SingleNavigationNode navigationNode = node as SingleNavigationNode;
                    ValidateNavigationPropertyNode(navigationNode.Source, navigationNode.NavigationProperty, settings);
                    break;

                case QueryNodeKind.Any:
                    ValidateAnyNode(node as AnyNode, settings);
                    break;

                case QueryNodeKind.All:
                    ValidateAllNode(node as AllNode, settings);
                    break;

                default:
                    throw new ODataException(Error.Format(SRResources.QueryNodeBindingNotSupported, node.Kind, typeof(FilterQueryValidator).Name));
            }
        }
Exemplo n.º 32
0
        /// <summary>
        /// The recursive method that validate most of the query node type is of SingleValueNode type.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="settings"></param>
        private void ValidateSingleValueNode(SingleValueNode node, ODataValidationSettings settings)
        {
            switch (node.Kind)
            {
                case QueryNodeKind.BinaryOperator:
                    ValidateBinaryOperatorNode(node as BinaryOperatorNode, settings);
                    break;

                case QueryNodeKind.Constant:
                    ValidateConstantNode(node as ConstantNode, settings);
                    break;

                case QueryNodeKind.Convert:
                    ValidateConvertNode(node as ConvertNode, settings);
                    break;

                case QueryNodeKind.EntityRangeVariableReference:
                    ValidateRangeVariable((node as EntityRangeVariableReferenceNode).RangeVariable, settings);
                    break;

                case QueryNodeKind.NonentityRangeVariableReference:
                    ValidateRangeVariable((node as NonentityRangeVariableReferenceNode).RangeVariable, settings);
                    break;

                case QueryNodeKind.SingleValuePropertyAccess:
                    ValidateSingleValuePropertyAccessNode(node as SingleValuePropertyAccessNode, settings);
                    break;

                case QueryNodeKind.UnaryOperator:
                    ValidateUnaryOperatorNode(node as UnaryOperatorNode, settings);
                    break;

                case QueryNodeKind.SingleValueFunctionCall:
                    ValidateSingleValueFunctionCallNode(node as SingleValueFunctionCallNode, settings);
                    break;

                case QueryNodeKind.SingleNavigationNode:
                    SingleNavigationNode navigationNode = node as SingleNavigationNode;
                    ValidateNavigationPropertyNode(navigationNode.Source, navigationNode.NavigationProperty, settings);
                    break;

                case QueryNodeKind.SingleEntityCast:
                    ValidateSingleEntityCastNode(node as SingleEntityCastNode, settings);
                    break;

                case QueryNodeKind.Any:
                    ValidateAnyNode(node as AnyNode, settings);
                    break;

                case QueryNodeKind.All:
                    ValidateAllNode(node as AllNode, settings);
                    break;
            }
        }
Exemplo n.º 33
0
        private static bool IsSubstringOfFunctionCall(SingleValueNode expression)
        {
            // If necessary, unwrap SingleValueFunctionCall from ConvertNode
            if (expression.Kind == QueryNodeKind.Convert)
            {
                expression = ((ConvertNode)expression).Source;
            }

            if (expression.Kind == QueryNodeKind.SingleValueFunctionCall)
            {
                var functionCallExpression = (SingleValueFunctionCallNode)expression;
                return string.Equals(functionCallExpression.Name, "substringof", StringComparison.OrdinalIgnoreCase);
            }
            return false;
        }
 /// <summary>
 /// Initialises a new instance of the <see cref="BinaryOperatorNode"/> class.
 /// </summary>
 /// <param name="left">The left query node.</param>
 /// <param name="operatorKind">Kind of the operator.</param>
 /// <param name="right">The right query node.</param>
 public BinaryOperatorNode(SingleValueNode left, BinaryOperatorKind operatorKind, SingleValueNode right)
 {
     this.Left = left;
     this.OperatorKind = operatorKind;
     this.Right = right;
 }
        /// <summary>
        /// The recursive method that validate most of the query node type is of SingleValueNode type.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="settings"></param>
        private void ValidateSingleValueNode(SingleValueNode node, ODataValidationSettings settings)
        {
            switch (node.Kind)
            {
                case QueryNodeKind.BinaryOperator:
                    ValidateBinaryOperatorNode(node as BinaryOperatorNode, settings);
                    break;

                case QueryNodeKind.Constant:
                    ValidateConstantNode(node as ConstantNode, settings);
                    break;

                case QueryNodeKind.Convert:
                    ValidateConvertNode(node as ConvertNode, settings);
                    break;

                case QueryNodeKind.EntityRangeVariableReference:
                    ValidateRangeVariable((node as EntityRangeVariableReferenceNode).RangeVariable, settings);
                    break;

                case QueryNodeKind.NonentityRangeVariableReference:
                    ValidateRangeVariable((node as NonentityRangeVariableReferenceNode).RangeVariable, settings);
                    break;

                case QueryNodeKind.SingleValuePropertyAccess:
                    ValidateSingleValuePropertyAccessNode(node as SingleValuePropertyAccessNode, settings);
                    break;

                case QueryNodeKind.UnaryOperator:
                    ValidateUnaryOperatorNode(node as UnaryOperatorNode, settings);
                    break;

                case QueryNodeKind.SingleValueFunctionCall:
                    ValidateSingleValueFunctionCallNode(node as SingleValueFunctionCallNode, settings);
                    break;

                case QueryNodeKind.SingleNavigationNode:
                    SingleNavigationNode navigationNode = node as SingleNavigationNode;
                    ValidateNavigationPropertyNode(navigationNode.Source, navigationNode.NavigationProperty, settings);
                    break;

                case QueryNodeKind.SingleEntityCast:
                    ValidateSingleEntityCastNode(node as SingleEntityCastNode, settings);
                    break;

                case QueryNodeKind.Any:
                    ValidateAnyNode(node as AnyNode, settings);
                    break;

                case QueryNodeKind.All:
                    ValidateAllNode(node as AllNode, settings);
                    break;

                case QueryNodeKind.NamedFunctionParameter:
                case QueryNodeKind.SingleValueOpenPropertyAccess:
                    // Unused or have unknown uses.
                case QueryNodeKind.SingleEntityFunctionCall:
                    // Used for some 'cast' calls but not supported here or in FilterBinder.
                default:
                    throw Error.NotSupported(SRResources.QueryNodeValidationNotSupported, node.Kind, typeof(FilterQueryValidator).Name);
            }
        }
Exemplo n.º 36
0
        /// <summary>
        /// Creates a <see cref="SearchClause"/>.
        /// </summary>
        /// <param name="expression">The filter expression - this should evaluate to a single boolean value. Cannot be null.</param>
        /// <exception cref="System.ArgumentNullException">Throws if the input expression or rangeVariable is null.</exception>
        public SearchClause(SingleValueNode expression)
        {
            ExceptionUtils.CheckArgumentNotNull(expression, "expression");

            this.expression = expression;
        }
 /// <summary>
 /// Initialises a new instance of the <see cref="UnaryOperatorNode"/> class.
 /// </summary>
 /// <param name="operand">The operand of the unary operator.</param>
 /// <param name="operatorKind">Kind of the operator.</param>
 public UnaryOperatorNode(SingleValueNode operand, UnaryOperatorKind operatorKind)
 {
     this.Operand = operand;
     this.OperatorKind = operatorKind;
 }
 private string BindNavigationPropertyNode(SingleValueNode singleValueNode, IEdmNavigationProperty edmNavigationProperty)
 {
     return Bind(singleValueNode) + "." + edmNavigationProperty.Name;
 }