public void EntityTypeReferenceSetCorrectly() { SingleResourceFunctionCallNode singleEntityFunctionCall = new SingleResourceFunctionCallNode("stuff", new QueryNode[] { new ConstantNode(1) }, HardCodedTestModel.GetPersonTypeReference(), HardCodedTestModel.GetPeopleSet()); singleEntityFunctionCall.StructuredTypeReference.FullName().Should().Be(HardCodedTestModel.GetPersonTypeReference().FullName()); singleEntityFunctionCall.TypeReference.FullName().Should().Be(HardCodedTestModel.GetPersonTypeReference().FullName()); }
/// <summary> /// Compares SingleEntityFunctionCall 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(SingleResourceFunctionCallNode left, SingleResourceFunctionCallNode right) { if (left.Parameters.Count() != right.Parameters.Count()) { return(false); } if (left.NavigationSource != right.NavigationSource) { return(false); } if (left.StructuredTypeReference != right.StructuredTypeReference) { return(false); } if (left.Name != right.Name) { 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 ArgumentsSetCorrectly() { SingleResourceFunctionCallNode singleEntityFunctionCall = new SingleResourceFunctionCallNode("stuff", new QueryNode[] { new ConstantNode(1) }, ModelBuildingHelpers.BuildValidEntityType().ToTypeReference().AsEntity(), HardCodedTestModel.GetPeopleSet()); singleEntityFunctionCall.Parameters.Should().HaveCount(1); singleEntityFunctionCall.Parameters.ElementAt(0).ShouldBeConstantQueryNode(1); }
private Expression BindSingleResourceCastFunctionCall(SingleResourceFunctionCallNode node) { Contract.Assert(ClrCanonicalFunctions.CastFunctionName == node.Name); Expression[] arguments = BindArguments(node.Parameters); Contract.Assert(arguments.Length == 2); string targetEdmTypeName = (string)((ConstantNode)node.Parameters.Last()).Value; IEdmType targetEdmType = Model.FindType(targetEdmTypeName); Type targetClrType = null; if (targetEdmType != null) { targetClrType = EdmLibHelpers.GetClrType(targetEdmType.ToEdmTypeReference(false), Model); } if (arguments[0].Type == targetClrType) { // We only support to cast Entity type to the same type now. return(arguments[0]); } else if (arguments[0].Type.IsAssignableFrom(targetClrType)) { // To support to cast Entity/Complex type to the sub type now. Expression source = BindCastSourceNode(node.Source); return(Expression.TypeAs(source, targetClrType)); } else { // Cast fails and return null. return(NullConstant); } }
public void ParametersSetCorrectly() { SingleResourceFunctionCallNode singleEntityFunctionCall = new SingleResourceFunctionCallNode("stuff", null, null, ModelBuildingHelpers.BuildValidEntityType().ToTypeReference().AsEntity(), null, null); singleEntityFunctionCall.Parameters.Should().NotBeNull(); singleEntityFunctionCall.Parameters.Should().BeEmpty(); }
/// <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) { if (node == null) { return(null); } 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)); case QueryNodeKind.CollectionNavigationNode: CollectionNavigationNode collectionNavigationNode = node as CollectionNavigationNode; return(GetResourceRangeVariableReferenceNode(collectionNavigationNode.Source)); case QueryNodeKind.SingleNavigationNode: SingleNavigationNode singleNavigationNode = node as SingleNavigationNode; return(GetResourceRangeVariableReferenceNode(singleNavigationNode.Source)); case QueryNodeKind.CollectionResourceFunctionCall: CollectionResourceFunctionCallNode collectionResourceFunctionCallNode = node as CollectionResourceFunctionCallNode; return(GetResourceRangeVariableReferenceNode(collectionResourceFunctionCallNode.Source)); case QueryNodeKind.SingleResourceFunctionCall: SingleResourceFunctionCallNode singleResourceFunctionCallNode = node as SingleResourceFunctionCallNode; return(GetResourceRangeVariableReferenceNode(singleResourceFunctionCallNode.Source)); } return(null); }
public void EntityTypeReferenceSetCorrectly() { string name = HardCodedTestModel.GetPersonTypeReference().FullName(); SingleResourceFunctionCallNode singleEntityFunctionCall = new SingleResourceFunctionCallNode("stuff", new QueryNode[] { new ConstantNode(1) }, HardCodedTestModel.GetPersonTypeReference(), HardCodedTestModel.GetPeopleSet()); Assert.Equal(name, singleEntityFunctionCall.StructuredTypeReference.FullName()); Assert.Equal(name, singleEntityFunctionCall.TypeReference.FullName()); }
private void ValidateSingleResourceFunctionCallNode(SingleResourceFunctionCallNode node, ValidationSettings settings) { ValidateFunction(node.Name, settings); foreach (var argumentNode in node.Parameters) { ValidateQueryNode(argumentNode, settings); } }
/// <summary> /// Translate a SingleResourceFunctionCallNode. /// </summary> /// <param name="nodeIn">The node to be translated.</param> /// <returns>The translated node.</returns> public override QueryNode Visit(SingleResourceFunctionCallNode nodeIn) { return(new SingleResourceFunctionCallNode( nodeIn.Name, nodeIn.Functions, nodeIn.Parameters.Select(p => p.Accept(this)), nodeIn.StructuredTypeReference, nodeIn.NavigationSource, nodeIn.Source == null ? null : nodeIn.Source.Accept(this))); }
/// <summary> /// Translates a <see cref="SingleEntityFunctionCallNode"/> into a corresponding <see cref="string"/>. /// </summary> /// <param name="node">The node to translate.</param> /// <returns>The translated string.</returns> public override string Visit(SingleResourceFunctionCallNode node) { string result = node.Name; if (node.Source != null) { result = this.TranslatePropertyAccess(node.Source, result); } return(this.TranslateFunctionCall(result, node.Parameters)); }
/// <summary> /// Binds a <see cref="SingleResourceFunctionCallNode"/> to create a LINQ <see cref="Expression"/> that /// represents the semantics of the <see cref="SingleResourceFunctionCallNode"/>. /// </summary> /// <param name="node">The node to bind.</param> /// <returns>The LINQ <see cref="Expression"/> created.</returns> public virtual Expression BindSingleResourceFunctionCallNode(SingleResourceFunctionCallNode node) { switch (node.Name) { case ClrCanonicalFunctions.CastFunctionName: return(BindSingleResourceCastFunctionCall(node)); default: throw Error.NotSupported(SRResources.ODataFunctionNotSupported, node.Name); } }
/// <summary> /// Override this method to validate single resource function calls, such as 'cast'. /// </summary> /// <param name="node">The node to validate.</param> /// <param name="settings">The settings to use while validating.</param> /// <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> protected virtual void ValidateSingleResourceFunctionCallNode(SingleResourceFunctionCallNode node, ODataValidationSettings settings) { Contract.Assert(node != null); Contract.Assert(settings != null); ValidateFunction(node.Name, settings); foreach (QueryNode argumentNode in node.Parameters) { ValidateQueryNode(argumentNode, settings); } }
public override QueryNode Visit(SingleResourceFunctionCallNode nodeIn) { QueryNode?source = nodeIn.Source == null ? null : Visit(nodeIn.Source); IEnumerable <QueryNode>?parameters = VisitParameters(nodeIn.Parameters); if (nodeIn.Source != source || nodeIn.Parameters != parameters) { nodeIn = new SingleResourceFunctionCallNode(nodeIn.Name, nodeIn.Functions, parameters, nodeIn.StructuredTypeReference, nodeIn.NavigationSource, source); } return(nodeIn); }
/// <summary> /// Translates a <see cref="SingleResourceFunctionCallNode"/> into a corresponding <see cref="String"/>. /// </summary> /// <param name="node">The node to translate.</param> /// <returns>The translated String.</returns> public override String Visit(SingleResourceFunctionCallNode node) { ExceptionUtils.CheckArgumentNotNull(node, "node"); String result = node.Name; if (node.Source != null) { result = this.TranslatePropertyAccess(node.Source, result); } return this.TranslateFunctionCall(result, node.Parameters); }
/// <summary> /// Visit a SingleResourceFunctionCallNode /// </summary> /// <param name="nodeIn">the node to visit</param> /// <returns>true, indicating that the node has been visited.</returns> public override bool Visit(SingleResourceFunctionCallNode 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> /// Writes single entity 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(SingleResourceFunctionCallNode node) { if (node != null) { return(tabHelper.Prefix + "SingleResourceFunctionCallNode" + tabHelper.Indent(() => tabHelper.Prefix + "NavigationSource = " + node.NavigationSource.Name + tabHelper.Prefix + "Type Reference = " + node.TypeReference + tabHelper.Prefix + "Name = " + node.Name + tabHelper.Prefix + "Function = " + ToString(node.Functions) + ArgumentsToString(node.Parameters) )); } return(String.Empty); }
private Expression BindSingleResourceCastFunctionCall(SingleResourceFunctionCallNode node) { Contract.Assert(ClrCanonicalFunctions.CastFunctionName == node.Name); Expression[] arguments = BindArguments(node.Parameters); Contract.Assert(arguments.Length == 2); string targetEdmTypeName = (string)((ConstantNode)node.Parameters.Last()).Value; IEdmType targetEdmType = Model.FindType(targetEdmTypeName); Type targetClrType = null; if (targetEdmType != null) { targetClrType = Model.GetClrType(targetEdmType.ToEdmTypeReference(false)); } if (arguments[0].Type == targetClrType) { // We only support to cast Entity type to the same type now. return(arguments[0]); } else if (arguments[0].Type.IsAssignableFrom(targetClrType)) { // To support to cast Entity/Complex type to the sub type now. Expression source; if (node.Source != null) { source = BindCastSourceNode(node.Source); } else { // if the cast is on the root i.e $it (~/Products?$filter=NS.PopularProducts/.....), // node.Source would be null. Calling BindCastSourceNode will always return '$it'. // In scenarios where we are casting a navigation property to return an expression that queries against the parent property, // we need to have a memberAccess expression e.g '$it.Category'. We can get this from arguments[0]. source = arguments[0]; } return(Expression.TypeAs(source, targetClrType)); } else { // Cast fails and return null. return(NullConstant); } }
/// <summary> /// Override this method to validate single resource function calls, such as 'cast'. /// </summary> /// <param name="node">The node to validate.</param> /// <param name="settings">The settings to use while validating.</param> /// <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> public virtual void ValidateSingleResourceFunctionCallNode(SingleResourceFunctionCallNode node, ODataValidationSettings settings) { if (node == null) { throw Error.ArgumentNull(nameof(node)); } if (settings == null) { throw Error.ArgumentNull(nameof(settings)); } ValidateFunction(node.Name, settings); foreach (QueryNode argumentNode in node.Parameters) { ValidateQueryNode(argumentNode, settings); } }
public void NameIsSetCorrectly() { SingleResourceFunctionCallNode singleEntityFunctionCall = new SingleResourceFunctionCallNode("stuff", new QueryNode[] { }, ModelBuildingHelpers.BuildValidEntityType().ToTypeReference().AsEntity(), HardCodedTestModel.GetPeopleSet()); singleEntityFunctionCall.ShouldBeSingleResourceFunctionCallNode("stuff"); }
/// <summary> /// Visit a SingleResourceFunctionCallNode /// </summary> /// <param name="nodeIn">The node to visit</param> /// <returns>The translated expression</returns> public override Expression Visit(SingleResourceFunctionCallNode nodeIn) { throw new NotImplementedException(); }
public override T Visit(SingleResourceFunctionCallNode nodeIn) => DebuggerBreakVisited(nodeIn);
public void KindIsSingleEntityFunction() { SingleResourceFunctionCallNode singleEntityFunctionCall = new SingleResourceFunctionCallNode("stuff", new QueryNode[] { new ConstantNode(1) }, ModelBuildingHelpers.BuildValidEntityType().ToTypeReference().AsEntity(), HardCodedTestModel.GetPeopleSet()); singleEntityFunctionCall.Kind.Should().Be(QueryNodeKind.SingleResourceFunctionCall); }
public void FunctionImportsAreSetCorrectly() { SingleResourceFunctionCallNode singleEntityFunctionCall = new SingleResourceFunctionCallNode("HasDog", HardCodedTestModel.GetHasDogOverloads(), null, ModelBuildingHelpers.BuildValidEntityType().ToTypeReference().AsEntity(), ModelBuildingHelpers.BuildValidEntitySet(), null); singleEntityFunctionCall.Functions.Should().ContainExactly(HardCodedTestModel.GetHasDogOverloads()); }