Esempio n. 1
0
        private static void BuildFilterWithBinaryOperator()
        {
            var personTypeRef = new EdmEntityTypeReference(TripPinModel.Person, false);
            var friendsProp = (IEdmNavigationProperty)TripPinModel.Person.FindProperty("Friends");
            var firstNameProp = TripPinModel.Person.FindProperty("FirstName");
            var lastNameProp = TripPinModel.Person.FindProperty("LastName");

            var topIt = new EntityRangeVariable("$it", personTypeRef, TripPinModel.PeopleSet);
            var topItRef = new EntityRangeVariableReferenceNode("$it", topIt);
            var friendsNavNode = new CollectionNavigationNode(friendsProp, topItRef);
            var e0 = new EntityRangeVariable("e0", personTypeRef, friendsNavNode);
            var e0Ref = new EntityRangeVariableReferenceNode("e0", e0);
            var fun1 = new SingleValueFunctionCallNode(
                "startswith",
                new QueryNode[]
                {
                    new SingleValuePropertyAccessNode(e0Ref, firstNameProp),
                    new ConstantNode("var1", "'var1'")
                },
                EdmCoreModel.Instance.GetBoolean(false));

            var friendsNavNode2 = new CollectionNavigationNode(friendsProp, e0Ref);
            var e1 = new EntityRangeVariable("e1", personTypeRef, friendsNavNode2);
            var e1Ref = new EntityRangeVariableReferenceNode("e1", e1);
            var fun2 = new SingleValueFunctionCallNode(
                "contains",
                new QueryNode[]
                {
                    new SingleValuePropertyAccessNode(e1Ref, lastNameProp),
                    new ConstantNode("var2", "'var2'")
                },
                EdmCoreModel.Instance.GetBoolean(false));

            // Actually $it also needed, but would not be used in UriBuilder, so omit it here.
            var any2 = new AnyNode(new Collection<RangeVariable> { e1 }, e1)
            {
                Body = fun2,
                Source = friendsNavNode2
            };

            var any1 = new AnyNode(new Collection<RangeVariable> { e0 }, e0)
            {
                Body = new BinaryOperatorNode(BinaryOperatorKind.And, fun1, any2),
                Source = friendsNavNode
            };

            var odataUri = new ODataUri
            {
                Path = new ODataPath(new EntitySetSegment(TripPinModel.PeopleSet)),
                ServiceRoot = TripPinRoot,
                Filter = new FilterClause(any1, topIt)
            };
            var builder = new ODataUriBuilder(ODataUrlConventions.Default, odataUri);
            Console.WriteLine(builder.BuildUri());

            // http://services.odata.org/V4/TripPinService/People?$filter=Friends%2Fany(
            // e0:startswith(e0%2FFirstName%2C'var1') and e0%2FFriends%2Fany(e1:contains(e1%2FLastName%2C'var2')))
        }
Esempio n. 2
0
        public static AndConstraint <SingleValueFunctionCallNode> ShouldBeSingleValueFunctionCallQueryNode(this QueryNode token, string name, IEdmTypeReference returnType = null)
        {
            token.Should().BeOfType <SingleValueFunctionCallNode>();
            SingleValueFunctionCallNode functionCallNode = token.As <SingleValueFunctionCallNode>();

            functionCallNode.Name.Should().Be(name);
            if (returnType != null)
            {
                functionCallNode.TypeReference.ShouldBeEquivalentTo(returnType);
            }

            return(new AndConstraint <SingleValueFunctionCallNode>(functionCallNode));
        }
        public void TranslatorShouldTranslateIsOfFunctionCallWithImplicitParameter()
        {
            ConstantNode constantNode;
            var          testSubjectWithResourceTypeLiteral = CreateTestSubjectWithResourceTypeStringLiteral(out constantNode);

            QueryNode node = new SingleValueFunctionCallNode("isof", new[] { constantNode }, null);

            var result = testSubjectWithResourceTypeLiteral.TranslateNode(node);

            var expected = Expression.TypeIs(this.implicitParameterExpression, typeof(Customer));

            CompareExpressions(expected, result);
        }
 public void ArgumentsAreSetCorrectly()
 {
     QueryNode[] args = new QueryNode[]
         {
             new ConstantNode(1),
             new ConstantNode(2),
             new ConstantNode(3),
             new ConstantNode(4),
             new ConstantNode(5) 
         };
     SingleValueFunctionCallNode singleValueFunction = new SingleValueFunctionCallNode("stuff", args, EdmCoreModel.Instance.GetInt32(true));
     singleValueFunction.Parameters.Should().BeEquivalentTo(args);
 }
        private static Expression CastFunction(SingleValueFunctionCallNode nodeIn, List <Expression> expressions)
        {
            EdmPrimitiveTypeKind primitiveKind = nodeIn.TypeReference.PrimitiveKind();

            if (primitiveKind == EdmPrimitiveTypeKind.DateTimeOffset && expressions[0].Type == typeof(DateTime))
            {
                return(expressions[0]);
            }

            Type clrType = ModelBuilder.PrimitiveTypeHelper.GetClrType(primitiveKind);

            return(Expression.Convert(expressions[0], clrType));
        }
Esempio n. 6
0
        /// <summary>
        /// Binds a 'time' function to create a LINQ <see cref="Expression"/>.
        /// </summary>
        /// <param name="node">The query node to bind.</param>
        /// <param name="context">The query binder context.</param>
        /// <returns>The LINQ <see cref="Expression"/> created.</returns>
        protected virtual Expression BindTime(SingleValueFunctionCallNode node, QueryBinderContext context)
        {
            CheckArgumentNull(node, context, "time");

            Expression[] arguments = BindArguments(node.Parameters, context);

            // We should support DateTime & DateTimeOffset even though DateTime is not part of OData v4 Spec.
            Contract.Assert(arguments.Length == 1 && ExpressionBinderHelper.IsDateOrOffset(arguments[0].Type));

            // EF doesn't support new TimeOfDay(int, int, int, int), also doesn't support other property access, for example DateTimeOffset.DateTime.
            // Therefore, we just return the source (DateTime or DateTimeOffset).
            return(arguments[0]);
        }
        private string BindSingleValueFunctionCallNode(SingleValueFunctionCallNode singleValueFunctionCallNode, ICollection <BinderNode> nodes)
        {
            var arguments = singleValueFunctionCallNode.Parameters.ToList();

            switch (singleValueFunctionCallNode.Name)
            {
            case "concat":
                return(singleValueFunctionCallNode.Name + "(" + Bind(arguments[0], nodes) + "," + Bind(arguments[1], nodes) + ")");

            default:
                return(singleValueFunctionCallNode.Name + "(" + Bind(arguments[0], nodes) + ")");
            }
        }
Esempio n. 8
0
        public static SingleValueFunctionCallNode ShouldBeSingleValueFunctionCallQueryNode(this QueryNode node, string name, IEdmTypeReference returnType = null)
        {
            Assert.NotNull(node);
            SingleValueFunctionCallNode functionCallNode = Assert.IsType <SingleValueFunctionCallNode>(node);

            Assert.Equal(name, functionCallNode.Name);
            if (returnType != null)
            {
                Assert.True(functionCallNode.TypeReference.IsEquivalentTo(returnType));
            }

            return(functionCallNode);
        }
Esempio n. 9
0
        public override FilterNode <ClrValue> Visit(SingleValueFunctionCallNode nodeIn)
        {
            var fieldNode = nodeIn.Parameters.ElementAt(0);

            if (string.Equals(nodeIn.Name, "empty", StringComparison.OrdinalIgnoreCase))
            {
                return(ClrFilter.Empty(PropertyPathVisitor.Visit(fieldNode)));
            }

            if (string.Equals(nodeIn.Name, "empty", StringComparison.OrdinalIgnoreCase))
            {
                return(ClrFilter.Empty(PropertyPathVisitor.Visit(fieldNode)));
            }

            if (string.Equals(nodeIn.Name, "exists", StringComparison.OrdinalIgnoreCase))
            {
                return(ClrFilter.Exists(PropertyPathVisitor.Visit(fieldNode)));
            }

            var valueNode = nodeIn.Parameters.ElementAt(1);

            if (string.Equals(nodeIn.Name, "matchs", StringComparison.OrdinalIgnoreCase))
            {
                var value = ConstantWithTypeVisitor.Visit(valueNode);

                return(ClrFilter.Matchs(PropertyPathVisitor.Visit(fieldNode), value));
            }

            if (string.Equals(nodeIn.Name, "endswith", StringComparison.OrdinalIgnoreCase))
            {
                var value = ConstantWithTypeVisitor.Visit(valueNode);

                return(ClrFilter.EndsWith(PropertyPathVisitor.Visit(fieldNode), value));
            }

            if (string.Equals(nodeIn.Name, "startswith", StringComparison.OrdinalIgnoreCase))
            {
                var value = ConstantWithTypeVisitor.Visit(valueNode);

                return(ClrFilter.StartsWith(PropertyPathVisitor.Visit(fieldNode), value));
            }

            if (string.Equals(nodeIn.Name, "contains", StringComparison.OrdinalIgnoreCase))
            {
                var value = ConstantWithTypeVisitor.Visit(valueNode);

                return(ClrFilter.Contains(PropertyPathVisitor.Visit(fieldNode), value));
            }

            throw new NotSupportedException();
        }
Esempio n. 10
0
        /// <summary>
        /// Binds a 'isof' function to create a LINQ <see cref="Expression"/>.
        /// </summary>
        /// <param name="node">The query node to bind.</param>
        /// <param name="context">The query binder context.</param>
        /// <returns>The LINQ <see cref="Expression"/> created.</returns>
        protected virtual Expression BindIsOf(SingleValueFunctionCallNode node, QueryBinderContext context)
        {
            CheckArgumentNull(node, context, "isof");

            Expression[] arguments = BindArguments(node.Parameters, context);

            // Edm.Boolean isof(type)  or
            // Edm.Boolean isof(expression,type)
            Contract.Assert(arguments.Length == 1 || arguments.Length == 2);

            Expression source = arguments.Length == 1 ? context.CurrentParameter : arguments[0];

            if (source == NullConstant)
            {
                return(FalseConstant);
            }

            string typeName = (string)((ConstantNode)node.Parameters.Last()).Value;

            IEdmType edmType = context.Model.FindType(typeName);
            Type     clrType = null;

            if (edmType != null)
            {
                // bool nullable = source.Type.IsNullable();
                IEdmTypeReference edmTypeReference = edmType.ToEdmTypeReference(false);
                clrType = context.Model.GetClrType(edmTypeReference);
            }

            if (clrType == null)
            {
                return(FalseConstant);
            }

            bool isSourcePrimitiveOrEnum = context.Model.GetEdmPrimitiveTypeReference(source.Type) != null ||
                                           TypeHelper.IsEnum(source.Type);

            bool isTargetPrimitiveOrEnum = context.Model.GetEdmPrimitiveTypeReference(clrType) != null ||
                                           TypeHelper.IsEnum(clrType);

            if (isSourcePrimitiveOrEnum && isTargetPrimitiveOrEnum)
            {
                if (TypeHelper.IsNullable(source.Type))
                {
                    clrType = TypeHelper.ToNullable(clrType);
                }
            }

            // Be caution: Type method of LINQ to Entities only supports entity type.
            return(Expression.Condition(Expression.TypeIs(source, clrType), TrueConstant, FalseConstant));
        }
Esempio n. 11
0
        /// <summary>
        /// Binds 'ceiling' function to create a LINQ <see cref="Expression"/>.
        /// </summary>
        /// <param name="node">The query node to bind.</param>
        /// <param name="context">The query binder context.</param>
        /// <returns>The LINQ <see cref="Expression"/> created.</returns>
        protected virtual Expression BindCeiling(SingleValueFunctionCallNode node, QueryBinderContext context)
        {
            CheckArgumentNull(node, context, "ceiling");

            Expression[] arguments = BindArguments(node.Parameters, context);

            Contract.Assert(arguments.Length == 1 && ExpressionBinderHelper.IsDoubleOrDecimal(arguments[0].Type));

            MethodInfo ceiling = ExpressionBinderHelper.IsType <double>(arguments[0].Type)
                ? ClrCanonicalFunctions.CeilingOfDouble
                : ClrCanonicalFunctions.CeilingOfDecimal;

            return(ExpressionBinderHelper.MakeFunctionCall(ceiling, context.QuerySettings, arguments));
        }
        public void ArgumentsAreSetCorrectly()
        {
            QueryNode[] args = new QueryNode[]
            {
                new ConstantNode(1),
                new ConstantNode(2),
                new ConstantNode(3),
                new ConstantNode(4),
                new ConstantNode(5)
            };
            SingleValueFunctionCallNode singleValueFunction = new SingleValueFunctionCallNode("stuff", args, EdmCoreModel.Instance.GetInt32(true));

            singleValueFunction.Parameters.Should().BeEquivalentTo(args);
        }
Esempio n. 13
0
 /// <summary>
 /// Visit a SingleValueFunctionCallNode
 /// </summary>
 /// <param name="nodeIn">the node to visit</param>
 /// <returns>true, indicating that the node has been visited.</returns>
 public override bool Visit(SingleValueFunctionCallNode nodeIn)
 {
     validate(nodeIn);
     validate(nodeIn.TypeReference.Definition);
     foreach (IEdmFunction function in nodeIn.Functions)
     {
         validate(function);
     }
     foreach (QueryNode param in nodeIn.Parameters)
     {
         ValidateNode(param);
     }
     return(true);
 }
        /// <summary>
        /// Translate a SingleValueFunctionCallNode.
        /// </summary>
        /// <param name="nodeIn">The node to be translated.</param>
        /// <returns>The translated node.</returns>
        public override QueryNode Visit(SingleValueFunctionCallNode nodeIn)
        {
            if (nodeIn == null)
            {
                throw Error.ArgumentNull(nameof(nodeIn));
            }

            return(new SingleValueFunctionCallNode(
                       nodeIn.Name,
                       nodeIn.Functions,
                       nodeIn.Parameters.Select(p => p.Accept(this)),
                       nodeIn.TypeReference,
                       nodeIn.Source == null ? null : nodeIn.Source.Accept(this)));
        }
        private Expression BindContainsAny(SingleValueFunctionCallNode node)
        {
            var argument = Bind(node.Parameters.First());

            var collection = ((IEnumerable)JsonConvert.DeserializeObject(node.Parameters.OfType <ConstantNode>().First().LiteralText,
                                                                         typeof(IEnumerable <>).MakeGenericType(argument.Type))).AsQueryable();

            var data     = Expression.Constant(collection);
            var anyParam = Expression.Parameter(argument.Type);
            var anyFunc  = Expression.Lambda(Expression.Call(argument, "Contains", new Type[] { }, anyParam), anyParam);
            var result   = Expression.Call(typeof(Queryable), "Any", new Type[] { argument.Type }, data, anyFunc);

            return(result);
        }
        //private string BindNavigationPropertyNode(SingleEntityNode singleEntityNode, IEdmNavigationProperty edmNavigationProperty)
        //{
        //    return Bind(singleEntityNode) + "." + edmNavigationProperty.Name;
        //}

        private string BindSingleValueFunctionCallNode(SingleValueFunctionCallNode singleValueFunctionCallNode)
        {
            var arguments = singleValueFunctionCallNode.Parameters.ToList();

            switch (singleValueFunctionCallNode.Name)
            {
            case "concat":
                return(singleValueFunctionCallNode.Name + "(" + Bind(arguments[0]) + "," + Bind(arguments[1]) + ")");

            case "contains":
                return(string.Format("{0} like '%{1}%'", Bind(arguments[0]), ReplaceSQLSpecialCharacters((arguments[1] as ConstantNode).Value)));

            case "endswith":
                return(string.Format("{0} like '%{1}'", Bind(arguments[0]), ReplaceSQLSpecialCharacters((arguments[1] as ConstantNode).Value)));

            case "startswith":
                return(string.Format("{0} like '{1}%'", Bind(arguments[0]), ReplaceSQLSpecialCharacters((arguments[1] as ConstantNode).Value)));

            case "length":
                return(string.Format("len({0})", Bind(arguments[0])));

            case "indexof":
                return(string.Format("charindex('{0}',{1}", (arguments[1] as ConstantNode).Value, Bind(arguments[0])));

            case "substring":
            case "tolower":
            case "toupper":
            case "trim":
            case "year":
            case "years":
            case "month":
            case "months":
            case "day":
            case "days":
            case "hour":
            case "hours":
            case "minute":
            case "minutes":
            case "second":
            case "seconds":
            case "round":
            case "floor":
            case "ceiling":
                return(singleValueFunctionCallNode.Name + "(" + Bind(arguments[0]) + ")");

            default:
                throw new NotImplementedException();
            }
        }
Esempio n. 17
0
        /// <summary>
        /// Writes single value function call node to string.
        /// </summary>
        /// <param name="node">Node to write to string</param>
        /// <returns>String representation of node.</returns>
        private static string ToString(SingleValueFunctionCallNode node)
        {
            if (node != null)
            {
                return(tabHelper.Prefix + "SingleValueFunctionCallNode" +
                       tabHelper.Indent(() =>
                                        tabHelper.Prefix + "Name = " + node.Name +
                                        tabHelper.Prefix + "Return Type = " + node.TypeReference +
                                        tabHelper.Prefix + "Function = " + ToString(node.Functions) +
                                        ArgumentsToString(node.Parameters)
                                        ));
            }

            return(String.Empty);
        }
        private IEnumerable<Customer> BindGeoIntersections(SingleValueFunctionCallNode node, IEnumerable<Customer> customers)
        {
            Debug.Assert(node.Name == "geo.intersects");
            Debug.Assert(2 == node.Parameters.Count());

            SingleValuePropertyAccessNode first = node.Parameters.First() as SingleValuePropertyAccessNode;
            ConstantNode second = node.Parameters.Last() as ConstantNode;

            Debug.Assert(first != null && second != null);

            IEdmProperty property = first.Property;
            GeographyPolygon polygon = second.Value as GeographyPolygon;

            Debug.Assert(property != null && polygon != null);

            return DoGeoIntersections(customers, property, polygon);
        }
Esempio n. 19
0
        /// <summary>
        /// Binds customized function to create a LINQ <see cref="Expression"/>.
        /// </summary>
        /// <param name="node">The query node to bind.</param>
        /// <param name="context">The query binder context.</param>
        /// <returns>The LINQ <see cref="Expression"/> created.</returns>
        protected virtual Expression BindCustomMethodExpressionOrNull(SingleValueFunctionCallNode node, QueryBinderContext context)
        {
            CheckArgumentNull(node, context);

            Expression[]       arguments           = BindArguments(node.Parameters, context);
            IEnumerable <Type> methodArgumentsType = arguments.Select(argument => argument.Type);

            // Search for custom method info that are binded to the node name
            MethodInfo methodInfo;

            if (UriFunctionsBinder.TryGetMethodInfo(node.Name, methodArgumentsType, out methodInfo))
            {
                return(ExpressionBinderHelper.MakeFunctionCall(methodInfo, context.QuerySettings, arguments));
            }

            return(null);
        }
        //$filter=contains(EnterpriseName,%27NPDB%27)
        //$filter=startswith(EnterpriseName,%27NPDB%27)
        //$filter=endswith(EnterpriseName,%27NPDB%27)
        public SingleValueFunctionResolver(SingleValueFunctionCallNode function)
        {
            if (function != null)
            {
                var property = function.Parameters.First() as SingleValuePropertyAccessNode;
                var constant = function.Parameters.Last() as ConstantNode;

                Name = function.Name;
                Query = function.Kind;

                if (property != null && property.Property != null && constant != null && constant.Value != null)
                {
                    Property = property.Property.Name;
                    Value = constant.Value.ToString();
                }
            }
        }
Esempio n. 21
0
        //$filter=contains(EnterpriseName,%27NPDB%27)
        //$filter=startswith(EnterpriseName,%27NPDB%27)
        //$filter=endswith(EnterpriseName,%27NPDB%27)
        public SingleValueFunctionResolver(SingleValueFunctionCallNode function)
        {
            if (function != null)
            {
                var property = function.Parameters.First() as SingleValuePropertyAccessNode;
                var constant = function.Parameters.Last() as ConstantNode;

                Name  = function.Name;
                Query = function.Kind;

                if (property != null && property.Property != null && constant != null && constant.Value != null)
                {
                    Property = property.Property.Name;
                    Value    = constant.Value.ToString();
                }
            }
        }
Esempio n. 22
0
        private IEnumerable <Customer> BindGeoIntersections(SingleValueFunctionCallNode node, IEnumerable <Customer> customers)
        {
            Debug.Assert(node.Name == "geo.intersects");
            Debug.Assert(2 == node.Parameters.Count());

            SingleValuePropertyAccessNode first = node.Parameters.First() as SingleValuePropertyAccessNode;
            ConstantNode second = node.Parameters.Last() as ConstantNode;

            Debug.Assert(first != null && second != null);

            IEdmProperty     property = first.Property;
            GeographyPolygon polygon  = second.Value as GeographyPolygon;

            Debug.Assert(property != null && polygon != null);

            return(DoGeoIntersections(customers, property, polygon));
        }
Esempio n. 23
0
        private static Condition BindSingleValueFunctionCallNode(SingleValueFunctionCallNode singleValueFunctionCallNode)
        {
            switch (singleValueFunctionCallNode.Name)
            {
            case "startswith":
                return(BindStartsWith(singleValueFunctionCallNode));

            case "endswith":
                return(BindEndsWith(singleValueFunctionCallNode));

            case "substringof":
                return(BindSubstringof(singleValueFunctionCallNode));

            default:
                throw new NotSupportedException(string.Format("Function call {0} isn't supported.", singleValueFunctionCallNode.Name));
            }
        }
Esempio n. 24
0
        /// <summary>
        /// Binds time related functions to create a LINQ <see cref="Expression"/>.
        /// </summary>
        /// <param name="node">The query node to bind.</param>
        /// <param name="context">The query binder context.</param>
        /// <returns>The LINQ <see cref="Expression"/> created.</returns>
        protected virtual Expression BindTimeRelatedProperty(SingleValueFunctionCallNode node, QueryBinderContext context)
        {
            CheckArgumentNull(node, context);

            Expression[] arguments = BindArguments(node.Parameters, context);

            Contract.Assert(arguments.Length == 1 && ExpressionBinderHelper.IsTimeRelated(arguments[0].Type));

            // We should support DateTime & DateTimeOffset even though DateTime is not part of OData v4 Spec.
            Expression parameter = arguments[0];

            PropertyInfo property;

            if (ExpressionBinderHelper.IsTimeOfDay(parameter.Type))
            {
                Contract.Assert(ClrCanonicalFunctions.TimeOfDayProperties.ContainsKey(node.Name));
                property = ClrCanonicalFunctions.TimeOfDayProperties[node.Name];
            }
#if NET6_0
            else if (parameter.Type.IsTimeOnly())
            {
                Contract.Assert(ClrCanonicalFunctions.TimeOnlyProperties.ContainsKey(node.Name));
                property = ClrCanonicalFunctions.TimeOnlyProperties[node.Name];
            }
#endif
            else if (ExpressionBinderHelper.IsDateTime(parameter.Type))
            {
                Contract.Assert(ClrCanonicalFunctions.DateTimeProperties.ContainsKey(node.Name));
                property = ClrCanonicalFunctions.DateTimeProperties[node.Name];
            }
            else if (ExpressionBinderHelper.IsTimeSpan(parameter.Type))
            {
                Contract.Assert(ClrCanonicalFunctions.TimeSpanProperties.ContainsKey(node.Name));
                property = ClrCanonicalFunctions.TimeSpanProperties[node.Name];
            }
            else
            {
                Contract.Assert(ClrCanonicalFunctions.DateTimeOffsetProperties.ContainsKey(node.Name));
                property = ClrCanonicalFunctions.DateTimeOffsetProperties[node.Name];
            }

            return(ExpressionBinderHelper.MakeFunctionCall(property, context.QuerySettings, parameter));
        }
Esempio n. 25
0
        /*
         * [EnableQuery]
         * public IHttpActionResult Get()
         * {
         *  return Ok(db.Customers);
         * }*/

        public IHttpActionResult Get(ODataQueryOptions <Customer> options)
        {
            IList <Customer> customers = db.Customers.ToList();

            FilterQueryOption filter = options.Filter;

            FilterClause filterClause = filter.FilterClause;
            SingleValueFunctionCallNode functionCall = filterClause.Expression as SingleValueFunctionCallNode;

            if (functionCall != null)
            {
                if (functionCall.Name == "geo.intersects")
                {
                    customers = BindGeoIntersections(functionCall, customers).ToList();
                }
            }

            return(Ok(customers));
        }
        public override Expression BindSingleValueFunctionCallNode(SingleValueFunctionCallNode node)
        {
            if (node.Name == "containsany")
            {
                return(BindContainsAny(node));
            }
            if (node.Name == "incollection")
            {
                return(BindInCollection(node));
            }
            if (node.Name == "notincollection")
            {
                return(BindNotInCollection(node));
            }

            var exp = base.BindSingleValueFunctionCallNode(node);

            return(exp);
        }
Esempio n. 27
0
        /// <summary>
        /// Override this method to validate Function calls, such as 'length', 'years', etc.
        /// </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 ValidateSingleValueFunctionCallNode(SingleValueFunctionCallNode node, ODataValidationSettings settings)
        {
            if (node == null)
            {
                throw Error.ArgumentNull("node");
            }

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

            ValidateFunction(node.Name, settings);

            foreach (QueryNode argumentNode in node.Parameters)
            {
                ValidateQueryNode(argumentNode, settings);
            }
        }
        public void ArgumentsAreSetCorrectly()
        {
            QueryNode[] args = new QueryNode[]
            {
                new ConstantNode(1),
                new ConstantNode(2),
                new ConstantNode(3),
                new ConstantNode(4),
                new ConstantNode(5)
            };
            SingleValueFunctionCallNode singleValueFunction = new SingleValueFunctionCallNode("stuff", args, EdmCoreModel.Instance.GetInt32(true));

            Assert.Equal(5, singleValueFunction.Parameters.Count());
            int index = 1;

            foreach (var parameter in singleValueFunction.Parameters)
            {
                var constantNode = Assert.IsType <ConstantNode>(parameter);
                Assert.Equal(index++, constantNode.Value);
            }
        }
Esempio n. 29
0
        /// <summary>
        /// Bind $it to the <see cref="SingleValueFunctionCallNode"/> translated string.
        /// </summary>
        /// <param name="node">node to bind.</param>
        /// <param name="filterClauseRangeVariable">The <see cref="FilterClause"/> range variable.</param>
        /// <returns>The translated string with $it binding.</returns>
        private string BindSingleValueFunctionCallNode(SingleValueFunctionCallNode node, ResourceRangeVariable filterClauseRangeVariable)
        {
            string translatedNode = this.TranslateNode(node);
            ResourceRangeVariableReferenceNode firstParameterRangeVariableNode = GetResourceRangeVariableReferenceNode(node);

            char[]   separators     = { '(', ')' };
            string[] subtrings      = translatedNode.Trim().Split(separators, StringSplitOptions.RemoveEmptyEntries);
            string   withinBrackets = subtrings[1];

            char[]   parameterSeparators = { ',' };
            string[] parameters          = withinBrackets.Trim().Split(parameterSeparators, StringSplitOptions.RemoveEmptyEntries);
            string   leftParameter       = parameters[0];
            string   rightParameter      = parameters.Length == 2 ? parameters[1] : String.Empty;

            if (firstParameterRangeVariableNode != null && IsDifferentSource(filterClauseRangeVariable, firstParameterRangeVariableNode))
            {
                leftParameter  = ExpressionConstants.It + ExpressionConstants.SymbolForwardSlash + leftParameter;
                translatedNode = parameters.Length == 1 ? subtrings[0] + '(' + leftParameter + ')' : subtrings[0] + '(' + leftParameter + ',' + rightParameter + ')';
            }

            return(translatedNode);
        }
Esempio n. 30
0
        public void BuildExpandOrderby_AliasInFunction()
        {
            Uri            fullUri        = new Uri("http://gobbledygook/People?$expand=MyPet2Set($orderby=concat(Color, @p1 )asc )&@p1='abc'");
            ODataUriParser odataUriParser = new ODataUriParser(HardCodedTestModel.TestModel, serviceRoot, fullUri);

            SetODataUriParserSettingsTo(this.settings, odataUriParser.Settings);
            odataUriParser.UrlKeyDelimiter = ODataUrlKeyDelimiter.Parentheses;
            ODataUri odataUri = odataUriParser.ParseUri();

            IDictionary <string, SingleValueNode> aliasNodes = odataUri.ParameterAliasNodes;
            SingleValueFunctionCallNode           node       = (odataUri.SelectAndExpand.SelectedItems.First() as ExpandedNavigationSelectItem).OrderByOption.Expression as SingleValueFunctionCallNode;

            node.Parameters.Last().ShouldBeParameterAliasNode("@p1", EdmCoreModel.Instance.GetString(true));
            aliasNodes["@p1"].ShouldBeConstantQueryNode("abc");

            Uri actualUri = odataUri.BuildUri(ODataUrlKeyDelimiter.Parentheses);

            Assert.Equal("http://gobbledygook/People?$expand=" + Uri.EscapeDataString("MyPet2Set($orderby=concat(Color,@p1))") + "&@p1=" + Uri.EscapeDataString("'abc'"), actualUri.OriginalString);

            actualUri = odataUri.BuildUri(ODataUrlKeyDelimiter.Slash);
            Assert.Equal("http://gobbledygook/People?$expand=" + Uri.EscapeDataString("MyPet2Set($orderby=concat(Color,@p1))") + "&@p1=" + Uri.EscapeDataString("'abc'"), actualUri.OriginalString);
        }
Esempio n. 31
0
        /// <summary>
        /// We return the <see cref="ResourceRangeVariableReferenceNode"/> within a <see cref="QueryNode"/>
        /// </summary>
        /// <param name="node">The node to extract the ResourceRangeVariableReferenceNode.</param>
        /// <returns>The extracted ResourceRangeVariableReferenceNode.</returns>
        private ResourceRangeVariableReferenceNode GetResourceRangeVariableReferenceNode(QueryNode node)
        {
            switch (node.Kind)
            {
            case QueryNodeKind.SingleValuePropertyAccess:
                SingleValuePropertyAccessNode singleValuePropertyAccessNode = node as SingleValuePropertyAccessNode;
                return(GetResourceRangeVariableReferenceNode(singleValuePropertyAccessNode.Source));

            case QueryNodeKind.Convert:
                ConvertNode convertNode = node as ConvertNode;
                return(GetResourceRangeVariableReferenceNode(convertNode.Source));

            case QueryNodeKind.Any:
                AnyNode anyNode = node as AnyNode;
                return(GetResourceRangeVariableReferenceNode(anyNode.Source));

            case QueryNodeKind.SingleValueFunctionCall:
                SingleValueFunctionCallNode singleValueFunctionCallNode = node as SingleValueFunctionCallNode;
                return(GetResourceRangeVariableReferenceNode(singleValueFunctionCallNode.Parameters.First()));

            case QueryNodeKind.ResourceRangeVariableReference:
                return(node as ResourceRangeVariableReferenceNode);

            case QueryNodeKind.SingleValueOpenPropertyAccess:
                SingleValueOpenPropertyAccessNode singleValueOpenPropertyAccessNode = node as SingleValueOpenPropertyAccessNode;
                return(GetResourceRangeVariableReferenceNode(singleValueOpenPropertyAccessNode.Source));

            case QueryNodeKind.SingleComplexNode:
                SingleComplexNode singleComplexNode = node as SingleComplexNode;
                return(GetResourceRangeVariableReferenceNode(singleComplexNode.Source));

            case QueryNodeKind.CollectionComplexNode:
                CollectionComplexNode collectionComplexNode = node as CollectionComplexNode;
                return(GetResourceRangeVariableReferenceNode(collectionComplexNode.Source));
            }

            return(null);
        }
Esempio n. 32
0
        /// <summary>
        /// Binds 'fractionalseconds' function to create a LINQ <see cref="Expression"/>.
        /// </summary>
        /// <param name="node">The query node to bind.</param>
        /// <param name="context">The query binder context.</param>
        /// <returns>The LINQ <see cref="Expression"/> created.</returns>
        protected virtual Expression BindFractionalSeconds(SingleValueFunctionCallNode node, QueryBinderContext context)
        {
            CheckArgumentNull(node, context, "fractionalseconds");

            Expression[] arguments = BindArguments(node.Parameters, context);
            Contract.Assert(arguments.Length == 1 && (ExpressionBinderHelper.IsTimeRelated(arguments[0].Type)));

            // We should support DateTime & DateTimeOffset even though DateTime is not part of OData v4 Spec.
            Expression parameter = arguments[0];

            PropertyInfo property;

            if (ExpressionBinderHelper.IsTimeOfDay(parameter.Type))
            {
                property = ClrCanonicalFunctions.TimeOfDayProperties[ClrCanonicalFunctions.MillisecondFunctionName];
            }
            else if (ExpressionBinderHelper.IsDateTime(parameter.Type))
            {
                property = ClrCanonicalFunctions.DateTimeProperties[ClrCanonicalFunctions.MillisecondFunctionName];
            }
            else if (ExpressionBinderHelper.IsTimeSpan(parameter.Type))
            {
                property = ClrCanonicalFunctions.TimeSpanProperties[ClrCanonicalFunctions.MillisecondFunctionName];
            }
            else
            {
                property = ClrCanonicalFunctions.DateTimeOffsetProperties[ClrCanonicalFunctions.MillisecondFunctionName];
            }

            // Millisecond
            Expression milliSecond        = ExpressionBinderHelper.MakePropertyAccess(property, parameter, context.QuerySettings);
            Expression decimalMilliSecond = Expression.Convert(milliSecond, typeof(decimal));
            Expression fractionalSeconds  = Expression.Divide(decimalMilliSecond, Expression.Constant(1000m, typeof(decimal)));

            return(ExpressionBinderHelper.CreateFunctionCallWithNullPropagation(fractionalSeconds, arguments, context.QuerySettings));
        }
Esempio n. 33
0
        private static ISparqlExpression BuildFunctionExpression(SingleValueFunctionCallNode functionOperator)
        {
            var funcName = functionOperator.Name;

            string[] funcNames = { "contains",  "endswith", "startswith", "length",  "tolower", "toupper",
                                   "substring", "replace",  "concat",     "indexof", "trim",    "year",   "day","month", "hour", "minute",
                                   "second",    "now",      "ceiling",    "floor",   "round",   };

            if (!funcNames.Contains(funcName))
            {
                throw new NotImplementedException($"Function {funcName} not implemented.");
            }

            if (funcName == "now") // NOW() in sparql does not work, will generate this now in .net instead.
            {
                ISparqlExpression exp = new NowFunction();
                return((new UnaryExpressionFilter(exp)).Expression);
            }

            var parameter = functionOperator.Parameters.ElementAt(0);
            ISparqlExpression valueTerm = null;

            if (parameter.GetType() == typeof(SingleValuePropertyAccessNode))
            {
                valueTerm = new VariableTerm($"?{(parameter as SingleValuePropertyAccessNode).Property.Name}");
            }
            else if (parameter.GetType() == typeof(SingleValueFunctionCallNode))
            {
                valueTerm = BuildFunctionExpression(parameter as SingleValueFunctionCallNode);
            }

            if (funcName == "length")
            {
                return((new UnaryExpressionFilter(new StrLenFunction(valueTerm))).Expression);
            }
            else if (funcName == "tolower")
            {
                return((new UnaryExpressionFilter(new LCaseFunction(valueTerm))).Expression);
            }
            else if (funcName == "toupper")
            {
                return((new UnaryExpressionFilter(new UCaseFunction(valueTerm))).Expression);
            }
            else if (funcName == "year")
            {
                return((new UnaryExpressionFilter(new YearFunction(valueTerm))).Expression);
            }
            else if (funcName == "day")
            {
                return((new UnaryExpressionFilter(new DayFunction(valueTerm))).Expression);
            }
            else if (funcName == "month")
            {
                return((new UnaryExpressionFilter(new MonthFunction(valueTerm))).Expression);
            }
            else if (funcName == "hour")
            {
                return((new UnaryExpressionFilter(new HoursFunction(valueTerm))).Expression);
            }
            else if (funcName == "minute")
            {
                return((new UnaryExpressionFilter(new MinutesFunction(valueTerm))).Expression);
            }
            else if (funcName == "second")
            {
                return((new UnaryExpressionFilter(new SecondsFunction(valueTerm))).Expression);
            }
            else if (funcName == "ceiling")
            {
                return((new UnaryExpressionFilter(new CeilFunction(valueTerm))).Expression);
            }
            else if (funcName == "floor")
            {
                return((new UnaryExpressionFilter(new FloorFunction(valueTerm))).Expression);
            }
            else if (funcName == "round")
            {
                return((new UnaryExpressionFilter(new RoundFunction(valueTerm))).Expression);
            }
            else
            {
                var          constant     = functionOperator.Parameters.ElementAt(1) as ConstantNode;
                ConstantTerm constantTerm = new ConstantTerm(CreateLiteralNode(constant));
                if (funcName == "contains")
                {
                    return((new UnaryExpressionFilter(new ContainsFunction(valueTerm, constantTerm))).Expression);
                }
                else if (funcName == "endswith")
                {
                    return((new UnaryExpressionFilter(new StrEndsFunction(valueTerm, constantTerm))).Expression);
                }
                else if (funcName == "startswith")
                {
                    return((new UnaryExpressionFilter(new StrStartsFunction(valueTerm, constantTerm))).Expression);
                }
                else if (funcName == "concat")
                {
                    return((new UnaryExpressionFilter(new ConcatFunction(new List <ISparqlExpression> {
                        valueTerm, constantTerm
                    }))).Expression);
                }
                else if (funcName == "indexof")
                {
                    throw new NotImplementedException("Sparql does not have counterpart of indexof function.");
                }
                else if (funcName == "trim")
                {
                    throw new NotImplementedException("Sparql needs regex to do trim.");
                }
                else if (funcName == "substring")
                {
                    if (functionOperator.Parameters.Count() > 2)
                    {
                        var          constant2     = functionOperator.Parameters.ElementAt(2) as ConstantNode;
                        ConstantTerm constantTerm2 = new ConstantTerm(CreateLiteralNode(constant2));
                        return((new UnaryExpressionFilter(new SubStrFunction(valueTerm, constantTerm, constantTerm2))).Expression);
                    }
                    else
                    {
                        return((new UnaryExpressionFilter(new SubStrFunction(valueTerm, constantTerm))).Expression);
                    }
                }
                else if (funcName == "replace")
                {
                    var          constant2     = functionOperator.Parameters.ElementAt(2) as ConstantNode;
                    ConstantTerm constantTerm2 = new ConstantTerm(CreateLiteralNode(constant2));
                    return((new UnaryExpressionFilter(new ReplaceFunction(valueTerm, constantTerm, constantTerm2))).Expression);
                }
            }
            return(null);
        }
 public void NameIsSetCorrectly()
 {
     SingleValueFunctionCallNode singleValueFunction = new SingleValueFunctionCallNode("stuff", null, EdmCoreModel.Instance.GetInt32(true));
     singleValueFunction.Name.Should().Be("stuff");
 }
Esempio n. 35
0
 private static void VerifySingleValueFunctionCallQueryNodesAreEqual(SingleValueFunctionCallNode expected, SingleValueFunctionCallNode actual, AssertionHandler assert)
 {
     assert.AreEqual(expected.Name, actual.Name, "The names of the functions are different.");
     VerifyQueryNodesAreEqual(expected.Parameters, actual.Parameters, assert);
     QueryTestUtils.VerifyTypesAreEqual(expected.TypeReference, actual.TypeReference, assert);
 }
Esempio n. 36
0
        private bool TryBindIdentifier(string identifier, IEnumerable<FunctionParameterToken> arguments, QueryNode parent, BindingState state, out QueryNode boundFunction)
        {
            boundFunction = null;

            IEdmType bindingType = null;
            var singleValueParent = parent as SingleValueNode;
            if (singleValueParent != null)
            {
                if (singleValueParent.TypeReference != null)
                {
                    bindingType = singleValueParent.TypeReference.Definition;
                }
            }
            else
            {
                var collectionValueParent = parent as CollectionNode;
                if (collectionValueParent != null)
                {
                    bindingType = collectionValueParent.CollectionType.Definition;
                }
            }

            if (!UriEdmHelpers.IsBindingTypeValid(bindingType))
            {
                return false;
            }

            // All functions should be fully qualified, if they aren't they they aren't functions.
            // When using extension, there may be function call with unqualified name. So loose the restriction here.
            if (identifier.IndexOf(".", StringComparison.Ordinal) == -1 && this.Resolver.GetType() == typeof(ODataUriResolver))
            {
                return false;
            }

            IEdmOperation operation;
            List<FunctionParameterToken> syntacticArguments = arguments == null ? new List<FunctionParameterToken>() : arguments.ToList();
            if (!FunctionOverloadResolver.ResolveOperationFromList(identifier, syntacticArguments.Select(ar => ar.ParameterName).ToList(), bindingType, state.Model, out operation, this.Resolver))
            {
                // TODO: FunctionOverloadResolver.ResolveOperationFromList() looks up the function by parameter names, but it shouldn't ignore parameter types. (test case ParseFilter_AliasInFunction_PropertyAsValue_TypeMismatch should fail)
                return false;
            }

            if (singleValueParent != null && singleValueParent.TypeReference == null)
            {
                // if the parent exists, but has no type information, then we're in open type land, and we 
                // shouldn't go any farther.
                throw new ODataException(ODataErrorStrings.FunctionCallBinder_CallingFunctionOnOpenProperty(identifier));
            }

            if (operation.IsAction())
            {
                return false;
            }

            IEdmFunction function = (IEdmFunction)operation;

            // TODO:  $filter $orderby parameter expression which contains complex or collection should NOT be supported in this way
            //     but should be parsed into token tree, and binded to node tree: parsedParameters.Select(p => this.bindMethod(p));
            ICollection<FunctionParameterToken> parsedParameters = HandleComplexOrCollectionParameterValueIfExists(state.Configuration.Model, function, syntacticArguments, state.Configuration.Resolver.EnableCaseInsensitive);

            IEnumerable<QueryNode> boundArguments = parsedParameters.Select(p => this.bindMethod(p));
            boundArguments = boundArguments.ToList(); // force enumerable to run : will immediately evaluate all this.bindMethod(p).
            IEdmTypeReference returnType = function.ReturnType;
            IEdmEntitySetBase returnSet = null;
            var singleEntityNode = parent as SingleEntityNode;
            if (singleEntityNode != null)
            {
                returnSet = function.GetTargetEntitySet(singleEntityNode.NavigationSource, state.Model);
            }

            string functionName = function.FullName();

            if (returnType.IsEntity())
            {
                boundFunction = new SingleEntityFunctionCallNode(functionName, new[] { function }, boundArguments, (IEdmEntityTypeReference)returnType.Definition.ToTypeReference(), returnSet, parent);
            }
            else if (returnType.IsEntityCollection())
            {
                IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType;
                boundFunction = new EntityCollectionFunctionCallNode(functionName, new[] { function }, boundArguments, collectionTypeReference, returnSet, parent);
            }
            else if (returnType.IsCollection())
            {
                IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType;
                boundFunction = new CollectionFunctionCallNode(functionName, new[] { function }, boundArguments, collectionTypeReference, parent);
            }
            else
            {
                boundFunction = new SingleValueFunctionCallNode(functionName, new[] { function }, boundArguments, returnType, parent);
            }

            return true;
        }
        /// <summary>
        /// Override this method to validate Function calls, such as 'length', 'years', etc.
        /// </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 ValidateSingleValueFunctionCallNode(SingleValueFunctionCallNode node, ODataValidationSettings settings)
        {
            if (node == null)
            {
                throw Error.ArgumentNull("node");
            }

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

            ValidateFunction(node.Name, settings);

            foreach (QueryNode argumentNode in node.Arguments)
            {
                ValidateQueryNode(argumentNode, settings);
            }
        }
        public static IEnumerable<FilterTestCase> BuiltInStringFunctionCallTestCases(IEdmModel model)
        {
            QueryNode[] args = new QueryNode[]
            {
                new ConstantNode("Johny"),
                new ConstantNode ("John" )
            };
            yield return new FilterTestCase
            {
                Filter = "endswith('Johny','John')",
                ExpectedFilterCondition = new SingleValueFunctionCallNode("endswith", args, EdmCoreModel.Instance.GetBoolean(false))
            };

            QueryNode[] args2 = new QueryNode[]
                {
                    new ConstantNode("Johny"),
                    new ConstantNode("John")
                };
            SingleValueFunctionCallNode outer = new SingleValueFunctionCallNode("indexof", args2, EdmCoreModel.Instance.GetInt32(false));
            yield return new FilterTestCase
            {
                Filter = "indexof('Johny','John') eq 0",
                ExpectedFilterCondition = new BinaryOperatorNode(BinaryOperatorKind.Equal, outer, new ConstantNode(0))
            };

            QueryNode[] args3 = new QueryNode[]
                {
                    new ConstantNode("Johny"),
                    new ConstantNode("John"),
                    new ConstantNode("Vitek")
                };
            SingleValueFunctionCallNode outer2 = new SingleValueFunctionCallNode("replace", args3, EdmCoreModel.Instance.GetString(true));
            yield return new FilterTestCase
            {
                Filter = "replace('Johny','John','Vitek') eq ''",
                ExpectedFilterCondition = new BinaryOperatorNode(BinaryOperatorKind.Equal, outer2, new ConstantNode(""))
            };

            QueryNode[] args4 = new QueryNode[]
                {
                    new ConstantNode("Johny"),
                    new ConstantNode("John") 
                };
            yield return new FilterTestCase
            {
                Filter = "startswith('Johny','John')",
                ExpectedFilterCondition = new SingleValueFunctionCallNode("startswith", args4, EdmCoreModel.Instance.GetBoolean(false))
            };

            QueryNode[] args5 = new QueryNode[]
                {
                    new ConstantNode("Johny")
                };
            SingleValueFunctionCallNode outer3 = new SingleValueFunctionCallNode("tolower", args5, EdmCoreModel.Instance.GetString(true));
            yield return new FilterTestCase
            {
                Filter = "tolower('Johny') eq 'johny'",
                ExpectedFilterCondition = new BinaryOperatorNode(BinaryOperatorKind.Equal, outer3, new ConstantNode("johny"))
            };

            QueryNode[] args6 = new QueryNode[]
                {
                    new ConstantNode("Johny")
                };
            SingleValueFunctionCallNode outer4 = new SingleValueFunctionCallNode("toupper", args6, EdmCoreModel.Instance.GetString(true));
            yield return new FilterTestCase
            {
                Filter = "toupper('Johny') eq 'JOHNY'",
                ExpectedFilterCondition = new BinaryOperatorNode(BinaryOperatorKind.Equal, outer4, new ConstantNode("JOHNY"))
            };

            QueryNode[] args7 = new QueryNode[]
                {
                    new ConstantNode("Johny")
                };
            SingleValueFunctionCallNode outer5 = new SingleValueFunctionCallNode("trim", args7, EdmCoreModel.Instance.GetString(true));
            yield return new FilterTestCase
            {
                Filter = "trim('Johny') eq ''",
                ExpectedFilterCondition = new BinaryOperatorNode(BinaryOperatorKind.Equal, outer5, new ConstantNode(""))
            };

            QueryNode[] args8 = new QueryNode[]
                {
                    new ConstantNode("Johny"),
                    new ConstantNode (3)
                };
            SingleValueFunctionCallNode outer6 = new SingleValueFunctionCallNode("substring", args8, EdmCoreModel.Instance.GetString(true));
            yield return new FilterTestCase
            {
                Filter = "substring('Johny',3) eq 'ny'",
                ExpectedFilterCondition = new BinaryOperatorNode(BinaryOperatorKind.Equal, outer6, new ConstantNode("ny"))
            };

            QueryNode[] args9 = new QueryNode[]
                {
                    new ConstantNode("Johny"),
                    new ConstantNode(3),
                    new ConstantNode(1)
                };
            SingleValueFunctionCallNode outer7 = new SingleValueFunctionCallNode("substring", args9, EdmCoreModel.Instance.GetString(true));
            yield return new FilterTestCase
            {
                Filter = "substring('Johny',3,1) eq 'n'",
                ExpectedFilterCondition = new BinaryOperatorNode(BinaryOperatorKind.Equal, outer7, new ConstantNode("n"))
            };

            QueryNode[] args10 = new QueryNode[]
                {
                    new ConstantNode("oh"),
                    new ConstantNode("Johny")
                };
            yield return new FilterTestCase
            {
                Filter = "contains('oh','Johny')",
                ExpectedFilterCondition = new SingleValueFunctionCallNode("contains", args10, EdmCoreModel.Instance.GetBoolean(false))
            };

            QueryNode[] args11 = new QueryNode[]
                {
                    new ConstantNode("Johny"),
                    new ConstantNode(" Smith")
                };
            SingleValueFunctionCallNode outer8 = new SingleValueFunctionCallNode("concat", args11, EdmCoreModel.Instance.GetString(true));
            yield return new FilterTestCase
            {
                Filter = "concat('Johny',' Smith') eq ''",
                ExpectedFilterCondition = new BinaryOperatorNode(BinaryOperatorKind.Equal, outer8, new ConstantNode(""))
            };

            QueryNode[] args12 = new QueryNode[]
                {
                    new ConstantNode("Johny")
                };
            SingleValueFunctionCallNode outer9 = new SingleValueFunctionCallNode("length", args12, EdmCoreModel.Instance.GetInt32(false));
            yield return new FilterTestCase
            {
                Filter = "length('Johny') gt 0",
                ExpectedFilterCondition = new BinaryOperatorNode(BinaryOperatorKind.GreaterThan, outer9, new ConstantNode(0))
            };
        }
 public override void ValidateSingleValueFunctionCallNode(SingleValueFunctionCallNode node, ODataValidationSettings settings)
 {
     IncrementCount("ValidateSingleValueFunctionCallQueryNode");
     base.ValidateSingleValueFunctionCallNode(node, settings);
 }
        private string BindSingleValueFunctionCallNode(SingleValueFunctionCallNode singleValueFunctionCallNode)
        {
            var arguments = singleValueFunctionCallNode.Arguments.ToList();
            switch (singleValueFunctionCallNode.Name)
            {
                case "concat":
                    return singleValueFunctionCallNode.Name + "(" + Bind(arguments[0]) + "," + Bind(arguments[1]) + ")";

                case "length":
                case "trim":
                case "year":
                case "years":
                case "month":
                case "months":
                case "day":
                case "days":
                case "hour":
                case "hours":
                case "minute":
                case "minutes":
                case "second":
                case "seconds":
                case "round":
                case "floor":
                case "ceiling":
                    return singleValueFunctionCallNode.Name + "(" + Bind(arguments[0]) + ")";
                default:
                    throw new NotImplementedException();
            }
        }
 public void KindIsSingleValueFunctionCall()
 {
     SingleValueFunctionCallNode singleValueFunction = new SingleValueFunctionCallNode("stuff", null, EdmCoreModel.Instance.GetInt32(true));
     singleValueFunction.InternalKind.Should().Be(InternalQueryNodeKind.SingleValueFunctionCall);
 }
        /// <summary>
        /// Writes single value function call node to string.
        /// </summary>
        /// <param name="node">Node to write to string</param>
        /// <returns>String representation of node.</returns>
        private static string ToString(SingleValueFunctionCallNode node)
        {
            if (node != null)
            {
                return tabHelper.Prefix + "SingleValueFunctionCallNode" +
                    tabHelper.Indent(() =>
                        tabHelper.Prefix + "Name = " + node.Name +
                        tabHelper.Prefix + "Return Type = " + node.TypeReference +
                        tabHelper.Prefix + "Function = " + ToString(node.Functions) +
                        ArgumentsToString(node.Parameters)
                    );
            }

            return String.Empty;
        }
Esempio n. 43
0
 private string BindSingleValueFunctionCallNode(SingleValueFunctionCallNode singleValueFunctionCallNode)
 {
     var arguments = singleValueFunctionCallNode.Parameters.ToList();
     switch (singleValueFunctionCallNode.Name)
     {
         case "concat":
             return singleValueFunctionCallNode.Name + "(" + Bind(arguments[0]) + "," + Bind(arguments[1]) + ")";
         case "contains":
             return string.Format("{0} like '%{1}%'", Bind(arguments[0]), (arguments[1] as ConstantNode).Value);
         case "endswith":
             return string.Format("{0} like '%{1}'", Bind(arguments[0]), (arguments[1] as ConstantNode).Value);
         case "startswith":
             return string.Format("{0} like '{1}%'", Bind(arguments[0]), (arguments[1] as ConstantNode).Value);
         case "length":
             return string.Format("len({0})", Bind(arguments[0]));
         case "indexof":
             return string.Format("charindex('{0}',{1}", (arguments[1] as ConstantNode).Value, Bind(arguments[0]));
         case "substring":
         case "tolower":
         case "toupper":
         case "trim":
         case "year":
         case "years":
         case "month":
         case "months":
         case "day":
         case "days":
         case "hour":
         case "hours":
         case "minute":
         case "minutes":
         case "second":
         case "seconds":
         case "round":
         case "floor":
         case "ceiling":
             return singleValueFunctionCallNode.Name + "(" + Bind(arguments[0]) + ")";
         default:
             throw new NotImplementedException();
     }
 }
 public void TypeReferenceIsSetCorrectly()
 {
     SingleValueFunctionCallNode singleValueFunction = new SingleValueFunctionCallNode("stuff", null, EdmCoreModel.Instance.GetInt32(true));
     singleValueFunction.TypeReference.FullName().Should().Be(EdmCoreModel.Instance.GetInt32(true).FullName());
 }
Esempio n. 45
0
        /// <summary>
        /// Compares custom query option query nodes.
        /// </summary>
        /// <param name="left">Left side of comparison</param>
        /// <param name="right">Right side of comparison</param>
        /// <returns>True if equal, otherwise false</returns>
        //private bool Compare(CustomQueryOptionNode left, CustomQueryOptionNode right)
        //{
        //    if (left.Name != right.Name) return false;
        //    if (left.Value != right.Value) return false;
        //    return true;
        //}

        /// <summary>
        /// Compares single value function call query nodes.
        /// </summary>
        /// <param name="left">Left side of comparison</param>
        /// <param name="right">Right side of comparison</param>
        /// <returns>True if equal, otherwise false</returns>
        private bool Compare(SingleValueFunctionCallNode left, SingleValueFunctionCallNode right)
        {
            if (left.Name != right.Name) return false;
            if (left.TypeReference != right.TypeReference) return false;
            if (left.TypeReference != right.TypeReference) return false;

            for (int i = 0; i < left.Parameters.Count(); ++i)
            {
                if (!this.Compare(left.Parameters.ElementAt(i), right.Parameters.ElementAt(i))) return false;
            }

            return true;
        }
 public void ArgumentsBeConvertedToEmptyCollection()
 {
     SingleValueFunctionCallNode singleValueFunction = new SingleValueFunctionCallNode("stuff", null, EdmCoreModel.Instance.GetInt32(true));
     singleValueFunction.Parameters.Should().BeEmpty();
 }
Esempio n. 47
0
 /// <summary>
 /// Visit a SingleValueFunctionCallNode
 /// </summary>
 /// <param name="nodeIn">The node to visit</param>
 /// <returns>The translated expression</returns>
 public override Expression Visit(SingleValueFunctionCallNode nodeIn)
 {
     this.CheckArgumentNull(nodeIn, "node");
     return(this.TranslateFunctionCall(nodeIn.Name, nodeIn.Parameters));
 }