private object ProcessNode(SingleValueQueryNode queryNode) { switch (queryNode.Kind) { case QueryNodeKind.Constant: return(ProcessConstant(queryNode as ConstantQueryNode)); case QueryNodeKind.Convert: var convertNode = queryNode as ConvertQueryNode; var sourceValue = ProcessNode(convertNode.Source); if (convertNode.Source is ConstantQueryNode) { if (convertNode.TargetType.IsInt32()) { return(Convert.ToInt32(sourceValue)); } if (convertNode.TargetType.IsString()) { return(sourceValue.ToString()); } if (convertNode.TargetType.IsDecimal()) { return(Convert.ToDecimal(sourceValue)); } throw new NotImplementedException("Haven't yet implemented convert to type " + convertNode.TargetType); } return(sourceValue); case QueryNodeKind.BinaryOperator: var binaryOperatorNode = queryNode as BinaryOperatorQueryNode; return(BindOperator(binaryOperatorNode)); case QueryNodeKind.UnaryOperator: var unaryOperatorNode = queryNode as UnaryOperatorQueryNode; return(BindOperator(unaryOperatorNode)); case QueryNodeKind.PropertyAccess: return(ProcessNode(queryNode as PropertyAccessQueryNode)); case QueryNodeKind.SingleValueFunctionCall: return(BindSingleValueFunctionCall(queryNode as SingleValueFunctionCallQueryNode)); default: throw new NotImplementedException("No support for " + queryNode.Kind); } }
/// <summary> /// Checks if the source is of the specified type and if not tries to inject a convert. /// </summary> /// <param name="source">The source node to apply the convertion to.</param> /// <param name="targetTypeReference">The target primitive type.</param> /// <returns>The converted query node.</returns> private static SingleValueQueryNode ConvertToType(SingleValueQueryNode source, IEdmTypeReference targetTypeReference) { Debug.Assert(source != null, "source != null"); Debug.Assert(targetTypeReference != null, "targetType != null"); Debug.Assert(targetTypeReference.IsODataPrimitiveTypeKind(), "Can only convert primitive types."); if (source.TypeReference != null) { // TODO: Do we check this here or in the caller? Debug.Assert(source.TypeReference.IsODataPrimitiveTypeKind(), "Can only work on primitive types."); if (source.TypeReference.IsEquivalentTo(targetTypeReference)) { return source; } else { if (!TypePromotionUtils.CanConvertTo(source.TypeReference, targetTypeReference)) { throw new ODataException(Strings.MetadataBinder_CannotConvertToType(source.TypeReference.ODataFullName(), targetTypeReference.ODataFullName())); } } } // If the source doesn't have a type (possibly an open property), then it's possible to convert it // cause we don't know for sure. return new ConvertQueryNode() { Source = source, TargetType = targetTypeReference }; }
private Expression Bind(QueryNode node) { CollectionQueryNode collectionNode = node as CollectionQueryNode; SingleValueQueryNode singleValueNode = node as SingleValueQueryNode; IncrementBindCount(); if (collectionNode != null) { switch (node.Kind) { case QueryNodeKind.Filter: return(BindFilterQueryNode(node as FilterQueryNode)); case QueryNodeKind.Segment: CollectionNavigationNode navigationNode = node as CollectionNavigationNode; return(BindNavigationPropertyNode(navigationNode.Source, navigationNode.NavigationProperty())); default: throw Error.NotSupported(SRResources.QueryNodeBindingNotSupported, node.Kind, typeof(FilterBinder).Name); } } else if (singleValueNode != null) { switch (node.Kind) { case QueryNodeKind.BinaryOperator: return(BindBinaryOperatorQueryNode(node as BinaryOperatorQueryNode)); case QueryNodeKind.Constant: return(BindConstantQueryNode(node as ConstantQueryNode)); case QueryNodeKind.Convert: return(BindConvertQueryNode(node as ConvertQueryNode)); case QueryNodeKind.Parameter: return(BindParameterQueryNode(node as ParameterQueryNode)); case QueryNodeKind.PropertyAccess: return(BindPropertyAccessQueryNode(node as PropertyAccessQueryNode)); case QueryNodeKind.UnaryOperator: return(BindUnaryOperatorQueryNode(node as UnaryOperatorQueryNode)); case QueryNodeKind.SingleValueFunctionCall: return(BindSingleValueFunctionCallQueryNode(node as SingleValueFunctionCallQueryNode)); case QueryNodeKind.Segment: SingletonNavigationNode navigationNode = node as SingletonNavigationNode; return(BindNavigationPropertyNode(navigationNode.Source, navigationNode.NavigationProperty)); case QueryNodeKind.Any: return(BindAnyQueryNode(node as AnyQueryNode)); case QueryNodeKind.All: return(BindAllQueryNode(node as AllQueryNode)); default: throw Error.NotSupported(SRResources.QueryNodeBindingNotSupported, node.Kind, typeof(FilterBinder).Name); } } else { throw Error.NotSupported(SRResources.QueryNodeBindingNotSupported, node.Kind, typeof(FilterBinder).Name); } }
private object ProcessNode(SingleValueQueryNode queryNode) { switch (queryNode.Kind) { case QueryNodeKind.Constant: return ProcessConstant(queryNode as ConstantQueryNode); case QueryNodeKind.Convert: var convertNode = queryNode as ConvertQueryNode; var sourceValue = ProcessNode(convertNode.Source); if (convertNode.Source is ConstantQueryNode) { if (convertNode.TargetType.IsInt32()) { return Convert.ToInt32(sourceValue); } if (convertNode.TargetType.IsString()) { return sourceValue.ToString(); } if (convertNode.TargetType.IsDecimal()) { return Convert.ToDecimal(sourceValue); } throw new NotImplementedException("Haven't yet implemented convert to type " + convertNode.TargetType); } return sourceValue; case QueryNodeKind.BinaryOperator: var binaryOperatorNode = queryNode as BinaryOperatorQueryNode; return BindOperator(binaryOperatorNode); case QueryNodeKind.UnaryOperator: var unaryOperatorNode = queryNode as UnaryOperatorQueryNode; return BindOperator(unaryOperatorNode); case QueryNodeKind.PropertyAccess: return ProcessNode(queryNode as PropertyAccessQueryNode); case QueryNodeKind.SingleValueFunctionCall: return BindSingleValueFunctionCall(queryNode as SingleValueFunctionCallQueryNode); default: throw new NotImplementedException("No support for " + queryNode.Kind); } }
/// <summary> /// Checks if the source is of the specified type and if not tries to inject a convert. /// </summary> /// <param name="source">The source node to apply the convertion to.</param> /// <param name="targetType">The target primitive resource type.</param> /// <returns>The converted query node.</returns> private SingleValueQueryNode ConvertToType(SingleValueQueryNode source, ResourceType targetType) { Debug.Assert(source != null, "source != null"); Debug.Assert(targetType != null, "targetType != null"); Debug.Assert(targetType.ResourceTypeKind == ResourceTypeKind.Primitive, "Can only convert primitive types."); if (source.ResourceType != null) { // TODO: Do we check this here or in the caller? Debug.Assert(source.ResourceType.ResourceTypeKind == ResourceTypeKind.Primitive, "Can only work on primitive types."); ResourceType sourceResourceType = this.metadataProvider.ValidateResourceType(source.ResourceType); // NOTE we have to also allow different resource types with the same name if they are primitive resource // types since the resource types for 'bool' and 'bool?' have the same name. Debug.Assert( sourceResourceType == targetType || sourceResourceType.FullName != targetType.FullName || sourceResourceType.ResourceTypeKind == ResourceTypeKind.Primitive && targetType.ResourceTypeKind == ResourceTypeKind.Primitive, "The types were not atomized correctly."); if (this.ResourceTypesEqual(sourceResourceType, targetType)) { return source; } else { if (!TypePromotionUtils.CanConvertTo(sourceResourceType.InstanceType, targetType.InstanceType)) { throw new ODataException(Strings.MetadataBinder_CannotConvertToType(sourceResourceType.FullName, targetType.FullName)); } } } // If the source doesn't have a type (possibly an open property), then it's possible to convert it // cause we don't know for sure. return new ConvertQueryNode() { Source = source, TargetResourceType = targetType }; }