private static List<StmtClassForgeableFactory> PlanMultikeys( QueryPlanIndexForge[] indexSpecs, StatementRawInfo raw, StatementCompileTimeServices compileTimeServices) { List<StmtClassForgeableFactory> multiKeyForgeables = new List<StmtClassForgeableFactory>(); foreach (QueryPlanIndexForge spec in indexSpecs) { if (spec == null) { continue; } foreach (var entry in spec.Items) { QueryPlanIndexItemForge forge = entry.Value; MultiKeyPlan plan = MultiKeyPlanner.PlanMultiKey( forge.HashTypes, false, raw, compileTimeServices.SerdeResolver); multiKeyForgeables.AddAll(plan.MultiKeyForgeables); forge.HashMultiKeyClasses = plan.ClassRef; DataInputOutputSerdeForge[] rangeSerdes = new DataInputOutputSerdeForge[forge.RangeTypes.Length]; for (int i = 0; i < forge.RangeTypes.Length; i++) { rangeSerdes[i] = compileTimeServices.SerdeResolver.SerdeForIndexBtree(forge.RangeTypes[i], raw); } forge.RangeSerdes = rangeSerdes; } } return multiKeyForgeables; }
public override IList<StmtClassForgeableFactory> InitAdditionalForgeables(ViewForgeEnv viewForgeEnv) { MultiKeyPlan desc = MultiKeyPlanner.PlanMultiKey( criteriaExpressions, false, viewForgeEnv.StatementRawInfo, viewForgeEnv.StatementCompileTimeServices.SerdeResolver); multiKeyClassNames = desc.ClassRef; return desc.MultiKeyForgeables; }
public override IList<StmtClassForgeableFactory> Validate( StreamTypeService typeService, StatementBaseInfo @base, StatementCompileTimeServices services) { int count = 0; ExprValidationContext validationContext = new ExprValidationContextBuilder(typeService, @base.StatementRawInfo, services) .WithAllowBindingConsumption(true) .Build(); ExprNode[] inputParamNodes = new ExprNode[inputParameters.Length]; foreach (string inputParam in inputParameters) { ExprNode raw = FindSQLExpressionNode(StreamNum, count, @base.StatementSpec.Raw.SqlParameters); if (raw == null) { throw new ExprValidationException( "Internal error find expression for historical stream parameter " + count + " stream " + StreamNum); } ExprNode evaluator = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.DATABASEPOLL, raw, validationContext); inputParamNodes[count++] = evaluator; ExprNodeIdentifierCollectVisitor visitor = new ExprNodeIdentifierCollectVisitor(); visitor.Visit(evaluator); foreach (ExprIdentNode identNode in visitor.ExprProperties) { if (identNode.StreamId == StreamNum) { throw new ExprValidationException( "Invalid expression '" + inputParam + "' resolves to the historical data itself"); } SubordinateStreams.Add(identNode.StreamId); } } InputParamEvaluators = ExprNodeUtilityQuery.GetForges(inputParamNodes); // plan multikey MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey(InputParamEvaluators, false, @base.StatementRawInfo, services.SerdeResolver); MultiKeyClassRef = multiKeyPlan.ClassRef; return multiKeyPlan.MultiKeyForgeables; }
public override IList<StmtClassForgeableFactory> Validate( StreamTypeService typeService, StatementBaseInfo @base, StatementCompileTimeServices services) { // validate and visit var validationContext = new ExprValidationContextBuilder(typeService, @base.StatementRawInfo, services) .WithAllowBindingConsumption(true) .Build(); var visitor = new ExprNodeIdentifierAndStreamRefVisitor(true); var validatedInputParameters = new List<ExprNode>(); foreach (var exprNode in methodStreamSpec.Expressions) { var validated = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.METHODINVJOIN, exprNode, validationContext); validatedInputParameters.Add(validated); validated.Accept(visitor); } // determine required streams foreach (ExprNodePropOrStreamDesc @ref in visitor.Refs) { SubordinateStreams.Add(@ref.StreamNum); } // class-based evaluation MethodInfo targetMethod = null; if (metadata.MethodProviderClass != null) { // resolve actual method to use ExprNodeUtilResolveExceptionHandler handler = new ProxyExprNodeUtilResolveExceptionHandler { ProcHandle = e => { if (methodStreamSpec.Expressions.Count == 0) { return new ExprValidationException( "Method footprint does not match the number or type of expression parameters, expecting no parameters in method: " + e.Message); } var resultTypes = ExprNodeUtilityQuery.GetExprResultTypes(validatedInputParameters); return new ExprValidationException( "Method footprint does not match the number or type of expression parameters, expecting a method where parameters are typed '" + TypeHelper.GetParameterAsString(resultTypes) + "': " + e.Message); } }; var desc = ExprNodeUtilityResolve.ResolveMethodAllowWildcardAndStream( metadata.MethodProviderClass.FullName, metadata.IsStaticMethod ? null : metadata.MethodProviderClass, methodStreamSpec.MethodName, validatedInputParameters, false, null, handler, methodStreamSpec.MethodName, @base.StatementRawInfo, services); InputParamEvaluators = desc.ChildForges; targetMethod = desc.ReflectionMethod; } else { // script-based evaluation InputParamEvaluators = ExprNodeUtilityQuery.GetForges(ExprNodeUtilityQuery.ToArray(validatedInputParameters)); } // plan multikey MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey(InputParamEvaluators, false, @base.StatementRawInfo, services.SerdeResolver); MultiKeyClassRef = multiKeyPlan.ClassRef; Pair<MethodTargetStrategyForge, MethodConversionStrategyForge> strategies = PollExecStrategyPlanner.Plan(metadata, targetMethod, EventType); target = strategies.First; conversion = strategies.Second; return multiKeyPlan.MultiKeyForgeables; }
public static SelectExprProcessorDescriptor GetProcessor( SelectProcessorArgs args, InsertIntoDesc insertIntoDesc, bool withSubscriber) { IList<StmtClassForgeableFactory> additionalForgeables = new List<StmtClassForgeableFactory>(); SelectExprProcessorWInsertTarget synthetic = GetProcessorInternal(args, insertIntoDesc); additionalForgeables.AddAll(synthetic.AdditionalForgeables); // plan serdes for variant event types if (synthetic.InsertIntoTargetType is VariantEventType || synthetic.InsertIntoTargetType is WrapperEventType && (((WrapperEventType) synthetic.InsertIntoTargetType).UnderlyingEventType is VariantEventType)) { var serdeForgeables = SerdeEventTypeUtility.Plan( synthetic.Forge.ResultEventType, args.StatementRawInfo, args.CompileTimeServices.SerdeEventTypeRegistry, args.CompileTimeServices.SerdeResolver); additionalForgeables.AddAll(serdeForgeables); foreach (EventType eventType in args.TypeService.EventTypes) { serdeForgeables = SerdeEventTypeUtility.Plan( eventType, args.StatementRawInfo, args.CompileTimeServices.SerdeEventTypeRegistry, args.CompileTimeServices.SerdeResolver); additionalForgeables.AddAll(serdeForgeables); } } if (args.IsFireAndForget || !withSubscriber) { return new SelectExprProcessorDescriptor(new SelectSubscriberDescriptor(), synthetic.Forge, additionalForgeables); } // Handle for-clause delivery contract checking ExprNode[] groupedDeliveryExpr = null; MultiKeyClassRef groupedDeliveryMultiKey = null; var forDelivery = false; if (args.ForClauseSpec != null) { foreach (var item in args.ForClauseSpec.Clauses) { if (item.Keyword == null) { throw new ExprValidationException( "Expected any of the " + EnumHelper.GetValues<ForClauseKeyword>().RenderAny().ToLowerInvariant() + " for-clause keywords after reserved keyword 'for'"); } try { var keyword = EnumHelper.Parse<ForClauseKeyword>(item.Keyword); if (keyword == ForClauseKeyword.GROUPED_DELIVERY && item.Expressions.IsEmpty()) { throw new ExprValidationException( "The for-clause with the " + ForClauseKeyword.GROUPED_DELIVERY.GetName() + " keyword requires one or more grouping expressions"); } if (keyword == ForClauseKeyword.DISCRETE_DELIVERY && !item.Expressions.IsEmpty()) { throw new ExprValidationException( "The for-clause with the " + ForClauseKeyword.DISCRETE_DELIVERY.GetName() + " keyword does not allow grouping expressions"); } if (forDelivery) { throw new ExprValidationException( "The for-clause with delivery keywords may only occur once in a statement"); } } catch (ExprValidationException) { throw; } catch (EPException) { throw; } catch (Exception) { throw new ExprValidationException( "Expected any of the " + EnumHelper.GetValues<ForClauseKeyword>().RenderAny().ToLowerInvariant() + " for-clause keywords after reserved keyword 'for'"); } StreamTypeService type = new StreamTypeServiceImpl(synthetic.Forge.ResultEventType, null, false); groupedDeliveryExpr = new ExprNode[item.Expressions.Count]; var validationContext = new ExprValidationContextBuilder( type, args.StatementRawInfo, args.CompileTimeServices) .WithAllowBindingConsumption(true) .Build(); for (var i = 0; i < item.Expressions.Count; i++) { groupedDeliveryExpr[i] = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.FORCLAUSE, item.Expressions[i], validationContext); } forDelivery = true; MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey( groupedDeliveryExpr, false, args.StatementRawInfo, args.SerdeResolver); groupedDeliveryMultiKey = multiKeyPlan.ClassRef; additionalForgeables = multiKeyPlan.MultiKeyForgeables; } if (groupedDeliveryExpr != null && groupedDeliveryExpr.Length == 0) { groupedDeliveryExpr = null; } } var allowSubscriber = args.CompileTimeServices.Configuration.Compiler.ByteCode.IsAllowSubscriber; SelectSubscriberDescriptor descriptor; SelectExprProcessorForge forge; if (allowSubscriber) { BindProcessorForge bindProcessor = new BindProcessorForge( synthetic.Forge, args.SelectionList, args.TypeService.EventTypes, args.TypeService.StreamNames, args.TableCompileTimeResolver); descriptor = new SelectSubscriberDescriptor( bindProcessor.ExpressionTypes, bindProcessor.ColumnNamesAssigned, forDelivery, groupedDeliveryExpr, groupedDeliveryMultiKey); forge = new BindSelectExprProcessorForge(synthetic.Forge, bindProcessor); } else { descriptor = new SelectSubscriberDescriptor(); forge = new ListenerOnlySelectExprProcessorForge(synthetic.Forge); } return new SelectExprProcessorDescriptor(descriptor, forge, additionalForgeables); }
public static RowRecogPlan ValidateAndPlan( IContainer container, EventType parentEventType, bool unbound, StatementBaseInfo @base, StatementCompileTimeServices services) { var statementRawInfo = @base.StatementRawInfo; var matchRecognizeSpec = @base.StatementSpec.Raw.MatchRecognizeSpec; var annotations = statementRawInfo.Annotations; var iterateOnly = HintEnum.ITERATE_ONLY.GetHint(annotations) != null; var additionalForgeables = new List<StmtClassForgeableFactory>(); // Expanded pattern already there RowRecogExprNode expandedPatternNode = matchRecognizeSpec.Pattern; // Determine single-row and multiple-row variables var variablesSingle = new LinkedHashSet<string>(); var variablesMultiple = new LinkedHashSet<string>(); RowRecogHelper.RecursiveInspectVariables(expandedPatternNode, false, variablesSingle, variablesMultiple); // each variable gets associated with a stream number (multiple-row variables as well to hold the current event for the expression). var streamNum = 0; var variableStreams = new LinkedHashMap<string, Pair<int, bool>>(); foreach (var variableSingle in variablesSingle) { variableStreams.Put(variableSingle, new Pair<int, bool>(streamNum, false)); streamNum++; } foreach (var variableMultiple in variablesMultiple) { variableStreams.Put(variableMultiple, new Pair<int, bool>(streamNum, true)); streamNum++; } // mapping of stream to variable var streamVariables = new OrderedListDictionary<int, string>(); foreach (var entry in variableStreams) { streamVariables.Put(entry.Value.First, entry.Key); } // determine visibility rules var visibility = RowRecogHelper.DetermineVisibility(expandedPatternNode); // assemble all single-row variables for expression validation var allStreamNames = new string[variableStreams.Count]; var allTypes = new EventType[variableStreams.Count]; streamNum = 0; foreach (var variableSingle in variablesSingle) { allStreamNames[streamNum] = variableSingle; allTypes[streamNum] = parentEventType; streamNum++; } foreach (var variableMultiple in variablesMultiple) { allStreamNames[streamNum] = variableMultiple; allTypes[streamNum] = parentEventType; streamNum++; } // determine type service for use with DEFINE // validate each DEFINE clause expression ISet<string> definedVariables = new HashSet<string>(); IList<ExprAggregateNode> aggregateNodes = new List<ExprAggregateNode>(); var isExprRequiresMultimatchState = new bool[variableStreams.Count]; var previousNodes = new OrderedListDictionary<int, IList<ExprPreviousMatchRecognizeNode>>(); for (var defineIndex = 0; defineIndex < matchRecognizeSpec.Defines.Count; defineIndex++) { MatchRecognizeDefineItem defineItem = matchRecognizeSpec.Defines[defineIndex]; if (definedVariables.Contains(defineItem.Identifier)) { throw new ExprValidationException( "Variable '" + defineItem.Identifier + "' has already been defined"); } definedVariables.Add(defineItem.Identifier); // stream-type visibilities handled here var typeServiceDefines = BuildDefineStreamTypeServiceDefine( defineIndex, variableStreams, defineItem, visibility, parentEventType, statementRawInfo, services); var exprNodeResult = HandlePreviousFunctions(defineItem.Expression, previousNodes); var validationContext = new ExprValidationContextBuilder(typeServiceDefines, statementRawInfo, services) .WithAllowBindingConsumption(true) .WithDisablePropertyExpressionEventCollCache(true) .Build(); ExprNode validated; try { // validate validated = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.MATCHRECOGDEFINE, exprNodeResult, validationContext); // check aggregates defineItem.Expression = validated; ExprAggregateNodeUtil.GetAggregatesBottomUp(validated, aggregateNodes); if (!aggregateNodes.IsEmpty()) { throw new ExprValidationException("An aggregate function may not appear in a DEFINE clause"); } } catch (ExprValidationException ex) { throw new ExprValidationException( "Failed to validate condition expression for variable '" + defineItem.Identifier + "': " + ex.Message, ex); } // determine access to event properties from multi-matches var visitor = new ExprNodeStreamRequiredVisitor(); validated.Accept(visitor); var streamsRequired = visitor.StreamsRequired; foreach (var streamRequired in streamsRequired) { if (streamRequired >= variableStreams.Count) { var streamNumIdent = variableStreams.Get(defineItem.Identifier).First; isExprRequiresMultimatchState[streamNumIdent] = true; break; } } } var defineAsksMultimatches = CollectionUtil.IsAnySet(isExprRequiresMultimatchState); // determine type service for use with MEASURE IDictionary<string, object> measureTypeDef = new LinkedHashMap<string, object>(); foreach (var variableSingle in variablesSingle) { measureTypeDef.Put(variableSingle, parentEventType); } foreach (var variableMultiple in variablesMultiple) { measureTypeDef.Put(variableMultiple, new[] {parentEventType}); } var compositeTypeName = services.EventTypeNameGeneratorStatement.AnonymousRowrecogCompositeName; var compositeTypeMetadata = new EventTypeMetadata( compositeTypeName, @base.ModuleName, EventTypeTypeClass.MATCHRECOGDERIVED, EventTypeApplicationType.OBJECTARR, NameAccessModifier.TRANSIENT, EventTypeBusModifier.NONBUS, false, EventTypeIdPair.Unassigned()); var compositeEventType = BaseNestableEventUtil.MakeOATypeCompileTime( compositeTypeMetadata, measureTypeDef, null, null, null, null, services.BeanEventTypeFactoryPrivate, services.EventTypeCompileTimeResolver); services.EventTypeCompileTimeRegistry.NewType(compositeEventType); StreamTypeService compositeTypeServiceMeasure = new StreamTypeServiceImpl(compositeEventType, "MATCH_RECOGNIZE", true); // find MEASURE clause aggregations var measureReferencesMultivar = false; IList<ExprAggregateNode> measureAggregateExprNodes = new List<ExprAggregateNode>(); foreach (var measureItem in matchRecognizeSpec.Measures) { ExprAggregateNodeUtil.GetAggregatesBottomUp(measureItem.Expr, measureAggregateExprNodes); } AggregationServiceForgeDesc[] aggregationServices = null; if (!measureAggregateExprNodes.IsEmpty()) { aggregationServices = PlanAggregations( measureAggregateExprNodes, compositeTypeServiceMeasure, allStreamNames, allTypes, streamVariables, variablesMultiple, @base, services); foreach (AggregationServiceForgeDesc svc in aggregationServices) { if (svc != null) { additionalForgeables.AddAll(svc.AdditionalForgeables); } } } // validate each MEASURE clause expression IDictionary<string, object> rowTypeDef = new LinkedHashMap<string, object>(); var streamRefVisitor = new ExprNodeStreamUseCollectVisitor(); foreach (var measureItem in matchRecognizeSpec.Measures) { if (measureItem.Name == null) { throw new ExprValidationException( "The measures clause requires that each expression utilizes the AS keyword to assign a column name"); } var validated = ValidateMeasureClause( measureItem.Expr, compositeTypeServiceMeasure, variablesMultiple, variablesSingle, statementRawInfo, services); measureItem.Expr = validated; rowTypeDef.Put(measureItem.Name, validated.Forge.EvaluationType); validated.Accept(streamRefVisitor); } // Determine if any of the multi-var streams are referenced in the measures (non-aggregated only) foreach (var @ref in streamRefVisitor.Referenced) { var rootPropName = @ref.RootPropertyNameIfAny; if (rootPropName != null) { if (variablesMultiple.Contains(rootPropName)) { measureReferencesMultivar = true; break; } } var streamRequired = @ref.StreamReferencedIfAny; if (streamRequired != null) { var streamVariable = streamVariables.Get(streamRequired.Value); if (streamVariable != null) { var def = variableStreams.Get(streamVariable); if (def != null && def.Second) { measureReferencesMultivar = true; break; } } } } var collectMultimatches = measureReferencesMultivar || defineAsksMultimatches; // create rowevent type var rowTypeName = services.EventTypeNameGeneratorStatement.AnonymousRowrecogRowName; var rowTypeMetadata = new EventTypeMetadata( rowTypeName, @base.ModuleName, EventTypeTypeClass.MATCHRECOGDERIVED, EventTypeApplicationType.MAP, NameAccessModifier.TRANSIENT, EventTypeBusModifier.NONBUS, false, EventTypeIdPair.Unassigned()); var rowEventType = BaseNestableEventUtil.MakeMapTypeCompileTime( rowTypeMetadata, rowTypeDef, null, null, null, null, services.BeanEventTypeFactoryPrivate, services.EventTypeCompileTimeResolver); services.EventTypeCompileTimeRegistry.NewType(rowEventType); // validate partition-by expressions, if any ExprNode[] partitionBy; MultiKeyClassRef partitionMultiKey; if (!matchRecognizeSpec.PartitionByExpressions.IsEmpty()) { StreamTypeService typeServicePartition = new StreamTypeServiceImpl( parentEventType, "MATCH_RECOGNIZE_PARTITION", true); IList<ExprNode> validated = new List<ExprNode>(); var validationContext = new ExprValidationContextBuilder(typeServicePartition, statementRawInfo, services) .WithAllowBindingConsumption(true) .Build(); foreach (var partitionExpr in matchRecognizeSpec.PartitionByExpressions) { validated.Add( ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.MATCHRECOGPARTITION, partitionExpr, validationContext)); } matchRecognizeSpec.PartitionByExpressions = validated; partitionBy = ExprNodeUtilityQuery.ToArray(validated); MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey(partitionBy, false, @base.StatementRawInfo, services.SerdeResolver); partitionMultiKey = multiKeyPlan.ClassRef; additionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables); } else { partitionBy = null; partitionMultiKey = null; } // validate interval if present if (matchRecognizeSpec.Interval != null) { var validationContext = new ExprValidationContextBuilder(new StreamTypeServiceImpl(false), statementRawInfo, services) .WithAllowBindingConsumption(true) .Build(); var validated = (ExprTimePeriod) ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.MATCHRECOGINTERVAL, matchRecognizeSpec.Interval.TimePeriodExpr, validationContext); matchRecognizeSpec.Interval.TimePeriodExpr = validated; } // compile variable definition expressions IDictionary<string, ExprNode> variableDefinitions = new Dictionary<string, ExprNode>(); foreach (var defineItem in matchRecognizeSpec.Defines) { variableDefinitions.Put(defineItem.Identifier, defineItem.Expression); } // create evaluators var columnNames = new string[matchRecognizeSpec.Measures.Count]; var columnForges = new ExprNode[matchRecognizeSpec.Measures.Count]; var count = 0; foreach (var measureItem in matchRecognizeSpec.Measures) { columnNames[count] = measureItem.Name; columnForges[count] = measureItem.Expr; count++; } // build states var strand = RowRecogHelper.BuildStartStates( expandedPatternNode, variableDefinitions, variableStreams, isExprRequiresMultimatchState); var startStates = strand.StartStates.ToArray(); RowRecogNFAStateForge[] allStates = strand.AllStates.ToArray(); if (Log.IsInfoEnabled) { Log.Info("NFA tree:\n" + RowRecogNFAViewUtil.Print(startStates)); } // determine names of multimatching variables string[] multimatchVariablesArray; int[] multimatchStreamNumToVariable; int[] multimatchVariableToStreamNum; if (variablesSingle.Count == variableStreams.Count) { multimatchVariablesArray = new string[0]; multimatchStreamNumToVariable = new int[0]; multimatchVariableToStreamNum = new int[0]; } else { multimatchVariablesArray = new string[variableStreams.Count - variablesSingle.Count]; multimatchVariableToStreamNum = new int[multimatchVariablesArray.Length]; multimatchStreamNumToVariable = new int[variableStreams.Count]; CompatExtensions.Fill(multimatchStreamNumToVariable, -1); count = 0; foreach (var entry in variableStreams) { if (entry.Value.Second) { var index = count; multimatchVariablesArray[index] = entry.Key; multimatchVariableToStreamNum[index] = entry.Value.First; multimatchStreamNumToVariable[entry.Value.First] = index; count++; } } } var numEventsEventsPerStreamDefine = defineAsksMultimatches ? variableStreams.Count + 1 : variableStreams.Count; // determine interval-or-terminated var orTerminated = matchRecognizeSpec.Interval != null && matchRecognizeSpec.Interval.IsOrTerminated; TimePeriodComputeForge intervalCompute = null; if (matchRecognizeSpec.Interval != null) { intervalCompute = matchRecognizeSpec.Interval.TimePeriodExpr.TimePeriodComputeForge; } EventType multimatchEventType = null; if (defineAsksMultimatches) { multimatchEventType = GetDefineMultimatchEventType(variableStreams, parentEventType, @base, services); } // determine previous-access indexes and assign "prev" node indexes // Since an expression such as "prior(2, price), prior(8, price)" translates into {2, 8} the relative index is {0, 1}. // Map the expression-supplied index to a relative index int[] previousRandomAccessIndexes = null; if (!previousNodes.IsEmpty()) { previousRandomAccessIndexes = new int[previousNodes.Count]; var countPrev = 0; foreach (var entry in previousNodes) { previousRandomAccessIndexes[countPrev] = entry.Key; foreach (var callback in entry.Value) { callback.AssignedIndex = countPrev; } countPrev++; } } RowRecogDescForge forge = new RowRecogDescForge( parentEventType, rowEventType, compositeEventType, multimatchEventType, multimatchStreamNumToVariable, multimatchVariableToStreamNum, partitionBy, partitionMultiKey, variableStreams, matchRecognizeSpec.Interval != null, iterateOnly, unbound, orTerminated, collectMultimatches, defineAsksMultimatches, numEventsEventsPerStreamDefine, multimatchVariablesArray, startStates, allStates, matchRecognizeSpec.IsAllMatches, matchRecognizeSpec.Skip.Skip, columnForges, columnNames, intervalCompute, previousRandomAccessIndexes, aggregationServices); return new RowRecogPlan(forge, additionalForgeables); }
private IList<StmtClassForgeableFactory> ValidateContextDetail( ContextSpec contextSpec, int nestingLevel, CreateContextValidationEnv validationEnv) { ISet<string> eventTypesReferenced = new HashSet<string>(); IList<StmtClassForgeableFactory> additionalForgeables = new List<StmtClassForgeableFactory>(); if (contextSpec is ContextSpecKeyed) { var segmented = (ContextSpecKeyed) contextSpec; IDictionary<string, EventType> asNames = new Dictionary<string, EventType>(); var partitionHasNameAssignment = false; Type[] getterTypes = null; foreach (var partition in segmented.Items) { Pair<FilterSpecCompiled, IList<StmtClassForgeableFactory>> pair = CompilePartitionedFilterSpec( partition.FilterSpecRaw, eventTypesReferenced, validationEnv); FilterSpecCompiled filterSpecCompiled = pair.First; additionalForgeables.AddAll(pair.Second); partition.FilterSpecCompiled = filterSpecCompiled; var getters = new EventPropertyGetterSPI[partition.PropertyNames.Count]; var serdes = new DataInputOutputSerdeForge[partition.PropertyNames.Count]; var eventType = (EventTypeSPI) filterSpecCompiled.FilterForEventType; getterTypes = new Type[partition.PropertyNames.Count]; for (var i = 0; i < partition.PropertyNames.Count; i++) { var propertyName = partition.PropertyNames[i]; var getter = eventType.GetGetterSPI(propertyName); if (getter == null) { throw new ExprValidationException( "For context '" + validationEnv.ContextName + "' property name '" + propertyName + "' not found on type " + eventType.Name); } getters[i] = getter; getterTypes[i] = eventType.GetPropertyType(propertyName); serdes[i] = validationEnv.Services.SerdeResolver.SerdeForFilter( getterTypes[i], validationEnv.StatementRawInfo); } partition.Getters = getters; partition.LookupableSerdes = serdes; if (partition.AliasName != null) { partitionHasNameAssignment = true; ValidateAsName(asNames, partition.AliasName, filterSpecCompiled.FilterForEventType); } } // plan multi-key, make sure we use the same multikey for all items MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey( getterTypes, false, @base.StatementRawInfo, validationEnv.Services.SerdeResolver); additionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables); foreach (ContextSpecKeyedItem partition in segmented.Items) { partition.KeyMultiKey = multiKeyPlan.ClassRef; } segmented.MultiKeyClassRef = multiKeyPlan.ClassRef; if (segmented.OptionalInit != null) { asNames.Clear(); foreach (var initCondition in segmented.OptionalInit) { ContextDetailMatchPair pair = ValidateRewriteContextCondition( true, nestingLevel, initCondition, eventTypesReferenced, new MatchEventSpec(), new EmptySet<string>(), validationEnv); additionalForgeables.AddAll(pair.AdditionalForgeables); var filterForType = initCondition.FilterSpecCompiled.FilterForEventType; var found = false; foreach (var partition in segmented.Items) { if (partition.FilterSpecCompiled.FilterForEventType == filterForType) { found = true; break; } } if (!found) { throw new ExprValidationException( "Segmented context '" + validationEnv.ContextName + "' requires that all of the event types that are listed in the initialized-by also appear in the partition-by, type '" + filterForType.Name + "' is not one of the types listed in partition-by"); } if (initCondition.OptionalFilterAsName != null) { if (partitionHasNameAssignment) { throw new ExprValidationException( "Segmented context '" + validationEnv.ContextName + "' requires that either partition-by or initialized-by assign stream names, but not both"); } ValidateAsName(asNames, initCondition.OptionalFilterAsName, filterForType); } } } if (segmented.OptionalTermination != null) { var matchEventSpec = new MatchEventSpec(); var allTags = new LinkedHashSet<string>(); foreach (var partition in segmented.Items) { if (partition.AliasName != null) { allTags.Add(partition.AliasName); var eventType = partition.FilterSpecCompiled.FilterForEventType; matchEventSpec.TaggedEventTypes[partition.AliasName] = new Pair<EventType,string>( eventType, partition.FilterSpecRaw.EventTypeName); var serdeForgeables = SerdeEventTypeUtility.Plan( eventType, validationEnv.StatementRawInfo, validationEnv.Services.SerdeEventTypeRegistry, validationEnv.Services.SerdeResolver); additionalForgeables.AddAll(serdeForgeables); } } if (segmented.OptionalInit != null) { foreach (var initCondition in segmented.OptionalInit) { if (initCondition.OptionalFilterAsName != null) { allTags.Add(initCondition.OptionalFilterAsName); matchEventSpec.TaggedEventTypes.Put( initCondition.OptionalFilterAsName, new Pair<EventType, string>( initCondition.FilterSpecCompiled.FilterForEventType, initCondition.FilterSpecRaw.EventTypeName)); } } } var endCondition = ValidateRewriteContextCondition( false, nestingLevel, segmented.OptionalTermination, eventTypesReferenced, matchEventSpec, allTags, validationEnv); additionalForgeables.AddAll(endCondition.AdditionalForgeables); segmented.OptionalTermination = endCondition.Condition; } } else if (contextSpec is ContextSpecCategory) { // compile filter var category = (ContextSpecCategory) contextSpec; ValidateNotTable(category.FilterSpecRaw.EventTypeName, validationEnv.Services); var raw = new FilterStreamSpecRaw( category.FilterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, StreamSpecOptions.DEFAULT); var compiledDesc = StreamSpecCompiler.CompileFilter( raw, false, false, true, false, null, validationEnv.StatementRawInfo, validationEnv.Services); var result = (FilterStreamSpecCompiled) compiledDesc.StreamSpecCompiled; additionalForgeables.AddAll(compiledDesc.AdditionalForgeables); category.FilterSpecCompiled = result.FilterSpecCompiled; validationEnv.FilterSpecCompileds.Add(result.FilterSpecCompiled); // compile expressions foreach (var item in category.Items) { ValidateNotTable(category.FilterSpecRaw.EventTypeName, validationEnv.Services); var filterSpecRaw = new FilterSpecRaw( category.FilterSpecRaw.EventTypeName, Collections.SingletonList(item.Expression), null); var rawExpr = new FilterStreamSpecRaw( filterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, StreamSpecOptions.DEFAULT); var compiledDescItems = StreamSpecCompiler.CompileFilter( rawExpr, false, false, true, false, null, validationEnv.StatementRawInfo, validationEnv.Services); var compiled = (FilterStreamSpecCompiled) compiledDescItems.StreamSpecCompiled; additionalForgeables.AddAll(compiledDescItems.AdditionalForgeables); compiled.FilterSpecCompiled.TraverseFilterBooleanExpr( node => validationEnv.FilterBooleanExpressions.Add(node)); item.FilterPlan = compiled.FilterSpecCompiled.Parameters; } } else if (contextSpec is ContextSpecHash) { var hashed = (ContextSpecHash) contextSpec; foreach (var hashItem in hashed.Items) { var raw = new FilterStreamSpecRaw( hashItem.FilterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, StreamSpecOptions.DEFAULT); ValidateNotTable(hashItem.FilterSpecRaw.EventTypeName, validationEnv.Services); var compiledDesc = StreamSpecCompiler.Compile( raw, eventTypesReferenced, false, false, true, false, null, 0, validationEnv.StatementRawInfo, validationEnv.Services); additionalForgeables.AddAll(compiledDesc.AdditionalForgeables); var result = (FilterStreamSpecCompiled) compiledDesc.StreamSpecCompiled; validationEnv.FilterSpecCompileds.Add(result.FilterSpecCompiled); hashItem.FilterSpecCompiled = result.FilterSpecCompiled; // validate parameters var streamTypes = new StreamTypeServiceImpl( result.FilterSpecCompiled.FilterForEventType, null, true); var validationContext = new ExprValidationContextBuilder( streamTypes, validationEnv.StatementRawInfo, validationEnv.Services) .WithIsFilterExpression(true) .Build(); ExprNodeUtilityValidate.Validate( ExprNodeOrigin.CONTEXT, Collections.SingletonList(hashItem.Function), validationContext); } } else if (contextSpec is ContextSpecInitiatedTerminated) { var def = (ContextSpecInitiatedTerminated) contextSpec; var startCondition = ValidateRewriteContextCondition( true, nestingLevel, def.StartCondition, eventTypesReferenced, new MatchEventSpec(), new LinkedHashSet<string>(), validationEnv); additionalForgeables.AddAll(startCondition.AdditionalForgeables); var endCondition = ValidateRewriteContextCondition( false, nestingLevel, def.EndCondition, eventTypesReferenced, startCondition.Matches, startCondition.AllTags, validationEnv); additionalForgeables.AddAll(endCondition.AdditionalForgeables); def.StartCondition = startCondition.Condition; def.EndCondition = endCondition.Condition; if (def.DistinctExpressions != null) { if (!(startCondition.Condition is ContextSpecConditionFilter)) { throw new ExprValidationException( "Distinct-expressions require a stream as the initiated-by condition"); } var distinctExpressions = def.DistinctExpressions; if (distinctExpressions.Length == 0) { throw new ExprValidationException("Distinct-expressions have not been provided"); } var filter = (ContextSpecConditionFilter) startCondition.Condition; if (filter.OptionalFilterAsName == null) { throw new ExprValidationException( "Distinct-expressions require that a stream name is assigned to the stream using 'as'"); } var types = new StreamTypeServiceImpl( filter.FilterSpecCompiled.FilterForEventType, filter.OptionalFilterAsName, true); var validationContext = new ExprValidationContextBuilder(types, validationEnv.StatementRawInfo, validationEnv.Services) .WithAllowBindingConsumption(true) .Build(); for (var i = 0; i < distinctExpressions.Length; i++) { ExprNodeUtilityValidate.ValidatePlainExpression( ExprNodeOrigin.CONTEXTDISTINCT, distinctExpressions[i]); distinctExpressions[i] = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.CONTEXTDISTINCT, distinctExpressions[i], validationContext); } var multiKeyPlan = MultiKeyPlanner.PlanMultiKey( distinctExpressions, false, @base.StatementRawInfo, validationEnv.Services.SerdeResolver); def.DistinctMultiKey = multiKeyPlan.ClassRef; additionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables); } } else if (contextSpec is ContextNested) { var nested = (ContextNested) contextSpec; var level = 0; ISet<string> namesUsed = new HashSet<string>(); namesUsed.Add(validationEnv.ContextName); foreach (var nestedContext in nested.Contexts) { if (namesUsed.Contains(nestedContext.ContextName)) { throw new ExprValidationException( "Context by name '" + nestedContext.ContextName + "' has already been declared within nested context '" + validationEnv.ContextName + "'"); } namesUsed.Add(nestedContext.ContextName); var forgeables = ValidateContextDetail(nestedContext.ContextDetail, level, validationEnv); additionalForgeables.AddAll(forgeables); level++; } } else { throw new IllegalStateException("Unrecognized context detail " + contextSpec); } return additionalForgeables; }
// Obtain those method and state factories for each level private static AggregationGroupByLocalGroupLevelDesc GetLevel( int levelNumber, AggregationGroupByLocalGroupLevel level, ExprForge[][] methodForgesAll, AggregationForgeFactory[] methodFactoriesAll, AggregationStateFactoryForge[] accessForges, AggregationLocalGroupByColumnForge[] columns, bool defaultLevel, AggregationAccessorSlotPairForge[] accessors, ExprNode[] groupByExpressions, MultiKeyClassRef optionalGroupByMultiKey, StatementRawInfo raw, SerdeCompileTimeResolver serdeResolver) { var partitionExpr = level.PartitionExpr; MultiKeyPlan multiKeyPlan; if (defaultLevel && optionalGroupByMultiKey != null) { // use default multi-key that is already generated multiKeyPlan = new MultiKeyPlan(EmptyList<StmtClassForgeableFactory>.Instance, optionalGroupByMultiKey); partitionExpr = groupByExpressions; } else { multiKeyPlan = MultiKeyPlanner.PlanMultiKey(partitionExpr, false, raw, serdeResolver); } IList<ExprForge[]> methodForges = new List<ExprForge[]>(); IList<AggregationForgeFactory> methodFactories = new List<AggregationForgeFactory>(); IList<AggregationStateFactoryForge> stateFactories = new List<AggregationStateFactoryForge>(); foreach (var expr in level.Expressions) { int column = expr.AggregationNode.Column; var methodOffset = -1; var methodAgg = true; AggregationAccessorSlotPairForge pair = null; if (column < methodForgesAll.Length) { methodForges.Add(methodForgesAll[column]); methodFactories.Add(methodFactoriesAll[column]); methodOffset = methodFactories.Count - 1; } else { // slot gives us the number of the state factory int absoluteSlot = accessors[column - methodForgesAll.Length].Slot; AggregationAccessorForge accessor = accessors[column - methodForgesAll.Length].AccessorForge; var factory = accessForges[absoluteSlot]; var relativeSlot = stateFactories.IndexOf(factory); if (relativeSlot == -1) { stateFactories.Add(factory); relativeSlot = stateFactories.Count - 1; } methodAgg = false; pair = new AggregationAccessorSlotPairForge(relativeSlot, accessor); } columns[column] = new AggregationLocalGroupByColumnForge( defaultLevel, partitionExpr, methodOffset, methodAgg, pair, levelNumber); } var forge = new AggregationLocalGroupByLevelForge( methodForges.ToArray(), methodFactories.ToArray(), stateFactories.ToArray(), partitionExpr, multiKeyPlan.ClassRef, defaultLevel); // NOTE: The original code tests for multiKeyPlan being null, but if it was null it would have caused // a null pointer exception on the previous statement since it dereferences ClassRef. var additionalForgeables = multiKeyPlan?.MultiKeyForgeables ?? EmptyList<StmtClassForgeableFactory>.Instance; return new AggregationGroupByLocalGroupLevelDesc(forge, additionalForgeables); }
/// <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 static OutputProcessViewFactoryForgeDesc Make( EventType[] typesPerStream, EventType resultEventType, ResultSetProcessorType resultSetProcessorType, StatementSpecCompiled statementSpec, StatementRawInfo statementRawInfo, StatementCompileTimeServices services) { InsertIntoDesc insertIntoDesc = statementSpec.Raw.InsertIntoDesc; SelectClauseStreamSelectorEnum selectStreamSelector = statementSpec.Raw.SelectStreamSelectorEnum; OutputLimitSpec outputLimitSpec = statementSpec.Raw.OutputLimitSpec; int streamCount = statementSpec.StreamSpecs.Length; bool isDistinct = statementSpec.Raw.SelectClauseSpec.IsDistinct; bool isGrouped = statementSpec.GroupByExpressions != null && statementSpec.GroupByExpressions.GroupByNodes.Length > 0; List<StmtClassForgeableFactory> additionalForgeables = new List<StmtClassForgeableFactory>(); // determine routing bool isRouted = false; bool routeToFront = false; if (insertIntoDesc != null) { isRouted = true; routeToFront = services.NamedWindowCompileTimeResolver.Resolve(insertIntoDesc.EventTypeName) != null; } OutputStrategyPostProcessForge outputStrategyPostProcessForge = null; if ((insertIntoDesc != null) || (selectStreamSelector == SelectClauseStreamSelectorEnum.RSTREAM_ONLY)) { SelectClauseStreamSelectorEnum? insertIntoStreamSelector = null; TableMetaData table = null; if (insertIntoDesc != null) { insertIntoStreamSelector = insertIntoDesc.StreamSelector; table = services.TableCompileTimeResolver.Resolve(statementSpec.Raw.InsertIntoDesc.EventTypeName); if (table != null) { EPLValidationUtil.ValidateContextName( true, table.TableName, table.OptionalContextName, statementSpec.Raw.OptionalContextName, true); } } bool audit = AuditEnum.INSERT.GetAudit(statementSpec.Annotations) != null; outputStrategyPostProcessForge = new OutputStrategyPostProcessForge( isRouted, insertIntoStreamSelector, selectStreamSelector, routeToFront, table, audit); } MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKeyDistinct( isDistinct, resultEventType, statementRawInfo, SerdeCompileTimeResolverNonHA.INSTANCE); MultiKeyClassRef distinctMultiKey = multiKeyPlan.ClassRef; additionalForgeables.AddRange(multiKeyPlan.MultiKeyForgeables); OutputProcessViewFactoryForge outputProcessViewFactoryForge; if (outputLimitSpec == null) { if (!isDistinct) { if (outputStrategyPostProcessForge == null || !outputStrategyPostProcessForge.HasTable) { // without table we have a shortcut implementation outputProcessViewFactoryForge = new OutputProcessViewDirectSimpleForge(outputStrategyPostProcessForge); } else { outputProcessViewFactoryForge = new OutputProcessViewDirectForge(outputStrategyPostProcessForge); } } else { outputProcessViewFactoryForge = new OutputProcessViewDirectDistinctOrAfterFactoryForge( outputStrategyPostProcessForge, isDistinct, distinctMultiKey, null, null, resultEventType); } } else if (outputLimitSpec.RateType == OutputLimitRateType.AFTER) { outputProcessViewFactoryForge = new OutputProcessViewDirectDistinctOrAfterFactoryForge( outputStrategyPostProcessForge, isDistinct, distinctMultiKey, outputLimitSpec.AfterTimePeriodExpr, outputLimitSpec.AfterNumberOfEvents, resultEventType); } else { try { bool isWithHavingClause = statementSpec.Raw.HavingClause != null; bool isStartConditionOnCreation = HasOnlyTables(statementSpec.StreamSpecs); OutputConditionFactoryForge outputConditionFactoryForge = OutputConditionFactoryFactory.CreateCondition( outputLimitSpec, isGrouped, isWithHavingClause, isStartConditionOnCreation, statementRawInfo, services); bool hasOrderBy = statementSpec.Raw.OrderByList != null && statementSpec.Raw.OrderByList.Count > 0; bool hasAfter = outputLimitSpec.AfterNumberOfEvents != null || outputLimitSpec.AfterTimePeriodExpr != null; // hint checking with order-by bool hasOptHint = ResultSetProcessorOutputConditionTypeExtensions .GetOutputLimitOpt(statementSpec.Annotations, services.Configuration, hasOrderBy); ResultSetProcessorOutputConditionType conditionType = ResultSetProcessorOutputConditionTypeExtensions .GetConditionType( outputLimitSpec.DisplayLimit, resultSetProcessorType.IsAggregated(), hasOrderBy, hasOptHint, resultSetProcessorType.IsGrouped()); // plan serdes foreach (EventType eventType in typesPerStream) { IList<StmtClassForgeableFactory> serdeForgeables = SerdeEventTypeUtility.Plan( eventType, statementRawInfo, services.SerdeEventTypeRegistry, services.SerdeResolver); additionalForgeables.AddRange(serdeForgeables); } bool terminable = outputLimitSpec.RateType == OutputLimitRateType.TERM || outputLimitSpec.IsAndAfterTerminate; outputProcessViewFactoryForge = new OutputProcessViewConditionForge( outputStrategyPostProcessForge, isDistinct, distinctMultiKey, outputLimitSpec.AfterTimePeriodExpr, outputLimitSpec.AfterNumberOfEvents, outputConditionFactoryForge, streamCount, conditionType, terminable, hasAfter, resultSetProcessorType.IsUnaggregatedUngrouped(), selectStreamSelector, typesPerStream, resultEventType); } catch (Exception ex) { throw new ExprValidationException("Failed to validate the output rate limiting clause: " + ex.Message, ex); } } return new OutputProcessViewFactoryForgeDesc(outputProcessViewFactoryForge, 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; } }
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); }
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()); } // determine multikey plan MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey( explicitIndexDesc.HashTypes, false, _base.StatementRawInfo, services.SerdeResolver); explicitIndexDesc.HashMultiKeyClasses = multiKeyPlan.ClassRef; DataInputOutputSerdeForge[] rangeSerdes = new DataInputOutputSerdeForge[explicitIndexDesc.RangeProps.Length]; for (int i = 0; i < explicitIndexDesc.RangeProps.Length; i++) { rangeSerdes[i] = services.SerdeResolver.SerdeForIndexBtree( explicitIndexDesc.RangeTypes[i], _base.StatementRawInfo); } explicitIndexDesc.RangeSerdes = rangeSerdes; var statementFieldsClassName = CodeGenerationIDGenerator.GenerateClassNameSimple( typeof(StatementFields), classPostfix); var namespaceScope = new CodegenNamespaceScope( @namespace, statementFieldsClassName, services.IsInstrumented); var fieldsForgeable = new StmtClassForgeableStmtFields(statementFieldsClassName, namespaceScope, 0); var aiFactoryProviderClassName = CodeGenerationIDGenerator.GenerateClassNameSimple( typeof(StatementAIFactoryProvider), classPostfix); var forge = new StatementAgentInstanceFactoryCreateIndexForge( indexedEventType, spec.IndexName, _base.ModuleName, explicitIndexDesc, imk, namedWindow, table); var aiFactoryForgeable = new StmtClassForgeableAIFactoryProviderCreateIndex( aiFactoryProviderClassName, namespaceScope, forge); var selectSubscriberDescriptor = new SelectSubscriberDescriptor(); var informationals = StatementInformationalsUtil.GetInformationals( _base, EmptyList<FilterSpecCompiled>.Instance, EmptyList<ScheduleHandleCallbackProvider>.Instance, EmptyList<NamedWindowConsumerStreamSpec>.Instance, true, selectSubscriberDescriptor, namespaceScope, services); informationals.Properties.Put(StatementProperty.CREATEOBJECTNAME, spec.IndexName); var statementProviderClassName = CodeGenerationIDGenerator.GenerateClassNameSimple(typeof(StatementProvider), classPostfix); var stmtProvider = new StmtClassForgeableStmtProvider( aiFactoryProviderClassName, statementProviderClassName, informationals, namespaceScope); var forgeables = new List<StmtClassForgeable>(); foreach (var additional in multiKeyPlan.MultiKeyForgeables) { forgeables.Add(additional.Make(namespaceScope, classPostfix)); } forgeables.Add(fieldsForgeable); forgeables.Add(aiFactoryForgeable); forgeables.Add(stmtProvider); return new StmtForgeMethodResult( forgeables, EmptyList<FilterSpecCompiled>.Instance, EmptyList<ScheduleHandleCallbackProvider>.Instance, EmptyList<NamedWindowConsumerStreamSpec>.Instance, EmptyList<FilterSpecParamExprNodeForge>.Instance); }