Example #1
0
        /// <summary>Creates a custom method definition from it's label.</summary>
        /// <param name="customMethodLabel">The label to call the custom method definition.</param>
        /// <returns>The custom method created.</returns>
        public static AggregationMethodDefinition Custom(string customMethodLabel)
        {
            ExceptionUtils.CheckArgumentNotNull(customMethodLabel, "customMethodLabel");

            // Custom aggregation methods MUST use a namespace-qualified name (see [OData-ABNF]), i.e. contain at least one dot.
            Debug.Assert(customMethodLabel.Contains(OData.ExpressionConstants.SymbolDot));

            var aggregationMethod = new AggregationMethodDefinition(AggregationMethod.Custom);

            aggregationMethod.MethodLabel = customMethodLabel;
            return(aggregationMethod);
        }
Example #2
0
        private IEdmTypeReference CreateAggregateExpressionTypeReference(SingleValueNode expression, AggregationMethodDefinition method)
        {
            var expressionType = expression.TypeReference;

            if (expressionType == null && aggregateExpressionsCache != null)
            {
                var openProperty = expression as SingleValueOpenPropertyAccessNode;
                if (openProperty != null)
                {
                    expressionType = GetTypeReferenceByPropertyName(openProperty.Name);
                }
            }

            switch (method.MethodKind)
            {
            case AggregationMethod.Average:
                var expressionPrimitiveKind = expressionType.PrimitiveKind();
                switch (expressionPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.Int32:
                case EdmPrimitiveTypeKind.Int64:
                case EdmPrimitiveTypeKind.Double:
                    return(EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Double, expressionType.IsNullable));

                case EdmPrimitiveTypeKind.Decimal:
                    return(EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Decimal, expressionType.IsNullable));

                default:
                    throw new ODataException(
                              ODataErrorStrings.ApplyBinder_AggregateExpressionIncompatibleTypeForMethod(expression,
                                                                                                         expressionPrimitiveKind));
                }

            case AggregationMethod.VirtualPropertyCount:
            case AggregationMethod.CountDistinct:
                // Issue #758: CountDistinct and $Count should return type Edm.Decimal with Scale="0" and sufficient Precision.
                return(EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Int64, false));

            case AggregationMethod.Max:
            case AggregationMethod.Min:
            case AggregationMethod.Sum:
                return(expressionType);

            default:
                // Only the EdmModel knows which type the custom aggregation methods returns.
                // Since we do not have a reference for it, right now we are assuming that all custom aggregation methods returns Doubles
                // TODO: find a appropriate way of getting the return type.
                return(EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Double, expressionType.IsNullable));
            }
        }
 /// <summary>
 /// Create a AggregateExpression.
 /// </summary>
 /// <param name="expression">The aggregation expression.</param>
 /// <param name="methodDefinition">The <see cref="AggregationMethodDefinition"/>.</param>
 /// <param name="alias">The aggregation alias.</param>
 /// <param name="typeReference">The <see cref="IEdmTypeReference"/> of this aggregate expression.</param>
 public AggregateExpression(SingleValueNode expression, AggregationMethodDefinition methodDefinition, string alias, IEdmTypeReference typeReference)
     : this(expression, methodDefinition.MethodKind, alias, typeReference)
 {
     this.methodDefinition = methodDefinition;
 }