Beispiel #1
0
        public StatementAgentInstanceFactoryOnTriggerTable(StatementContext statementContext, StatementSpecCompiled statementSpec, EPServicesContext services, ViewableActivator activator, SubSelectStrategyCollection subSelectStrategyCollection, ResultSetProcessorFactoryDesc resultSetProcessorPrototype, ExprNode validatedJoin, TableOnViewFactory onExprFactory, EventType activatorResultEventType, TableMetadata tableMetadata, ResultSetProcessorFactoryDesc outputResultSetProcessorPrototype, OutputProcessViewFactory outputProcessViewFactory)
            : base(statementContext, statementSpec, services, activator, subSelectStrategyCollection)
        {
            _resultSetProcessorPrototype = resultSetProcessorPrototype;
            _onExprFactory = onExprFactory;
            _outputResultSetProcessorPrototype = outputResultSetProcessorPrototype;
            _outputProcessViewFactory          = outputProcessViewFactory;

            var pair            = StatementAgentInstanceFactoryOnTriggerNamedWindow.GetIndexHintPair(statementContext, statementSpec);
            var indexHint       = pair.IndexHint;
            var excludePlanHint = pair.ExcludePlanHint;

            _queryPlanResult = SubordinateQueryPlanner.PlanOnExpression(
                validatedJoin, activatorResultEventType, indexHint, true, -1, excludePlanHint,
                false, tableMetadata.EventTableIndexMetadataRepo, tableMetadata.InternalEventType,
                tableMetadata.UniqueKeyProps, true, statementContext.StatementName, statementContext.StatementId, statementContext.Annotations);
            if (_queryPlanResult.IndexDescs != null)
            {
                for (var i = 0; i < _queryPlanResult.IndexDescs.Length; i++)
                {
                    tableMetadata.AddIndexReference(_queryPlanResult.IndexDescs[i].IndexName, statementContext.StatementName);
                }
            }
            SubordinateQueryPlannerUtil.QueryPlanLogOnExpr(tableMetadata.IsQueryPlanLogging, TableServiceImpl.QueryPlanLog,
                                                           _queryPlanResult, statementContext.Annotations);
        }
        public override OnExprViewResult DetermineOnExprView(AgentInstanceContext agentInstanceContext, IList <StopCallback> stopCallbacks, bool isRecoveringResilient)
        {
            // get result set processor and aggregation services
            Pair <ResultSetProcessor, AggregationService> pair = EPStatementStartMethodHelperUtil.StartResultSetAndAggregation(_resultSetProcessorPrototype, agentInstanceContext, false, null);

            // get named window processor instance
            NamedWindowProcessorInstance processorInstance = _processor.GetProcessorInstance(agentInstanceContext);

            // obtain on-expr view
            EventTable[] indexes = null;
            if (_queryPlan.IndexDescs != null)
            {
                indexes = SubordinateQueryPlannerUtil.RealizeTables(
                    _queryPlan.IndexDescs,
                    _processor.NamedWindowType,
                    processorInstance.RootViewInstance.IndexRepository,
                    processorInstance.RootViewInstance.DataWindowContents,
                    processorInstance.TailViewInstance.AgentInstanceContext,
                    isRecoveringResilient);
            }
            SubordWMatchExprLookupStrategy strategy       = _queryPlan.Factory.Realize(indexes, agentInstanceContext, processorInstance.RootViewInstance.DataWindowContents, processorInstance.RootViewInstance.VirtualDataWindow);
            NamedWindowOnExprBaseView      onExprBaseView = _onExprFactory.Make(strategy, processorInstance.RootViewInstance, agentInstanceContext, pair.First);

            return(new OnExprViewResult(onExprBaseView, pair.Second));
        }
        public StatementAgentInstanceFactoryOnTriggerNamedWindow(StatementContext statementContext, StatementSpecCompiled statementSpec, EPServicesContext services, ViewableActivator activator, SubSelectStrategyCollection subSelectStrategyCollection, ResultSetProcessorFactoryDesc resultSetProcessorPrototype, ExprNode validatedJoin, ResultSetProcessorFactoryDesc outputResultSetProcessorPrototype, NamedWindowOnExprFactory onExprFactory, OutputProcessViewFactory outputProcessViewFactory, EventType activatorResultEventType, NamedWindowProcessor processor, IList <StopCallback> stopCallbacks)
            : base(statementContext, statementSpec, services, activator, subSelectStrategyCollection)
        {
            _resultSetProcessorPrototype       = resultSetProcessorPrototype;
            _outputResultSetProcessorPrototype = outputResultSetProcessorPrototype;
            _onExprFactory            = onExprFactory;
            _outputProcessViewFactory = outputProcessViewFactory;
            _processor = processor;

            IndexHintPair   pair            = GetIndexHintPair(statementContext, statementSpec);
            IndexHint       indexHint       = pair.IndexHint;
            ExcludePlanHint excludePlanHint = pair.ExcludePlanHint;

            _queryPlan = SubordinateQueryPlanner.PlanOnExpression(
                validatedJoin, activatorResultEventType, indexHint, processor.IsEnableSubqueryIndexShare, -1, excludePlanHint,
                processor.IsVirtualDataWindow, processor.EventTableIndexMetadataRepo, processor.NamedWindowType,
                processor.OptionalUniqueKeyProps, false, statementContext.StatementName, statementContext.StatementId, statementContext.Annotations);
            if (_queryPlan.IndexDescs != null)
            {
                SubordinateQueryPlannerUtil.AddIndexMetaAndRef(_queryPlan.IndexDescs, processor.EventTableIndexMetadataRepo, statementContext.StatementName);
                stopCallbacks.Add(new ProxyStopCallback(() =>
                {
                    for (int i = 0; i < _queryPlan.IndexDescs.Length; i++)
                    {
                        bool last = processor.EventTableIndexMetadataRepo.RemoveIndexReference(_queryPlan.IndexDescs[i].IndexMultiKey, statementContext.StatementName);
                        if (last)
                        {
                            processor.EventTableIndexMetadataRepo.RemoveIndex(_queryPlan.IndexDescs[i].IndexMultiKey);
                            processor.RemoveAllInstanceIndexes(_queryPlan.IndexDescs[i].IndexMultiKey);
                        }
                    }
                }));
            }
            SubordinateQueryPlannerUtil.QueryPlanLogOnExpr(processor.RootView.IsQueryPlanLogging, NamedWindowRootView.QueryPlanLog,
                                                           _queryPlan, statementContext.Annotations, statementContext.EngineImportService);
        }
Beispiel #4
0
        public SubSelectStrategyFactoryIndexShare(
            string statementName,
            int statementId,
            int subqueryNum,
            EventType[] outerEventTypesSelect,
            NamedWindowProcessor optionalNamedWindowProcessor,
            TableMetadata optionalTableMetadata,
            bool fullTableScan,
            IndexHint optionalIndexHint,
            SubordPropPlan joinedPropPlan,
            ExprEvaluator filterExprEval,
            AggregationServiceFactoryDesc aggregationServiceFactory,
            ExprEvaluator[] groupByKeys,
            TableService tableService,
            Attribute[] annotations,
            StatementStopService statementStopService)
        {
            _optionalNamedWindowProcessor = optionalNamedWindowProcessor;
            _optionalTableMetadata        = optionalTableMetadata;
            _filterExprEval            = filterExprEval;
            _aggregationServiceFactory = aggregationServiceFactory;
            _groupByKeys  = groupByKeys;
            _tableService = tableService;

            bool isLogging;
            ILog log;

            if (optionalTableMetadata != null)
            {
                isLogging  = optionalTableMetadata.IsQueryPlanLogging;
                log        = TableServiceImpl.QueryPlanLog;
                _queryPlan = SubordinateQueryPlanner.PlanSubquery(outerEventTypesSelect, joinedPropPlan, false, fullTableScan, optionalIndexHint, true, subqueryNum,
                                                                  false, optionalTableMetadata.EventTableIndexMetadataRepo, optionalTableMetadata.UniqueKeyProps, true, statementName, statementId, annotations);
                if (_queryPlan != null)
                {
                    for (int i = 0; i < _queryPlan.IndexDescs.Length; i++)
                    {
                        optionalTableMetadata.AddIndexReference(_queryPlan.IndexDescs[i].IndexName, statementName);
                    }
                }
            }
            else
            {
                isLogging  = optionalNamedWindowProcessor.RootView.IsQueryPlanLogging;
                log        = NamedWindowRootView.QueryPlanLog;
                _queryPlan = SubordinateQueryPlanner.PlanSubquery(outerEventTypesSelect, joinedPropPlan, false, fullTableScan, optionalIndexHint, true, subqueryNum,
                                                                  optionalNamedWindowProcessor.IsVirtualDataWindow, optionalNamedWindowProcessor.EventTableIndexMetadataRepo, optionalNamedWindowProcessor.OptionalUniqueKeyProps, false, statementName, statementId, annotations);
                if (_queryPlan != null && _queryPlan.IndexDescs != null)
                {
                    SubordinateQueryPlannerUtil.AddIndexMetaAndRef(_queryPlan.IndexDescs, optionalNamedWindowProcessor.EventTableIndexMetadataRepo, statementName);
                    statementStopService.StatementStopped += () =>
                    {
                        for (int i = 0; i < _queryPlan.IndexDescs.Length; i++)
                        {
                            bool last = optionalNamedWindowProcessor.EventTableIndexMetadataRepo.RemoveIndexReference(_queryPlan.IndexDescs[i].IndexMultiKey, statementName);
                            if (last)
                            {
                                optionalNamedWindowProcessor.EventTableIndexMetadataRepo.RemoveIndex(_queryPlan.IndexDescs[i].IndexMultiKey);
                                optionalNamedWindowProcessor.RemoveAllInstanceIndexes(_queryPlan.IndexDescs[i].IndexMultiKey);
                            }
                        }
                    };
                }
            }

            SubordinateQueryPlannerUtil.QueryPlanLogOnSubq(isLogging, log, _queryPlan, subqueryNum, annotations);
        }
Beispiel #5
0
        public SubSelectStrategyRealization Instantiate(
            EPServicesContext services,
            Viewable viewableRoot,
            AgentInstanceContext agentInstanceContext,
            IList <StopCallback> stopCallbackList,
            int subqueryNumber,
            bool isRecoveringResilient)
        {
            SubselectAggregationPreprocessorBase subselectAggregationPreprocessor = null;

            AggregationService aggregationService = null;

            if (_aggregationServiceFactory != null)
            {
                aggregationService = _aggregationServiceFactory.AggregationServiceFactory.MakeService(
                    agentInstanceContext, agentInstanceContext.StatementContext.EngineImportService, true, subqueryNumber);
                if (_groupByKeys == null)
                {
                    if (_filterExprEval == null)
                    {
                        subselectAggregationPreprocessor =
                            new SubselectAggregationPreprocessorUnfilteredUngrouped(
                                aggregationService, _filterExprEval, null);
                    }
                    else
                    {
                        subselectAggregationPreprocessor =
                            new SubselectAggregationPreprocessorFilteredUngrouped(aggregationService, _filterExprEval, null);
                    }
                }
                else
                {
                    if (_filterExprEval == null)
                    {
                        subselectAggregationPreprocessor =
                            new SubselectAggregationPreprocessorUnfilteredGrouped(
                                aggregationService, _filterExprEval, _groupByKeys);
                    }
                    else
                    {
                        subselectAggregationPreprocessor =
                            new SubselectAggregationPreprocessorFilteredGrouped(
                                aggregationService, _filterExprEval, _groupByKeys);
                    }
                }
            }

            SubordTableLookupStrategy subqueryLookup;

            if (_optionalNamedWindowProcessor != null)
            {
                NamedWindowProcessorInstance instance =
                    _optionalNamedWindowProcessor.GetProcessorInstance(agentInstanceContext);
                if (_queryPlan == null)
                {
                    if (instance.RootViewInstance.IsQueryPlanLogging && NamedWindowRootView.QueryPlanLog.IsInfoEnabled)
                    {
                        NamedWindowRootView.QueryPlanLog.Info("shared, full table scan");
                    }
                    subqueryLookup =
                        new SubordFullTableScanLookupStrategyLocking(
                            instance.RootViewInstance.DataWindowContents,
                            agentInstanceContext.EpStatementAgentInstanceHandle.StatementAgentInstanceLock);
                }
                else
                {
                    EventTable[] tables = null;
                    if (!_optionalNamedWindowProcessor.IsVirtualDataWindow)
                    {
                        tables = SubordinateQueryPlannerUtil.RealizeTables(
                            _queryPlan.IndexDescs, instance.RootViewInstance.EventType,
                            instance.RootViewInstance.IndexRepository,
                            instance.RootViewInstance.DataWindowContents, agentInstanceContext,
                            isRecoveringResilient);
                    }
                    SubordTableLookupStrategy strategy = _queryPlan.LookupStrategyFactory.MakeStrategy(
                        tables, instance.RootViewInstance.VirtualDataWindow);
                    subqueryLookup = new SubordIndexedTableLookupStrategyLocking(
                        strategy, instance.TailViewInstance.AgentInstanceContext.AgentInstanceLock);
                }
            }
            else
            {
                TableStateInstance state = _tableService.GetState(
                    _optionalTableMetadata.TableName, agentInstanceContext.AgentInstanceId);
                ILockable iLock = agentInstanceContext.StatementContext.IsWritesToTables
                    ? state.TableLevelRWLock.WriteLock
                    : state.TableLevelRWLock.ReadLock;
                if (_queryPlan == null)
                {
                    subqueryLookup = new SubordFullTableScanTableLookupStrategy(iLock, state.IterableTableScan);
                }
                else
                {
                    EventTable[] indexes = new EventTable[_queryPlan.IndexDescs.Length];
                    for (int i = 0; i < indexes.Length; i++)
                    {
                        indexes[i] = state.IndexRepository.GetIndexByDesc(_queryPlan.IndexDescs[i].IndexMultiKey);
                    }
                    subqueryLookup = _queryPlan.LookupStrategyFactory.MakeStrategy(indexes, null);
                    subqueryLookup = new SubordIndexedTableLookupTableStrategy(subqueryLookup, iLock);
                }
            }

            return(new SubSelectStrategyRealization(
                       subqueryLookup, subselectAggregationPreprocessor, aggregationService,
                       Collections.GetEmptyMap <ExprPriorNode, ExprPriorEvalStrategy>(),
                       Collections.GetEmptyMap <ExprPreviousNode, ExprPreviousEvalStrategy>(),
                       null, null));
        }
Beispiel #6
0
        /// <summary>
        /// Create the table lookup plan for a from-stream to look up in an indexed stream
        /// using the columns supplied in the query graph and looking at the actual indexes available
        /// and their index number.
        /// </summary>
        /// <param name="queryGraph">contains properties joining the 2 streams</param>
        /// <param name="currentLookupStream">stream to use key values from</param>
        /// <param name="indexedStream">stream to look up in</param>
        /// <param name="indexSpecs">index specification defining indexes to be created for stream</param>
        /// <param name="typesPerStream">event types for each stream</param>
        /// <returns>plan for performing a lookup in a given table using one of the indexes supplied</returns>
        public static TableLookupPlan CreateLookupPlan(QueryGraph queryGraph, int currentLookupStream, int indexedStream,
                                                       QueryPlanIndex indexSpecs, EventType[] typesPerStream,
                                                       TableMetadata indexedStreamTableMeta)
        {
            var queryGraphValue = queryGraph.GetGraphValue(currentLookupStream, indexedStream);
            var hashKeyProps    = queryGraphValue.HashKeyProps;
            var hashPropsKeys   = hashKeyProps.Keys;
            var hashIndexProps  = hashKeyProps.Indexed.ToArray();

            var rangeProps      = queryGraphValue.RangeProps;
            var rangePropsKeys  = rangeProps.Keys;
            var rangeIndexProps = rangeProps.Indexed.ToArray();

            var pairIndexHashRewrite = indexSpecs.GetIndexNum(hashIndexProps, rangeIndexProps);
            var indexNum             = pairIndexHashRewrite == null ? null : pairIndexHashRewrite.First;

            // handle index redirection towards unique index
            if (pairIndexHashRewrite != null && pairIndexHashRewrite.Second != null)
            {
                var indexes           = pairIndexHashRewrite.Second;
                var newHashIndexProps = new string[indexes.Length];
                IList <QueryGraphValueEntryHashKeyed> newHashKeys = new List <QueryGraphValueEntryHashKeyed>();
                for (var i = 0; i < indexes.Length; i++)
                {
                    newHashIndexProps[i] = hashIndexProps[indexes[i]];
                    newHashKeys.Add(hashPropsKeys[indexes[i]]);
                }
                hashIndexProps  = newHashIndexProps;
                hashPropsKeys   = newHashKeys;
                rangeIndexProps = new string[0];
                rangePropsKeys  = Collections.GetEmptyList <QueryGraphValueEntryRange>();
            }

            // no direct hash or range lookups
            if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 0)
            {
                // handle single-direction 'in' keyword
                var singles = queryGraphValue.InKeywordSingles;
                if (!singles.Key.IsEmpty())
                {
                    QueryGraphValueEntryInKeywordSingleIdx single = null;
                    indexNum = null;
                    if (indexedStreamTableMeta != null)
                    {
                        var indexes = singles.Indexed;
                        var count   = 0;
                        foreach (var index in indexes)
                        {
                            Pair <IndexMultiKey, EventTableIndexEntryBase> indexPairFound =
                                EventTableIndexUtil.FindIndexBestAvailable(
                                    indexedStreamTableMeta.EventTableIndexMetadataRepo.Indexes,
                                    Collections.SingletonSet(index),
                                    Collections.GetEmptySet <string>(), null);
                            if (indexPairFound != null)
                            {
                                indexNum = new TableLookupIndexReqKey(indexPairFound.Second.OptionalIndexName, indexedStreamTableMeta.TableName);
                                single   = singles.Key[count];
                            }
                            count++;
                        }
                    }
                    else
                    {
                        single = singles.Key[0];
                        var pairIndex = indexSpecs.GetIndexNum(new string[] { singles.Indexed[0] }, null);
                        indexNum = pairIndex.First;
                    }

                    if (indexNum != null)
                    {
                        return(new InKeywordTableLookupPlanSingleIdx(currentLookupStream, indexedStream, indexNum, single.KeyExprs));
                    }
                }

                // handle multi-direction 'in' keyword
                var multis = queryGraphValue.InKeywordMulti;
                if (!multis.IsEmpty())
                {
                    if (indexedStreamTableMeta != null)
                    {
                        return(GetFullTableScanTable(currentLookupStream, indexedStream, indexedStreamTableMeta));
                    }
                    QueryGraphValuePairInKWMultiIdx multi = multis[0];
                    var indexNameArray = new TableLookupIndexReqKey[multi.Indexed.Length];
                    var foundAll       = true;
                    for (var i = 0; i < multi.Indexed.Length; i++)
                    {
                        var identNode = (ExprIdentNode)multi.Indexed[i];
                        var pairIndex = indexSpecs.GetIndexNum(new string[] { identNode.ResolvedPropertyName }, null);
                        if (pairIndex == null)
                        {
                            foundAll = false;
                        }
                        else
                        {
                            indexNameArray[i] = pairIndex.First;
                        }
                    }
                    if (foundAll)
                    {
                        return(new InKeywordTableLookupPlanMultiIdx(currentLookupStream, indexedStream, indexNameArray, multi.Key.KeyExpr));
                    }
                }

                // We don't use a keyed index but use the full stream set as the stream does not have any indexes

                // If no such full set index exists yet, add to specs
                if (indexedStreamTableMeta != null)
                {
                    return(GetFullTableScanTable(currentLookupStream, indexedStream, indexedStreamTableMeta));
                }
                if (indexNum == null)
                {
                    indexNum = new TableLookupIndexReqKey(indexSpecs.AddIndex(null, null));
                }
                return(new FullTableScanLookupPlan(currentLookupStream, indexedStream, indexNum));
            }

            if (indexNum == null)
            {
                throw new IllegalStateException("Failed to query plan as index for " + hashIndexProps.Render() + " and " + rangeIndexProps.Render() + " in the index specification");
            }

            if (indexedStreamTableMeta != null)
            {
                var indexPairFound = EventTableIndexUtil.FindIndexBestAvailable(indexedStreamTableMeta.EventTableIndexMetadataRepo.Indexes, ToSet(hashIndexProps), ToSet(rangeIndexProps), null);
                if (indexPairFound != null)
                {
                    var indexKeyInfo = SubordinateQueryPlannerUtil.CompileIndexKeyInfo(indexPairFound.First, hashIndexProps, GetHashKeyFuncsAsSubProp(hashPropsKeys), rangeIndexProps, GetRangeFuncsAsSubProp(rangePropsKeys));
                    if (indexKeyInfo.OrderedKeyCoercionTypes.IsCoerce || indexKeyInfo.OrderedRangeCoercionTypes.IsCoerce)
                    {
                        return(GetFullTableScanTable(currentLookupStream, indexedStream, indexedStreamTableMeta));
                    }
                    hashPropsKeys   = ToHashKeyFuncs(indexKeyInfo.OrderedHashDesc);
                    hashIndexProps  = IndexedPropDesc.GetIndexProperties(indexPairFound.First.HashIndexedProps);
                    rangePropsKeys  = ToRangeKeyFuncs(indexKeyInfo.OrderedRangeDesc);
                    rangeIndexProps = IndexedPropDesc.GetIndexProperties(indexPairFound.First.RangeIndexedProps);
                    indexNum        = new TableLookupIndexReqKey(indexPairFound.Second.OptionalIndexName, indexedStreamTableMeta.TableName);
                    // the plan will be created below
                    if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 0)
                    {
                        return(GetFullTableScanTable(currentLookupStream, indexedStream, indexedStreamTableMeta));
                    }
                }
                else
                {
                    return(GetFullTableScanTable(currentLookupStream, indexedStream, indexedStreamTableMeta));
                }
            }

            // straight keyed-index lookup
            if (hashIndexProps.Length > 0 && rangeIndexProps.Length == 0)
            {
                TableLookupPlan tableLookupPlan;
                if (hashPropsKeys.Count == 1)
                {
                    tableLookupPlan = new IndexedTableLookupPlanSingle(currentLookupStream, indexedStream, indexNum, hashPropsKeys[0]);
                }
                else
                {
                    tableLookupPlan = new IndexedTableLookupPlanMulti(currentLookupStream, indexedStream, indexNum, hashPropsKeys);
                }

                // Determine coercion required
                var coercionTypes = CoercionUtil.GetCoercionTypesHash(typesPerStream, currentLookupStream, indexedStream, hashPropsKeys, hashIndexProps);
                if (coercionTypes.IsCoerce)
                {
                    // check if there already are coercion types for this index
                    var existCoercionTypes = indexSpecs.GetCoercionTypes(hashIndexProps);
                    if (existCoercionTypes != null)
                    {
                        for (var i = 0; i < existCoercionTypes.Length; i++)
                        {
                            coercionTypes.CoercionTypes[i] = TypeHelper.GetCompareToCoercionType(existCoercionTypes[i], coercionTypes.CoercionTypes[i]);
                        }
                    }
                    indexSpecs.SetCoercionTypes(hashIndexProps, coercionTypes.CoercionTypes);
                }

                return(tableLookupPlan);
            }

            // sorted index lookup
            if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 1)
            {
                QueryGraphValueEntryRange range = rangePropsKeys[0];
                return(new SortedTableLookupPlan(currentLookupStream, indexedStream, indexNum, range));
            }
            // composite range and index lookup
            else
            {
                return(new CompositeTableLookupPlan(currentLookupStream, indexedStream, indexNum, hashPropsKeys, rangePropsKeys));
            }
        }
Beispiel #7
0
        /// <summary>
        ///     Create the table lookup plan for a from-stream to look up in an indexed stream
        ///     using the columns supplied in the query graph and looking at the actual indexes available
        ///     and their index number.
        /// </summary>
        /// <param name="queryGraph">contains properties joining the 2 streams</param>
        /// <param name="currentLookupStream">stream to use key values from</param>
        /// <param name="indexedStream">stream to look up in</param>
        /// <param name="indexSpecs">index specification defining indexes to be created for stream</param>
        /// <param name="typesPerStream">event types for each stream</param>
        /// <param name="indexedStreamTableMeta">table info</param>
        /// <param name="indexedStreamIsVDW">vdw indicators</param>
        /// <param name="raw">raw statement information</param>
        /// <param name="serdeResolver">serde resolver</param>
        /// <returns>plan for performing a lookup in a given table using one of the indexes supplied</returns>
        public static TableLookupPlanDesc CreateLookupPlan(
            QueryGraphForge queryGraph,
            int currentLookupStream,
            int indexedStream,
            bool indexedStreamIsVDW,
            QueryPlanIndexForge indexSpecs,
            EventType[] typesPerStream,
            TableMetaData indexedStreamTableMeta,
            StatementRawInfo raw,
            SerdeCompileTimeResolver serdeResolver)
        {
            var queryGraphValue = queryGraph.GetGraphValue(currentLookupStream, indexedStream);
            var hashKeyProps = queryGraphValue.HashKeyProps;
            var hashPropsKeys = hashKeyProps.Keys;
            var hashIndexProps = hashKeyProps.Indexed;

            var rangeProps = queryGraphValue.RangeProps;
            var rangePropsKeys = rangeProps.Keys;
            var rangeIndexProps = rangeProps.Indexed;

            var pairIndexHashRewrite =
                indexSpecs.GetIndexNum(hashIndexProps, rangeIndexProps);
            var indexNum = pairIndexHashRewrite == null ? null : pairIndexHashRewrite.First;

            // handle index redirection towards unique index
            if (pairIndexHashRewrite != null && pairIndexHashRewrite.Second != null) {
                var indexes = pairIndexHashRewrite.Second;
                var newHashIndexProps = new string[indexes.Length];
                IList<QueryGraphValueEntryHashKeyedForge> newHashKeys = new List<QueryGraphValueEntryHashKeyedForge>();
                for (var i = 0; i < indexes.Length; i++) {
                    newHashIndexProps[i] = hashIndexProps[indexes[i]];
                    newHashKeys.Add(hashPropsKeys[indexes[i]]);
                }

                hashIndexProps = newHashIndexProps;
                hashPropsKeys = newHashKeys;
                rangeIndexProps = new string[0];
                rangePropsKeys = Collections.GetEmptyList<QueryGraphValueEntryRangeForge>();
            }

            // no direct hash or range lookups
            if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 0) {
                // handle single-direction 'in' keyword
                var singles = queryGraphValue.InKeywordSingles;
                if (!singles.Key.IsEmpty()) {
                    QueryGraphValueEntryInKeywordSingleIdxForge single = null;
                    indexNum = null;
                    if (indexedStreamTableMeta != null) {
                        var indexes = singles.Indexed;
                        var count = 0;
                        foreach (var index in indexes) {
                            var indexPairFound =
                                EventTableIndexUtil.FindIndexBestAvailable(
                                    indexedStreamTableMeta.IndexMetadata.Indexes,
                                    Collections.SingletonSet(index),
                                    Collections.GetEmptySet<string>(),
                                    null);
                            if (indexPairFound != null) {
                                indexNum = new TableLookupIndexReqKey(
                                    indexPairFound.Second.OptionalIndexName,
                                    indexPairFound.Second.OptionalIndexModuleName,
                                    indexedStreamTableMeta.TableName);
                                single = singles.Key[count];
                            }

                            count++;
                        }
                    }
                    else {
                        single = singles.Key[0];
                        var pairIndex = indexSpecs.GetIndexNum(
                            new[] {singles.Indexed[0]},
                            new string[0]);
                        indexNum = pairIndex.First;
                    }

                    if (indexNum != null) {
                        var forge = new InKeywordTableLookupPlanSingleIdxForge(
                            currentLookupStream,
                            indexedStream,
                            indexedStreamIsVDW,
                            typesPerStream,
                            indexNum,
                            single.KeyExprs);
                        return new TableLookupPlanDesc(forge, EmptyList<StmtClassForgeableFactory>.Instance);
                    }
                }

                // handle multi-direction 'in' keyword
                var multis = queryGraphValue.InKeywordMulti;
                if (!multis.IsEmpty()) {
                    if (indexedStreamTableMeta != null) {
                        return GetFullTableScanTable(
                            currentLookupStream,
                            indexedStream,
                            indexedStreamIsVDW,
                            typesPerStream,
                            indexedStreamTableMeta);
                    }

                    var multi = multis[0];
                    var indexNameArray = new TableLookupIndexReqKey[multi.Indexed.Length];
                    var foundAll = true;
                    for (var i = 0; i < multi.Indexed.Length; i++) {
                        var identNode = (ExprIdentNode) multi.Indexed[i];
                        var pairIndex = indexSpecs.GetIndexNum(
                            new[] {identNode.ResolvedPropertyName},
                            new string[0]);
                        if (pairIndex == null) {
                            foundAll = false;
                        }
                        else {
                            indexNameArray[i] = pairIndex.First;
                        }
                    }

                    if (foundAll) {
                        var forge = new InKeywordTableLookupPlanMultiIdxForge(
                            currentLookupStream,
                            indexedStream,
                            indexedStreamIsVDW,
                            typesPerStream,
                            indexNameArray,
                            multi.Key.KeyExpr);
                        return new TableLookupPlanDesc(forge, EmptyList<StmtClassForgeableFactory>.Instance);
                    }
                }

                // We don't use a keyed index but use the full stream set as the stream does not have any indexes

                // If no such full set index exists yet, add to specs
                if (indexedStreamTableMeta != null) {
                    return GetFullTableScanTable(
                        currentLookupStream,
                        indexedStream,
                        indexedStreamIsVDW,
                        typesPerStream,
                        indexedStreamTableMeta);
                }

                if (indexNum == null) {
                    indexNum = new TableLookupIndexReqKey(
                        indexSpecs.AddIndex(new string[0], new Type[0], typesPerStream[indexedStream]),
                        null);
                }

                var forgeX = new FullTableScanLookupPlanForge(currentLookupStream, indexedStream, indexedStreamIsVDW, typesPerStream, indexNum);
                return new TableLookupPlanDesc(forgeX, EmptyList<StmtClassForgeableFactory>.Instance);
            }

            if (indexNum == null) {
                throw new IllegalStateException(
                    "Failed to query plan as index for " +
                    hashIndexProps.RenderAny() +
                    " and " +
                    rangeIndexProps.RenderAny() +
                    " in the index specification");
            }

            if (indexedStreamTableMeta != null) {
                var indexPairFound =
                    EventTableIndexUtil.FindIndexBestAvailable(
                        indexedStreamTableMeta.IndexMetadata.Indexes,
                        ToSet(hashIndexProps),
                        ToSet(rangeIndexProps),
                        null);
                if (indexPairFound != null) {
                    var indexKeyInfo = SubordinateQueryPlannerUtil.CompileIndexKeyInfo(
                        indexPairFound.First,
                        hashIndexProps,
                        GetHashKeyFuncsAsSubProp(hashPropsKeys),
                        rangeIndexProps,
                        GetRangeFuncsAsSubProp(rangePropsKeys));
                    if (indexKeyInfo.OrderedKeyCoercionTypes.IsCoerce ||
                        indexKeyInfo.OrderedRangeCoercionTypes.IsCoerce) {
                        return GetFullTableScanTable(
                            currentLookupStream,
                            indexedStream,
                            indexedStreamIsVDW,
                            typesPerStream,
                            indexedStreamTableMeta);
                    }

                    hashPropsKeys = ToHashKeyFuncs(indexKeyInfo.OrderedHashDesc);
                    hashIndexProps = IndexedPropDesc.GetIndexProperties(indexPairFound.First.HashIndexedProps);
                    rangePropsKeys = ToRangeKeyFuncs(indexKeyInfo.OrderedRangeDesc);
                    rangeIndexProps = IndexedPropDesc.GetIndexProperties(indexPairFound.First.RangeIndexedProps);
                    indexNum = new TableLookupIndexReqKey(
                        indexPairFound.Second.OptionalIndexName,
                        indexPairFound.Second.OptionalIndexModuleName,
                        indexedStreamTableMeta.TableName);
                    // the plan will be created below
                    if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 0) {
                        return GetFullTableScanTable(
                            currentLookupStream,
                            indexedStream,
                            indexedStreamIsVDW,
                            typesPerStream,
                            indexedStreamTableMeta);
                    }
                }
                else {
                    return GetFullTableScanTable(
                        currentLookupStream,
                        indexedStream,
                        indexedStreamIsVDW,
                        typesPerStream,
                        indexedStreamTableMeta);
                }
            }

            // straight keyed-index lookup
            if (hashIndexProps.Length > 0 && rangeIndexProps.Length == 0) {
                // Determine coercion required
                var coercionTypes = CoercionUtil.GetCoercionTypesHash(
                    typesPerStream,
                    currentLookupStream,
                    indexedStream,
                    hashPropsKeys,
                    hashIndexProps);
                if (coercionTypes.IsCoerce) {
                    // check if there already are coercion types for this index
                    var existCoercionTypes = indexSpecs.GetCoercionTypes(hashIndexProps);
                    if (existCoercionTypes != null) {
                        for (var i = 0; i < existCoercionTypes.Length; i++) {
                            coercionTypes.CoercionTypes[i] = existCoercionTypes[i]
                                .GetCompareToCoercionType(coercionTypes.CoercionTypes[i]);
                        }
                    }

                    if (!indexSpecs.Items.IsEmpty()) {
                        indexSpecs.SetCoercionTypes(hashIndexProps, coercionTypes.CoercionTypes);
                    }
                }

                var coercionTypesArray = coercionTypes.CoercionTypes;
                MultiKeyClassRef tableLookupMultiKey = null;
                IList<StmtClassForgeableFactory> additionalForgeables = EmptyList<StmtClassForgeableFactory>.Instance;
                if (indexNum.TableName != null) {
                    var tableMultiKeyPlan = MultiKeyPlanner.PlanMultiKey(coercionTypesArray, true, raw, serdeResolver);
                    tableLookupMultiKey = tableMultiKeyPlan.ClassRef;
                    additionalForgeables = tableMultiKeyPlan.MultiKeyForgeables;
                }

                var forge = new IndexedTableLookupPlanHashedOnlyForge(
                    currentLookupStream,
                    indexedStream,
                    indexedStreamIsVDW,
                    typesPerStream,
                    indexNum,
                    hashPropsKeys.ToArray(),
                    indexSpecs,
                    coercionTypesArray,
                    tableLookupMultiKey);
                return new TableLookupPlanDesc(forge, additionalForgeables);
            }

            // sorted index lookup
            var coercionTypesRange = CoercionUtil.GetCoercionTypesRange(
                typesPerStream,
                indexedStream,
                rangeIndexProps,
                rangePropsKeys);
            var coercionTypesHash = CoercionUtil.GetCoercionTypesHash(
                typesPerStream,
                currentLookupStream,
                indexedStream,
                hashPropsKeys,
                hashIndexProps);
            if (hashIndexProps.Length == 0 && rangeIndexProps.Length == 1) {
                var range = rangePropsKeys[0];
                Type coercionType = null;
                if (coercionTypesRange.IsCoerce) {
                    coercionType = coercionTypesRange.CoercionTypes[0];
                }

                SortedTableLookupPlanForge forge = new SortedTableLookupPlanForge(
                    currentLookupStream,
                    indexedStream,
                    indexedStreamIsVDW,
                    typesPerStream,
                    indexNum,
                    range,
                    coercionType);
                return new TableLookupPlanDesc(forge, EmptyList<StmtClassForgeableFactory>.Instance);
            }
            else {
                MultiKeyClassRef tableLookupMultiKey = null;
                IList<StmtClassForgeableFactory> additionalForgeables = EmptyList<StmtClassForgeableFactory>.Instance;
                if (indexNum.TableName != null) {
                    MultiKeyPlan tableMultiKeyPlan = MultiKeyPlanner.PlanMultiKey(coercionTypesHash.CoercionTypes, true, raw, serdeResolver);
                    tableLookupMultiKey = tableMultiKeyPlan.ClassRef;
                    additionalForgeables = tableMultiKeyPlan.MultiKeyForgeables;
                }

                // composite range and index lookup
                CompositeTableLookupPlanForge forge = new CompositeTableLookupPlanForge(
                    currentLookupStream,
                    indexedStream,
                    indexedStreamIsVDW,
                    typesPerStream,
                    indexNum,
                    hashPropsKeys,
                    coercionTypesHash.CoercionTypes,
                    rangePropsKeys,
                    coercionTypesRange.CoercionTypes,
                    indexSpecs,
                    tableLookupMultiKey);
                return new TableLookupPlanDesc(forge, additionalForgeables);
            }
        }
        public SubSelectStrategyFactoryIndexShareForge(
            int subqueryNumber,
            SubSelectActivationPlan subselectActivation,
            EventType[] outerEventTypesSelect,
            NamedWindowMetaData namedWindow,
            TableMetaData table,
            bool fullTableScan,
            IndexHint indexHint,
            SubordPropPlan joinedPropPlan,
            ExprForge filterExprEval,
            ExprNode[] groupKeys,
            AggregationServiceForgeDesc aggregationServiceForgeDesc,
            StatementBaseInfo statement,
            StatementCompileTimeServices services)
        {
            _subqueryNumber = subqueryNumber;
            _namedWindow    = namedWindow;
            _table          = table;
            _filterExprEval = filterExprEval;
            _groupKeys      = groupKeys;
            _aggregationServiceForgeDesc = aggregationServiceForgeDesc;

            bool queryPlanLogging = services.Configuration.Common.Logging.IsEnableQueryPlan;

            // We only use existing indexes in all cases. This means "create index" is required.
            SubordinateQueryPlan plan;

            if (table != null)
            {
                plan = SubordinateQueryPlanner.PlanSubquery(
                    outerEventTypesSelect,
                    joinedPropPlan,
                    false,
                    fullTableScan,
                    indexHint,
                    true,
                    subqueryNumber,
                    false,
                    table.IndexMetadata,
                    table.UniquenessAsSet,
                    true,
                    table.InternalEventType,
                    statement.StatementRawInfo,
                    services);
            }
            else
            {
                plan = SubordinateQueryPlanner.PlanSubquery(
                    outerEventTypesSelect,
                    joinedPropPlan,
                    false,
                    fullTableScan,
                    indexHint,
                    true,
                    subqueryNumber,
                    namedWindow.IsVirtualDataWindow,
                    namedWindow.IndexMetadata,
                    namedWindow.UniquenessAsSet,
                    true,
                    namedWindow.EventType,
                    statement.StatementRawInfo,
                    services);
            }

            _queryPlan = plan == null ? null : plan.Forge;
            if (plan != null)
            {
                _additionalForgeables.AddAll(plan.AdditionalForgeables);
            }

            if (_queryPlan != null && _queryPlan.IndexDescs != null)
            {
                for (int i = 0; i < _queryPlan.IndexDescs.Length; i++)
                {
                    SubordinateQueryIndexDescForge index = _queryPlan.IndexDescs[i];

                    if (table != null)
                    {
                        if (table.TableVisibility == NameAccessModifier.PUBLIC)
                        {
                            services.ModuleDependenciesCompileTime.AddPathIndex(
                                false,
                                table.TableName,
                                table.TableModuleName,
                                index.IndexName,
                                index.IndexModuleName,
                                services.NamedWindowCompileTimeRegistry,
                                services.TableCompileTimeRegistry);
                        }
                    }
                    else
                    {
                        if (namedWindow.EventType.Metadata.AccessModifier == NameAccessModifier.PUBLIC)
                        {
                            services.ModuleDependenciesCompileTime.AddPathIndex(
                                true,
                                namedWindow.EventType.Name,
                                namedWindow.NamedWindowModuleName,
                                index.IndexName,
                                index.IndexModuleName,
                                services.NamedWindowCompileTimeRegistry,
                                services.TableCompileTimeRegistry);
                        }
                    }
                }
            }

            SubordinateQueryPlannerUtil.QueryPlanLogOnSubq(
                queryPlanLogging,
                QUERY_PLAN_LOG,
                _queryPlan,
                subqueryNumber,
                statement.StatementRawInfo.Annotations,
                services.ImportServiceCompileTime);

            if (groupKeys == null || groupKeys.Length == 0)
            {
                _groupByMultiKey = null;
            }
            else
            {
                MultiKeyPlan mkplan = MultiKeyPlanner.PlanMultiKey(groupKeys, false, statement.StatementRawInfo, services.SerdeResolver);
                _additionalForgeables.AddAll(mkplan.MultiKeyForgeables);
                _groupByMultiKey = mkplan.ClassRef;
            }
        }
Beispiel #9
0
        public static OnTriggerPlan HandleContextFactoryOnTrigger(
            string className,
            CodegenNamespaceScope namespaceScope,
            string classPostfix,
            NamedWindowMetaData namedWindow,
            TableMetaData table,
            OnTriggerWindowPlan planDesc,
            StatementBaseInfo @base,
            StatementCompileTimeServices services)
        {
            // validate context
            var infraName = planDesc.OnTriggerDesc.WindowName;
            var infraTitle = (namedWindow != null ? "Named window" : "Table") + " '" + infraName + "'";
            var infraContextName = namedWindow != null ? namedWindow.ContextName : table.OptionalContextName;
            var infraModuleName = namedWindow != null ? namedWindow.NamedWindowModuleName : table.TableModuleName;
            var infraEventType = namedWindow != null ? namedWindow.EventType : table.InternalEventType;
            var resultEventType = namedWindow != null ? namedWindow.EventType : table.PublicEventType;
            var infraVisibility = namedWindow != null
                ? namedWindow.EventType.Metadata.AccessModifier
                : table.TableVisibility;
            ValidateOnExpressionContext(planDesc.ContextName, infraContextName, infraTitle);

            List<StmtClassForgeableFactory> additionalForgeables = new List<StmtClassForgeableFactory>();

            // validate expressions and plan subselects
            var validationResult = OnTriggerPlanValidator.ValidateOnTriggerPlan(
                infraEventType,
                planDesc.OnTriggerDesc,
                planDesc.StreamSpec,
                planDesc.ActivatorResult,
                planDesc.SubselectActivation,
                @base,
                services);
            additionalForgeables.AddAll(validationResult.AdditionalForgeables);

            var validatedJoin = validationResult.ValidatedJoin;
            var activatorResultEventType = planDesc.ActivatorResult.ActivatorResultEventType;

            var pair = IndexHintPair.GetIndexHintPair(
                planDesc.OnTriggerDesc,
                @base.StatementSpec.StreamSpecs[0].OptionalStreamName,
                @base.StatementRawInfo,
                services);
            var indexHint = pair.IndexHint;
            var excludePlanHint = pair.ExcludePlanHint;

            var enabledSubqueryIndexShare = namedWindow != null && namedWindow.IsEnableIndexShare;
            var isVirtualWindow = namedWindow != null && namedWindow.IsVirtualDataWindow;
            var indexMetadata = namedWindow != null ? namedWindow.IndexMetadata : table.IndexMetadata;
            var optionalUniqueKeySet = namedWindow != null ? namedWindow.UniquenessAsSet : table.UniquenessAsSet;

            // query plan
            var onlyUseExistingIndexes = table != null;
            SubordinateWMatchExprQueryPlanResult planResult = SubordinateQueryPlanner.PlanOnExpression(
                validatedJoin,
                activatorResultEventType,
                indexHint,
                enabledSubqueryIndexShare,
                -1,
                excludePlanHint,
                isVirtualWindow,
                indexMetadata,
                infraEventType,
                optionalUniqueKeySet,
                onlyUseExistingIndexes,
                @base.StatementRawInfo,
                services);
            SubordinateWMatchExprQueryPlanForge queryPlan = planResult.Forge;
            additionalForgeables.AddAll(planResult.AdditionalForgeables);
            
            // indicate index dependencies
            if (queryPlan.Indexes != null && infraVisibility == NameAccessModifier.PUBLIC) {
                foreach (var index in queryPlan.Indexes) {
                    services.ModuleDependenciesCompileTime.AddPathIndex(
                        namedWindow != null,
                        infraName,
                        infraModuleName,
                        index.IndexName,
                        index.IndexModuleName,
                        services.NamedWindowCompileTimeRegistry,
                        services.TableCompileTimeRegistry);
                }
            }

            var onTriggerType = planDesc.OnTriggerDesc.OnTriggerType;
            var activator = planDesc.ActivatorResult.Activator;
            var subselectForges = validationResult.SubselectForges;
            var tableAccessForges = validationResult.TableAccessForges;

            IList<StmtClassForgeable> forgeables = new List<StmtClassForgeable>(2);
            StatementAgentInstanceFactoryOnTriggerInfraBaseForge forge;
            var classNameRSP = CodeGenerationIDGenerator.GenerateClassNameSimple(
                typeof(ResultSetProcessorFactoryProvider),
                classPostfix);
            ResultSetProcessorDesc resultSetProcessor;

            if (onTriggerType == OnTriggerType.ON_SELECT) {
                resultSetProcessor = validationResult.ResultSetProcessorPrototype;
                var outputEventType = resultSetProcessor.ResultEventType;

                var insertInto = false;
                TableMetaData optionalInsertIntoTable = null;
                var insertIntoDesc = @base.StatementSpec.Raw.InsertIntoDesc;
                var addToFront = false;
                if (insertIntoDesc != null) {
                    insertInto = true;
                    optionalInsertIntoTable = services.TableCompileTimeResolver.Resolve(insertIntoDesc.EventTypeName);
                    var optionalInsertIntoNamedWindow =
                        services.NamedWindowCompileTimeResolver.Resolve(insertIntoDesc.EventTypeName);
                    addToFront = optionalInsertIntoNamedWindow != null || optionalInsertIntoTable != null;
                }

                var selectAndDelete = planDesc.OnTriggerDesc.IsDeleteAndSelect;
                var distinct = @base.StatementSpec.SelectClauseCompiled.IsDistinct;
                MultiKeyPlan distinctMultiKeyPlan = MultiKeyPlanner.PlanMultiKeyDistinct(
                    distinct,
                    outputEventType,
                    @base.StatementRawInfo,
                    services.SerdeResolver);
                additionalForgeables.AddAll(distinctMultiKeyPlan.MultiKeyForgeables);
                forge = new StatementAgentInstanceFactoryOnTriggerInfraSelectForge(
                    activator,
                    outputEventType,
                    subselectForges,
                    tableAccessForges,
                    namedWindow,
                    table,
                    queryPlan,
                    classNameRSP,
                    insertInto,
                    addToFront,
                    optionalInsertIntoTable,
                    selectAndDelete,
                    distinct,
                    distinctMultiKeyPlan.ClassRef);
            }
            else {
                var defaultSelectAllSpec = new StatementSpecCompiled();
                defaultSelectAllSpec.SelectClauseCompiled.WithSelectExprList(new SelectClauseElementWildcard());
                defaultSelectAllSpec.Raw.SelectStreamDirEnum = SelectClauseStreamSelectorEnum.RSTREAM_ISTREAM_BOTH;
                StreamTypeService typeService = new StreamTypeServiceImpl(
                    new[] {resultEventType},
                    new[] {infraName},
                    new[] {false},
                    false,
                    false);
                resultSetProcessor = ResultSetProcessorFactoryFactory.GetProcessorPrototype(
                    new ResultSetSpec(defaultSelectAllSpec),
                    typeService,
                    null,
                    new bool[1],
                    false,
                    @base.ContextPropertyRegistry,
                    false,
                    false,
                    @base.StatementRawInfo,
                    services);

                if (onTriggerType == OnTriggerType.ON_DELETE) {
                    forge = new StatementAgentInstanceFactoryOnTriggerInfraDeleteForge(
                        activator,
                        resultEventType,
                        subselectForges,
                        tableAccessForges,
                        classNameRSP,
                        namedWindow,
                        table,
                        queryPlan);
                }
                else if (onTriggerType == OnTriggerType.ON_UPDATE) {
                    var updateDesc = (OnTriggerWindowUpdateDesc) planDesc.OnTriggerDesc;
                    EventBeanUpdateHelperForge updateHelper = EventBeanUpdateHelperForgeFactory.Make(
                        infraName,
                        (EventTypeSPI) infraEventType,
                        updateDesc.Assignments,
                        validationResult.ZeroStreamAliasName,
                        activatorResultEventType,
                        namedWindow != null,
                        @base.StatementName,
                        services.EventTypeAvroHandler);
                    forge = new StatementAgentInstanceFactoryOnTriggerInfraUpdateForge(
                        activator,
                        resultEventType,
                        subselectForges,
                        tableAccessForges,
                        classNameRSP,
                        namedWindow,
                        table,
                        queryPlan,
                        updateHelper);
                }
                else if (onTriggerType == OnTriggerType.ON_MERGE) {
                    var onMergeTriggerDesc = (OnTriggerMergeDesc) planDesc.OnTriggerDesc;
                    var onMergeHelper = new InfraOnMergeHelperForge(
                        onMergeTriggerDesc,
                        activatorResultEventType,
                        planDesc.StreamSpec.OptionalStreamName,
                        infraName,
                        (EventTypeSPI) infraEventType,
                        @base.StatementRawInfo,
                        services,
                        table);
                    forge = new StatementAgentInstanceFactoryOnTriggerInfraMergeForge(
                        activator,
                        resultEventType,
                        subselectForges,
                        tableAccessForges,
                        classNameRSP,
                        namedWindow,
                        table,
                        queryPlan,
                        onMergeHelper);
                }
                else {
                    throw new IllegalStateException("Unrecognized trigger type " + onTriggerType);
                }
            }

            forgeables.Add(
                new StmtClassForgeableRSPFactoryProvider(
                    classNameRSP,
                    resultSetProcessor,
                    namespaceScope,
                    @base.StatementRawInfo));

            var queryPlanLogging = services.Configuration.Common.Logging.IsEnableQueryPlan;
            SubordinateQueryPlannerUtil.QueryPlanLogOnExpr(
                queryPlanLogging,
                QUERY_PLAN_LOG,
                queryPlan,
                @base.StatementSpec.Annotations,
                services.ImportServiceCompileTime);

            StmtClassForgeableAIFactoryProviderOnTrigger onTrigger = new StmtClassForgeableAIFactoryProviderOnTrigger(className, namespaceScope, forge);
            return new OnTriggerPlan(onTrigger, forgeables, resultSetProcessor.SelectSubscriberDescriptor, additionalForgeables);
        }