示例#1
0
        protected override bool CanGenerateColumnar()
        {
            var typeOfTKey   = typeof(TKey);
            var typeOfTLeft  = typeof(TLeft);
            var typeOfTRight = typeof(TRight);

            if (!typeOfTLeft.CanRepresentAsColumnar())
            {
                return(false);
            }
            if (!typeOfTRight.CanRepresentAsColumnar())
            {
                return(false);
            }
            if (typeOfTKey.GetPartitionType() != null)
            {
                return(false);
            }

            var lookupKey = CacheKey.Create(this.Properties.KeyEqualityComparer.GetEqualsExpr().ToString(), this.LeftComparer.GetEqualsExpr().ToString());

            var generatedPipeType = cachedPipes.GetOrAdd(lookupKey, key => LeftAntiSemiJoinTemplate.Generate(this, this.Left.Properties.IsConstantDuration));

            this.errorMessages = generatedPipeType.Item2;
            return(generatedPipeType.Item1 != null);
        }
示例#2
0
        /// <summary>
        /// Generate a batch class definition to be used as a Clip pipe.
        /// Compile the definition, dynamically load the assembly containing it, and return the Type representing the
        /// aggregate class.
        /// </summary>
        /// <typeparam name="TKey">The key type for both sides.</typeparam>
        /// <typeparam name="TLeft">The payload type for the left side.</typeparam>
        /// <typeparam name="TRight">The payload type for the right side.</typeparam>
        /// <returns>
        /// A type that is defined to be a subtype of BinaryPipe&lt;<typeparamref name="TKey"/>,<typeparamref name="TLeft"/>, <typeparamref name="TKey"/>, <typeparamref name="TRight"/>&gt;.
        /// </returns>
        internal static Tuple <Type, string> Generate <TKey, TLeft, TRight>(LeftAntiSemiJoinStreamable <TKey, TLeft, TRight> stream, bool leftIsConstantDuration)
        {
            Contract.Requires(stream != null);
            Contract.Ensures(Contract.Result <Tuple <Type, string> >() == null || typeof(BinaryPipe <TKey, TLeft, TRight, TLeft>).GetTypeInfo().IsAssignableFrom(Contract.Result <Tuple <Type, string> >().Item1));

            var template = new LeftAntiSemiJoinTemplate($"GeneratedLeftAntiSemiJoin_{LASJSequenceNumber++}", typeof(TKey), typeof(TLeft), typeof(TRight));

            var gps = template.tm.GenericTypeVariables(template.keyType, template.leftType, template.rightType);

            template.genericParameters = gps.BracketedCommaSeparatedString();

            var leftMessageRepresentation = new ColumnarRepresentation(template.leftType);
            var resultRepresentation      = new ColumnarRepresentation(template.leftType);

            #region Key Comparer
            var keyComparer = stream.Properties.KeyEqualityComparer.GetEqualsExpr();
            template.keyComparer =
                (left, right) =>
                keyComparer.Inline(left, right);
            #endregion

            #region Left Comparer
            template.ActiveEventType        = template.leftType.GetTypeInfo().IsValueType ? template.TLeft : "Active_Event";
            template.noLeftFields           = leftMessageRepresentation.noFields;
            template.leftIsConstantDuration = leftIsConstantDuration;

            var leftComparer = stream.LeftComparer.GetEqualsExpr();
            var newLambda    = Extensions.TransformFunction <TKey, TLeft>(leftComparer, "index");
            template.leftComparer = (left, right) => newLambda.Inline(left, right);
            #endregion

            template.BatchGeneratedFrom_TKey_TLeft = Transformer.GetBatchClassName(template.keyType, template.leftType);
            template.TKeyTLeftGenericParameters    = template.tm.GenericTypeVariables(template.keyType, template.leftType).BracketedCommaSeparatedString();

            template.BatchGeneratedFrom_TKey_TRight = Transformer.GetBatchClassName(template.keyType, template.rightType);
            template.TKeyTRightGenericParameters    = template.tm.GenericTypeVariables(template.keyType, template.rightType).BracketedCommaSeparatedString();

            template.leftFields = resultRepresentation.AllFields;

            return(template.Generate <TKey, TLeft, TRight>(leftComparer));
        }
示例#3
0
        private BinaryPipe <TKey, TLeft, TRight, TLeft> GetPipe(IStreamObserver <TKey, TLeft> observer, bool leftIsConstantDuration, bool rightIsConstantDuration)
        {
            var lookupKey = CacheKey.Create(
                leftIsConstantDuration, this.Properties.KeyEqualityComparer.GetEqualsExpr().ToString(), this.LeftComparer.GetEqualsExpr().ToString());

            var generatedPipeType = cachedPipes.GetOrAdd(lookupKey, key => LeftAntiSemiJoinTemplate.Generate(this, leftIsConstantDuration));
            Func <PlanNode, PlanNode, IBinaryObserver, BinaryPlanNode> planNode = ((PlanNode left, PlanNode right, IBinaryObserver o) =>
            {
                var node = new JoinPlanNode(
                    left, right, o,
                    typeof(TLeft), typeof(TRight), typeof(TLeft), typeof(TKey),
                    JoinKind.LeftAntiSemiJoin, true, generatedPipeType.Item2, false);
                node.AddJoinExpression("key comparer", this.Properties.KeyEqualityComparer.GetEqualsExpr());
                node.AddJoinExpression("left key comparer", this.LeftComparer.GetEqualsExpr());
                return(node);
            });

            var instance    = Activator.CreateInstance(generatedPipeType.Item1, this, observer, this.Properties.KeyEqualityComparer, this.LeftComparer, planNode, leftIsConstantDuration, rightIsConstantDuration);
            var returnValue = (BinaryPipe <TKey, TLeft, TRight, TLeft>)instance;

            return(returnValue);
        }
        protected override bool CanGenerateColumnar()
        {
            // This operator uses the equality method on payloads
            if (this.Properties.IsColumnar && !this.LeftComparer.CanUsePayloadEquality())
            {
                this.errorMessages = $"The payload type, '{typeof(TLeft).FullName}', to Left Antisemijoin does not implement the interface {nameof(IEqualityComparerExpression<TLeft>)}. This interface is needed for code generation of this operator for columnar mode. Furthermore, the equality expression in the interface can only refer to input variables if used in field or property references.";
                if (Config.CodegenOptions.DontFallBackToRowBasedExecution)
                {
                    throw new StreamProcessingException(this.errorMessages);
                }
                return(false);
            }

            var typeOfTKey   = typeof(TKey);
            var typeOfTLeft  = typeof(TLeft);
            var typeOfTRight = typeof(TRight);

            if (!typeOfTLeft.CanRepresentAsColumnar())
            {
                return(false);
            }
            if (!typeOfTRight.CanRepresentAsColumnar())
            {
                return(false);
            }
            if (typeOfTKey.GetPartitionType() != null)
            {
                return(false);
            }

            var lookupKey = CacheKey.Create(this.Properties.KeyEqualityComparer.GetEqualsExpr().ToString(), this.LeftComparer.GetEqualsExpr().ToString());

            var generatedPipeType = cachedPipes.GetOrAdd(lookupKey, key => LeftAntiSemiJoinTemplate.Generate(this));

            this.errorMessages = generatedPipeType.Item2;
            return(generatedPipeType.Item1 != null);
        }
示例#5
0
        /// <summary>
        /// Generate a batch class definition to be used as a Clip pipe.
        /// Compile the definition, dynamically load the assembly containing it, and return the Type representing the
        /// aggregate class.
        /// </summary>
        /// <typeparam name="TKey">The key type for both sides.</typeparam>
        /// <typeparam name="TLeft">The payload type for the left side.</typeparam>
        /// <typeparam name="TRight">The payload type for the right side.</typeparam>
        /// <returns>
        /// A type that is defined to be a subtype of BinaryPipe&lt;<typeparamref name="TKey"/>,<typeparamref name="TLeft"/>, <typeparamref name="TKey"/>, <typeparamref name="TRight"/>&gt;.
        /// </returns>
        internal static Tuple <Type, string> Generate <TKey, TLeft, TRight>(LeftAntiSemiJoinStreamable <TKey, TLeft, TRight> stream, bool leftIsConstantDuration)
        {
            Contract.Requires(stream != null);
            Contract.Ensures(Contract.Result <Tuple <Type, string> >() == null || typeof(BinaryPipe <TKey, TLeft, TRight, TLeft>).GetTypeInfo().IsAssignableFrom(Contract.Result <Tuple <Type, string> >().Item1));

            string errorMessages = null;

            try
            {
                var template = new LeftAntiSemiJoinTemplate();

                var keyType   = template.keyType = typeof(TKey);
                var leftType  = template.leftType = typeof(TLeft);
                var rightType = template.rightType = typeof(TRight);

                var tm = new TypeMapper(keyType, leftType, rightType);
                template.TKey   = tm.CSharpNameFor(keyType);
                template.TLeft  = tm.CSharpNameFor(leftType);
                template.TRight = tm.CSharpNameFor(rightType);
                var gps = tm.GenericTypeVariables(keyType, leftType, rightType);
                template.genericParameters = gps.BracketedCommaSeparatedString();

                template.className = string.Format("GeneratedLeftAntiSemiJoin_{0}", LASJSequenceNumber++);

                var leftMessageRepresentation = new ColumnarRepresentation(leftType);
                var resultRepresentation      = new ColumnarRepresentation(leftType);

                #region Key Comparer
                var keyComparer = stream.Properties.KeyEqualityComparer.GetEqualsExpr();
                template.keyComparer =
                    (left, right) =>
                    keyComparer.Inline(left, right);
                #endregion

                #region Left Comparer
                template.ActiveEventType        = leftType.GetTypeInfo().IsValueType ? template.TLeft : "Active_Event";
                template.noLeftFields           = leftMessageRepresentation.noFields;
                template.leftIsConstantDuration = leftIsConstantDuration;

                var leftComparer = stream.LeftComparer.GetEqualsExpr();
                var newLambda    = Extensions.TransformFunction <TKey, TLeft>(leftComparer, "index");
                template.leftComparer = (left, right) => newLambda.Inline(left, right);
                #endregion

                template.BatchGeneratedFrom_TKey_TLeft = Transformer.GetBatchClassName(keyType, leftType);
                template.TKeyTLeftGenericParameters    = tm.GenericTypeVariables(keyType, leftType).BracketedCommaSeparatedString();

                template.BatchGeneratedFrom_TKey_TRight = Transformer.GetBatchClassName(keyType, rightType);
                template.TKeyTRightGenericParameters    = tm.GenericTypeVariables(keyType, rightType).BracketedCommaSeparatedString();

                template.leftFields = resultRepresentation.AllFields;

                template.staticCtor = Transformer.StaticCtor(template.className);
                var expandedCode = template.TransformText();

                var assemblyReferences = Transformer.AssemblyReferencesNeededFor(typeof(TKey), typeof(TLeft), typeof(TRight));
                assemblyReferences.Add(typeof(IStreamable <,>).GetTypeInfo().Assembly);
                assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TLeft>());
                assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TRight>());
                assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(leftComparer));

                var a             = Transformer.CompileSourceCode(expandedCode, assemblyReferences, out errorMessages);
                var realClassName = template.className.AddNumberOfNecessaryGenericArguments(keyType, leftType, rightType);
                var t             = a.GetType(realClassName);
                if (t.GetTypeInfo().IsGenericType)
                {
                    var list = keyType.GetAnonymousTypes();
                    list.AddRange(leftType.GetAnonymousTypes());
                    list.AddRange(rightType.GetAnonymousTypes());
                    return(Tuple.Create(t.MakeGenericType(list.ToArray()), errorMessages));
                }
                else
                {
                    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));
            }
        }