コード例 #1
0
        public static EPCompiled Compile(
            Compilable compilable,
            ModuleCompileTimeServices services,
            CompilerArguments args)
        {
            var compileTimeServices = new StatementCompileTimeServices(0, services);
            var walkResult = CompilerHelperSingleEPL.ParseCompileInlinedClassesWalk(compilable, compileTimeServices);
            var raw = walkResult.StatementSpecRaw;

            var statementType = StatementTypeUtil.GetStatementType(raw);
            if (statementType != StatementType.SELECT) {
                // the fire-and-forget spec is null for "select" and populated for I/U/D
                throw new StatementSpecCompileException(
                    "Provided EPL expression is a continuous query expression (not an on-demand query)",
                    compilable.ToEPL());
            }

            var annotations = AnnotationUtil.CompileAnnotations(
                raw.Annotations,
                services.ImportServiceCompileTime,
                compilable);

            // walk subselects, alias expressions, declared expressions, dot-expressions
            var visitor = StatementSpecRawWalkerSubselectAndDeclaredDot.WalkSubselectAndDeclaredDotExpr(raw);

            // compile context descriptor
            ContextCompileTimeDescriptor contextDescriptor = null;
            var optionalContextName = raw.OptionalContextName;
            if (optionalContextName != null) {
                var detail = services.ContextCompileTimeResolver.GetContextInfo(optionalContextName);
                if (detail == null) {
                    throw new StatementSpecCompileException(
                        "Context by name '" + optionalContextName + "' could not be found",
                        compilable.ToEPL());
                }

                contextDescriptor = new ContextCompileTimeDescriptor(
                    optionalContextName,
                    detail.ContextModuleName,
                    detail.ContextVisibility,
                    new ContextPropertyRegistry(detail),
                    detail.ValidationInfos);
            }

            var statementNameFromAnnotation = GetNameFromAnnotation(annotations);
            var statementName = statementNameFromAnnotation == null ? GetDefaultStatementName() : statementNameFromAnnotation.Trim();
            var statementRawInfo = new StatementRawInfo(
                0,
                statementName,
                annotations,
                statementType.Value,
                contextDescriptor,
                null,
                compilable,
                null);
            StatementSpecCompiledDesc compiledDesc = StatementRawCompiler.Compile(
                raw,
                compilable,
                false,
                true,
                annotations,
                visitor.Subselects,
                new List<ExprTableAccessNode>(raw.TableExpressions),
                statementRawInfo,
                compileTimeServices);
            StatementSpecCompiled specCompiled = compiledDesc.Compiled;

            var fafSpec = specCompiled.Raw.FireAndForgetSpec;

            //var @namespace = "generated";
            var classPostfix = IdentifierUtil.GetIdentifierMayStartNumeric(statementName);

            EPCompiledManifest manifest;
            Assembly assembly;

            FAFQueryMethodForge query;
            if (specCompiled.Raw.InsertIntoDesc != null) {
                query = new FAFQueryMethodIUDInsertIntoForge(
                    specCompiled,
                    compilable,
                    statementRawInfo,
                    compileTimeServices);
            }
            else if (fafSpec == null) { // null indicates a select-statement, same as continuous query
                var desc = new FAFQueryMethodSelectDesc(
                    specCompiled,
                    compilable,
                    statementRawInfo,
                    compileTimeServices);
                var classNameResultSetProcessor =
                    CodeGenerationIDGenerator.GenerateClassNameSimple(
                        typeof(ResultSetProcessorFactoryProvider),
                        classPostfix);
                query = new FAFQueryMethodSelectForge(desc, classNameResultSetProcessor, statementRawInfo);
            }
            else if (fafSpec is FireAndForgetSpecDelete) {
                query = new FAFQueryMethodIUDDeleteForge(
                    specCompiled,
                    compilable,
                    statementRawInfo,
                    compileTimeServices);
            }
            else if (fafSpec is FireAndForgetSpecUpdate) {
                query = new FAFQueryMethodIUDUpdateForge(
                    specCompiled,
                    compilable,
                    statementRawInfo,
                    compileTimeServices);
            }
            else {
                throw new IllegalStateException("Unrecognized FAF code " + fafSpec);
            }

            // verify substitution parameters
            VerifySubstitutionParams(raw.SubstitutionParameters);

            try {
                manifest = CompileToAssembly(query, classPostfix, args.Options, services, out assembly);
            }
            catch (EPCompileException) {
                throw;
            }
            catch (Exception ex) {
                throw new EPCompileException(
                    "Unexpected exception compiling module: " + ex.Message,
                    ex,
                    new EmptyList<EPCompileExceptionItem>());
            }

            return new EPCompiled(new [] { assembly }, manifest);
        }
コード例 #2
0
        public static CompilableItem CompileItem(
            Compilable compilable,
            string optionalModuleName,
            string moduleIdentPostfix,
            int statementNumber,
            ISet<string> statementNames,
            ModuleCompileTimeServices moduleCompileTimeServices,
            CompilerOptions compilerOptions,
            out Assembly assembly)
        {
            var compileTimeServices = new StatementCompileTimeServices(statementNumber, moduleCompileTimeServices);

            // Stage 0 - parse and compile-inline-classes and walk statement
            var walked = ParseCompileInlinedClassesWalk(compilable, compileTimeServices);
            var raw = walked.StatementSpecRaw;
            string classNameCreateClass = null;
            if (raw.CreateClassProvided != null) {
                classNameCreateClass = DetermineClassNameCreateClass(walked.ClassesInlined);
            }
            
            try {
                // Stage 2(a) - precompile: compile annotations
                var annotations = AnnotationUtil.CompileAnnotations(
                    raw.Annotations,
                    compileTimeServices.ImportServiceCompileTime,
                    compilable);

                // Stage 2(b) - walk subselects, alias expressions, declared expressions, dot-expressions
                ExprNodeSubselectDeclaredDotVisitor visitor;
                try {
                    visitor = StatementSpecRawWalkerSubselectAndDeclaredDot.WalkSubselectAndDeclaredDotExpr(raw);
                }
                catch (ExprValidationException ex) {
                    throw new StatementSpecCompileException(ex.Message, compilable.ToEPL());
                }

                var subselectNodes = visitor.Subselects;

                // Determine a statement name
                var statementNameProvided = GetNameFromAnnotation(annotations);
                if (compilerOptions.StatementName != null) {
                    var assignedName = compilerOptions.StatementName.Invoke(
                        new StatementNameContext(
                            () => compilable.ToEPL(),
                            statementNameProvided,
                            optionalModuleName,
                            annotations,
                            statementNumber));
                    if (assignedName != null) {
                        statementNameProvided = assignedName;
                    }
                }

                var statementName = statementNameProvided ?? Convert.ToString(statementNumber);
                if (statementNames.Contains(statementName)) {
                    var count = 1;
                    var newStatementName = statementName + "-" + count;
                    while (statementNames.Contains(newStatementName)) {
                        count++;
                        newStatementName = statementName + "-" + count;
                    }

                    statementName = newStatementName;
                }

                statementName = statementName.Trim();
                statementNames.Add(statementName);

                // Determine table access nodes
                var tableAccessNodes = DetermineTableAccessNodes(raw.TableExpressions, visitor);

                // compile scripts once in this central place, may also compile later in expression
                ScriptValidationPrecompileUtil.ValidateScripts(
                    raw.ScriptExpressions,
                    raw.ExpressionDeclDesc,
                    compileTimeServices);

                // Determine subselects for compilation, and lambda-expression shortcut syntax for named windows
                if (!visitor.ChainedExpressionsDot.IsEmpty()) {
                    RewriteNamedWindowSubselect(
                        visitor.ChainedExpressionsDot,
                        subselectNodes,
                        compileTimeServices.NamedWindowCompileTimeResolver);
                }

                // Stage 2(c) compile context descriptor
                ContextCompileTimeDescriptor contextDescriptor = null;
                var optionalContextName = raw.OptionalContextName;
                if (optionalContextName != null) {
                    var detail = compileTimeServices.ContextCompileTimeResolver.GetContextInfo(optionalContextName);
                    if (detail == null) {
                        throw new StatementSpecCompileException(
                            "Context by name '" + optionalContextName + "' could not be found",
                            compilable.ToEPL());
                    }

                    contextDescriptor = new ContextCompileTimeDescriptor(
                        optionalContextName,
                        detail.ContextModuleName,
                        detail.ContextVisibility,
                        new ContextPropertyRegistry(detail),
                        detail.ValidationInfos);
                }

                // Stage 2(d) compile raw statement spec
                var statementType = StatementTypeUtil.GetStatementType(raw).Value;
                var statementRawInfo = new StatementRawInfo(
                    statementNumber,
                    statementName,
                    annotations,
                    statementType,
                    contextDescriptor,
                    raw.IntoTableSpec?.Name,
                    compilable,
                    optionalModuleName);
                var compiledDesc = StatementRawCompiler.Compile(
                    raw,
                    compilable,
                    false,
                    false,
                    annotations,
                    subselectNodes,
                    tableAccessNodes,
                    statementRawInfo,
                    compileTimeServices);
                var specCompiled = compiledDesc.Compiled;
                var statementIdentPostfix = IdentifierUtil.GetIdentifierMayStartNumeric(statementName);

                // get compile-time user object
                object userObjectCompileTime = null;
                if (compilerOptions.StatementUserObject != null) {
                    userObjectCompileTime = compilerOptions.StatementUserObject.Invoke(
                        new StatementUserObjectContext(
                            () => compilable.ToEPL(),
                            statementName,
                            optionalModuleName,
                            annotations,
                            statementNumber));
                }

                // handle hooks
                HandleStatementCompileHook(annotations, compileTimeServices, specCompiled);

                // Stage 3(a) - statement-type-specific forge building
                var @base = new StatementBaseInfo(
                    compilable,
                    specCompiled,
                    userObjectCompileTime,
                    statementRawInfo,
                    optionalModuleName);
                StmtForgeMethod forgeMethod;
                if (raw.UpdateDesc != null) {
                    forgeMethod = new StmtForgeMethodUpdate(@base);
                }
                else if (raw.OnTriggerDesc != null) {
                    forgeMethod = new StmtForgeMethodOnTrigger(@base);
                }
                else if (raw.CreateIndexDesc != null) {
                    forgeMethod = new StmtForgeMethodCreateIndex(@base);
                }
                else if (raw.CreateVariableDesc != null) {
                    forgeMethod = new StmtForgeMethodCreateVariable(@base);
                }
                else if (raw.CreateDataFlowDesc != null) {
                    forgeMethod = new StmtForgeMethodCreateDataflow(@base);
                }
                else if (raw.CreateTableDesc != null) {
                    forgeMethod = new StmtForgeMethodCreateTable(@base);
                }
                else if (raw.CreateExpressionDesc != null) {
                    forgeMethod = new StmtForgeMethodCreateExpression(@base);
                }
                else if (raw.CreateClassProvided != null) {
                    forgeMethod = new StmtForgeMethodCreateClass(@base, walked.ClassesInlined, classNameCreateClass);
                }
                else if (raw.CreateWindowDesc != null) {
                    forgeMethod = new StmtForgeMethodCreateWindow(@base);
                }
                else if (raw.CreateContextDesc != null) {
                    forgeMethod = new StmtForgeMethodCreateContext(@base);
                }
                else if (raw.CreateSchemaDesc != null) {
                    forgeMethod = new StmtForgeMethodCreateSchema(@base);
                }
                else {
                    forgeMethod = new StmtForgeMethodSelect(@base);
                }

                // check context-validity conditions for this statement
                if (contextDescriptor != null) {
                    try {
                        foreach (var validator in contextDescriptor.ValidationInfos) {
                            validator.ValidateStatement(
                                contextDescriptor.ContextName,
                                specCompiled,
                                compileTimeServices);
                        }
                    }
                    catch (ExprValidationException ex) {
                        throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
                    }
                }

                // Stage 3(b) - forge-factory-to-forge
                var classPostfix = moduleIdentPostfix + "_" + statementIdentPostfix;
                var forgeables = new List<StmtClassForgeable>();
                
                // add forgeables from filter-related processing i.e. multikeys
                foreach (var additional in compiledDesc.AdditionalForgeables) {
                    var namespaceScope = new CodegenNamespaceScope(compileTimeServices.Namespace, null, false);
                    forgeables.Add(additional.Make(namespaceScope, classPostfix));
                }
                
                var filterSpecCompileds = new List<FilterSpecCompiled>();
                var scheduleHandleCallbackProviders = new List<ScheduleHandleCallbackProvider>();
                var namedWindowConsumers = new List<NamedWindowConsumerStreamSpec>();
                var filterBooleanExpressions = new List<FilterSpecParamExprNodeForge>();
                
                var result = forgeMethod.Make(compileTimeServices.Namespace, classPostfix, compileTimeServices);
                forgeables.AddAll(result.Forgeables);
                VerifyForgeables(forgeables);
                
                filterSpecCompileds.AddAll(result.Filtereds);
                scheduleHandleCallbackProviders.AddAll(result.Scheduleds);
                namedWindowConsumers.AddAll(result.NamedWindowConsumers);
                filterBooleanExpressions.AddAll(result.FilterBooleanExpressions);

                // Stage 3(c) - filter assignments: assign filter callback ids and filter-path-num for boolean expressions
                var filterId = -1;
                foreach (var provider in filterSpecCompileds) {
                    var assigned = ++filterId;
                    provider.FilterCallbackId = assigned;
                }

                // Stage 3(d) - schedule assignments: assign schedule callback ids
                var scheduleId = 0;
                foreach (var provider in scheduleHandleCallbackProviders) {
                    provider.ScheduleCallbackId = scheduleId++;
                }

                // Stage 3(e) - named window consumers: assign consumer id
                var namedWindowConsumerId = 0;
                foreach (var provider in namedWindowConsumers) {
                    provider.NamedWindowConsumerId = namedWindowConsumerId++;
                }

                // Stage 3(f) - filter boolean expression id assignment
                var filterBooleanExprNum = 0;
                foreach (var expr in filterBooleanExpressions) {
                    expr.FilterBoolExprId = filterBooleanExprNum++;
                }

                // Stage 3(f) - verify substitution parameters
                VerifySubstitutionParams(raw.SubstitutionParameters);

                // Stage 4 - forge-to-class (forge with statement-fields last)
                var classes = forgeables
                    .Select(forgeable => forgeable.Forge(true, false))
                    .ToList();

                // Stage 5 - refactor methods to make sure the constant pool does not grow too large for any given class
                CompilerHelperRefactorToStaticMethods.RefactorMethods(
                    classes, compileTimeServices.Configuration.Compiler.ByteCode.MaxMethodsPerClass);

                // Stage 6 - sort to make the "fields" class first and all the rest later
                var sorted = classes
                    .OrderBy(c => c.ClassType.GetSortCode())
                    .ToList();

                // We are making sure JsonEventType receives the underlying class itself
                CompilableItemPostCompileLatch postCompile = CompilableItemPostCompileLatchDefault.INSTANCE;
                foreach (var eventType in compileTimeServices.EventTypeCompileTimeRegistry.NewTypesAdded) {
                    if (eventType is JsonEventType) {
                        postCompile = new CompilableItemPostCompileLatchJson(
                            compileTimeServices.EventTypeCompileTimeRegistry.NewTypesAdded,
                            compileTimeServices.ParentClassLoader);
                        break;
                    }
                }

                var container = compileTimeServices.Container;
                var compiler = container
                    .RoslynCompiler()
                    .WithCodeLogging(compileTimeServices.Configuration.Compiler.Logging.IsEnableCode)
                    .WithCodeAuditDirectory(compileTimeServices.Configuration.Compiler.Logging.AuditDirectory)
                    .WithCodegenClasses(sorted);

                assembly = compiler.Compile();

                string statementProviderClassName = CodeGenerationIDGenerator.GenerateClassNameWithNamespace(
                    compileTimeServices.Namespace,
                    typeof(StatementProvider),
                    classPostfix);

                var additionalClasses = new HashSet<Type>();
                additionalClasses.AddAll(walked.ClassesInlined.Classes);
                compileTimeServices.ClassProvidedCompileTimeResolver.AddTo(additionalClasses);
                compileTimeServices.ClassProvidedCompileTimeRegistry.AddTo(additionalClasses);

                return new CompilableItem(
                    statementProviderClassName,
                    classes,
                    postCompile,
                    additionalClasses);
            }
            catch (StatementSpecCompileException) {
                throw;
            }
            catch (ExprValidationException ex) {
                throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
            }
            catch (EPException ex) {
                throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
            }
            catch (Exception ex) {
                var text = ex.Message ?? ex.GetType().FullName;
                throw new StatementSpecCompileException(text, ex, compilable.ToEPL());
            }
        }
コード例 #3
0
        public static StatementSpecCompiled Compile(
            StatementSpecRaw spec,
            Compilable compilable,
            bool isSubquery,
            bool isOnDemandQuery,
            Attribute[] annotations,
            IList<ExprSubselectNode> subselectNodes,
            IList<ExprTableAccessNode> tableAccessNodes,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices compileTimeServices)
        {
            IList<StreamSpecCompiled> compiledStreams;
            ISet<string> eventTypeReferences = new HashSet<string>();

            if (!isOnDemandQuery && spec.FireAndForgetSpec != null) {
                throw new StatementSpecCompileException(
                    "Provided EPL expression is an on-demand query expression (not a continuous query)",
                    compilable.ToEPL());
            }

            // If not using a join and not specifying a data window, make the where-clause, if present, the filter of the stream
            // if selecting using filter spec, and not subquery in where clause
            if (spec.StreamSpecs.Count == 1 &&
                spec.StreamSpecs[0] is FilterStreamSpecRaw &&
                spec.StreamSpecs[0].ViewSpecs.Length == 0 &&
                spec.WhereClause != null &&
                spec.OnTriggerDesc == null &&
                !isSubquery &&
                !isOnDemandQuery &&
                (tableAccessNodes == null || tableAccessNodes.IsEmpty())) {
                bool disqualified;
                ExprNode whereClause = spec.WhereClause;

                var visitorX = new ExprNodeSubselectDeclaredDotVisitor();
                whereClause.Accept(visitorX);
                disqualified = visitorX.Subselects.Count > 0 ||
                               HintEnum.DISABLE_WHEREEXPR_MOVETO_FILTER.GetHint(annotations) != null;

                if (!disqualified) {
                    var viewResourceVisitor = new ExprNodeViewResourceVisitor();
                    whereClause.Accept(viewResourceVisitor);
                    disqualified = viewResourceVisitor.ExprNodes.Count > 0;
                }

                if (!disqualified) {
                    spec.WhereClause = null;
                    var streamSpec = (FilterStreamSpecRaw) spec.StreamSpecs[0];
                    streamSpec.RawFilterSpec.FilterExpressions.Add(whereClause);
                }
            }

            // compile select-clause
            var selectClauseCompiled = CompileSelectClause(spec.SelectClauseSpec);

            // Determine subselects in filter streams, these may need special handling for locking
            var visitor = new ExprNodeSubselectDeclaredDotVisitor();
            try {
                StatementSpecRawWalkerSubselectAndDeclaredDot.WalkStreamSpecs(spec, visitor);
            }
            catch (ExprValidationException ex) {
                throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
            }

            foreach (var subselectNode in visitor.Subselects) {
                subselectNode.IsFilterStreamSubselect = true;
            }

            // Determine subselects for compilation, and lambda-expression shortcut syntax for named windows
            visitor.Reset();
            GroupByClauseExpressions groupByRollupExpressions;
            try {
                StatementSpecRawWalkerSubselectAndDeclaredDot.WalkSubselectAndDeclaredDotExpr(spec, visitor);

                var expressionCopier = new ExpressionCopier(
                    spec,
                    statementRawInfo.OptionalContextDescriptor,
                    compileTimeServices,
                    visitor);
                groupByRollupExpressions = GroupByExpressionHelper.GetGroupByRollupExpressions(
                    spec.GroupByExpressions,
                    spec.SelectClauseSpec,
                    spec.HavingClause,
                    spec.OrderByList,
                    expressionCopier);
            }
            catch (ExprValidationException ex) {
                throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
            }

            if (isSubquery && !visitor.Subselects.IsEmpty()) {
                throw new StatementSpecCompileException(
                    "Invalid nested subquery, subquery-within-subquery is not supported",
                    compilable.ToEPL());
            }

            if (isOnDemandQuery && !visitor.Subselects.IsEmpty()) {
                throw new StatementSpecCompileException(
                    "Subqueries are not a supported feature of on-demand queries",
                    compilable.ToEPL());
            }

            foreach (var subselectNode in visitor.Subselects) {
                if (!subselectNodes.Contains(subselectNode)) {
                    subselectNodes.Add(subselectNode);
                }
            }

            // Compile subselects found
            var subselectNumber = 0;
            foreach (var subselect in subselectNodes) {
                StatementSpecRaw raw = subselect.StatementSpecRaw;
                var compiled = Compile(
                    raw,
                    compilable,
                    true,
                    isOnDemandQuery,
                    annotations,
                    Collections.GetEmptyList<ExprSubselectNode>(),
                    Collections.GetEmptyList<ExprTableAccessNode>(),
                    statementRawInfo,
                    compileTimeServices);
                subselect.SetStatementSpecCompiled(compiled, subselectNumber);
                subselectNumber++;
            }

            // Set table-access number
            var tableAccessNumber = 0;
            foreach (var tableAccess in tableAccessNodes) {
                tableAccess.TableAccessNumber = tableAccessNumber;
                tableAccessNumber++;
            }

            // compile each stream used
            try {
                compiledStreams = new List<StreamSpecCompiled>(spec.StreamSpecs.Count);
                var streamNum = 0;
                foreach (var rawSpec in spec.StreamSpecs) {
                    streamNum++;
                    var compiled = StreamSpecCompiler.Compile(
                        rawSpec,
                        eventTypeReferences,
                        spec.InsertIntoDesc != null,
                        spec.StreamSpecs.Count > 1,
                        false,
                        spec.OnTriggerDesc != null,
                        rawSpec.OptionalStreamName,
                        streamNum,
                        statementRawInfo,
                        compileTimeServices);
                    compiledStreams.Add(compiled);
                }
            }
            catch (ExprValidationException ex) {
                if (ex.Message == null) {
                    throw new StatementSpecCompileException(
                        "Unexpected exception compiling statement, please consult the log file and report the exception",
                        ex,
                        compilable.ToEPL());
                }

                throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
            }
            catch (EPException ex) {
                throw new StatementSpecCompileException(ex.Message, ex, compilable.ToEPL());
            }
            catch (Exception ex) {
                var text = "Unexpected error compiling statement";
                Log.Error(text, ex);
                throw new StatementSpecCompileException(
                    text + ": " + ex.GetType().Name + ":" + ex.Message,
                    ex,
                    compilable.ToEPL());
            }

            return new StatementSpecCompiled(
                spec,
                compiledStreams.ToArray(),
                selectClauseCompiled,
                annotations,
                groupByRollupExpressions,
                subselectNodes,
                visitor.DeclaredExpressions,
                tableAccessNodes);
        }
コード例 #4
0
        public DataFlowOpForgeInitializeResult InitializeForge(DataFlowOpForgeInitializeContext context)
        {
            if (context.InputPorts.IsEmpty()) {
                throw new ArgumentException("Select operator requires at least one input stream");
            }

            if (context.OutputPorts.Count != 1) {
                throw new ArgumentException(
                    "Select operator requires one output stream but produces " +
                    context.OutputPorts.Count +
                    " streams");
            }

            var portZero = context.OutputPorts[0];
            if (portZero.OptionalDeclaredType != null && !portZero.OptionalDeclaredType.IsUnderlying) {
                submitEventBean = true;
            }

            // determine adapter factories for each type
            var numStreams = context.InputPorts.Count;
            eventTypes = new EventType[numStreams];
            for (var i = 0; i < numStreams; i++) {
                eventTypes[i] = context.InputPorts.Get(i).TypeDesc.EventType;
            }

            // validate
            if (select.InsertIntoDesc != null) {
                throw new ExprValidationException("Insert-into clause is not supported");
            }

            if (select.SelectStreamSelectorEnum != SelectClauseStreamSelectorEnum.ISTREAM_ONLY) {
                throw new ExprValidationException("Selecting remove-stream is not supported");
            }

            ExprNodeSubselectDeclaredDotVisitor visitor =
                StatementSpecRawWalkerSubselectAndDeclaredDot.WalkSubselectAndDeclaredDotExpr(select);
            GroupByClauseExpressions groupByExpressions = GroupByExpressionHelper.GetGroupByRollupExpressions(
                select.GroupByExpressions,
                select.SelectClauseSpec,
                select.WhereClause,
                select.OrderByList,
                null);
            if (!visitor.Subselects.IsEmpty()) {
                throw new ExprValidationException("Subselects are not supported");
            }

            IDictionary<int, FilterStreamSpecRaw> streams = new Dictionary<int, FilterStreamSpecRaw>();
            for (var streamNum = 0; streamNum < select.StreamSpecs.Count; streamNum++) {
                StreamSpecRaw rawStreamSpec = select.StreamSpecs[streamNum];
                if (!(rawStreamSpec is FilterStreamSpecRaw)) {
                    throw new ExprValidationException(
                        "From-clause must contain only streams and cannot contain patterns or other constructs");
                }

                streams.Put(streamNum, (FilterStreamSpecRaw) rawStreamSpec);
            }

            // compile offered streams
            IList<StreamSpecCompiled> streamSpecCompileds = new List<StreamSpecCompiled>();
            originatingStreamToViewableStream = new int[select.StreamSpecs.Count];
            for (var streamNum = 0; streamNum < select.StreamSpecs.Count; streamNum++) {
                var filter = streams.Get(streamNum);
                var inputPort = FindInputPort(filter.RawFilterSpec.EventTypeName, context.InputPorts);
                if (inputPort == null) {
                    throw new ExprValidationException(
                        "Failed to find stream '" +
                        filter.RawFilterSpec.EventTypeName +
                        "' among input ports, input ports are " +
                        CompatExtensions.RenderAny(GetInputPortNames(context.InputPorts)));
                }

                var inputPortValue = inputPort.Value;
                var eventType = inputPortValue.Value.TypeDesc.EventType;
                originatingStreamToViewableStream[inputPortValue.Key] = streamNum;
                var streamAlias = filter.OptionalStreamName;
                var filterSpecCompiled = new FilterSpecCompiled(
                    eventType,
                    streamAlias,
                    new IList<FilterSpecParamForge>[] {
                        new EmptyList<FilterSpecParamForge>()
                    },
                    null);
                ViewSpec[] viewSpecs = select.StreamSpecs[streamNum].ViewSpecs;
                var filterStreamSpecCompiled = new FilterStreamSpecCompiled(
                    filterSpecCompiled,
                    viewSpecs,
                    streamAlias,
                    StreamSpecOptions.DEFAULT);
                streamSpecCompileds.Add(filterStreamSpecCompiled);
            }

            // create compiled statement spec
            var selectClauseCompiled = StatementLifecycleSvcUtil.CompileSelectClause(select.SelectClauseSpec);

            Attribute[] mergedAnnotations = AnnotationUtil.MergeAnnotations(
                context.StatementRawInfo.Annotations,
                context.OperatorAnnotations);
            mergedAnnotations = AddObjectArrayRepresentation(mergedAnnotations);
            var streamSpecArray = streamSpecCompileds.ToArray();

            // determine if snapshot output is needed
            var outputLimitSpec = select.OutputLimitSpec;
            if (iterate) {
                if (outputLimitSpec != null) {
                    throw new ExprValidationException("Output rate limiting is not supported with 'iterate'");
                }

                outputLimitSpec = new OutputLimitSpec(OutputLimitLimitType.SNAPSHOT, OutputLimitRateType.TERM);
                select.OutputLimitSpec = outputLimitSpec;
            }

            // override the statement spec
            var compiled = new StatementSpecCompiled(
                select,
                streamSpecArray,
                selectClauseCompiled,
                mergedAnnotations,
                groupByExpressions,
                new EmptyList<ExprSubselectNode>(),
                new EmptyList<ExprDeclaredNode>(),
                new EmptyList<ExprTableAccessNode>());
            var dataflowClassPostfix = context.CodegenEnv.ClassPostfix + "__dfo" + context.OperatorNumber;
            var containerStatement = context.Base.StatementSpec;
            context.Base.StatementSpec = compiled;

            // make forgable
            var forablesResult = StmtForgeMethodSelectUtil.Make(
                context.Container,
                true,
                context.CodegenEnv.Namespace,
                dataflowClassPostfix,
                context.Base,
                context.Services);

            // return the statement spec
            context.Base.StatementSpec = containerStatement;

            EventType outputEventType = forablesResult.EventType;

            var initializeResult = new DataFlowOpForgeInitializeResult();
            initializeResult.TypeDescriptors = new[] {new GraphTypeDesc(false, true, outputEventType)};
            initializeResult.AdditionalForgables = forablesResult.ForgeResult;

            foreach (StmtClassForgable forgable in forablesResult.ForgeResult.Forgables) {
                if (forgable.ForgableType == StmtClassForgableType.AIFACTORYPROVIDER) {
                    classNameAIFactoryProvider = forgable.ClassName;
                } else if (forgable.ForgableType == StmtClassForgableType.FIELDS) {
                    classNameFieldsFactoryProvider = forgable.ClassName;
                }
            }

            return initializeResult;
        }