예제 #1
0
        /// <summary>
        /// Create a GroupByPropertyNode.
        /// </summary>
        /// <param name="name">The name of this node.</param>
        /// <param name="expression">The <see cref="SingleValueNode"/> of this node.</param>
        public GroupByPropertyNode(string name, SingleValueNode expression)
        {
            ExceptionUtils.CheckArgumentNotNull(name, "name");

            this.Name = name;
            this.Expression = expression;
        }
예제 #2
0
        /// <summary>
        /// Create a GroupByPropertyNode.
        /// </summary>
        /// <param name="name">The name of this node.</param>
        /// <param name="accessor">The <see cref="SingleValueNode"/> of this node.</param>
        public GroupByPropertyNode(string name, SingleValueNode accessor)
        {
            ExceptionUtils.CheckArgumentNotNull(name, "name");

            this.Name = name;
            this.Accessor = accessor;
        }
예제 #3
0
        /// <summary>
        /// Generates a bound query node representing an <see cref="IEdmProperty"/> given an already semantically bound parent node.
        /// </summary>
        /// <param name="parentNode">The semantically bound source node of this end path token</param>
        /// <param name="property">The <see cref="IEdmProperty"/> that will be bound to this node. Must not be primitive collection</param>
        /// <returns>QueryNode bound to this property.</returns>
        internal static QueryNode GeneratePropertyAccessQueryNode(SingleValueNode parentNode, IEdmProperty property)
        {
            ExceptionUtils.CheckArgumentNotNull(parentNode, "parent");
            ExceptionUtils.CheckArgumentNotNull(property, "property");

            // TODO: Remove this check. 
            // We should verify that the top level of an expression is a bool rather than arbitrarily restrict property types.
            // We can get here if there is a query like $filter=MyCollectionProperty eq 'foo' or something.
            // If it was $filter=MyCollectionProperty/any(...) then we would have gone down the 'NonRootSegment' code path instead of this one
            if (property.Type.IsNonEntityCollectionType())
            {
                // if this happens to be a top level node (i.e. $filter=MyCollection), then it will fail further up the chain, so
                // don't need to worry about checking for that here.
                return new CollectionPropertyAccessNode(parentNode, property);
            }

            if (property.PropertyKind == EdmPropertyKind.Navigation)
            {
                // These are error cases in practice, but we let ourselves throw later for better context-sensitive error messages
                var edmNavigationProperty = (IEdmNavigationProperty)property;
                var singleEntityParentNode = (SingleEntityNode)parentNode;
                if (edmNavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
                {
                    return new CollectionNavigationNode(edmNavigationProperty, singleEntityParentNode);
                }

                return new SingleNavigationNode(edmNavigationProperty, singleEntityParentNode);
            }

            return new SingleValuePropertyAccessNode(parentNode, property);
        }
        public ParameterAliasNodeTranslatorTest()
        {
            var builder = new ODataConventionModelBuilder();
            builder.EntitySet<ParameterAliasCustomer>("Customers");
            builder.EntitySet<ParameterAliasOrder>("Orders");

            builder.EntityType<ParameterAliasCustomer>().Function("CollectionFunctionCall")
                .ReturnsCollection<int>().Parameter<int>("p1");

            builder.EntityType<ParameterAliasCustomer>().Function("EntityCollectionFunctionCall")
                .ReturnsCollectionFromEntitySet<ParameterAliasCustomer>("Customers").Parameter<int>("p1");

            builder.EntityType<ParameterAliasCustomer>().Function("SingleEntityFunctionCall")
                .Returns<ParameterAliasCustomer>().Parameter<int>("p1");

            builder.EntityType<ParameterAliasCustomer>().Function("SingleEntityFunctionCallWithoutParameters")
                .Returns<ParameterAliasCustomer>();

            builder.EntityType<ParameterAliasCustomer>().Function("SingleValueFunctionCall")
                .Returns<int>().Parameter<int>("p1");

            _model = builder.GetEdmModel();
            _customersEntitySet = _model.FindDeclaredEntitySet("Customers");
            _customerEntityType = _customersEntitySet.EntityType();
            _parameterAliasMappedNode = new ConstantNode(123);
        }
예제 #5
0
        /// <summary>
        /// Creates a <see cref="FilterClause"/>.
        /// </summary>
        /// <param name="expression">The filter expression - this should evaluate to a single boolean value. Cannot be null.</param>
        /// <param name="rangeVariable">The parameter for the expression which represents a single value from the collection. Cannot be null.</param>
        /// <exception cref="System.ArgumentNullException">Throws if the input expression or rangeVariable is null.</exception>
        public FilterClause(SingleValueNode expression, RangeVariable rangeVariable)
        {
            ExceptionUtils.CheckArgumentNotNull(expression, "expression");
            ExceptionUtils.CheckArgumentNotNull(rangeVariable, "parameter");

            this.expression = expression;
            this.rangeVariable = rangeVariable;
        }
예제 #6
0
 public override void PromoteBinaryOperandTypes(
     BinaryOperatorKind binaryOperatorKind,
     ref SingleValueNode leftNode,
     ref SingleValueNode rightNode,
     out IEdmTypeReference typeReference)
 {
     stringAsEnum.PromoteBinaryOperandTypes(binaryOperatorKind, ref leftNode, ref rightNode, out typeReference);
 }
예제 #7
0
 /// <summary>
 /// Promote the left and right operand types
 /// </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 virtual void PromoteBinaryOperandTypes(
        BinaryOperatorKind binaryOperatorKind,
        ref SingleValueNode leftNode,
        ref SingleValueNode rightNode,
        out IEdmTypeReference typeReference)
 {
     typeReference = null;
     BinaryOperatorBinder.PromoteOperandTypes(binaryOperatorKind, ref leftNode, ref rightNode);
 }
예제 #8
0
        /// <summary>
        /// Creates an <see cref="OrderByClause"/>.
        /// </summary>
        /// <param name="thenBy">The next orderby to perform after performing this orderby, can be null in the case of only a single orderby expression.</param>
        /// <param name="expression">The order-by expression. Cannot be null.</param>
        /// <param name="direction">The direction to order.</param>
        /// <param name="rangeVariable">The rangeVariable for the expression which represents a single value from the collection we iterate over. </param>
        /// <exception cref="System.ArgumentNullException">Throws if the input expression or rangeVariable is null.</exception>
        public OrderByClause(OrderByClause thenBy, SingleValueNode expression, OrderByDirection direction, RangeVariable rangeVariable)
        {
            ExceptionUtils.CheckArgumentNotNull(expression, "expression");
            ExceptionUtils.CheckArgumentNotNull(rangeVariable, "parameter");

            this.thenBy = thenBy;
            this.expression = expression;
            this.direction = direction;
            this.rangeVariable = rangeVariable;
        }
예제 #9
0
        /// <summary>
        /// Ensures that the parent node is of entity type, throwing if it is not.
        /// </summary>
        /// <param name="parent">Parent node to a navigation property.</param>
        /// <returns>The given parent node as a SingleEntityNode.</returns>
        internal static SingleEntityNode EnsureParentIsEntityForNavProp(SingleValueNode parent)
        {
            ExceptionUtils.CheckArgumentNotNull(parent, "parent");
            SingleEntityNode parentEntity = parent as SingleEntityNode;
            if (parentEntity == null)
            {
                throw new ODataException(ODataErrorStrings.MetadataBinder_NavigationPropertyNotFollowingSingleEntityType);
            }

            return parentEntity;
        }
예제 #10
0
        /// <summary>
        /// Create a AggregateExpression.
        /// </summary>
        /// <param name="expression">The aggregation expression.</param>
        /// <param name="method">The <see cref="AggregationMethod"/>.</param>
        /// <param name="alias">The aggregation alias.</param>
        /// <param name="typeReference">The <see cref="IEdmTypeReference"/> of this aggregate expression.</param>
        public AggregateExpression(SingleValueNode expression, AggregationMethod method, string alias, IEdmTypeReference typeReference)
        {
            ExceptionUtils.CheckArgumentNotNull(expression, "expression");
            ExceptionUtils.CheckArgumentNotNull(alias, "alias");
            ExceptionUtils.CheckArgumentNotNull(typeReference, "typeReference");

            this.expression = expression;
            this.method = method;
            this.alias = alias;
            this.typeReference = typeReference;
        }
예제 #11
0
        /// <summary>
        /// Get the promoted type reference of the operand
        /// </summary>
        /// <param name="operand">the operand</param>
        /// <param name="unaryOperatorKind">the operator kind</param>
        /// <returns>the type reference of the operand</returns>
        private static IEdmTypeReference PromoteOperandType(SingleValueNode operand, UnaryOperatorKind unaryOperatorKind)
        {
            IEdmTypeReference typeReference = operand.TypeReference;
            if (!TypePromotionUtils.PromoteOperandType(unaryOperatorKind, ref typeReference))
            {
                string typeName = operand.TypeReference == null ? "<null>" : operand.TypeReference.ODataFullName();
                throw new ODataException(ODataErrorStrings.MetadataBinder_IncompatibleOperandError(typeName, unaryOperatorKind));
            }

            return typeReference;
        }
예제 #12
0
        /// <summary>
        /// This method generates a <see cref="SingleValueOpenPropertyAccessNode"/> for properties of open type
        /// </summary>
        /// <param name="endPathToken">EndPathToken to bind into an open property node.</param>
        /// <param name="parentNode">Parent node of this open property</param>
        /// <returns>Will return a <see cref="SingleValueOpenPropertyAccessNode"/> when open types are supported</returns>
        internal static SingleValueOpenPropertyAccessNode GeneratePropertyAccessQueryForOpenType(EndPathToken endPathToken, SingleValueNode parentNode)
        {
            if (parentNode.TypeReference != null && !parentNode.TypeReference.Definition.IsOpenType())
            {
                throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(
                    parentNode.TypeReference.FullName(),
                    endPathToken.Identifier));
            }

            return new SingleValueOpenPropertyAccessNode(parentNode, endPathToken.Identifier);
        }
        public void OrOperatorShouldResultInBinaryOperatorNode()
        {
            this.leftParameterSingleValueQueryNode = new ConstantNode(false);
            this.rightParameterSingleValueQueryNode = new ConstantNode(true);
            var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.Or, new LiteralToken(false), new LiteralToken(true));

            var resultNode = this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken);

            resultNode.ShouldBeBinaryOperatorNode(BinaryOperatorKind.Or).And.TypeReference.PrimitiveKind().Should().Be(EdmPrimitiveTypeKind.Boolean);
            resultNode.As<BinaryOperatorNode>().Left.ShouldBeConstantQueryNode(false);
            resultNode.As<BinaryOperatorNode>().Right.ShouldBeConstantQueryNode(true);
        }
        public void AndOperatorCompatibleTypeShouldResultInBinaryOperatorNode()
        {
            this.leftParameterSingleValueQueryNode = new UnaryOperatorNode(UnaryOperatorKind.Negate, new UnaryOperatorNode(UnaryOperatorKind.Not, new ConstantNode(null)));
            this.rightParameterSingleValueQueryNode = new SingleValueFunctionCallNode("func", null, EdmCoreModel.Instance.GetBoolean(false));
            var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.And, new LiteralToken("foo"), new LiteralToken("bar"));

            var resultNode = this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken);

            resultNode.ShouldBeBinaryOperatorNode(BinaryOperatorKind.And).And.TypeReference.PrimitiveKind().Should().Be(EdmPrimitiveTypeKind.Boolean);
            resultNode.As<BinaryOperatorNode>().Left.ShouldBeConvertQueryNode(EdmPrimitiveTypeKind.Boolean);
            resultNode.As<BinaryOperatorNode>().Right.ShouldBeConvertQueryNode(EdmPrimitiveTypeKind.Boolean);
        }
예제 #15
0
        /// <summary>
        /// Create a AggregateStatement.
        /// </summary>
        /// <param name="expression">The aggregation expression.</param>
        /// <param name="withVerb">The <see cref="AggregationVerb"/>.</param>
        /// <param name="from">The aggregation from <see cref="SingleValuePropertyAccessNode"/>.</param>
        /// <param name="alias">The aggregation alias.</param>
        /// <param name="typeReference">The <see cref="IEdmTypeReference"/> of this aggregate statement.</param>
        public AggregateStatement(SingleValueNode expression, AggregationVerb withVerb, SingleValuePropertyAccessNode from, string alias, IEdmTypeReference typeReference)
        {
            ExceptionUtils.CheckArgumentNotNull(expression, "expression");
            ExceptionUtils.CheckArgumentNotNull(alias, "alias");
            ExceptionUtils.CheckArgumentNotNull(typeReference, "typeReference");

            this.expression = expression;
            this.withVerb = withVerb;
            this.from = from;
            this.alias = alias;
            this.typeReference = typeReference;
        }
예제 #16
0
        /// <summary>
        /// Promote the left and right operand types
        /// </summary>
        /// <param name="binaryOperatorKind">the operator kind</param>
        /// <param name="left">the left operand</param>
        /// <param name="right">the right operand</param>
        internal static void PromoteOperandTypes(BinaryOperatorKind binaryOperatorKind, ref SingleValueNode left, ref SingleValueNode right)
        {
            IEdmTypeReference leftType;
            IEdmTypeReference rightType;
            if (!TypePromotionUtils.PromoteOperandTypes(binaryOperatorKind, left, right, out leftType, out rightType))
            {
                string leftTypeName = left.TypeReference == null ? "<null>" : left.TypeReference.FullName();
                string rightTypeName = right.TypeReference == null ? "<null>" : right.TypeReference.FullName();
                throw new ODataException(ODataErrorStrings.MetadataBinder_IncompatibleOperandsError(leftTypeName, rightTypeName, binaryOperatorKind));
            }

            left = MetadataBindingUtils.ConvertToTypeIfNeeded(left, leftType);
            right = MetadataBindingUtils.ConvertToTypeIfNeeded(right, rightType);
        }
        /// <summary>
        /// Constructs a new <see cref="CollectionPropertyAccessNode"/>.
        /// </summary>
        /// <param name="source">The value containing the property.</param>
        /// <param name="property">The EDM property which is to be accessed.</param>
        /// <exception cref="System.ArgumentNullException">Throws if the input source or property is null.</exception>
        /// <exception cref="ArgumentException">Throws if the input property is not a collection of structural properties</exception>
        public CollectionPropertyAccessNode(SingleValueNode source, IEdmProperty property)
        {
            ExceptionUtils.CheckArgumentNotNull(source, "source");
            ExceptionUtils.CheckArgumentNotNull(property, "property");

            if (property.PropertyKind != EdmPropertyKind.Structural)
            {
                throw new ArgumentException(ODataErrorStrings.Nodes_PropertyAccessShouldBeNonEntityProperty(property.Name));
            }

            if (!property.Type.IsCollection())
            {
                throw new ArgumentException(ODataErrorStrings.Nodes_PropertyAccessTypeMustBeCollection(property.Name));
            }

            this.source   = source;
            this.property = property;
            this.collectionTypeReference = property.Type.AsCollection();
            this.itemType = this.collectionTypeReference.ElementType();
        }
예제 #18
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;
        }
예제 #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);
        }
예제 #20
0
        /// <summary>
        /// Translate parameter alias node to corresponding single value node.
        /// </summary>
        /// <param name="node">The node to be translated.</param>
        /// <param name="parameterAliasNodes">The parameter alias node mapping.</param>
        /// <returns>The translated node.</returns>
        public static Semantic.SingleValueNode TranslateParameterAlias(
            Semantic.SingleValueNode node,
            IDictionary <string, Semantic.SingleValueNode> parameterAliasNodes)
        {
            if (node == null)
            {
                throw Error.ArgumentNull("node");
            }

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

            Semantic.ParameterAliasNode parameterAliasNode = node as Semantic.ParameterAliasNode;

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

            Semantic.SingleValueNode singleValueNode;

            if (parameterAliasNodes.TryGetValue(parameterAliasNode.Alias, out singleValueNode) &&
                singleValueNode != null)
            {
                if (singleValueNode is Semantic.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);
        }
예제 #21
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);
        }
        public void AndOperatorNullLiteralShouldResultInBinaryOperatorNodeWithConvert()
        {
            this.leftParameterSingleValueQueryNode = new ConstantNode(null);
            this.rightParameterSingleValueQueryNode =
                new SingleValueFunctionCallNode(FuncName, null, EdmCoreModel.Instance.GetBoolean(false));

            var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.And, new LiteralToken("foo"), new LiteralToken("bar"));

            var resultNode = this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken);

            var binaryNode = resultNode.ShouldBeBinaryOperatorNode(BinaryOperatorKind.And).And;

            binaryNode.TypeReference.IsNullable.Should().BeTrue();

            var left = binaryNode.Left.ShouldBeConvertQueryNode(EdmPrimitiveTypeKind.Boolean).And;
            left.TypeReference.IsNullable.Should().BeTrue();
            left.Source.ShouldBeConstantQueryNode<object>(null);

            var right = binaryNode.Right.ShouldBeConvertQueryNode(EdmPrimitiveTypeKind.Boolean).And;
            right.TypeReference.IsNullable.Should().BeTrue();
            right.Source.ShouldBeSingleValueFunctionCallQueryNode(FuncName);
        }
예제 #23
0
 private Expression BindAccessor(SingleValueNode node)
 {
     switch (node.Kind)
     {
         case QueryNodeKind.EntityRangeVariableReference:
             return this._lambdaParameter;
         case QueryNodeKind.SingleValuePropertyAccess:
             var propAccessNode = node as SingleValuePropertyAccessNode;
             return CreatePropertyAccessExpression(BindAccessor(propAccessNode.Source), propAccessNode.Property);
         case QueryNodeKind.SingleValueOpenPropertyAccess:
             var openNode = node as SingleValueOpenPropertyAccessNode;
             return Expression.Property(BindAccessor(openNode.Source), openNode.Name);
         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);
     }
 }
예제 #24
0
 /// <summary>
 /// Create a BinaryOperatorNode
 /// </summary>
 /// <param name="operatorKind">The binary operator type.</param>
 /// <param name="left">The left operand.</param>
 /// <param name="right">The right operand.</param>
 /// <exception cref="System.ArgumentNullException">Throws if the left or right inputs are null.</exception>
 /// <exception cref="ODataException">Throws if the two operands don't have the same type.</exception>
 public BinaryOperatorNode(BinaryOperatorKind operatorKind, SingleValueNode left, SingleValueNode right)
     : this(operatorKind, left, right, /*typeReference*/ null)
 {
 }
        public void LeftTokenTypeImcompatibleWithRightTokenShouldFail()
        {
            this.leftParameterSingleValueQueryNode = new ConstantNode(true);
            this.rightParameterSingleValueQueryNode = new ConstantNode(1);
            var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.Equal, new LiteralToken("foo"), new LiteralToken("bar"));
            Action bind = () => this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken);

            bind.ShouldThrow<ODataException>().
                WithMessage((Strings.MetadataBinder_IncompatibleOperandsError("Edm.Boolean", "Edm.Int32", BinaryOperatorKind.Equal)));
        }
        public void RightTokenTypeImcompatibleWithOperatorShouldFail()
        {
            this.leftParameterSingleValueQueryNode = new ConstantNode(999);
            this.rightParameterSingleValueQueryNode = new ConstantNode(string.Empty);
            var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.Multiply, new LiteralToken("foo"), new LiteralToken("bar"));
            Action bind = () => this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken);

            bind.ShouldThrow<ODataException>().
                WithMessage((Strings.MetadataBinder_IncompatibleOperandsError("Edm.Int32", "Edm.String", BinaryOperatorKind.Multiply)));
        }
        public void LeftTokenTypeIncompatibleWithOperatorAndRightTokenOpenPropertyShouldFail()
        {
            this.leftParameterSingleValueQueryNode = new ConstantNode(DateTimeOffset.Now);
            this.rightParameterSingleValueQueryNode = new SingleValueOpenPropertyAccessNode(new ConstantNode(null), "SomeProperty");
            var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.And, new LiteralToken("foo"), new LiteralToken("bar"));
            Action bind = () => this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken);

            bind.ShouldThrow<ODataException>().
                WithMessage((Strings.MetadataBinder_IncompatibleOperandsError("Edm.DateTimeOffset", "<null>", BinaryOperatorKind.And)));
        }
        public void GreaterThanOrEqualOperatorShouldResultInBinaryOperatorNode()
        {
            this.leftParameterSingleValueQueryNode = new ConstantNode(99);
            this.rightParameterSingleValueQueryNode = new ConstantNode(99.1);
            var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.GreaterThanOrEqual, new LiteralToken("foo"), new LiteralToken("bar"));

            var resultNode = this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken);

            resultNode.ShouldBeBinaryOperatorNode(BinaryOperatorKind.GreaterThanOrEqual).And.TypeReference.PrimitiveKind().Should().Be(EdmPrimitiveTypeKind.Boolean);
            resultNode.As<BinaryOperatorNode>().Left.ShouldBeConstantQueryNode(99d);
            resultNode.As<BinaryOperatorNode>().Right.ShouldBeConstantQueryNode(99.1);
        }
예제 #29
0
 /// <summary>
 /// Create a GroupByPropertyNode.
 /// </summary>
 /// <param name="name">The name of this node.</param>
 /// <param name="expression">The <see cref="SingleValueNode"/> of this node.</param>
 /// <param name="type">The <see cref="IEdmTypeReference"/> of this node.</param>
 public GroupByPropertyNode(string name, SingleValueNode expression, IEdmTypeReference type)
     : this(name, expression)
 {
     this.typeReference = type;
 }
        public void AndOperatorNullAndOpenPropertyShouldResultInBinaryOperatorNodeWithNullType()
        {
            this.leftParameterSingleValueQueryNode = new ConstantNode(null);
            this.rightParameterSingleValueQueryNode = new SingleValueOpenPropertyAccessNode(new ConstantNode(null), OpenPropertyName);

            var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.And, new LiteralToken("foo"), new LiteralToken("bar"));

            var resultNode = this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken);

            var binaryNode = resultNode.ShouldBeBinaryOperatorNode(BinaryOperatorKind.And).And;

            binaryNode.TypeReference.Should().BeNull();
            binaryNode.Left.ShouldBeConstantQueryNode<object>(null);
            binaryNode.Right.ShouldBeSingleValueOpenPropertyAccessQueryNode(OpenPropertyName);
        }
        /// <summary>
        /// Create a BinaryOperatorNode
        /// </summary>
        /// <param name="operatorKind">The binary operator type.</param>
        /// <param name="left">The left operand.</param>
        /// <param name="right">The right operand.</param>
        /// <exception cref="System.ArgumentNullException">Throws if the left or right inputs are null.</exception>
        /// <exception cref="ODataException">Throws if the two operands don't have the same type.</exception>
        public BinaryOperatorNode(BinaryOperatorKind operatorKind, SingleValueNode left, SingleValueNode right)
        {
            ExceptionUtils.CheckArgumentNotNull(left, "left");
            ExceptionUtils.CheckArgumentNotNull(right, "right");
            this.operatorKind = operatorKind;
            this.left         = left;
            this.right        = right;

            // set the TypeReerence based on the Operands.
            if (this.Left == null || this.Right == null || this.Left.TypeReference == null || this.Right.TypeReference == null)
            {
                this.typeReference = null;
            }
            else
            {
                // Ensure that both operands have the same type
                if (!this.Left.TypeReference.Definition.IsEquivalentTo(this.Right.TypeReference.Definition))
                {
                    throw new ODataException(
                              ODataErrorStrings.BinaryOperatorQueryNode_OperandsMustHaveSameTypes(
                                  this.Left.TypeReference.ODataFullName(), this.Right.TypeReference.ODataFullName()));
                }

                // Get a primitive type reference; this must not fail since we checked that the type is of kind 'primitive'.
                IEdmPrimitiveTypeReference primitiveOperatorTypeReference =
                    this.Left.TypeReference.AsPrimitive();

                this.typeReference = QueryNodeUtils.GetBinaryOperatorResultType(primitiveOperatorTypeReference, this.OperatorKind);
            }
        }
예제 #32
0
 public override void PromoteBinaryOperandTypes(BinaryOperatorKind binaryOperatorKind,
                                                ref SingleValueNode leftNode, ref SingleValueNode rightNode, out IEdmTypeReference typeReference)
 {
     _stringAsEnum.PromoteBinaryOperandTypes(binaryOperatorKind, ref leftNode, ref rightNode, out typeReference);
 }
예제 #33
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)
        {
            // TODO 1577: remove this and add it to switch, once the ODataLib v4 EnumNode.Kind bug is fixed.
            EnumNode enumNode = node as EnumNode;
            if (enumNode != null)
            {
                ValidateEnumNode(enumNode, settings);
                return;
            }

            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;
            }
        }
예제 #34
0
        /// <summary>
        /// Create a BinaryOperatorNode
        /// </summary>
        /// <param name="operatorKind">The binary operator type.</param>
        /// <param name="left">The left operand.</param>
        /// <param name="right">The right operand.</param>
        /// <param name="typeReference">The result typeReference.</param>
        /// <exception cref="System.ArgumentNullException">Throws if the left or right inputs are null.</exception>
        internal BinaryOperatorNode(BinaryOperatorKind operatorKind, SingleValueNode left, SingleValueNode right, IEdmTypeReference typeReference)
        {
            ExceptionUtils.CheckArgumentNotNull(left, "left");
            ExceptionUtils.CheckArgumentNotNull(right, "right");
            this.operatorKind = operatorKind;
            this.left         = left;
            this.right        = right;

            // set the TypeReference if explictly given, otherwise based on the Operands.
            if (typeReference != null)
            {
                this.typeReference = typeReference;
            }
            else if (this.Left == null || this.Right == null || this.Left.TypeReference == null || this.Right.TypeReference == null)
            {
                this.typeReference = null;
            }
            else
            {
                // Get a primitive type reference; this must not fail since we checked that the type is of kind 'primitive'.
                IEdmPrimitiveTypeReference leftType  = this.Left.TypeReference.AsPrimitive();
                IEdmPrimitiveTypeReference rightType = this.Right.TypeReference.AsPrimitive();

                this.typeReference = QueryNodeUtils.GetBinaryOperatorResultType(leftType, rightType, this.OperatorKind);
            }
        }
        public void ModuloOperatorShouldResultInBinaryOperatorNode()
        {
            this.leftParameterSingleValueQueryNode = new ConstantNode(-9.9);
            this.rightParameterSingleValueQueryNode = new ConstantNode(-100.9);
            var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.Modulo, new LiteralToken("foo"), new LiteralToken("bar"));

            var resultNode = this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken);

            resultNode.ShouldBeBinaryOperatorNode(BinaryOperatorKind.Modulo).And.TypeReference.PrimitiveKind().Should().Be(EdmPrimitiveTypeKind.Double);
            resultNode.As<BinaryOperatorNode>().Left.ShouldBeConstantQueryNode(-9.9);
            resultNode.As<BinaryOperatorNode>().Right.ShouldBeConstantQueryNode(-100.9);
        }
        /// <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;
            }
        }
 /// <summary>
 /// Created a SingleValueCastNode with the given source node and the given type to cast to.
 /// </summary>
 /// <param name="source"> Source <see cref="SingleValueNode"/> that is being cast.</param>
 /// <param name="complexType">Type to cast to.</param>
 /// <exception cref="System.ArgumentNullException">Throws if the input complexType is null.</exception>
 public SingleValueCastNode(SingleValueNode source, IEdmComplexType complexType)
 {
     ExceptionUtils.CheckArgumentNotNull(complexType, "complexType");
     this.source        = source;
     this.typeReference = new EdmComplexTypeReference(complexType, false);
 }