Beispiel #1
0
        private bool CanGenerateColumnar()
        {
            var typeOfTOuterKey = typeof(TOuterKey);
            var typeOfTInnerKey = typeof(TInnerKey);
            var typeOfTResult   = typeof(TResult);

            if (!typeOfTResult.CanRepresentAsColumnar())
            {
                return(false);
            }
            if (typeOfTOuterKey.GetPartitionType() != null)
            {
                return(false);
            }
            if (typeOfTInnerKey.GetPartitionType() != null)
            {
                return(false);
            }
            // For now, restrict the inner key to be anything other than an anonymous type since those can't be ungrouped without using reflection.
            if (typeOfTInnerKey.IsAnonymousType())
            {
                return(false);
            }

            var lookupKey = CacheKey.Create(ResultSelector.ExpressionToCSharp());

            var generatedPipeType = cachedPipes.GetOrAdd(lookupKey, key => UngroupTemplate.Generate <TOuterKey, TInnerKey, TInnerResult, TResult>(ResultSelector));

            errorMessages = generatedPipeType.Item2;
            return(generatedPipeType.Item1 != null);
        }
Beispiel #2
0
        private IStreamObserver <CompoundGroupKey <TOuterKey, TInnerKey>, TInnerResult> GetPipe(IStreamObserver <TOuterKey, TResult> observer)
        {
            var lookupKey = CacheKey.Create(ResultSelector.ExpressionToCSharp());

            var generatedPipeType = cachedPipes.GetOrAdd(lookupKey, key => UngroupTemplate.Generate <TOuterKey, TInnerKey, TInnerResult, TResult>(ResultSelector));
            Func <PlanNode, IQueryObject, PlanNode> planNode = ((PlanNode p, IQueryObject o) => new UngroupPlanNode(
                                                                    p,
                                                                    o,
                                                                    typeof(CompoundGroupKey <TOuterKey, TInnerKey>),
                                                                    typeof(TOuterKey),
                                                                    typeof(TInnerResult),
                                                                    typeof(TResult),
                                                                    ResultSelector,
                                                                    true,
                                                                    generatedPipeType.Item2));

            var instance    = Activator.CreateInstance(generatedPipeType.Item1, this, observer, planNode);
            var returnValue = (IStreamObserver <CompoundGroupKey <TOuterKey, TInnerKey>, TInnerResult>)instance;

            return(returnValue);
        }
Beispiel #3
0
        private static Tuple <Type, string> GenerateInternal <TOuterKey, TInnerKey, TInnerResult, TResult>(Expression <Func <TInnerKey, TInnerResult, TResult> > resultSelector, bool isFirstLevelGroup)
        {
            Contract.Ensures(Contract.Result <Tuple <Type, string> >() != null);
            Contract.Ensures(typeof(Pipe <TOuterKey, TResult>).GetTypeInfo().IsAssignableFrom(Contract.Result <Tuple <Type, string> >().Item1));

            string errorMessages = null;

            try
            {
                var typeOfTOuterKey    = typeof(TOuterKey);
                var typeOfTInnerKey    = typeof(TInnerKey);
                var typeofTInnerResult = typeof(TInnerResult);
                var typeofTResult      = typeof(TResult);

                string          expandedCode;
                List <Assembly> assemblyReferences;
                int             numberOfGenericParameters;

                // inline: var ok = UngroupTemplate.GetGeneratedCode<TOuterKey, TInnerKey, TInnerResult, TResult>(resultSelector, false, out generatedClassName, out expandedCode, out assemblyReferences, out numberOfGenericParameters);


                var generatedClassName = string.Format(
                    "UngroupPipeGeneratedFrom_{0}_{1}_{2}_{3}_{4}",
                    typeOfTOuterKey.GetValidIdentifier(),
                    typeOfTInnerKey.GetValidIdentifier(),
                    typeofTInnerResult.GetValidIdentifier(),
                    typeofTResult.GetValidIdentifier(),
                    UngroupSequenceNumber++);

                var inputMessageType = StreamMessageManager.GetStreamMessageType <CompoundGroupKey <TOuterKey, TInnerKey>, TInnerResult>();

                var innerResultRepresentation = new ColumnarRepresentation(typeofTInnerResult);
                var resultRepresentation      = new ColumnarRepresentation(typeofTResult);

                var parameterSubstitutions = new List <Tuple <ParameterExpression, SelectParameterInformation> >
                {
                    // Leave the key parameter to the selector unchanged, so no substitution for parameters[0]
                    Tuple.Create(resultSelector.Parameters[1], new SelectParameterInformation()
                    {
                        BatchName = "inputBatch", BatchType = inputMessageType, IndexVariableName = "i", parameterRepresentation = innerResultRepresentation,
                    })
                };
                var result = SelectTransformer.Transform(resultSelector, parameterSubstitutions, resultRepresentation);
                if (result.Error)
                {
                    return(Tuple.Create((Type)null, errorMessages));
                }

                var template = new UngroupTemplate(generatedClassName, !isFirstLevelGroup, typeOfTOuterKey, typeOfTInnerKey, typeofTInnerResult, typeofTResult)
                {
                    innerResultRepresentation = innerResultRepresentation,
                    swingingFields            = result.SwingingFields,
                    computedFields            = result.ComputedFields,
                    unassignedFields          = result.UnmentionedFields,
                    keyParameter = resultSelector.Parameters.First()
                };

                template.staticCtor = Transformer.StaticCtor(template.CLASSNAME);
                expandedCode        = template.TransformText();

                assemblyReferences = Transformer.AssemblyReferencesNeededFor(typeOfTOuterKey, typeOfTInnerKey, typeofTInnerResult, typeofTResult);
                assemblyReferences.Add(typeof(IStreamable <,>).GetTypeInfo().Assembly);
                // input messages
                assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <CompoundGroupKey <TOuterKey, TInnerKey>, TInnerResult>());
                // output messages
                assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TOuterKey, TResult>());
                // memory pool
                assemblyReferences.Add(Transformer.GeneratedMemoryPoolAssembly <TOuterKey, TResult>());
                assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(resultSelector));

                numberOfGenericParameters = template.numberOfGenericParameters;

                var a = Transformer.CompileSourceCode(expandedCode, assemblyReferences, out errorMessages);

                if (numberOfGenericParameters > 0)
                {
                    generatedClassName = generatedClassName + "`" + numberOfGenericParameters.ToString(CultureInfo.InvariantCulture);
                }
                var t = a.GetType(generatedClassName);
                t = t.InstantiateAsNecessary(typeOfTOuterKey, typeOfTInnerKey, typeofTInnerResult, typeofTResult);

                return(Tuple.Create(t, errorMessages));
            }
            catch
            {
                if (Config.CodegenOptions.DontFallBackToRowBasedExecution)
                {
                    throw new InvalidOperationException("Code Generation failed when it wasn't supposed to!");
                }
                return(Tuple.Create((Type)null, errorMessages));
            }
        }