Exemple #1
0
        private static string GetTargetPath(DimensionExpression g)
        {
            if (string.IsNullOrWhiteSpace(g.Target))
            {
                if (g.Child != null)
                {
                    var childAsSelector = g.Child as SelectorExpression;

                    if (childAsSelector != null)
                    {
                        var childTargePath = GetTargetPath(childAsSelector);
                        return(childTargePath);
                    }
                    else
                    {
                        throw new Exception("Child does not provide an alias");
                    }
                }
                else
                {
                    if (g.Source != null)
                    {
                        return(g.Source);
                    }
                    if (g.Function != null)
                    {
                        return("_" + g.Function);
                    }
                }
            }

            return(g.Target);
        }
Exemple #2
0
        private static Type GetTargetTypeForGroupByDimension(Type itemType, DimensionExpression g)
        {
            Type memberType = null;

            if (g.Source != null)
            {
                var member = GetMember(itemType, g.Source);
                memberType = GetMemberType(member);
                if (memberType == typeof(DateTime))
                {
                    memberType = typeof(long);
                }

                if (IsCollectionType(memberType))
                {
                    memberType = GetTypeOfEnumerable(memberType);
                }
            }
            else if (g.IsFunctionCall)
            {
                var methodInfo = typeof(UtilityExtensions).GetMethods().Where(x => string.Equals(x.Name, g.Function, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
                memberType = methodInfo.ReturnType;
            }
            else if (g.Child != null)
            {
                var childExpr = g.Child.CreateExpression(null);
                memberType = childExpr.Type;
            }
            else
            {
                throw new Exception("Not able to infer the return type of " + g);
            }
            return(memberType);
        }
Exemple #3
0
 public void RemoveArgument(DimensionExpression dim)
 {
     if (Dimensions.Contains(dim))
     {
         Dimensions.Remove(dim);
     }
 }
Exemple #4
0
 internal void CopyFrom(DimensionExpression s)
 {
     this.Function = s.Function;
     this.Target   = s.Target;
     this.SetChild(s.Child);
     this.AddArguments(s.Arguments);
 }
Exemple #5
0
        private static Expression MakeWhereExpression(Expression filter, Expression collectionParameter, DimensionExpression[] groupBy, Type itemType)
        {
            List<Expression> filters = new List<Expression>();
            var elementType = GetTypeOfEnumerable(collectionParameter.Type);
            var genericWhereInfo = typeof(Enumerable).GetMethods().FirstOrDefault(x => x.Name == "Where" && x.IsGenericMethod && x.GetParameters().Length == 2);
            var whereInfo = genericWhereInfo.MakeGenericMethod(elementType);

            var mentionParameter = Expression.Parameter(type: elementType, name: GenerateParamName(elementType));

            if (groupBy != null)
            {
                var collectionFields = groupBy.Where(x => x.Source != null).Select(x => new { x.Source, Member = GetMember(itemType, x.Source) });

                collectionFields = collectionFields.Where(x => TypeImplements(GetMemberType(x.Member), typeof(IEnumerable<>)));

                var count = collectionFields.Count();
                if (count == 0 && filter == null) return collectionParameter;

                filters.AddRange(collectionFields.Select
                (
                    x => Expression.ReferenceNotEqual
                    (
                        left: Expression.MakeMemberAccess(mentionParameter, x.Member),
                        right: Expression.Constant(null)
                    )
                ).Cast<Expression>());
            }

            if (filter != null) filters.Add(ParameterRebinder.ReplaceParameters(filter, "x", mentionParameter));

            if (!filters.Any()) return collectionParameter;

            Expression sourceCollection = collectionParameter;
            sourceCollection = AppendAsParallel(typeof(ParallelEnumerable), collectionParameter);

            var whereBody = ChainAndExpressionCollection(filters);

            var result = Expression.Call
            (
                method: whereInfo,
                arguments: new Expression[]
                {
                    sourceCollection,
                    Expression.Lambda
                    (
                        delegateType: typeof(Func<,>).MakeGenericType(elementType, typeof(bool)),
                        parameters: mentionParameter, 
                        body: whereBody
                    )
                }
            );

            //collectionParameter = Expression.Parameter(type: result.Type, name: "c");

            return result;
        }
Exemple #6
0
        private static void LinkDimensions(DimensionExpression[] groupBy, DimensionExpression[] selects)
        {
            if (groupBy == null || selects == null) return;

            foreach (var select in selects.Where(x => !x.IsStar && !string.Equals(x.Function, CountAggregateString, StringComparison.InvariantCultureIgnoreCase)))
            {
                string targetPath = GetTargetPath(select);

                var matchingGroupByFieldReverse = groupBy.FirstOrDefault(x => string.Equals(targetPath, GetSourcePath(x), StringComparison.InvariantCultureIgnoreCase));

                if (matchingGroupByFieldReverse != null)
                {
                    matchingGroupByFieldReverse.Target = select.Target;
                    matchingGroupByFieldReverse.Source = select.Source;
                    select.IsBasedOnGrouping = true;
                    matchingGroupByFieldReverse.IsAutoSelect = true;
                    matchingGroupByFieldReverse.LinkedSelect = select;
                    select.LinkedGroupBy = matchingGroupByFieldReverse;
                    select.IsLinkReversed = true;
                    matchingGroupByFieldReverse.IsLinkReversed = true;
                    continue;
                }

                if (select.Source != null)
                {
                    //find a matching field in the grouping parameters
                    var matchingGroupByField = groupBy.FirstOrDefault(x => string.Equals(GetTargetPath(x), select.Source, StringComparison.InvariantCultureIgnoreCase));

                    if (matchingGroupByField != null)
                    {
                        matchingGroupByField.IsAutoSelect = true;
                        matchingGroupByField.LinkedSelect = select;
                        select.LinkedGroupBy = matchingGroupByField;
                        select.IsBasedOnGrouping = true;
                        continue;
                    }
                }
            }

            foreach (var select in selects)
            {
                if (select.IsStar)
                {
                    foreach (var g in groupBy)
                    {
                        g.IsAutoSelect = true;
                    }
                }
            }
        }
Exemple #7
0
        private static Expression MakeConvertExpression(DimensionExpression currentDimension, Type itemType, ParameterExpression keySelectorParameter, string targetType = null)
        {
            if (currentDimension.Arguments.Count != 2 && targetType == null)
            {
                throw new BermudaExpressionGenerationException("Convert function requires 2 arguments");
            }
            if (currentDimension.Arguments.Count != 1 && targetType != null)
            {
                throw new BermudaExpressionGenerationException("Cast function requires 1 argument");
            }

            string lowerType;

            if (targetType == null)
            {
                targetType = currentDimension.Arguments[1].ToString();
                lowerType  = targetType.ToLower();
            }
            else
            {
                lowerType = targetType.ToLower();
            }

            var firstArg = currentDimension.Arguments.FirstOrDefault();

            Expression firstArgExpr         = MakeDimensionExpression(itemType, keySelectorParameter, firstArg);
            Type       conversionTargetType = null;

            switch (lowerType)
            {
            case "sql_bigint": conversionTargetType = typeof(long); break;

            case "integer": conversionTargetType = typeof(int); break;

            case "date": conversionTargetType = typeof(DateTime); break;

            default: throw new BermudaExpressionGenerationException("Unknown target type: " + targetType);
            }

            if (conversionTargetType == firstArgExpr.Type)
            {
                return(firstArgExpr);
            }

            var convexpr = Expression.Convert(firstArgExpr, conversionTargetType);

            return(convexpr);
            //throw new BermudaExpressionGenerationException("Invalid cast arguments: " + firstArg + " to " + targetType);
        }
Exemple #8
0
        private static string GetSourcePath(DimensionExpression x)
        {
            var dimensionChild = x.Child as SelectorExpression;
            if(dimensionChild != null)
            {
                var dimChild = dimensionChild.Child as DimensionExpression;
                if (dimChild != null)
                {
                    var result = GetSourcePath(dimChild);
                    return result;
                }
            }

            return x.Source;
        }
Exemple #9
0
 internal void RemoveSelect(DimensionExpression selLol)
 {
     if (selLol == null)
     {
         return;
     }
     else if (_selects.Contains(selLol))
     {
         _selects.Remove(selLol);
     }
     else
     {
         throw new Exception("Could not remove select from clause");
     }
 }
Exemple #10
0
        private static string GetSourcePath(DimensionExpression x)
        {
            var dimensionChild = x.Child as SelectorExpression;

            if (dimensionChild != null)
            {
                var dimChild = dimensionChild.Child as DimensionExpression;
                if (dimChild != null)
                {
                    var result = GetSourcePath(dimChild);
                    return(result);
                }
            }

            return(x.Source);
        }
Exemple #11
0
        public static Expression AppendCropping(Expression source, DimensionExpression[] selects, DimensionExpression[] groupBy, Type elementType)
        {
            //listlol.GroupBy(x => x.OccurredOn).Take(5).SelectMany(x => x).GroupBy(x => x.Name).Take(5).SelectMany(x => x);
            
            var genericGroupByInfos = typeof(ParallelEnumerable).GetMethods().Where(x => x.Name == "GroupBy" && x.IsGenericMethod && x.GetParameters().Length == 2);
            var genericGroupByInfo = genericGroupByInfos.FirstOrDefault();
            var groupByInfo = genericGroupByInfo.MakeGenericMethod(elementType, elementType);

            var genericTakeInfos = typeof(ParallelEnumerable).GetMethods().Where(x => x.Name == "Take" && x.IsGenericMethod && x.GetParameters().Length == 2);
            var genericTakeInfo = genericTakeInfos.FirstOrDefault();
            var takeInfo = genericTakeInfo.MakeGenericMethod(elementType, elementType);

            List<MemberBinding> memberBindings = new List<MemberBinding>();

            var fields = elementType.GetFields();

            //var valueField = fields.FirstOrDefault(x => !groupBy.Any(g => string.Equals(GetTargetPath(g), x.Name, StringComparison.InvariantCultureIgnoreCase)));

            foreach (var g in groupBy)
            {
                if (g.Take.HasValue)
                {
                    var targetPath = GetTargetPath(g);

                    var targetMember = GetMember(elementType, targetPath);

                    var iParam = Expression.Parameter( elementType, "i" );

                    var memberAccess = Expression.MakeMemberAccess(iParam, targetMember);

                    var lambda = Expression.Lambda(memberAccess, iParam);

                    var groupByCall = Expression.Call
                    (
                        method: groupByInfo,
                        arg0: source,
                        arg1: lambda
                    );
                }
            }

            return null;
        }
Exemple #12
0
        public static Type InferClrType(DimensionExpression[] selects, DimensionExpression[] groupBy, Type itemType)
        {
            if (selects == null || !selects.Any()) return itemType;

            var containsAggregates = selects.Any(x => x.IsAggregate);

            Dictionary<string, Type> requiredFields = null;

            if (groupBy != null || containsAggregates)
            {
                requiredFields = InferReduceType(selects, groupBy, itemType);
            }
            else
            {
                requiredFields = InferSelectType(selects, itemType);
            }

            var type = LinqRuntimeTypeBuilder.GetDynamicType(requiredFields);

            return type;

        }
Exemple #13
0
        public static Expression GetMapreduceExpression(Expression filter, DimensionExpression[] selects, DimensionExpression[] groupBy, Type itemType, GetExpression get, Expression source, string paramname)
        {
            var        hash = (filter == null ? 0 : filter.ToString().GetHashCode()) + "|" + (selects == null ? "" : string.Join(",", selects.Select(x => x.GetChecksum()))) + "|" + (groupBy == null ? "" : string.Join(",", groupBy.Select(x => x.GetChecksum()))) + "|" + (get == null ? null : get.Take);
            Expression expr;

            var containsAggregates = selects != null && selects.Any(x => x.IsAggregate);

            LinkDimensions(groupBy, selects);

            var resultType = InferClrType(selects, groupBy, itemType);

            if (expressionCache.TryGetValue(hash, out expr))
            {
                return(expr);
            }

            //a flat select transformation
            if (selects != null && groupBy == null && !containsAggregates)
            {
                expr = MakeSelectExpression(filter, selects, itemType, resultType, get, source, paramname);
            }
            else
            {
                //a non-grouping aggregate like "SELECT COUNT(*) FROM table"
                if (groupBy == null || !groupBy.Any())
                {
                    groupBy = new DimensionExpression[] { new DimensionExpression {
                                                              Source = null, Function = null
                                                          } }
                }
                ;

                expr = MakeMapreduceExpression(filter, selects, groupBy, itemType, resultType, get, source, paramname);
            }

            expressionCache[hash] = expr;

            return(expr);
        }
Exemple #14
0
 internal void RemoveSelect(DimensionExpression selLol)
 {
     if(selLol == null) return;
     else if (_selects.Contains(selLol)) _selects.Remove(selLol); 
     else throw new Exception("Could not remove select from clause");
 }
Exemple #15
0
        private static Expression MakeGroupByExpressionEx(Expression collectionParameter, DimensionExpression[] groupBy, DimensionExpression[] selects, int depth, Type itemType, Type metadataType, Type groupingType, Type resultType)
        {
            var linqExtensionClassType = !groupBy.Any(x => x.ParallelizedLinq) ? PLinqExtensionClassType : LinqExtensionClassType;
            var linqEnumType           = linqExtensionClassType == PLinqExtensionClassType ? PLinqEnumType : LinqEnumType;

            var remDepth         = groupBy.Skip(depth).Count();
            var currentDimension = groupBy.ElementAt(depth);
            var currentGroupBy   = currentDimension.Source;
            var currentFunction  = currentDimension.Function;
            var currentChild     = currentDimension.Child;

            if (currentDimension.LinkedSelect != null)
            {
                currentFunction = currentDimension.LinkedSelect.Function;
            }

            if (currentGroupBy == null && currentFunction == null && currentChild == null)
            {
                if (remDepth > 1)
                {
                    var newCollectionParameter = Expression.Parameter(type: typeof(EnumMetadata <>).MakeGenericType(linqEnumType.MakeGenericType(itemType)), name: MakeNumericName("gmd", depth + 1));
                    groupBy.ElementAt(depth + 1).GroupingEnumParameter = newCollectionParameter;
                    return(MakeGroupByExpressionEx(collectionParameter, groupBy, selects, depth + 1, itemType, metadataType, groupingType, resultType));
                }
            }

            var sourceCollection = collectionParameter.Type.GetGenericTypeDefinition() == typeof(EnumMetadata <>)
                ? Expression.MakeMemberAccess(collectionParameter, collectionParameter.Type.GetField("Enum"))
                : collectionParameter;

            if (linqEnumType == PLinqEnumType && !TypeImplements(GetTypeOfEnumerable(sourceCollection.Type), PLinqEnumType))
            {
                //.AsParallel()
                var res = AppendAsParallel(linqExtensionClassType, sourceCollection);

                groupBy.ElementAt(depth).ParallelizedLinq = true;

                sourceCollection = res;
            }

            var elementType = GetTypeOfEnumerable(sourceCollection.Type);
            var selectType  = resultType;

            Expression groupByExpr = null;

            DimensionExpression sortValueType = null;

            MemberInfo groupByMember;

            Expression currentChildExpression = null;

            if (currentChild != null)
            {
                currentChildExpression = currentChild.CreateExpression(null);
            }

            if (currentGroupBy == null && currentFunction == null && currentChild == null)
            {
                groupByExpr = Expression.NewArrayInit(sourceCollection.Type, sourceCollection);
            }
            else if ((groupByMember = GetMember(itemType, currentGroupBy)) != null && TypeImplements(GetMemberType(groupByMember), typeof(IEnumerable <>)) || (currentChildExpression != null && TypeImplements(currentChildExpression.Type, typeof(IEnumerable <>))))
            {
                //.SelectMany(m => m.Ngrams, (m, t) => new MentionMetadata { Mention = m, Id = t })
                var genericSelectManyInfos = linqExtensionClassType.GetMethods().Where(x => x.Name == "SelectMany" && x.IsGenericMethod && x.GetParameters().Length == 3);
                var extensionIndex         = (linqExtensionClassType == typeof(ParallelEnumerable)) ? 0 : 1;
                var genericSelectManyInfo  = genericSelectManyInfos.Skip(extensionIndex).FirstOrDefault();

                var collectionSelectorParameter = Expression.Parameter(type: elementType, name: GenerateParamName(elementType, depth));

                var sourcePath = GetSourcePath(currentDimension);

                var collectionGroupingMemberAccess = Expression.MakeMemberAccess(collectionSelectorParameter, GetField(collectionSelectorParameter.Type, sourcePath));

                var collectionSelector = Expression.Lambda
                                         (
                    delegateType: typeof(Func <,>).MakeGenericType(elementType, collectionGroupingMemberAccess.Type),
                    parameters: collectionSelectorParameter,
                    body: collectionGroupingMemberAccess
                                         );

                var keyType = GetTypeOfEnumerable(collectionGroupingMemberAccess.Type);

                var selectManyInfo = genericSelectManyInfo.MakeGenericMethod(elementType, keyType, metadataType);

                var resultSelectorParameters = new ParameterExpression[]
                {
                    Expression.Parameter(type: elementType, name: GenerateParamName(elementType, depth)),
                    Expression.Parameter(type: keyType, name: GenerateParamName(keyType, depth))
                };

                var memberBindings = new List <MemberBinding>
                {
                    Expression.Bind
                    (
                        member: metadataType.GetField("Item"),
                        expression: resultSelectorParameters[0]
                    )
                };

                string groupByTargetPath = GetTargetPath(keyType);

                var targetField = GetField(metadataType, groupByTargetPath);

                Expression sourceExpression = resultSelectorParameters[1];

                if (IsTupleType(sourceExpression.Type))
                {
                    var sourceItemInfo = sourceExpression.Type.GetProperty("Item2");

                    sourceExpression = Expression.MakeMemberAccess
                                       (
                        expression:   sourceExpression,
                        member: sourceItemInfo
                                       );
                }

                memberBindings.Add(Expression.Bind
                                   (
                                       member: targetField,
                                       expression: sourceExpression
                                   ));

                var resultSelector = Expression.Lambda
                                     (
                    delegateType: typeof(Func <, ,>).MakeGenericType(elementType, keyType, metadataType),
                    parameters: resultSelectorParameters,
                    body: Expression.MemberInit
                    (
                        newExpression: Expression.New(type: metadataType),
                        bindings: memberBindings
                    )
                                     );

                var selectManyExpr = Expression.Call
                                     (
                    method: selectManyInfo,
                    arguments: new Expression[]
                {
                    sourceCollection,
                    collectionSelector,
                    resultSelector
                }
                                     );

                //.GroupBy(md => md.Id, md => md.Mention)
                var keySelectorParameter    = Expression.Parameter(type: metadataType, name: "md");
                var resultSelectorParameter = Expression.Parameter(type: metadataType, name: "md");

                var keySelectorBody    = Expression.MakeMemberAccess(expression: keySelectorParameter, member: GetField(metadataType, groupByTargetPath));
                var resultSelectorBody = Expression.MakeMemberAccess(expression: resultSelectorParameter, member: metadataType.GetField("Item"));

                var genericGroupByInfos = linqExtensionClassType.GetMethods().Where(x => x.Name == "GroupBy" && x.IsGenericMethod && x.GetParameters().Length == 3);
                var genericGroupByInfo  = genericGroupByInfos.ElementAt(1);
                var groupByInfo         = genericGroupByInfo.MakeGenericMethod(metadataType, keySelectorBody.Type, resultSelectorBody.Type);

                var keySelectorLambda = Expression.Lambda
                                        (
                    delegateType: typeof(Func <,>).MakeGenericType(metadataType, keySelectorBody.Type),
                    parameters: keySelectorParameter,
                    body: keySelectorBody
                                        );

                var resultSelectorLambda = Expression.Lambda
                                           (
                    delegateType: typeof(Func <,>).MakeGenericType(metadataType, resultSelectorBody.Type),
                    parameters: resultSelectorParameter,
                    body: resultSelectorBody
                                           );

                groupByExpr = Expression.Call
                              (
                    method: groupByInfo,
                    arguments: new Expression[]
                {
                    selectManyExpr,
                    keySelectorLambda,
                    resultSelectorLambda
                }
                              );
            }
            else
            {
                //.GroupBy(m => m.OccurredOn.Ticks - 28189283)
                var keySelectorParameter = Expression.Parameter(type: itemType, name: "m");


                Expression keySelectorBody = null;

                if (currentFunction != null)
                {
                    keySelectorBody = MakeFunctionCallExpression(currentDimension, itemType, keySelectorParameter);
                }
                else if (currentGroupBy != null)
                {
                    var sourcePath   = GetSourcePath(currentDimension);
                    var targetMember = GetMember(itemType, sourcePath);
                    keySelectorBody = Expression.MakeMemberAccess(expression: keySelectorParameter, member: targetMember);
                }
                else if (currentChild != null)
                {
                    keySelectorBody = currentChild.CreateExpression(null);
                }
                else
                {
                    throw new BermudaExpressionGenerationException("Don't know how to handle for group by:" + currentDimension);
                }

                var genericGroupByInfos = linqExtensionClassType.GetMethods().Where(x => x.Name == "GroupBy" && x.IsGenericMethod && x.GetParameters().Length == 2);
                var genericGroupByInfo  = genericGroupByInfos.FirstOrDefault();
                var groupByInfo         = genericGroupByInfo.MakeGenericMethod(elementType, keySelectorBody.Type);

                keySelectorBody = ParameterRebinder.ReplaceParameters(keySelectorBody, "x", keySelectorParameter);

                var groupByLambda = Expression.Lambda
                                    (
                    delegateType: typeof(Func <,>).MakeGenericType(elementType, keySelectorBody.Type),
                    parameters: keySelectorParameter,
                    body: keySelectorBody
                                    );

                groupByExpr = Expression.Call
                              (
                    method: groupByInfo,
                    arguments: new Expression[]
                {
                    sourceCollection,
                    groupByLambda
                }
                              );
            }



            var inferredParameterType = typeof(EnumMetadata <>).MakeGenericType(GetTypeOfEnumerable(groupByExpr.Type));
            var groupingParameter     = Expression.Parameter(type: inferredParameterType, name: MakeNumericName("gmd", depth));

            if (groupBy.Length > depth)
            {
                groupBy.ElementAt(depth).GroupingEnumParameter = groupingParameter;
            }

            //var loldas = temp == groupBy.ElementAt(depth);

            var enumType         = GetTypeOfEnumerable(groupByExpr.Type);
            var enumMetadataType = typeof(EnumMetadata <>).MakeGenericType(enumType);


            //.AsParallel()
            //var genericAsParallelInfo = typeof(ParallelEnumerable).GetMethods().FirstOrDefault(x => x.Name == "AsParallel" && x.IsGenericMethod && x.GetParameters().Length == 1);
            //var asParallelInfo0 = genericAsParallelInfo.MakeGenericMethod(enumType);
            //groupByExpr = Expression.Call(method: asParallelInfo0, arg0: groupByExpr);

            //.Select(g => new GroupMetadata { Group = g, Value = g.Whatever() })
            var selectLinqClass    = groupByExpr.Type.IsArray ? LinqExtensionClassType : linqExtensionClassType;
            var genericSelectInfos = selectLinqClass.GetMethods().Where(x => x.Name == "Select" && x.IsGenericMethod && x.GetParameters().Length == 2);
            var genericSelectInfo  = genericSelectInfos.FirstOrDefault();
            var selectInfo0        = genericSelectInfo.MakeGenericMethod(enumType, enumMetadataType);
            var selectGroupParam   = Expression.Parameter(type: enumType, name: "g");

            var selectGroupMemberBindings = new List <MemberBinding>();

            //Group = g, Value
            selectGroupMemberBindings.Add(Expression.Bind(member: enumMetadataType.GetField("Enum"), expression: selectGroupParam));

            //Value = g.Whatever()
            if (currentDimension != null && currentDimension.Ordering != null && currentDimension.Ordering.Function != null)
            {
                sortValueType = currentDimension.Ordering;
                if (sortValueType != null)
                {
                    selectGroupMemberBindings.Add(MakeAggregateFunctionCallExpression(selectGroupParam, sortValueType, null, 0, enumMetadataType, "Value"));
                }
            }

            // = new GroupMetadata{}
            var selectInit = Expression.MemberInit
                             (
                newExpression: Expression.New(type: enumMetadataType),
                bindings: selectGroupMemberBindings
                             );

            var selectMetadataLambda = Expression.Lambda
                                       (
                parameters: selectGroupParam,
                body: selectInit
                                       );

            //.Select(...)
            var selectExpr = Expression.Call
                             (
                method: selectInfo0,
                arg0: groupByExpr,
                arg1: selectMetadataLambda
                             );

            Expression selectSourceExpression = selectExpr;

            //.OrderByDescending(g => g.Value)
            if (currentDimension != null && currentDimension.Ordering != null && (currentDimension.Ordering.Function != null || currentDimension.Ordering.Source != null))
            {
                var orderFuncName      = currentDimension.OrderDescending ? "OrderByDescending" : "OrderBy";
                var genericOrderByInfo = linqExtensionClassType.GetMethods().FirstOrDefault(x => x.Name == orderFuncName && x.IsGenericMethod && x.GetParameters().Length == 2);
                var orderByInfo        = genericOrderByInfo.MakeGenericMethod(enumMetadataType, typeof(long));
                var groupOrderParam    = Expression.Parameter(type: enumMetadataType, name: "gg");
                var orderByExpr        = Expression.Call
                                         (
                    method: orderByInfo,
                    arg0: selectExpr,
                    arg1: Expression.Lambda(parameters: groupOrderParam, body: Expression.MakeMemberAccess(expression: groupOrderParam, member: enumMetadataType.GetField("Value")))
                                         );

                selectSourceExpression = orderByExpr;
            }

            //.Take(5)
            if (currentDimension.Take.HasValue)
            {
                selectSourceExpression = AppendTake(linqExtensionClassType, enumMetadataType, selectSourceExpression, currentDimension.Take.Value);
            }

            if (remDepth <= 1)
            {
                //if (currentGroupBy == GroupByTypes.None) return collectionParameter;

                //.Select(gmd2 => new InferredType { Id = gmd.Group.Key, Id2 = gmd2.Group.Key, TargetPath = gmd2.SourcePath })
                var selectParameterType = GetTypeOfEnumerable(selectSourceExpression.Type);
                var selectInfo          = genericSelectInfo.MakeGenericMethod(selectParameterType, resultType);

                var selectMemberBindings = new List <MemberAssignment>();

                //gmd2
                var parentGroupBy        = groupBy.ElementAt(depth);
                var parentGroupParameter = parentGroupBy.GroupingEnumParameter;

                //gmd.Group
                var actualGroupAccess = Expression.MakeMemberAccess(parentGroupParameter, parentGroupParameter.Type.GetField("Enum"));
                //gmd.Value
                var groupValueAccess = Expression.MakeMemberAccess(parentGroupParameter, parentGroupParameter.Type.GetField("Value"));

                var lastGroupBy           = groupBy.LastOrDefault();
                var computedValueForGroup = lastGroupBy.Ordering; // lastGroupBy.IsDateTime ? null : lastGroupBy.OrderBy;

                var countSelect = selects.FirstOrDefault(x => string.Equals(x.Function, CountAggregateString, StringComparison.InvariantCultureIgnoreCase));

                if (countSelect != null)
                {
                    //CountAlias =
                    var countBinding = MakeAggregateFunctionCallExpression(actualGroupAccess, new DimensionExpression {
                        Function = CountAggregateString, Target = GetTargetPath(countSelect)
                    }, computedValueForGroup != null && computedValueForGroup.Function == CountAggregateString ? groupValueAccess : null, 0, resultType, null);
                    selectMemberBindings.Add(countBinding);
                }
                else if (selects.Any(x => IsCountRequiredForAggregate(x.Function)))
                {
                    //_Count =
                    var countBinding = MakeAggregateFunctionCallExpression(actualGroupAccess, new DimensionExpression {
                        Function = CountAggregateString, Target = CountTargetPath
                    }, computedValueForGroup != null && computedValueForGroup.Function == CountAggregateString ? groupValueAccess : null, 0, resultType, null);
                    selectMemberBindings.Add(countBinding);
                }

                //Value =
                foreach (var select in selects.Where(x => !x.IsStar && !string.Equals(x.Function, CountAggregateString, StringComparison.InvariantCultureIgnoreCase)))
                {
                    if (select.IsBasedOnGrouping)
                    {
                        continue;
                    }

                    if (select.IsFunctionCall)
                    {
                        var otherBinding = MakeAggregateFunctionCallExpression(actualGroupAccess, select, computedValueForGroup != null && computedValueForGroup.Equals(select) ? groupValueAccess : null, 0, resultType, null);

                        //it's not an aggregate... that's a problem
                        if (otherBinding == null)
                        {
                            throw new BermudaExpressionGenerationException("Non aggregate function call in an aggregate query not allowed: " + select);
                        }

                        selectMemberBindings.Add(otherBinding);
                    }
                    else
                    {
                        var targetPath = GetTargetPath(select);

                        //var sourceField = GetMember(itemType, select.Source, false);

                        var targetFieldInfo = GetField(resultType, targetPath);

                        var actualValue = Convert.ChangeType(select.Source, select.SourceType);
                        selectMemberBindings.Add(Expression.Bind
                                                 (
                                                     targetFieldInfo, Expression.Constant(actualValue)
                                                 ));
                    }
                }

                //Id = gmd.Group.Key, Id2 = gmd2.Group.Key
                AddStarSelectColumns(groupBy, selects, resultType, selectMemberBindings);

                //gmd => new Datapoint{...}
                var selectLambda = Expression.Lambda
                                   (
                    parameters: parentGroupParameter,
                    body: Expression.MemberInit
                    (
                        newExpression: Expression.New(type: resultType),
                        bindings: selectMemberBindings
                    )
                                   );

                //.Select(...)
                var result = Expression.Call
                             (
                    method: selectInfo,
                    arg0: selectSourceExpression,
                    arg1: selectLambda
                             );

                return(result);
            }
            else if (remDepth >= 2)
            {
                //var newCollectionParameter = Expression.Parameter(type: enumMetadataType, name: MakeNumericName("gmd", depth + 1));
                //groupBy.ElementAt(depth).GroupingEnumParameter = newCollectionParameter;

                var currentParameter = groupBy.ElementAt(depth).GroupingEnumParameter;

                var nestedExpression = MakeGroupByExpressionEx(currentParameter, groupBy, selects, depth + 1, itemType, metadataType, groupingType, resultType);

                var nestedExpressionLambda = Expression.Lambda
                                             (
                    parameters: currentParameter,
                    body: nestedExpression
                                             );


                //.SelectMany(gmd => Recurse())
                var sourceElementType      = GetTypeOfEnumerable(selectSourceExpression.Type);
                var genericSelectManyInfos = linqExtensionClassType.GetMethods().Where(x => x.Name == "SelectMany" && x.IsGenericMethod && x.GetParameters().Length == 2);
                var genericSelectManyInfo  = genericSelectManyInfos.Skip(0).FirstOrDefault();
                var selectManyInfo         = genericSelectManyInfo.MakeGenericMethod(sourceElementType, selectType);

                var selectManyRecursiveExpr = Expression.Call
                                              (
                    method: selectManyInfo,
                    arg0: selectSourceExpression,
                    arg1: nestedExpressionLambda
                                              );

                return(selectManyRecursiveExpr);
            }

            throw new Exception("not supposed to happen");
        }
Exemple #16
0
        private static Expression MakeDimensionExpression(Type itemType, ParameterExpression keySelectorParameter, DimensionExpression firstArg)
        {
            Expression firstArgExpr;
            bool dontNegate = false;

            if (firstArg.Child != null)
            {
                dontNegate = true;
                firstArgExpr = firstArg.CreateExpression(null);
            }
            else if (firstArg.Function != null)
            {
                firstArgExpr = MakeFunctionCallExpression(firstArg, itemType, keySelectorParameter);
            }
            else
            {
                var sourcePath = firstArg.Source;
                var member = GetMember(itemType, sourcePath, false);

                if (member == null)
                {
                    var stringVersion = firstArg.Source;

                    long num;
                    double num2;

                    if (long.TryParse(stringVersion, out num)) return Expression.Constant( num );
                    if (double.TryParse(stringVersion, out num2)) return Expression.Constant(num2);

                    firstArgExpr = Expression.Constant(stringVersion);
                }
                else
                {
                    firstArgExpr = Expression.MakeMemberAccess(keySelectorParameter, member);
                }
            }

            if (!dontNegate)
            {
                if (firstArg.IsNegated)
                {
                    firstArgExpr = Expression.Negate(firstArgExpr);
                }
                else if (firstArg.IsNotted)
                {
                    firstArgExpr = Expression.Not(firstArgExpr);
                }
            }

            return firstArgExpr;
        }
Exemple #17
0
        public static Expression MakeFunctionCallExpression(DimensionExpression currentDimension, Type itemType, ParameterExpression keySelectorParameter)
        {
            //var functionName = currentDimension.Function ?? currentDimension.LinkedSelect.Function;

            if (currentDimension.Function == null && currentDimension.LinkedSelect != null) currentDimension = currentDimension.LinkedSelect;

            if ( string.Equals(currentDimension.Function, "convert", StringComparison.InvariantCultureIgnoreCase) )
            {
                if (currentDimension.Arguments.Count != 2) throw new BermudaExpressionGenerationException("Convert requires 2 arguments");
                Expression conv = MakeConvertExpression(currentDimension, itemType, keySelectorParameter);
                if (currentDimension.IsNegated) 
                    conv = Expression.Negate(conv);
                if (currentDimension.IsNotted) 
                    conv = Expression.Not(conv);
                return conv;
            }

            if (string.Equals(currentDimension.Function, "cast", StringComparison.InvariantCultureIgnoreCase))
            {
                if (currentDimension.Arguments.Count != 1) throw new BermudaExpressionGenerationException("Cast requires 1 argument");
                Expression conv = MakeConvertExpression(currentDimension, itemType, keySelectorParameter, currentDimension.Arguments.First().Target);
                if (currentDimension.IsNegated) 
                    conv = Expression.Negate(conv);
                if (currentDimension.IsNotted) 
                    conv = Expression.Not(conv);
                return conv;
            }

            Expression keySelectorBody;
            currentDimension.IsDateTime = true;
            var functionInfo = typeof(UtilityExtensions).GetMethods().Where(x => string.Equals(x.Name, currentDimension.Function, StringComparison.InvariantCultureIgnoreCase) && currentDimension.Arguments.Count == x.GetParameters().Length).FirstOrDefault();
            //keySelectorBody = Expression.MakeMemberAccess(expression: keySelectorBody, member: typeof(DateTime).GetProperty("Ticks"));

            if (functionInfo == null) throw new BermudaExpressionGenerationException("Function " + currentDimension.Function + "(" + string.Join(",", Enumerable.Range(0, currentDimension.Arguments.Count).Select(n => "arg" + n)) + ") not supported.");

            var functionArguments = new List<Expression>();

            var methodParams = functionInfo.GetParameters();

            if (currentDimension.Arguments.Count != methodParams.Length) throw new BermudaExpressionGenerationException("Number of arguments does not match the number of parameters for function " + currentDimension.Function);

            for (int i = 0; i < methodParams.Length; i++)
            {
                var actualArg = currentDimension.Arguments[i];
                var parameterType = methodParams[i].ParameterType;

                if (actualArg.IsFunctionCall)
                {
                    Expression functionCall = MakeFunctionCallExpression(actualArg, itemType, keySelectorParameter);
                    
                    if (functionCall.Type != parameterType) 
                        functionCall = Expression.Convert(functionCall, parameterType);
                    functionArguments.Add(functionCall);
                }
                else if (actualArg.Source != null)
                {
                    if (actualArg.IsQuoted)
                    {
                        functionArguments.Add(Expression.Constant(actualArg.Source));
                        continue;
                    }

                    //see if the provided string is a column name
                    var targetMember = GetMember(itemType, actualArg.Source, false);

                    if (targetMember != null)
                    {
                        keySelectorBody = Expression.MakeMemberAccess(expression: keySelectorParameter, member: targetMember);
                        functionArguments.Add(keySelectorBody);
                    }
                    else
                    {
                        var actualValue = parameterType == typeof(string) ? actualArg.Source : Convert.ChangeType(actualArg.Source, parameterType);
                        functionArguments.Add(Expression.Constant(actualValue));
                    }
                }
                else if (actualArg.Child != null) 
                {
                    var childExpr = actualArg.Child.CreateExpression(null);

                    if (childExpr.Type != parameterType)
                        childExpr = Expression.Convert(childExpr, parameterType);

                    functionArguments.Add(childExpr);
                }
            }

            keySelectorBody = Expression.Call
            (
                method: functionInfo,
                arguments: functionArguments
            );

            if (currentDimension.IsNegated) 
                keySelectorBody = Expression.Negate(keySelectorBody);
            if (currentDimension.IsNotted) 
                keySelectorBody = Expression.Not(keySelectorBody);

            return keySelectorBody;
        }
Exemple #18
0
        private static Expression MakeGroupByExpressionEx(Expression collectionParameter, DimensionExpression[] groupBy, DimensionExpression[] selects, int depth, Type itemType, Type metadataType, Type groupingType, Type resultType)
        {
            var linqExtensionClassType = !groupBy.Any(x => x.ParallelizedLinq) ? PLinqExtensionClassType : LinqExtensionClassType;
            var linqEnumType = linqExtensionClassType == PLinqExtensionClassType ? PLinqEnumType : LinqEnumType;

            var remDepth = groupBy.Skip(depth).Count();
            var currentDimension = groupBy.ElementAt(depth);
            var currentGroupBy = currentDimension.Source;
            var currentFunction = currentDimension.Function;
            var currentChild = currentDimension.Child;

            if (currentDimension.LinkedSelect != null)
            {
                currentFunction = currentDimension.LinkedSelect.Function;
            }

            if (currentGroupBy == null && currentFunction == null && currentChild == null)
            {
                if (remDepth > 1)
                {
                    var newCollectionParameter = Expression.Parameter(type: typeof(EnumMetadata<>).MakeGenericType(linqEnumType.MakeGenericType(itemType)), name: MakeNumericName("gmd", depth + 1));
                    groupBy.ElementAt(depth + 1).GroupingEnumParameter = newCollectionParameter;
                    return MakeGroupByExpressionEx(collectionParameter, groupBy, selects, depth + 1, itemType, metadataType, groupingType, resultType);
                }
            }

            var sourceCollection = collectionParameter.Type.GetGenericTypeDefinition() == typeof(EnumMetadata<>)
                ? Expression.MakeMemberAccess(collectionParameter, collectionParameter.Type.GetField("Enum"))
                : collectionParameter;

            if (linqEnumType == PLinqEnumType && !TypeImplements(GetTypeOfEnumerable(sourceCollection.Type), PLinqEnumType))
            {
                //.AsParallel()
                var res = AppendAsParallel(linqExtensionClassType, sourceCollection);

                groupBy.ElementAt(depth).ParallelizedLinq = true;

                sourceCollection = res;
            }

            var elementType = GetTypeOfEnumerable(sourceCollection.Type);
            var selectType = resultType;

            Expression groupByExpr = null;

            DimensionExpression sortValueType = null;

            MemberInfo groupByMember;

            Expression currentChildExpression = null;

            if (currentChild != null)
            {
                currentChildExpression = currentChild.CreateExpression(null);
            }

            if (currentGroupBy == null && currentFunction == null && currentChild == null)
            {
                groupByExpr = Expression.NewArrayInit(sourceCollection.Type, sourceCollection);
            }
            else if ((groupByMember = GetMember(itemType, currentGroupBy)) != null && TypeImplements(GetMemberType(groupByMember), typeof(IEnumerable<>)) || (currentChildExpression != null && TypeImplements(currentChildExpression.Type, typeof(IEnumerable<>))))
            {
                //.SelectMany(m => m.Ngrams, (m, t) => new MentionMetadata { Mention = m, Id = t })
                var genericSelectManyInfos = linqExtensionClassType.GetMethods().Where(x => x.Name == "SelectMany" && x.IsGenericMethod && x.GetParameters().Length == 3);
                var extensionIndex = (linqExtensionClassType == typeof(ParallelEnumerable)) ? 0 : 1;
                var genericSelectManyInfo = genericSelectManyInfos.Skip(extensionIndex).FirstOrDefault();

                var collectionSelectorParameter = Expression.Parameter(type: elementType, name: GenerateParamName(elementType, depth));

                var sourcePath = GetSourcePath(currentDimension);

                var collectionGroupingMemberAccess = Expression.MakeMemberAccess(collectionSelectorParameter, GetField(collectionSelectorParameter.Type, sourcePath));

                var collectionSelector = Expression.Lambda
                (
                    delegateType: typeof(Func<,>).MakeGenericType(elementType, collectionGroupingMemberAccess.Type),
                    parameters: collectionSelectorParameter,
                    body: collectionGroupingMemberAccess
                );

                var keyType = GetTypeOfEnumerable(collectionGroupingMemberAccess.Type);

                var selectManyInfo = genericSelectManyInfo.MakeGenericMethod(elementType, keyType, metadataType);

                var resultSelectorParameters = new ParameterExpression[]
                {
                    Expression.Parameter(type: elementType, name: GenerateParamName(elementType, depth) ),
                    Expression.Parameter(type: keyType, name: GenerateParamName(keyType, depth) )
                };

                var memberBindings = new List<MemberBinding>
                {
                    Expression.Bind
                    (
                        member: metadataType.GetField("Item"),
                        expression: resultSelectorParameters[0]
                    )
                };

                string groupByTargetPath = GetTargetPath(keyType);

                var targetField = GetField(metadataType, groupByTargetPath);

                Expression sourceExpression = resultSelectorParameters[1];

                if (IsTupleType(sourceExpression.Type))
                {
                    var sourceItemInfo = sourceExpression.Type.GetProperty("Item2");

                    sourceExpression = Expression.MakeMemberAccess
                    (
                        expression:   sourceExpression,
                        member :sourceItemInfo
                    );
                }

                memberBindings.Add(Expression.Bind
                (
                    member: targetField,
                    expression: sourceExpression
                ));

                var resultSelector = Expression.Lambda
                (
                    delegateType: typeof(Func<,,>).MakeGenericType(elementType, keyType, metadataType),
                    parameters: resultSelectorParameters,
                    body: Expression.MemberInit
                    (
                        newExpression: Expression.New(type: metadataType),
                        bindings: memberBindings
                    )
                );

                var selectManyExpr = Expression.Call
                (
                    method: selectManyInfo,
                    arguments: new Expression[]
                    {
                        sourceCollection,
                        collectionSelector,
                        resultSelector
                    }
                );

                //.GroupBy(md => md.Id, md => md.Mention)
                var keySelectorParameter = Expression.Parameter(type: metadataType, name: "md");
                var resultSelectorParameter = Expression.Parameter(type: metadataType, name: "md");

                var keySelectorBody = Expression.MakeMemberAccess(expression: keySelectorParameter, member: GetField(metadataType, groupByTargetPath));
                var resultSelectorBody = Expression.MakeMemberAccess(expression: resultSelectorParameter, member: metadataType.GetField("Item"));

                var genericGroupByInfos = linqExtensionClassType.GetMethods().Where(x => x.Name == "GroupBy" && x.IsGenericMethod && x.GetParameters().Length == 3);
                var genericGroupByInfo = genericGroupByInfos.ElementAt(1);
                var groupByInfo = genericGroupByInfo.MakeGenericMethod(metadataType, keySelectorBody.Type, resultSelectorBody.Type);

                var keySelectorLambda = Expression.Lambda
                (
                    delegateType: typeof(Func<,>).MakeGenericType(metadataType, keySelectorBody.Type),
                    parameters: keySelectorParameter,
                    body: keySelectorBody
                );

                var resultSelectorLambda = Expression.Lambda
                (
                    delegateType: typeof(Func<,>).MakeGenericType(metadataType, resultSelectorBody.Type),
                    parameters: resultSelectorParameter,
                    body: resultSelectorBody
                );

                groupByExpr = Expression.Call
                (
                    method: groupByInfo,
                    arguments: new Expression[]
                    {
                        selectManyExpr,
                        keySelectorLambda,
                        resultSelectorLambda
                    }
                );
            }
            else
            {
                //.GroupBy(m => m.OccurredOn.Ticks - 28189283)
                var keySelectorParameter = Expression.Parameter(type: itemType, name: "m");

            
                Expression keySelectorBody = null;

                if (currentFunction != null)
                {
                    keySelectorBody = MakeFunctionCallExpression(currentDimension, itemType, keySelectorParameter);
                }
                else if(currentGroupBy != null)
                {
                    var sourcePath = GetSourcePath(currentDimension);
                    var targetMember = GetMember(itemType, sourcePath);
                    keySelectorBody = Expression.MakeMemberAccess(expression: keySelectorParameter, member: targetMember);
                }
                else if (currentChild != null)
                {
                    keySelectorBody = currentChild.CreateExpression(null);
                }
                else
                {
                    throw new BermudaExpressionGenerationException("Don't know how to handle for group by:" + currentDimension);
                }
                
                var genericGroupByInfos = linqExtensionClassType.GetMethods().Where(x => x.Name == "GroupBy" && x.IsGenericMethod && x.GetParameters().Length == 2);
                var genericGroupByInfo = genericGroupByInfos.FirstOrDefault();
                var groupByInfo = genericGroupByInfo.MakeGenericMethod(elementType, keySelectorBody.Type);

                keySelectorBody = ParameterRebinder.ReplaceParameters(keySelectorBody, "x", keySelectorParameter);

                var groupByLambda = Expression.Lambda
                (
                    delegateType: typeof(Func<,>).MakeGenericType(elementType, keySelectorBody.Type),
                    parameters: keySelectorParameter,
                    body: keySelectorBody
                );

                groupByExpr = Expression.Call
                (
                    method: groupByInfo,
                    arguments: new Expression[]
                    {
                        sourceCollection,
                        groupByLambda
                    }
                );
            }




            var inferredParameterType = typeof(EnumMetadata<>).MakeGenericType(GetTypeOfEnumerable(groupByExpr.Type));
            var groupingParameter = Expression.Parameter(type: inferredParameterType, name: MakeNumericName("gmd", depth));

            if (groupBy.Length > depth)
            {
                groupBy.ElementAt(depth).GroupingEnumParameter = groupingParameter;
            }

            //var loldas = temp == groupBy.ElementAt(depth);

            var enumType = GetTypeOfEnumerable(groupByExpr.Type);
            var enumMetadataType = typeof(EnumMetadata<>).MakeGenericType(enumType);


            //.AsParallel()
            //var genericAsParallelInfo = typeof(ParallelEnumerable).GetMethods().FirstOrDefault(x => x.Name == "AsParallel" && x.IsGenericMethod && x.GetParameters().Length == 1);
            //var asParallelInfo0 = genericAsParallelInfo.MakeGenericMethod(enumType);
            //groupByExpr = Expression.Call(method: asParallelInfo0, arg0: groupByExpr);

            //.Select(g => new GroupMetadata { Group = g, Value = g.Whatever() })
            var selectLinqClass = groupByExpr.Type.IsArray ? LinqExtensionClassType : linqExtensionClassType;
            var genericSelectInfos = selectLinqClass.GetMethods().Where(x => x.Name == "Select" && x.IsGenericMethod && x.GetParameters().Length == 2);
            var genericSelectInfo = genericSelectInfos.FirstOrDefault();
            var selectInfo0 = genericSelectInfo.MakeGenericMethod(enumType, enumMetadataType);
            var selectGroupParam = Expression.Parameter(type: enumType, name: "g");

            var selectGroupMemberBindings = new List<MemberBinding>();

            //Group = g, Value
            selectGroupMemberBindings.Add(Expression.Bind(member: enumMetadataType.GetField("Enum"), expression: selectGroupParam));

            //Value = g.Whatever()
            if (currentDimension != null && currentDimension.Ordering != null && currentDimension.Ordering.Function != null)
            {
                sortValueType = currentDimension.Ordering;
                if (sortValueType != null)
                {
                    selectGroupMemberBindings.Add(MakeAggregateFunctionCallExpression(selectGroupParam, sortValueType, null, 0, enumMetadataType, "Value"));
                }
            }

            // = new GroupMetadata{}
            var selectInit = Expression.MemberInit
            (
                newExpression: Expression.New(type: enumMetadataType),
                bindings: selectGroupMemberBindings
            );

            var selectMetadataLambda = Expression.Lambda
            (
                parameters: selectGroupParam,
                body: selectInit
            );

            //.Select(...)
            var selectExpr = Expression.Call
            (
                method: selectInfo0,
                arg0: groupByExpr,
                arg1: selectMetadataLambda
            );

            Expression selectSourceExpression = selectExpr;

            //.OrderByDescending(g => g.Value)
            if (currentDimension != null && currentDimension.Ordering != null && (currentDimension.Ordering.Function != null || currentDimension.Ordering.Source != null))
            {
                var orderFuncName = currentDimension.OrderDescending ? "OrderByDescending" : "OrderBy";
                var genericOrderByInfo = linqExtensionClassType.GetMethods().FirstOrDefault(x => x.Name == orderFuncName && x.IsGenericMethod && x.GetParameters().Length == 2);
                var orderByInfo = genericOrderByInfo.MakeGenericMethod(enumMetadataType, typeof(long));
                var groupOrderParam = Expression.Parameter(type: enumMetadataType, name: "gg");
                var orderByExpr = Expression.Call
                (
                    method: orderByInfo,
                    arg0: selectExpr,
                    arg1: Expression.Lambda(parameters: groupOrderParam, body: Expression.MakeMemberAccess(expression: groupOrderParam, member: enumMetadataType.GetField("Value")))
                );

                selectSourceExpression = orderByExpr;
            }

            //.Take(5)
            if (currentDimension.Take.HasValue)
            {
                selectSourceExpression = AppendTake(linqExtensionClassType, enumMetadataType, selectSourceExpression, currentDimension.Take.Value);
            }

            if (remDepth <= 1)
            {
                //if (currentGroupBy == GroupByTypes.None) return collectionParameter;

                //.Select(gmd2 => new InferredType { Id = gmd.Group.Key, Id2 = gmd2.Group.Key, TargetPath = gmd2.SourcePath })
                var selectParameterType = GetTypeOfEnumerable(selectSourceExpression.Type);
                var selectInfo = genericSelectInfo.MakeGenericMethod(selectParameterType, resultType);

                var selectMemberBindings = new List<MemberAssignment>();

                //gmd2
                var parentGroupBy = groupBy.ElementAt(depth);
                var parentGroupParameter = parentGroupBy.GroupingEnumParameter;

                //gmd.Group
                var actualGroupAccess = Expression.MakeMemberAccess(parentGroupParameter, parentGroupParameter.Type.GetField("Enum"));
                //gmd.Value
                var groupValueAccess = Expression.MakeMemberAccess(parentGroupParameter, parentGroupParameter.Type.GetField("Value"));

                var lastGroupBy = groupBy.LastOrDefault();
                var computedValueForGroup = lastGroupBy.Ordering; // lastGroupBy.IsDateTime ? null : lastGroupBy.OrderBy;

                var countSelect = selects.FirstOrDefault(x => string.Equals(x.Function, CountAggregateString, StringComparison.InvariantCultureIgnoreCase));

                if (countSelect != null)
                {
                    //CountAlias = 
                    var countBinding = MakeAggregateFunctionCallExpression(actualGroupAccess, new DimensionExpression { Function = CountAggregateString, Target = GetTargetPath(countSelect) }, computedValueForGroup != null && computedValueForGroup.Function == CountAggregateString ? groupValueAccess : null, 0, resultType, null);
                    selectMemberBindings.Add(countBinding);
                }
                else if (selects.Any(x => IsCountRequiredForAggregate(x.Function)))
                {
                    //_Count = 
                    var countBinding = MakeAggregateFunctionCallExpression(actualGroupAccess, new DimensionExpression { Function = CountAggregateString, Target = CountTargetPath }, computedValueForGroup != null && computedValueForGroup.Function == CountAggregateString ? groupValueAccess : null, 0, resultType, null);
                    selectMemberBindings.Add(countBinding);
                }

                //Value =
                foreach (var select in selects.Where(x => !x.IsStar && !string.Equals(x.Function, CountAggregateString, StringComparison.InvariantCultureIgnoreCase)))
                {
                    if (select.IsBasedOnGrouping) continue;

                    if (select.IsFunctionCall)
                    {
                        var otherBinding = MakeAggregateFunctionCallExpression(actualGroupAccess, select, computedValueForGroup != null && computedValueForGroup.Equals(select) ? groupValueAccess : null, 0, resultType, null);

                        //it's not an aggregate... that's a problem
                        if (otherBinding == null) throw new BermudaExpressionGenerationException("Non aggregate function call in an aggregate query not allowed: " + select);

                        selectMemberBindings.Add(otherBinding);
                    }
                    else
                    {
                        var targetPath = GetTargetPath(select);

                        //var sourceField = GetMember(itemType, select.Source, false);

                        var targetFieldInfo = GetField(resultType, targetPath);

                        var actualValue = Convert.ChangeType(select.Source, select.SourceType);
                        selectMemberBindings.Add(Expression.Bind
                        (
                            targetFieldInfo, Expression.Constant(actualValue)
                        ));                        
                    }
                }

                //Id = gmd.Group.Key, Id2 = gmd2.Group.Key
                AddStarSelectColumns(groupBy, selects, resultType, selectMemberBindings);

                //gmd => new Datapoint{...}
                var selectLambda = Expression.Lambda
                (
                    parameters: parentGroupParameter,
                    body: Expression.MemberInit
                    (
                        newExpression: Expression.New(type: resultType),
                        bindings: selectMemberBindings
                    )
                );

                //.Select(...)
                var result = Expression.Call
                (
                    method: selectInfo,
                    arg0: selectSourceExpression,
                    arg1: selectLambda
                );

                return result;
            }
            else if (remDepth >= 2)
            {
                //var newCollectionParameter = Expression.Parameter(type: enumMetadataType, name: MakeNumericName("gmd", depth + 1));
                //groupBy.ElementAt(depth).GroupingEnumParameter = newCollectionParameter;

                var currentParameter = groupBy.ElementAt(depth).GroupingEnumParameter;

                var nestedExpression = MakeGroupByExpressionEx(currentParameter, groupBy, selects, depth + 1, itemType, metadataType, groupingType, resultType);

                var nestedExpressionLambda = Expression.Lambda
                (
                    parameters: currentParameter,
                    body: nestedExpression
                );


                //.SelectMany(gmd => Recurse())
                var sourceElementType = GetTypeOfEnumerable(selectSourceExpression.Type);
                var genericSelectManyInfos = linqExtensionClassType.GetMethods().Where(x => x.Name == "SelectMany" && x.IsGenericMethod && x.GetParameters().Length == 2);
                var genericSelectManyInfo = genericSelectManyInfos.Skip(0).FirstOrDefault();
                var selectManyInfo = genericSelectManyInfo.MakeGenericMethod(sourceElementType, selectType);

                var selectManyRecursiveExpr = Expression.Call
                (
                    method: selectManyInfo,
                    arg0: selectSourceExpression,
                    arg1: nestedExpressionLambda
                );

                return selectManyRecursiveExpr;

            }

            throw new Exception("not supposed to happen");
        }
Exemple #19
0
	void Condition(SingleNodeTree parent, SelectorExpression parentSelector, bool? isAsOptional) {
		SelectorTypes selectorType = SelectorTypes.Unspecified; 
		ModifierTypes modifierType; 
		DimensionExpression dim; 
		ModifierTypes modifierResult; 
		
		SelectorExpression selector = new SelectorExpression(); MultiAdd(parent, selector); 
		if(parentSelector != null) 
		{
		selector.SetNodeType(parentSelector.NodeType);
		selector.SetModifierType(parentSelector.Modifier);
		selector.SetLeft(parentSelector.Left);
		}
		
		if (la.kind == 7) {
			ComplexCondition(parent, selector, false);
		} else if (StartOf(8)) {
			dim = new DimensionExpression(); selector.SetRight(dim); 
			Primary(dim, false);
		} else if (StartOf(9)) {
			ExpressionTreeBase expr = null;  
			LiteralExpression(ref expr);
			selector.SetRight(expr); 
		} else SynErr(48);
		if (StartOf(10)) {
			Modifier(out modifierResult);
			selector.SetLeft(selector.Right); selector.SetRight(null); modifierType = modifierResult; selector.SetModifierType(modifierType); selector.SetNodeType(SelectorTypes.Unknown); 
			if (la.kind == 7) {
				ComplexCondition(parent, selector, false);
			} else if (StartOf(8)) {
				dim = new DimensionExpression(); selector.SetRight(dim); 
				Primary(dim, false);
			} else if (StartOf(9)) {
				ExpressionTreeBase expr = null;  
				LiteralExpression(ref expr);
				selector.SetRight(expr); 
			} else SynErr(49);
		}
		if(isAsOptional == true){	 
		if (la.kind == 3 || la.kind == 4 || la.kind == 28) {
			if (la.kind == 28) {
				Get();
			}
			string alias = null; 
			AliasClause(ref alias);
			selector.Target = alias; 
		}
		}else if(isAsOptional == false){ 
		if (la.kind == 28) {
			Get();
			string alias = null; 
			AliasClause(ref alias);
			selector.Target = alias; 
		}
		} 
	}
Exemple #20
0
	void SelectField(ArgumentListExpression expression, DimensionExpression dimensionToUse = null) {
		var selLol = dimensionToUse ?? new DimensionExpression(); 
		  if(expression != null) 
		{
		selLol.SetParent(expression);  
		expression.AddArgument(selLol); 
		}
		
		if (la.kind == 6 || la.kind == 36) {
			if (la.kind == 6) {
				Get();
				selLol.IsNotted = true; 
			} else {
				Get();
				selLol.IsNegated = true; 
			}
			if (la.kind == 17) {
				Get();
			}
		}
		Condition(selLol, null, true);
		var selectorChild = selLol.Child as SelectorExpression;
		  if (expression != null && selectorChild != null)
		  {
		      var selectorChildRightDimension = selectorChild.Right as DimensionExpression;
		      if (selectorChildRightDimension != null && selectorChild.Left == null)
		      {
		          selectorChildRightDimension.Target = selectorChild.Target;
			selectorChildRightDimension.IsNegated = selLol.IsNegated;
		          selectorChildRightDimension.IsNotted = selLol.IsNotted;
		          expression.AddArgument(selectorChildRightDimension);
		          expression.RemoveArgument(selLol);
		      }
		  }
		
	}
Exemple #21
0
        private static Dictionary<string, Type> InferReduceType(DimensionExpression[] selects, DimensionExpression[] groupBy, Type itemType)
        {
            var requiredFields = new Dictionary<string, Type>();

            int i = 0;

            //            if( groupBy != null && selects != null && selects.Any(x => x.IsStar))
            if (groupBy != null)
                foreach (var g in groupBy)
                {
                    //if( g.GroupBy == null ) continue;
                    if (g.LinkedSelect != null) continue;

                    var nameBase = GetTargetPath(g);

                    //if( g.

                    Type memberType = GetTargetTypeForGroupByDimension(itemType, g);

                    if (IsCollectionType(memberType))
                        memberType = GetTypeOfEnumerable(memberType);

                    if (IsTupleType(memberType))
                        memberType = memberType.GetGenericArguments().Last();
                    

                    requiredFields[nameBase] = memberType;

                    //if (memberType == typeof(string))
                    //{
                    //    requiredFields[nameBase + "_Hash"] = typeof(long);
                    //}

                    i++;
                }

            bool isCountSelected = false;
            bool isCountRequired = false;
            if (selects != null)
                foreach (var select in selects.Where(x => !x.IsStar))
                {

                    var isCountSel = string.Equals(select.Function, "Count", StringComparison.InvariantCultureIgnoreCase);
                    var isCountReq = IsCountRequiredForAggregate(select.Function);
                    isCountSelected = isCountSelected || isCountSel;
                    isCountRequired = isCountRequired || isCountReq;

                    var targetPath = GetTargetPath(select);
                    if (targetPath != null)
                    {
                        if (isCountSel)
                        {
                            requiredFields[targetPath] = typeof(long);
                        }
                        else if (select.Function != null)
                        {
                            var firstArg = select.Arguments.FirstOrDefault();
                            Type argType = null;

                            if (firstArg != null)
                            {
                                var paramLol = Expression.Parameter(itemType, "param");
                                var firstArgExpression = MakeDimensionExpression(itemType, paramLol, firstArg);
                                argType = firstArgExpression.Type;
                            }

                            var aggregateMethodInfo = GetAggregateFunction(select.Function, itemType, argType);
                            if (aggregateMethodInfo != null)
                            {
                                requiredFields[targetPath] = aggregateMethodInfo.ReturnType;
                            }
                            else
                            {
                                var methodInfo = GetFunctionInfo(select.Function);
                                if (methodInfo != null)
                                {
                                    requiredFields[targetPath] = methodInfo.ReturnType;
                                }
                                else
                                {
                                    throw new BermudaExpressionGenerationException("Unknown function:" + select.Function);
                                }
                            }
                        }
                        else
                        {
                            if (select.Child != null)
                            {
                                var expr =  select.CreateExpression(null);
                                requiredFields[targetPath] = expr.Type;
                            }
                            else
                            {
                                //try to retrieve the source MemberInfo from the original type
                                var member = GetMember(itemType, select.Source, false);

                                //set the inferred member to the retrieved type
                                if (member != null)
                                {
                                    if (select.LinkedGroupBy == null) throw new Exception("Invalid Column Name: " + select.Source);
                                    requiredFields[targetPath] = GetMemberType(member);
                                }
                                else
                                {
                                    //try to fall back to a groupby dimension
                                    var matchingGroupBy = groupBy.FirstOrDefault(x => string.Equals(x.Target, select.Source));
                                    if (matchingGroupBy != null)
                                    {
                                        var targetType = GetTargetTypeForGroupByDimension(itemType, matchingGroupBy);
                                        requiredFields[targetPath] = targetType;
                                    }
                                    else
                                    {
                                        //if source path can't be found just use the column name as a literal value
                                        requiredFields[targetPath] = select.SourceType;
                                    }
                                }
                            }
                        }
                    }

                }

            if (!isCountSelected && isCountRequired)
            {
                requiredFields[CountTargetPath] = typeof(long);
            }
            return requiredFields;
        }
Exemple #22
0
        private static Dictionary<string, Type> InferSelectType(DimensionExpression[] selects, Type itemType)
        {
            var requiredFields = new Dictionary<string, Type>();

            var itemParam = Expression.Parameter(itemType, "p");

            foreach (var select in selects)
            {
                if (select.Function == null)
                {

                    //var sourceField = GetField(itemType, select.Source);
                    var sourceExpression = MakeDimensionExpression(itemType, itemParam, select);

                    if (!select.IsStar)
                    {
                        var targetPath = GetTargetPath(select);

                        if (targetPath == null) throw new BermudaExpressionGenerationException("No alias provided for the select field: " + select);

                        requiredFields[targetPath] = sourceExpression.Type;
                    }
                    else
                    {
                        foreach (var field in itemType.GetFields().Where(x => !IsCollectionType(x.FieldType) ))
                        {
                            requiredFields[field.Name] = field.FieldType;
                        }
                    }
                }
                else
                {
                    if (select.Target == null) throw new BermudaExpressionGenerationException("Alias not provided for function call: " + select);

                    //var methodInfo = GetFunctionInfo(select.Function);

                    if (IsAggregateFunction(select.Function)) throw new Exception("Cannot use an aggregate function without grouping or while having a non-aggregate select");

                    var functionCallExpr = MakeFunctionCallExpression(select, itemType, Expression.Parameter(itemType, "x"));


                    var targetPath = GetTargetPath(select);
                    requiredFields[targetPath] = functionCallExpr.Type;

                }
            }

            return requiredFields;
        }
Exemple #23
0
        public static Expression GetMapreduceExpression(Expression filter, DimensionExpression[] selects, DimensionExpression[] groupBy, Type itemType, GetExpression get, Expression source, string paramname)
        {
            var hash = (filter == null ? 0 : filter.ToString().GetHashCode()) + "|" + (selects == null ? "" : string.Join(",", selects.Select(x => x.GetChecksum()))) + "|" + (groupBy == null ? "" : string.Join(",", groupBy.Select(x => x.GetChecksum()))) + "|" + (get == null ? null : get.Take);
            Expression expr;

            var containsAggregates = selects != null && selects.Any(x => x.IsAggregate);

            LinkDimensions(groupBy, selects);

            var resultType = InferClrType(selects, groupBy, itemType);

            if (expressionCache.TryGetValue(hash, out expr))
            {
                return expr;
            }

            //a flat select transformation
            if (selects != null && groupBy == null && !containsAggregates)
            {
                expr = MakeSelectExpression(filter, selects, itemType, resultType, get, source, paramname);
            }
            else
            {
                //a non-grouping aggregate like "SELECT COUNT(*) FROM table"
                if (groupBy == null || !groupBy.Any()) groupBy = new DimensionExpression[] { new DimensionExpression { Source = null, Function = null } };

                expr = MakeMapreduceExpression(filter, selects, groupBy, itemType, resultType, get, source, paramname);
            }

            expressionCache[hash] = expr;

            return expr;
        }
Exemple #24
0
        private static MemberAssignment MakeAggregateFunctionCallExpression(Expression enumParameter, DimensionExpression select, Expression sourceExpression, int metadataDepth, Type resultType, string targetPathOverride)
        {
            var elementType = GetTypeOfEnumerable(enumParameter.Type);

            if (select.Function == "Count")
            {
                var targetPath = targetPathOverride ?? GetTargetPath(select);

                var genericCountInfo = typeof(Enumerable).GetMethods().FirstOrDefault(x => x.Name == "LongCount" && x.IsGenericMethod && x.GetParameters().Length == 1);
                var countInfo        = genericCountInfo.MakeGenericMethod(elementType);

                var memberInfo = GetMember(resultType, targetPath);

                if (memberInfo == null)
                {
                    throw new Exception("Unknown target path for " + resultType + ": " + targetPath);
                }

                var actualExpression = sourceExpression ?? Expression.Call(method: countInfo, arguments: enumParameter);
                var targetType       = GetMemberType(memberInfo);

                return(Expression.Bind
                       (
                           member: memberInfo,
                           expression: actualExpression.Type != targetType ? Expression.Convert(type: targetType, expression: actualExpression) : actualExpression
                       ));
            }
            else
            {
                var targetPath = targetPathOverride ?? GetTargetPath(select);

                if (targetPath == null)
                {
                    throw new Exception("Both target and source path required for aggregate: " + select.Function);
                }

                var mentionParameter = Expression.Parameter(type: elementType, name: GenerateParamName(elementType, metadataDepth));

                var firstArgument = select.Arguments.FirstOrDefault();

                //if (firstArgument.Function == null)
                //{

                Expression memberAccessBody = null;

                if (firstArgument.Function != null)
                {
                    var targetFieldInfo0 = GetField(resultType, targetPath);

                    var functionCall = MakeFunctionCallExpression(firstArgument, elementType, mentionParameter);

                    memberAccessBody = functionCall;
                }
                else
                {
                    string fieldName = firstArgument.Source;
                    memberAccessBody = GetMemberAccessRecursively(mentionParameter, fieldName, select.SourceType, metadataDepth, metadataDepth);
                }

                var targetFieldInfo = GetField(resultType, targetPath);

                var targetType = targetFieldInfo.FieldType;

                var averageInfo = GetAggregateFunction(select.Function, elementType, memberAccessBody.Type);

                if (averageInfo == null)
                {
                    return(null);
                }

                Expression functionCallBody = null;

                var averageLambda = Expression.Lambda
                                    (
                    delegateType: typeof(Func <,>).MakeGenericType(elementType, memberAccessBody.Type),
                    body: functionCallBody ?? memberAccessBody,
                    parameters: new ParameterExpression[] { mentionParameter }
                                    );

                var actualExpression = sourceExpression ?? Expression.Call(method: averageInfo, arguments: new Expression[] { enumParameter, averageLambda });

                var bindingres = Expression.Bind
                                 (
                    member: targetFieldInfo,
                    expression: actualExpression.Type != targetType ? Expression.Convert(type: targetType, expression: actualExpression) : actualExpression
                                 );

                return(bindingres);
            }

            throw new Exception("Unknown Select");
        }
 public void AddDimension(DimensionExpression dim)
 {
     _dimensions.Add(dim);
 }
Exemple #26
0
	void OrderClause(GetExpression expression) {
		Expect(19);
		Expect(20);
		var ordering = new DimensionExpression(); expression.Ordering = ordering; 
		Primary(ordering, true);
		if (la.kind == 21) {
			Get();
			expression.OrderDescending = true; 
		}
		if (la.kind == 22) {
			Get();
			Expect(1);
			expression.Take = Int32.Parse(t.val); 
			if (la.kind == 18) {
				Get();
				Expect(1);
				expression.Skip = expression.Take; expression.Take = Int32.Parse(t.val); 
			}
		}
	}
Exemple #27
0
	void Primary(DimensionExpression sel, bool? isAsOptional) {
		if (la.kind == 3 || la.kind == 4 || la.kind == 31) {
			var identifier = new IdentifierExpression(); 
			Identifier(identifier);
			sel.Source = identifier.LastPart; sel.SourceType = typeof(string); 
            sel.IsQuoted = identifier.IsQuoted; 
			if (la.kind == 7) {
				sel.Function = sel.Source; sel.Source = null; 
				Get();
				if (StartOf(4)) {
					var argList = new ArgumentListExpression(); argList.SetParent(sel); sel.IsFunctionCall = true; 
					SelectField(argList);
					while (la.kind == 18) {
						Get();
						SelectField(argList);
					}
					sel.AddArguments(argList.GetChildren()); 
				}
				Expect(8);
			}
		} else if (la.kind == 9) {
			Get();
			Expect(11);
			Primary(sel, null);
			Expect(10);
		} else if (la.kind == 1) {
			Get();
			sel.Source = t.val; sel.SourceType = typeof(long); 
		} else if (la.kind == 2) {
			Get();
			sel.Source = t.val; sel.SourceType = typeof(double); 
		} else if (la.kind == 4) {
			Get();
			sel.Source = t.val.Substring(1, t.val.Length - 2); sel.SourceType = typeof(string); sel.IsQuoted = true; 
		} else SynErr(47);
	}
Exemple #28
0
 internal void AddArgument(DimensionExpression dim)
 {
     dim.SetParent(this);
     Arguments.Add(dim);
 }
Exemple #29
0
	void GroupByClause(GetExpression expression) {
		Expect(30);
		Expect(20);
		var groupByDimension = new DimensionExpression(); 
		expression.AddDimension(groupByDimension); 
		
		GroupByField(groupByDimension);
		while (la.kind == 18) {
			Get();
			var groupByDimension2 = new DimensionExpression(); 
			expression.AddDimension(groupByDimension2); 
			
			GroupByField(groupByDimension2);
		}
		if (la.kind == 33) {
			HavingClause(expression);
		}
	}
Exemple #30
0
        private static Expression GetMergeExpression(Type elementType, ParameterExpression selectGroupParam, DimensionExpression[] selects, DimensionExpression[] groupBy)
        {
            //if (select.Aggregate == "First")
            //{
            //    var genericFirstOrDefaultInfos = typeof(Enumerable).GetMethods().Where(x => x.Name == "FirstOrDefault" && x.IsGenericMethod && x.GetParameters().Length == 1);
            //    var genericFirstOrDefaultInfo = genericFirstOrDefaultInfos.FirstOrDefault();
            //    var firstOrDefaultInfo = genericFirstOrDefaultInfo.MakeGenericMethod(elementType);
            //    var mergeExpr = Expression.Call(method: firstOrDefaultInfo, arg0: selectGroupParam);
            //    return mergeExpr;
            //}

            //if ((groupBy == null || !groupBy.Any()) && !selects.All(x => ReduceExpressionGeneration.IsAggregateFunction(x.Function) || x.IsStar)) return null;

            var memberBindigs = new List<MemberAssignment>();

            /*
            //group by all the non-select fields
            foreach (var x in elementType.GetFields())
            {
                if (selects.Any(s => string.Equals(x.Name, GetTargetPath(s), StringComparison.InvariantCultureIgnoreCase))) continue;

                var keyAccess = Expression.MakeMemberAccess
                (
                    member: selectGroupParam.Type.GetProperty("Key"),
                    expression: selectGroupParam
                );

                var memberAccess = Expression.Bind
                (
                    member: x,
                    expression: Expression.MakeMemberAccess
                    (
                        member: x,
                        expression: keyAccess
                    )
                );

                memberBindigs.Add(memberAccess);
            }*/

            var fields = elementType.GetFields();
            foreach (var sel in fields)
            {
                //if (sel.IsStar) continue;

                //var tar = GetTargetPath(sel);
                //if (fields.Any(x => string.Equals(x.Name, tar, StringComparison.InvariantCultureIgnoreCase))) continue;

                if (selects.Any(x => string.Equals(GetTargetPath(x), sel.Name, StringComparison.InvariantCultureIgnoreCase))) continue;
                if (string.Equals(sel.Name, CountTargetPath, StringComparison.InvariantCultureIgnoreCase)) continue;

                //var targetMember = fields.FirstOrDefault(x => string.Equals(x.Name, tar));
                var targetMember = sel;

                var keyAccess = Expression.MakeMemberAccess
                (
                    member: selectGroupParam.Type.GetProperty("Key"),
                    expression: selectGroupParam
                );

                var memberAccess = Expression.Bind
                (
                    member: targetMember,
                    expression: Expression.MakeMemberAccess
                    (
                        member: targetMember,
                        expression: keyAccess
                    )
                );

                memberBindigs.Add(memberAccess);
            }

            var actualSelects = selects.ToList();

            if (!actualSelects.Any(x => string.Equals(x.Function, CountAggregateString, StringComparison.InvariantCultureIgnoreCase)) && actualSelects.Any(x => IsCountRequiredForAggregate(x.Function) ))
            {
                actualSelects.Add(new DimensionExpression { Function = CountAggregateString, Target = CountTargetPath } );
            }

            foreach(var g in groupBy)
            {
                if (g.IsAutoSelect && g.LinkedSelect == null)
                {
                    var groupByTargetPath = GetTargetPath(g);
                    var selectTargetPath = g.LinkedSelect == null ? null : GetTargetPath(g.LinkedSelect);
                    actualSelects.Add(new DimensionExpression
                    {
                        Source = groupByTargetPath,
                        Target = selectTargetPath ?? groupByTargetPath,
                        IsBasedOnGrouping = true
                    });
                }
                //else
                //{
                //    var groupByTargetPath = GetTargetPath(g);
                //    if( g.LinkedSelect. != null ) groupByTargetPath = GetTargetPath(g.LinkedSelect);
                //    var matchingField = fields.FirstOrDefault(x => string.Equals(x.Name, groupByTargetPath, StringComparison.InvariantCultureIgnoreCase));
 
                    
                //}
            }

            foreach (var sel in actualSelects)
            {
                if (sel.IsStar) continue;

                var targetPath = GetTargetPath(sel);

                var targetField = GetField(elementType, targetPath);

                if (sel.IsBasedOnGrouping)
                {
                    var keyPropertyInfo = selectGroupParam.Type.GetProperty("Key");
                    var keyMemberAccess = Expression.MakeMemberAccess(selectGroupParam, keyPropertyInfo);
                    var keyPropertyAccess = Expression.MakeMemberAccess(keyMemberAccess, targetField);

                    memberBindigs.Add(Expression.Bind
                    (
                        member: targetField,
                        expression: keyPropertyAccess
                    ));
                }
                else
                {
                    //if( targetField.FieldType != ty

                    var genericSumInfos = typeof(Enumerable).GetMethods().Where(x => x.Name == "Sum" && x.IsGenericMethod && x.GetParameters().Length == 2 && x.ReturnType == targetField.FieldType);
                    var genericSumInfo = genericSumInfos.FirstOrDefault();
                    var sumInfo = genericSumInfo.MakeGenericMethod(elementType);

                    var genericSumInfos2 = typeof(Enumerable).GetMethods().Where(x => x.Name == "Sum" && x.IsGenericMethod && x.GetParameters().Length == 2 && x.ReturnType == typeof(long));
                    var genericSumInfo2 = genericSumInfos2.FirstOrDefault();
                    var sumInfo2 = genericSumInfo2.MakeGenericMethod(elementType);

                    ////TargetField = g.Sum(p => p.TargetField * p._Count) / g.Sum(p => p._Count)
                    if ( string.Equals(sel.Function, "Average", StringComparison.InvariantCultureIgnoreCase) )
                    {
                        var actualCountTargetPath = CountTargetPath;
                        var countSelect = actualSelects.FirstOrDefault(x => string.Equals(x.Function, CountAggregateString, StringComparison.InvariantCultureIgnoreCase));

                        if (countSelect == null) throw new Exception("The provided type has no required count field");

                        actualCountTargetPath = GetTargetPath(countSelect);

                        var pointParameter = Expression.Parameter(elementType, "p1");
                        var countAccess = Expression.MakeMemberAccess(pointParameter, GetField(elementType, actualCountTargetPath));
                        var targetPathAccess = Expression.MakeMemberAccess(pointParameter, GetField(elementType, targetPath));
                        var sumBody = Expression.Multiply
                        (
                            left: (countAccess.Type == targetPathAccess.Type) ? (Expression)countAccess : Expression.Convert(countAccess, targetPathAccess.Type),
                            right: targetPathAccess
                        );

                        var pointParameter2 = Expression.Parameter(elementType, "p2");
                        var sumBody2 = Expression.MakeMemberAccess(pointParameter2, GetField(elementType, actualCountTargetPath));

                        Expression sumOfProducts = Expression.Call(method: sumInfo, arg0: selectGroupParam, arg1: Expression.Lambda(parameters: pointParameter, body: sumBody));
                        Expression sumOfCounts = Expression.Call(method: sumInfo2, arg0: selectGroupParam, arg1: Expression.Lambda(parameters: pointParameter2, body: sumBody2));

                        var division = Expression.Divide
                        (
                            left: sumOfProducts,
                            right: sumOfProducts.Type != sumOfCounts.Type ? Expression.Convert(sumOfCounts, sumOfProducts.Type) : sumOfCounts
                        );

                        memberBindigs.Add(Expression.Bind
                        (
                            member: targetField,
                            expression: division
                        ));
                    }

                    //TargetField = g.Sum(p => p.TargetField)
                    else// (string.Equals(sel.Function, CountAggregateString, StringComparison.InvariantCultureIgnoreCase) || string.Equals(sel.Function, "Sum", StringComparison.InvariantCultureIgnoreCase))
                    {
                        var pointParameter = Expression.Parameter(elementType, "p0");
                        var sumBody = Expression.MakeMemberAccess(pointParameter, GetField(elementType, targetPath));

                        memberBindigs.Add(Expression.Bind
                        (
                            member: targetField,
                            expression: Expression.Call(method: sumInfo, arg0: selectGroupParam, arg1: Expression.Lambda(parameters: pointParameter, body: sumBody)))
                        );
                    }

                }
            }

            var result = Expression.MemberInit
            (
                newExpression: Expression.New(elementType),
                bindings: memberBindigs
            );

            return result;
        }
Exemple #31
0
	void GroupByField(DimensionExpression expression) {
		if (la.kind == 24 || la.kind == 26) {
			if (la.kind == 24) {
				Get();
				expression.OrderDescending = true; 
			} else {
				Get();
				expression.OrderDescending = false; 
			}
			Expect(1);
			expression.Take = Int32.Parse(t.val); 
		}
		SelectField(null, expression);
		if (la.kind == 25) {
			var inClause = new InExpression(); expression.InClause = inClause; 
			InClause(inClause);
		}
		if (la.kind == 27) {
			Get();
			var dim = new DimensionExpression(); 
			Primary(dim, false);
			expression.Ordering = dim; 
		}
	}
 internal void AddArgument(DimensionExpression dim)
 {
     dim.SetParent(this);
     Arguments.Add(dim);
 }
Exemple #33
0
        private static void AddStarSelectColumns(DimensionExpression[] groupBy, DimensionExpression[] selects, Type resultType, List<MemberAssignment> selectMemberBindings)
        {
            var starSelect = selects.FirstOrDefault(x => x.IsStar);

            int i = 0;
            foreach (var g in groupBy)
            {
                if (!(starSelect != null || g.IsAutoSelect)) continue;

                //if (g.Child != null)
                //{

                //}
                //else 
                    
                if (g.Source != null || g.Function != null || g.LinkedSelect != null || g.IsAutoSelect)
                {
                    var actualEnumAccess = Expression.MakeMemberAccess
                    (
                        expression: g.GroupingEnumParameter,
                        member: g.GroupingEnumParameter.Type.GetField("Enum")
                    );

                    var keyPropertyInfo = actualEnumAccess.Type.GetProperty("Key");

                    var keyAccess = Expression.MakeMemberAccess
                    (
                        expression: actualEnumAccess,
                        member: keyPropertyInfo
                    );

                    //var groupByTargetPath = GetTargetPath(keyPropertyInfo.PropertyType);
                    //var targetMemberName = MakeNumericName(groupByTargetPath, i);
                    var targetMemberName = GetTargetPath(g);

                    if (g.LinkedSelect != null)
                    {
                        targetMemberName = GetTargetPath(g.LinkedSelect);
                    }

                    //var isNumeric = keyPropertyInfo.PropertyType == typeof(long);

                    var field = GetField(resultType, targetMemberName);

                    var resultMemberAssignment = Expression.Bind
                    (
                        member: field,
                        expression: keyAccess
                    );

                    selectMemberBindings.Add(resultMemberAssignment);

                    //if (!isNumeric)
                    //{
                    //    var getHashCall = Expression.Call(instance: keyAccess, method: keyAccess.Type.GetMethod("GetHashCode"));

                    //    var setIdForStringGrouping = Expression.Bind
                    //    (
                    //        member: resultType.GetField( GetTargetPath(g) + "_Hash" ),
                    //        expression: Expression.Convert( type:typeof(long), expression: getHashCall )
                    //    );

                    //    selectMemberBindings.Add(setIdForStringGrouping);
                    //}
                }
                i++;
            }
            
        }
 internal void CopyFrom(DimensionExpression s)
 {
     this.Function = s.Function;
     this.Target = s.Target;
     this.SetChild(s.Child);
     this.AddArguments(s.Arguments);
 }
Exemple #35
0
        private static Expression MakeConvertExpression(DimensionExpression currentDimension, Type itemType, ParameterExpression keySelectorParameter, string targetType = null)
        {
            if (currentDimension.Arguments.Count != 2 && targetType == null) throw new BermudaExpressionGenerationException("Convert function requires 2 arguments");
            if (currentDimension.Arguments.Count != 1 && targetType != null) throw new BermudaExpressionGenerationException("Cast function requires 1 argument");

            string lowerType;

            if (targetType == null)
            {
                targetType = currentDimension.Arguments[1].ToString();
                lowerType = targetType.ToLower();
            }
            else
            {
                lowerType = targetType.ToLower();
            }

            var firstArg = currentDimension.Arguments.FirstOrDefault();

            Expression firstArgExpr = MakeDimensionExpression(itemType, keySelectorParameter, firstArg);
            Type conversionTargetType = null;

            switch (lowerType)
            {
                case "sql_bigint": conversionTargetType = typeof(long); break;
                case "integer": conversionTargetType = typeof(int); break;
                case "date": conversionTargetType = typeof(DateTime); break;
                default: throw new BermudaExpressionGenerationException("Unknown target type: " + targetType); 
            }

            if (conversionTargetType == firstArgExpr.Type) 
                return firstArgExpr;

            var convexpr = Expression.Convert(firstArgExpr, conversionTargetType);

            return convexpr;
            //throw new BermudaExpressionGenerationException("Invalid cast arguments: " + firstArg + " to " + targetType);
        }
Exemple #36
0
        private static Expression MakeDimensionExpression(Type itemType, ParameterExpression keySelectorParameter, DimensionExpression firstArg)
        {
            Expression firstArgExpr;
            bool       dontNegate = false;

            if (firstArg.Child != null)
            {
                dontNegate   = true;
                firstArgExpr = firstArg.CreateExpression(null);
            }
            else if (firstArg.Function != null)
            {
                firstArgExpr = MakeFunctionCallExpression(firstArg, itemType, keySelectorParameter);
            }
            else
            {
                var sourcePath = firstArg.Source;
                var member     = GetMember(itemType, sourcePath, false);

                if (member == null)
                {
                    var stringVersion = firstArg.Source;

                    long   num;
                    double num2;

                    if (long.TryParse(stringVersion, out num))
                    {
                        return(Expression.Constant(num));
                    }
                    if (double.TryParse(stringVersion, out num2))
                    {
                        return(Expression.Constant(num2));
                    }

                    firstArgExpr = Expression.Constant(stringVersion);
                }
                else
                {
                    firstArgExpr = Expression.MakeMemberAccess(keySelectorParameter, member);
                }
            }

            if (!dontNegate)
            {
                if (firstArg.IsNegated)
                {
                    firstArgExpr = Expression.Negate(firstArgExpr);
                }
                else if (firstArg.IsNotted)
                {
                    firstArgExpr = Expression.Not(firstArgExpr);
                }
            }

            return(firstArgExpr);
        }
Exemple #37
0
        public static Expression MakeFunctionCallExpression(DimensionExpression currentDimension, Type itemType, ParameterExpression keySelectorParameter)
        {
            //var functionName = currentDimension.Function ?? currentDimension.LinkedSelect.Function;

            if (currentDimension.Function == null && currentDimension.LinkedSelect != null)
            {
                currentDimension = currentDimension.LinkedSelect;
            }

            if (string.Equals(currentDimension.Function, "convert", StringComparison.InvariantCultureIgnoreCase))
            {
                if (currentDimension.Arguments.Count != 2)
                {
                    throw new BermudaExpressionGenerationException("Convert requires 2 arguments");
                }
                Expression conv = MakeConvertExpression(currentDimension, itemType, keySelectorParameter);
                if (currentDimension.IsNegated)
                {
                    conv = Expression.Negate(conv);
                }
                if (currentDimension.IsNotted)
                {
                    conv = Expression.Not(conv);
                }
                return(conv);
            }

            if (string.Equals(currentDimension.Function, "cast", StringComparison.InvariantCultureIgnoreCase))
            {
                if (currentDimension.Arguments.Count != 1)
                {
                    throw new BermudaExpressionGenerationException("Cast requires 1 argument");
                }
                Expression conv = MakeConvertExpression(currentDimension, itemType, keySelectorParameter, currentDimension.Arguments.First().Target);
                if (currentDimension.IsNegated)
                {
                    conv = Expression.Negate(conv);
                }
                if (currentDimension.IsNotted)
                {
                    conv = Expression.Not(conv);
                }
                return(conv);
            }

            Expression keySelectorBody;

            currentDimension.IsDateTime = true;
            var functionInfo = typeof(UtilityExtensions).GetMethods().Where(x => string.Equals(x.Name, currentDimension.Function, StringComparison.InvariantCultureIgnoreCase) && currentDimension.Arguments.Count == x.GetParameters().Length).FirstOrDefault();

            //keySelectorBody = Expression.MakeMemberAccess(expression: keySelectorBody, member: typeof(DateTime).GetProperty("Ticks"));

            if (functionInfo == null)
            {
                throw new BermudaExpressionGenerationException("Function " + currentDimension.Function + "(" + string.Join(",", Enumerable.Range(0, currentDimension.Arguments.Count).Select(n => "arg" + n)) + ") not supported.");
            }

            var functionArguments = new List <Expression>();

            var methodParams = functionInfo.GetParameters();

            if (currentDimension.Arguments.Count != methodParams.Length)
            {
                throw new BermudaExpressionGenerationException("Number of arguments does not match the number of parameters for function " + currentDimension.Function);
            }

            for (int i = 0; i < methodParams.Length; i++)
            {
                var actualArg     = currentDimension.Arguments[i];
                var parameterType = methodParams[i].ParameterType;

                if (actualArg.IsFunctionCall)
                {
                    Expression functionCall = MakeFunctionCallExpression(actualArg, itemType, keySelectorParameter);

                    if (functionCall.Type != parameterType)
                    {
                        functionCall = Expression.Convert(functionCall, parameterType);
                    }
                    functionArguments.Add(functionCall);
                }
                else if (actualArg.Source != null)
                {
                    if (actualArg.IsQuoted)
                    {
                        functionArguments.Add(Expression.Constant(actualArg.Source));
                        continue;
                    }

                    //see if the provided string is a column name
                    var targetMember = GetMember(itemType, actualArg.Source, false);

                    if (targetMember != null)
                    {
                        keySelectorBody = Expression.MakeMemberAccess(expression: keySelectorParameter, member: targetMember);
                        functionArguments.Add(keySelectorBody);
                    }
                    else
                    {
                        var actualValue = parameterType == typeof(string) ? actualArg.Source : Convert.ChangeType(actualArg.Source, parameterType);
                        functionArguments.Add(Expression.Constant(actualValue));
                    }
                }
                else if (actualArg.Child != null)
                {
                    var childExpr = actualArg.Child.CreateExpression(null);

                    if (childExpr.Type != parameterType)
                    {
                        childExpr = Expression.Convert(childExpr, parameterType);
                    }

                    functionArguments.Add(childExpr);
                }
            }

            keySelectorBody = Expression.Call
                              (
                method: functionInfo,
                arguments: functionArguments
                              );

            if (currentDimension.IsNegated)
            {
                keySelectorBody = Expression.Negate(keySelectorBody);
            }
            if (currentDimension.IsNotted)
            {
                keySelectorBody = Expression.Not(keySelectorBody);
            }

            return(keySelectorBody);
        }
Exemple #38
0
 public void AddDimension(DimensionExpression dim)
 {
     _dimensions.Add(dim);
 }
Exemple #39
0
        public static Expression GetMergeInvocationExpression(DimensionExpression[] selects, DimensionExpression[] groupBy, Type elementType)
        {

            if ((groupBy == null || !groupBy.Any()) && !selects.All(x => x.IsAggregate)) return null;

            //var elementType = ReduceExpressionGeneration.GetTypeOfEnumerable( collectionType );
            LinkDimensions(groupBy, selects);

            var collectionType = typeof(IEnumerable<>).MakeGenericType(elementType);

            var collectionParameter = Expression.Parameter(collectionType, "col");

            var genericGroupByInfos = typeof(Enumerable).GetMethods().Where(x => x.Name == "GroupBy" && x.IsGenericMethod && x.GetParameters().Length == 2);
            var genericGroupByInfo = genericGroupByInfos.FirstOrDefault();
            var groupByInfo = genericGroupByInfo.MakeGenericMethod(elementType, elementType);

            var lambdaParam = Expression.Parameter(elementType, "x");

            var groupingDimensionBindings = new List<MemberAssignment>();

            
            var fields = elementType.GetFields();
            foreach (var g in groupBy)
            {
                var tar = GetTargetPath(g);
                var tar2 = g.LinkedSelect == null ? null : GetTargetPath(g.LinkedSelect);
                //fields.Any(x => string.Equals(x.Name, tar, StringComparison.InvariantCultureIgnoreCase))
                //if( !sel.IsBasedOnGrouping )   continue;
                //if (string.Equals(GetTargetPath(sel), CountTargetPath)) continue;

                var targetField = fields.FirstOrDefault
                (
                    x =>  g.LinkedSelect == null 
                    ? string.Equals(x.Name, tar, StringComparison.InvariantCultureIgnoreCase) 
                    : string.Equals(x.Name, tar2, StringComparison.InvariantCultureIgnoreCase 
                ));

                var binding = Expression.Bind(targetField, Expression.MakeMemberAccess(lambdaParam, targetField));
                groupingDimensionBindings.Add(binding);
            }
            

            /*
            foreach (var x in elementType.GetFields())
            {
                if (selects.Any(s => !s.IsBasedOnGrouping && string.Equals(x.Name, GetTargetPath(s), StringComparison.InvariantCultureIgnoreCase)))
                    continue;



                var binding = Expression.Bind(x, Expression.MakeMemberAccess(lambdaParam, GetField(elementType, x.Name)));
                groupingDimensionBindings.Add(binding);
            }*/

            var groupByLambda = Expression.Lambda
            (
                parameters: lambdaParam,
                body: Expression.MemberInit
                (
                    Expression.New(elementType),
                    groupingDimensionBindings
                )
            );

            var pointGroups = Expression.Call(method: groupByInfo, arg0: collectionParameter, arg1: groupByLambda);

            var enumType = pointGroups.Type;
            var groupingType = GetTypeOfEnumerable(enumType);
            var genericSelectInfo = typeof(Enumerable).GetMethods().FirstOrDefault(x => x.Name == "Select" && x.IsGenericMethod && x.GetParameters().Length == 2);
            var selectInfo0 = genericSelectInfo.MakeGenericMethod(groupingType, elementType);

            var selectGroupParam = Expression.Parameter(type: groupingType, name: "g");
            //var selectBody = Expression.Invoke(mergeExpr, selectGroupParam);
            var mergeExpr = GetMergeExpression(elementType, selectGroupParam, selects, groupBy );


            var selectLambda = Expression.Lambda(parameters: selectGroupParam, body: mergeExpr);

            var selectExpr = Expression.Call(method: selectInfo0, arg0: pointGroups, arg1: selectLambda);

            //selectExpr = AppendToArray(elementType, selectExpr);

            var finalLambda = Expression.Lambda(selectExpr, collectionParameter);

            return finalLambda;
        }
 public void RemoveArgument(DimensionExpression dim)
 {
     if(Dimensions.Contains(dim)) Dimensions.Remove(dim);
 }