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); }
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); }
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)); } }