public override EPStatementStartResult StartInternal(EPServicesContext services, StatementContext statementContext, bool isNewStatement, bool isRecoveringStatement, bool isRecoveringResilient) { var spec = _statementSpec.CreateIndexDesc; var namedWindowProcessor = services.NamedWindowMgmtService.GetProcessor(spec.WindowName); var tableMetadata = services.TableService.GetTableMetadata(spec.WindowName); if (namedWindowProcessor == null && tableMetadata == null) { throw new ExprValidationException("A named window or table by name '" + spec.WindowName + "' does not exist"); } var indexedEventType = namedWindowProcessor != null ? namedWindowProcessor.NamedWindowType : tableMetadata.InternalEventType; var infraContextName = namedWindowProcessor != null ? namedWindowProcessor.ContextName : tableMetadata.ContextName; EPLValidationUtil.ValidateContextName(namedWindowProcessor == null, spec.WindowName, infraContextName, _statementSpec.OptionalContextName, true); // validate index var explicitIndexDesc = EventTableIndexUtil.ValidateCompileExplicitIndex(spec.IndexName, spec.IsUnique, spec.Columns, indexedEventType, statementContext); var advancedIndexDesc = explicitIndexDesc.AdvancedIndexProvisionDesc == null ? null : explicitIndexDesc.AdvancedIndexProvisionDesc.IndexDesc; var imk = new IndexMultiKey(spec.IsUnique, explicitIndexDesc.HashPropsAsList, explicitIndexDesc.BtreePropsAsList, advancedIndexDesc); // for tables we add the index to metadata if (tableMetadata != null) { services.TableService.ValidateAddIndex(statementContext.StatementName, tableMetadata, spec.IndexName, explicitIndexDesc, imk); } else { namedWindowProcessor.ValidateAddIndex(statementContext.StatementName, spec.IndexName, explicitIndexDesc, imk); } // allocate context factory Viewable viewable = new ViewableDefaultImpl(indexedEventType); var contextFactory = new StatementAgentInstanceFactoryCreateIndex( services, spec, viewable, namedWindowProcessor, tableMetadata?.TableName, _statementSpec.OptionalContextName, explicitIndexDesc); statementContext.StatementAgentInstanceFactory = contextFactory; // provide destroy method which de-registers interest in this index var finalTableService = services.TableService; var finalStatementName = statementContext.StatementName; var destroyMethod = new EPStatementDestroyCallbackList(); if (tableMetadata != null) { destroyMethod.AddCallback(() => finalTableService.RemoveIndexReferencesStmtMayRemoveIndex(finalStatementName, tableMetadata)); } else { destroyMethod.AddCallback(() => namedWindowProcessor.RemoveIndexReferencesStmtMayRemoveIndex(imk, finalStatementName)); } EPStatementStopMethod stopMethod; if (_statementSpec.OptionalContextName != null) { var mergeView = new ContextMergeView(indexedEventType); var statement = new ContextManagedStatementCreateIndexDesc(_statementSpec, statementContext, mergeView, contextFactory); services.ContextManagementService.AddStatement(_statementSpec.OptionalContextName, statement, isRecoveringResilient); stopMethod = new ProxyEPStatementStopMethod(() => {}); var contextManagementService = services.ContextManagementService; destroyMethod.AddCallback(() => contextManagementService.DestroyedStatement(_statementSpec.OptionalContextName, statementContext.StatementName, statementContext.StatementId)); } else { var defaultAgentInstanceContext = GetDefaultAgentInstanceContext(statementContext); StatementAgentInstanceFactoryResult result; try { result = contextFactory.NewContext(defaultAgentInstanceContext, isRecoveringResilient); } catch (EPException ex) { if (ex.InnerException is ExprValidationException) { throw (ExprValidationException)ex.InnerException; } destroyMethod.Destroy(); throw; } catch (Exception) { destroyMethod.Destroy(); throw; } var stopCallback = services.EpStatementFactory.MakeStopMethod(result); stopMethod = new ProxyEPStatementStopMethod(stopCallback.Stop); if (statementContext.StatementExtensionServicesContext != null && statementContext.StatementExtensionServicesContext.StmtResources != null) { var holder = statementContext.StatementExtensionServicesContext.ExtractStatementResourceHolder(result); statementContext.StatementExtensionServicesContext.StmtResources.Unpartitioned = holder; statementContext.StatementExtensionServicesContext.PostProcessStart(result, isRecoveringResilient); } } if (tableMetadata != null) { services.StatementVariableRefService.AddReferences(statementContext.StatementName, tableMetadata.TableName); } else { services.StatementVariableRefService.AddReferences(statementContext.StatementName, namedWindowProcessor.NamedWindowType.Name); } return(new EPStatementStartResult(viewable, stopMethod, destroyMethod)); }
/// <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)); } }
public StmtForgeMethodResult Make( string @namespace, string classPostfix, StatementCompileTimeServices services) { var spec = @base.StatementSpec.Raw.CreateIndexDesc; var infraName = spec.WindowName; var namedWindow = services.NamedWindowCompileTimeResolver.Resolve(infraName); var table = services.TableCompileTimeResolver.Resolve(infraName); if (namedWindow == null && table == null) { throw new ExprValidationException("A named window or table by name '" + infraName + "' does not exist"); } if (namedWindow != null && table != null) { throw new ExprValidationException("A named window or table by name '" + infraName + "' are both found"); } string infraModuleName; NameAccessModifier infraVisibility; EventType indexedEventType; string infraContextName; if (namedWindow != null) { infraModuleName = namedWindow.NamedWindowModuleName; infraVisibility = namedWindow.EventType.Metadata.AccessModifier; indexedEventType = namedWindow.EventType; infraContextName = namedWindow.ContextName; } else { infraModuleName = table.TableModuleName; infraVisibility = table.TableVisibility; indexedEventType = table.InternalEventType; infraContextName = table.OptionalContextName; if (!table.IsKeyed) { throw new ExprValidationException( "Tables without primary key column(s) do not allow creating an index"); } } EPLValidationUtil.ValidateContextName( namedWindow == null, infraName, infraContextName, @base.StatementSpec.Raw.OptionalContextName, true); // validate index var explicitIndexDesc = EventTableIndexUtil.ValidateCompileExplicitIndex( spec.IndexName, spec.IsUnique, spec.Columns, indexedEventType, @base.StatementRawInfo, services); var advancedIndexDesc = explicitIndexDesc.AdvancedIndexProvisionDesc == null ? null : explicitIndexDesc.AdvancedIndexProvisionDesc.IndexDesc.AdvancedIndexDescRuntime; var imk = new IndexMultiKey( spec.IsUnique, explicitIndexDesc.HashPropsAsList, explicitIndexDesc.BtreePropsAsList, advancedIndexDesc); // add index as a new index to module-init var indexKey = new IndexCompileTimeKey( infraModuleName, infraName, infraVisibility, namedWindow != null, spec.IndexName, @base.ModuleName); services.IndexCompileTimeRegistry.NewIndex(indexKey, new IndexDetailForge(imk, explicitIndexDesc)); // add index current named window information if (namedWindow != null) { namedWindow.AddIndex(spec.IndexName, @base.ModuleName, imk, explicitIndexDesc.ToRuntime()); } else { table.AddIndex(spec.IndexName, @base.ModuleName, imk, explicitIndexDesc.ToRuntime()); } var statementFieldsClassName = CodeGenerationIDGenerator.GenerateClassNameSimple( typeof(StatementFields), classPostfix); var namespaceScope = new CodegenNamespaceScope( @namespace, statementFieldsClassName, services.IsInstrumented); var fieldsForgable = new StmtClassForgableStmtFields(statementFieldsClassName, namespaceScope, 0); var aiFactoryProviderClassName = CodeGenerationIDGenerator.GenerateClassNameSimple( typeof(StatementAIFactoryProvider), classPostfix); var forge = new StatementAgentInstanceFactoryCreateIndexForge( indexedEventType, spec.IndexName, @base.ModuleName, explicitIndexDesc, imk, namedWindow, table); var aiFactoryForgable = new StmtClassForgableAIFactoryProviderCreateIndex( aiFactoryProviderClassName, namespaceScope, forge); var selectSubscriberDescriptor = new SelectSubscriberDescriptor(); var informationals = StatementInformationalsUtil.GetInformationals( @base, new EmptyList<FilterSpecCompiled>(), new EmptyList<ScheduleHandleCallbackProvider>(), new EmptyList<NamedWindowConsumerStreamSpec>(), true, selectSubscriberDescriptor, namespaceScope, services); var statementProviderClassName = CodeGenerationIDGenerator.GenerateClassNameSimple(typeof(StatementProvider), classPostfix); var stmtProvider = new StmtClassForgableStmtProvider( aiFactoryProviderClassName, statementProviderClassName, informationals, namespaceScope); IList<StmtClassForgable> forgables = new List<StmtClassForgable>(); forgables.Add(fieldsForgable); forgables.Add(aiFactoryForgable); forgables.Add(stmtProvider); return new StmtForgeMethodResult( forgables, new EmptyList<FilterSpecCompiled>(), new EmptyList<ScheduleHandleCallbackProvider>(), new EmptyList<NamedWindowConsumerStreamSpec>(), new EmptyList<FilterSpecParamExprNodeForge>()); }
/// <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 override EPStatementStartResult StartInternal( EPServicesContext services, StatementContext statementContext, bool isNewStatement, bool isRecoveringStatement, bool isRecoveringResilient) { var spec = StatementSpec.CreateIndexDesc; var namedWindowProcessor = services.NamedWindowService.GetProcessor(spec.WindowName); var tableMetadata = services.TableService.GetTableMetadata(spec.WindowName); if (namedWindowProcessor == null && tableMetadata == null) { throw new ExprValidationException("A named window or table by name '" + spec.WindowName + "' does not exist"); } var indexedEventType = namedWindowProcessor != null ? namedWindowProcessor.NamedWindowType : tableMetadata.InternalEventType; var infraContextName = namedWindowProcessor != null ? namedWindowProcessor.ContextName : tableMetadata.ContextName; EPLValidationUtil.ValidateContextName(namedWindowProcessor == null, spec.WindowName, infraContextName, StatementSpec.OptionalContextName, true); // validate index var validated = EventTableIndexUtil.ValidateCompileExplicitIndex(spec.IsUnique, spec.Columns, indexedEventType); var imk = new IndexMultiKey(spec.IsUnique, validated.HashProps, validated.BtreeProps); // for tables we add the index to metadata if (tableMetadata != null) { services.TableService.ValidateAddIndex(statementContext.StatementName, tableMetadata, spec.IndexName, imk); } else { namedWindowProcessor.ValidateAddIndex(statementContext.StatementName, spec.IndexName, imk); } // allocate context factory Viewable viewable = new ViewableDefaultImpl(indexedEventType); var contextFactory = new StatementAgentInstanceFactoryCreateIndex(services, spec, viewable, namedWindowProcessor, tableMetadata == null ? null : tableMetadata.TableName); // provide destroy method which de-registers interest in this index var finalTableService = services.TableService; var finalStatementName = statementContext.StatementName; var destroyMethod = new EPStatementDestroyCallbackList(); if (tableMetadata != null) { destroyMethod.AddCallback(() => finalTableService.RemoveIndexReferencesStmtMayRemoveIndex(finalStatementName, tableMetadata)); } else { destroyMethod.AddCallback(() => namedWindowProcessor.RemoveIndexReferencesStmtMayRemoveIndex(imk, finalStatementName)); } EPStatementStopMethod stopMethod; if (StatementSpec.OptionalContextName != null) { var mergeView = new ContextMergeView(indexedEventType); var statement = new ContextManagedStatementCreateIndexDesc(StatementSpec, statementContext, mergeView, contextFactory); services.ContextManagementService.AddStatement(StatementSpec.OptionalContextName, statement, isRecoveringResilient); stopMethod = () => {}; var contextManagementService = services.ContextManagementService; destroyMethod.AddCallback(() => contextManagementService.DestroyedStatement(StatementSpec.OptionalContextName, statementContext.StatementName, statementContext.StatementId)); } else { var defaultAgentInstanceContext = GetDefaultAgentInstanceContext(statementContext); StatementAgentInstanceFactoryCreateIndexResult result; try { result = (StatementAgentInstanceFactoryCreateIndexResult)contextFactory.NewContext(defaultAgentInstanceContext, false); } catch (EPException ex) { if (ex.InnerException is ExprValidationException) { throw (ExprValidationException)ex.InnerException; } throw; } var stopCallback = result.StopCallback; stopMethod = stopCallback.Invoke; } return(new EPStatementStartResult(viewable, stopMethod, destroyMethod.Destroy)); }