protected override AggregationMethodFactory ValidateAggregationChild(ExprValidationContext validationContext) { const string message = "The nth aggregation function requires two parameters, an expression returning aggregation values and a numeric index constant"; var positionalParams = PositionalParams; if (positionalParams.Length != 2) { throw new ExprValidationException(message); } ExprNode first = positionalParams[0]; ExprNode second = positionalParams[1]; if (!second.IsConstantResult) { throw new ExprValidationException(message); } var num = second.ExprEvaluator.Evaluate(new EvaluateParams(null, true, validationContext.ExprEvaluatorContext)); var size = num.AsInt(); var optionalFilter = OptionalFilter; if (optionalFilter != null) { PositionalParams = ExprNodeUtility.AddExpression(positionalParams, optionalFilter); } return(validationContext.EngineImportService.AggregationFactoryFactory.MakeNth(validationContext.StatementExtensionSvcContext, this, first.ExprEvaluator.ReturnType, size)); }
private LinearAggregationFactoryDesc HandleNonIntoTable( ExprNode[] childNodes, AggregationStateType stateType, ExprValidationContext validationContext) { var streamTypeService = validationContext.StreamTypeService; int streamNum; Type resultType; ExprEvaluator evaluator; ExprNode evaluatorIndex = null; bool istreamOnly; EventType containedType; Type scalarCollectionComponentType = null; // validate wildcard use var isWildcard = childNodes.Length == 0 || childNodes.Length > 0 && childNodes[0] is ExprWildcard; if (isWildcard) { ExprAggMultiFunctionUtil.ValidateWildcardStreamNumbers( validationContext.StreamTypeService, stateType.ToString().ToLowerInvariant()); streamNum = 0; containedType = streamTypeService.EventTypes[0]; resultType = containedType.UnderlyingType; var tableMetadata = validationContext.TableService.GetTableMetadataFromEventType(containedType); evaluator = ExprNodeUtility.MakeUnderlyingEvaluator(0, resultType, tableMetadata); istreamOnly = GetIstreamOnly(streamTypeService, 0); if (stateType == AggregationStateType.WINDOW && istreamOnly && !streamTypeService.IsOnDemandStreams) throw MakeUnboundValidationEx(stateType); } else if (childNodes.Length > 0 && childNodes[0] is ExprStreamUnderlyingNode) { // validate "stream.*" streamNum = ExprAggMultiFunctionUtil.ValidateStreamWildcardGetStreamNum(childNodes[0]); istreamOnly = GetIstreamOnly(streamTypeService, streamNum); if (stateType == AggregationStateType.WINDOW && istreamOnly && !streamTypeService.IsOnDemandStreams) throw MakeUnboundValidationEx(stateType); var type = streamTypeService.EventTypes[streamNum]; containedType = type; resultType = type.UnderlyingType; var tableMetadata = validationContext.TableService.GetTableMetadataFromEventType(type); evaluator = ExprNodeUtility.MakeUnderlyingEvaluator(streamNum, resultType, tableMetadata); } else { // validate when neither wildcard nor "stream.*" var child = childNodes[0]; var streams = ExprNodeUtility.GetIdentStreamNumbers(child); if (streams.IsEmpty() || streams.Count > 1) throw new ExprValidationException(GetErrorPrefix(stateType) + " requires that any child expressions evaluate properties of the same stream; Use 'firstever' or 'lastever' or 'nth' instead"); streamNum = streams.First(); istreamOnly = GetIstreamOnly(streamTypeService, streamNum); if (stateType == AggregationStateType.WINDOW && istreamOnly && !streamTypeService.IsOnDemandStreams) throw MakeUnboundValidationEx(stateType); resultType = childNodes[0].ExprEvaluator.ReturnType; evaluator = childNodes[0].ExprEvaluator; if (streamNum >= streamTypeService.EventTypes.Length) containedType = streamTypeService.EventTypes[0]; else containedType = streamTypeService.EventTypes[streamNum]; scalarCollectionComponentType = resultType; } if (childNodes.Length > 1) { if (stateType == AggregationStateType.WINDOW) throw new ExprValidationException(GetErrorPrefix(stateType) + " does not accept an index expression; Use 'first' or 'last' instead"); evaluatorIndex = childNodes[1]; if (!evaluatorIndex.ExprEvaluator.ReturnType.IsInt32()) { throw new ExprValidationException( GetErrorPrefix(stateType) + " requires an index expression that returns an integer value"); } } // determine accessor AggregationAccessor accessor; if (evaluatorIndex != null) { var isFirst = stateType == AggregationStateType.FIRST; var constant = -1; if (evaluatorIndex.IsConstantResult) constant = evaluatorIndex.ExprEvaluator.Evaluate(EvaluateParams.EmptyTrue).AsInt(); accessor = new AggregationAccessorFirstLastIndexWEval(streamNum, evaluator, evaluatorIndex.ExprEvaluator, constant, isFirst); } else { if (stateType == AggregationStateType.FIRST) accessor = new AggregationAccessorFirstWEval(streamNum, evaluator); else if (stateType == AggregationStateType.LAST) accessor = new AggregationAccessorLastWEval(streamNum, evaluator); else if (stateType == AggregationStateType.WINDOW) accessor = new AggregationAccessorWindowWEval(streamNum, evaluator, resultType); else throw new IllegalStateException("Access type is undefined or not known as code '" + stateType + "'"); } var accessorResultType = resultType; if (stateType == AggregationStateType.WINDOW) accessorResultType = TypeHelper.GetArrayType(resultType); var isFafWindow = streamTypeService.IsOnDemandStreams && stateType == AggregationStateType.WINDOW; var tableMetadataX = validationContext.TableService.GetTableMetadataFromEventType(containedType); var optionalFilter = OptionalFilter; if (tableMetadataX == null && !isFafWindow && (istreamOnly || streamTypeService.IsOnDemandStreams)) { if (optionalFilter != null) PositionalParams = ExprNodeUtility.AddExpression(PositionalParams, optionalFilter); var factory = validationContext.EngineImportService.AggregationFactoryFactory.MakeLinearUnbounded( validationContext.StatementExtensionSvcContext, this, containedType, accessorResultType, streamNum, optionalFilter != null); return new LinearAggregationFactoryDesc(factory, containedType, scalarCollectionComponentType); } var stateKey = new AggregationStateKeyWStream( streamNum, containedType, AggregationStateTypeWStream.DATAWINDOWACCESS_LINEAR, new ExprNode[0], optionalFilter); var optionalFilterEval = optionalFilter?.ExprEvaluator; var stateFactory = validationContext.EngineImportService.AggregationFactoryFactory.MakeLinear( validationContext.StatementExtensionSvcContext, this, streamNum, optionalFilterEval); var factoryX = new ExprAggMultiFunctionLinearAccessNodeFactoryAccess(this, accessor, accessorResultType, containedType, stateKey, stateFactory, AggregationAgentDefault.INSTANCE); var enumerationType = scalarCollectionComponentType == null ? containedType : null; return new LinearAggregationFactoryDesc(factoryX, enumerationType, scalarCollectionComponentType); }
protected override AggregationMethodFactory ValidateAggregationChild(ExprValidationContext validationContext) { var positionalParams = PositionalParams; var parameterTypes = new Type[positionalParams.Length]; var constant = new object[positionalParams.Length]; var isConstant = new bool[positionalParams.Length]; var expressions = new ExprNode[positionalParams.Length]; var count = 0; var hasDataWindows = true; var evaluateParams = new EvaluateParams(null, true, validationContext.ExprEvaluatorContext); foreach (var child in positionalParams) { if (child.IsConstantResult) { isConstant[count] = true; constant[count] = child.ExprEvaluator.Evaluate(evaluateParams); } parameterTypes[count] = child.ExprEvaluator.ReturnType; expressions[count] = child; if (!ExprNodeUtility.HasRemoveStreamForAggregations(child, validationContext.StreamTypeService, validationContext.IsResettingAggregations)) { hasDataWindows = false; } if (child is ExprWildcard) { ExprAggMultiFunctionUtil.CheckWildcardNotJoinOrSubquery(validationContext.StreamTypeService, _functionName); parameterTypes[count] = validationContext.StreamTypeService.EventTypes[0].UnderlyingType; isConstant[count] = false; constant[count] = null; } count++; } IDictionary <string, IList <ExprNode> > namedParameters = null; if (OptionalFilter != null) { namedParameters = new Dictionary <string, IList <ExprNode> >(); namedParameters.Put("filter", Collections.SingletonList(OptionalFilter)); positionalParams = ExprNodeUtility.AddExpression(positionalParams, OptionalFilter); } var context = new AggregationValidationContext(parameterTypes, isConstant, constant, base.IsDistinct, hasDataWindows, expressions, namedParameters); try { // the aggregation function factory is transient, obtain if not provided if (_aggregationFunctionFactory == null) { _aggregationFunctionFactory = validationContext.EngineImportService.ResolveAggregationFactory(_functionName); } _aggregationFunctionFactory.Validate(context); } catch (Exception ex) { throw new ExprValidationException("Plug-in aggregation function '" + _functionName + "' failed validation: " + ex.Message, ex); } Type childType = null; if (positionalParams.Length > 0) { childType = positionalParams[0].ExprEvaluator.ReturnType; } return(validationContext.EngineImportService.AggregationFactoryFactory.MakePlugInMethod(validationContext.StatementExtensionSvcContext, this, _aggregationFunctionFactory, childType)); }