internal static FilterSpecParamForge HandleInSetNode( ExprInNode constituent, IDictionary <string, Pair <EventType, string> > taggedEventTypes, IDictionary <string, Pair <EventType, string> > arrayEventTypes, ISet <string> allTagNamesOrdered, StatementRawInfo raw, StatementCompileTimeServices services) { var left = constituent.ChildNodes[0]; ExprFilterSpecLookupableForge lookupable = null; if (left is ExprFilterOptimizableNode) { var filterOptimizableNode = (ExprFilterOptimizableNode)left; lookupable = filterOptimizableNode.FilterLookupable; } else if (FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.LKUPCOMPOSITE, raw, services) && IsLimitedLookupableExpression(left)) { lookupable = MakeLimitedLookupableForgeMayNull(left, raw, services); } if (lookupable == null) { return(null); } var op = FilterOperator.IN_LIST_OF_VALUES; if (constituent.IsNotIn) { op = FilterOperator.NOT_IN_LIST_OF_VALUES; } var expectedNumberOfConstants = constituent.ChildNodes.Length - 1; IList <FilterSpecParamInValueForge> listofValues = new List <FilterSpecParamInValueForge>(); var it = Arrays.AsList(constituent.ChildNodes).GetEnumerator(); it.MoveNext(); // ignore the first node as it's the identifier while (it.MoveNext()) { var subNode = it.Current; if (subNode.Forge.ForgeConstantType.IsCompileTimeConstant) { var constant = subNode.Forge.ExprEvaluator.Evaluate(null, true, null); if (constant is ICollection <object> ) { return(null); } if (constant is IDictionary <object, object> ) { return(null); } if ((constant != null) && (constant is Array arrayConstant)) { for (var i = 0; i < arrayConstant.Length; i++) { var arrayElement = arrayConstant.GetValue(i); var arrayElementCoerced = HandleConstantsCoercion(lookupable, arrayElement); listofValues.Add(new FilterForEvalConstantAnyTypeForge(arrayElementCoerced)); if (i > 0) { expectedNumberOfConstants++; } } } else { constant = HandleConstantsCoercion(lookupable, constant); listofValues.Add(new FilterForEvalConstantAnyTypeForge(constant)); } } else if (subNode is ExprContextPropertyNode) { var contextPropertyNode = (ExprContextPropertyNode)subNode; var returnType = contextPropertyNode.Type; Coercer coercer; if (TypeHelper.IsCollectionMapOrArray(returnType)) { CheckArrayCoercion(returnType, lookupable.ReturnType, lookupable.Expression); coercer = null; } else { coercer = GetNumberCoercer(left.Forge.EvaluationType, contextPropertyNode.Type, lookupable.Expression); } var finalReturnType = coercer != null ? coercer.ReturnType : returnType; listofValues.Add(new FilterForEvalContextPropForge(contextPropertyNode.PropertyName, contextPropertyNode.Getter, coercer, finalReturnType)); } else if (subNode.Forge.ForgeConstantType.IsDeployTimeTimeConstant && subNode is ExprNodeDeployTimeConst) { var deployTimeConst = (ExprNodeDeployTimeConst)subNode; var returnType = subNode.Forge.EvaluationType; Coercer coercer; if (TypeHelper.IsCollectionMapOrArray(returnType)) { CheckArrayCoercion(returnType, lookupable.ReturnType, lookupable.Expression); coercer = null; } else { coercer = GetNumberCoercer(left.Forge.EvaluationType, returnType, lookupable.Expression); } listofValues.Add(new FilterForEvalDeployTimeConstForge(deployTimeConst, coercer, returnType)); } else if (subNode is ExprIdentNode) { var identNodeInner = (ExprIdentNode)subNode; if (identNodeInner.StreamId == 0) { break; // for same event evals use the boolean expression, via count compare failing below } var isMustCoerce = false; var coerceToType = Boxing.GetBoxedType(lookupable.ReturnType); var identReturnType = identNodeInner.Forge.EvaluationType; if (TypeHelper.IsCollectionMapOrArray(identReturnType)) { CheckArrayCoercion(identReturnType, lookupable.ReturnType, lookupable.Expression); coerceToType = identReturnType; // no action } else if (identReturnType != lookupable.ReturnType) { if (TypeHelper.IsNumeric(lookupable.ReturnType)) { if (!TypeHelper.CanCoerce(identReturnType, lookupable.ReturnType)) { ThrowConversionError(identReturnType, lookupable.ReturnType, lookupable.Expression); } isMustCoerce = true; } else { break; // assumed not compatible } } FilterSpecParamInValueForge inValue; var streamName = identNodeInner.ResolvedStreamName; if (arrayEventTypes != null && !arrayEventTypes.IsEmpty() && arrayEventTypes.ContainsKey(streamName)) { var indexAndProp = GetStreamIndex(identNodeInner.ResolvedPropertyName); var innerEventType = GetArrayInnerEventType(arrayEventTypes, streamName); inValue = new FilterForEvalEventPropIndexedForge( identNodeInner.ResolvedStreamName, indexAndProp.First, indexAndProp.Second, innerEventType, isMustCoerce, coerceToType); } else { inValue = new FilterForEvalEventPropForge( identNodeInner.ResolvedStreamName, identNodeInner.ResolvedPropertyName, identNodeInner.ExprEvaluatorIdent, isMustCoerce, coerceToType); } listofValues.Add(inValue); } else if (FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.VALUECOMPOSITE, raw, services) && IsLimitedValueExpression(subNode)) { var convertor = GetMatchEventConvertor(subNode, taggedEventTypes, arrayEventTypes, allTagNamesOrdered); var valueType = subNode.Forge.EvaluationType; var lookupableType = lookupable.ReturnType; var numberCoercer = GetNumberCoercer(lookupableType, valueType, lookupable.Expression); var forge = new FilterForEvalLimitedExprForge(subNode, convertor, numberCoercer); listofValues.Add(forge); } } // Fallback if not all values in the in-node can be resolved to properties or constants if (listofValues.Count == expectedNumberOfConstants) { return(new FilterSpecParamInForge(lookupable, op, listofValues)); } return(null); }
private static FilterSpecParamForge HandleInSetNode( ExprInNode constituent, IDictionary<string, Pair<EventType, string>> arrayEventTypes) { var left = constituent.ChildNodes[0]; if (!(left is ExprFilterOptimizableNode)) { return null; } var filterOptimizableNode = (ExprFilterOptimizableNode) left; var lookupable = filterOptimizableNode.FilterLookupable; var op = FilterOperator.IN_LIST_OF_VALUES; if (constituent.IsNotIn) { op = FilterOperator.NOT_IN_LIST_OF_VALUES; } var expectedNumberOfConstants = constituent.ChildNodes.Length - 1; IList<FilterSpecParamInValueForge> listofValues = new List<FilterSpecParamInValueForge>(); using (var enumerator = Arrays.AsList(constituent.ChildNodes).GetEnumerator()) { enumerator.MoveNext(); // ignore the first node as it's the identifier while (enumerator.MoveNext()) { var subNode = enumerator.Current; if (subNode.Forge.ForgeConstantType.IsCompileTimeConstant) { var constant = subNode.Forge.ExprEvaluator.Evaluate(null, true, null); if (constant != null) { if (constant.GetType().IsGenericCollection()) { return null; } if (constant.GetType().IsGenericDictionary()) { return null; } } if (constant != null && constant is Array constantArray) { for (var i = 0; i < constantArray.Length; i++) { object arrayElement = constantArray.GetValue(i); var arrayElementCoerced = HandleConstantsCoercion(lookupable, arrayElement); listofValues.Add(new FilterForEvalConstantAnyTypeForge(arrayElementCoerced)); if (i > 0) { expectedNumberOfConstants++; } } } else { constant = HandleConstantsCoercion(lookupable, constant); listofValues.Add(new FilterForEvalConstantAnyTypeForge(constant)); } } else if (subNode is ExprContextPropertyNode) { var contextPropertyNode = (ExprContextPropertyNode) subNode; var returnType = contextPropertyNode.Type; Coercer coercer; if (returnType.IsCollectionMapOrArray()) { CheckArrayCoercion(returnType, lookupable.ReturnType, lookupable.Expression); coercer = null; } else { coercer = GetNumberCoercer( left.Forge.EvaluationType, contextPropertyNode.Type, lookupable.Expression); } var finalReturnType = coercer != null ? coercer.ReturnType : returnType; listofValues.Add( new FilterForEvalContextPropForge( contextPropertyNode.PropertyName, contextPropertyNode.Getter, coercer, finalReturnType)); } else if (subNode.Forge.ForgeConstantType.IsDeployTimeTimeConstant && subNode is ExprNodeDeployTimeConst) { var deployTimeConst = (ExprNodeDeployTimeConst) subNode; var returnType = subNode.Forge.EvaluationType; Coercer coercer; if (returnType.IsCollectionMapOrArray()) { CheckArrayCoercion(returnType, lookupable.ReturnType, lookupable.Expression); coercer = null; } else { coercer = GetNumberCoercer(left.Forge.EvaluationType, returnType, lookupable.Expression); } listofValues.Add(new FilterForEvalDeployTimeConstForge(deployTimeConst, coercer, returnType)); } if (subNode is ExprIdentNode) { var identNodeInner = (ExprIdentNode) subNode; if (identNodeInner.StreamId == 0) { break; // for same event evals use the boolean expression, via count compare failing below } var isMustCoerce = false; var coerceToType = lookupable.ReturnType.GetBoxedType(); var identReturnType = identNodeInner.Forge.EvaluationType; if (identReturnType.IsCollectionMapOrArray()) { CheckArrayCoercion(identReturnType, lookupable.ReturnType, lookupable.Expression); coerceToType = identReturnType; // no action } else if (identReturnType != lookupable.ReturnType) { if (lookupable.ReturnType.IsNumeric()) { if (!identReturnType.CanCoerce(lookupable.ReturnType)) { ThrowConversionError(identReturnType, lookupable.ReturnType, lookupable.Expression); } isMustCoerce = true; } else { break; // assumed not compatible } } FilterSpecParamInValueForge inValue; var streamName = identNodeInner.ResolvedStreamName; if (arrayEventTypes != null && !arrayEventTypes.IsEmpty() && arrayEventTypes.ContainsKey(streamName)) { var indexAndProp = GetStreamIndex(identNodeInner.ResolvedPropertyName); var innerEventType = GetArrayInnerEventType(arrayEventTypes, streamName); inValue = new FilterForEvalEventPropIndexedForge( identNodeInner.ResolvedStreamName, indexAndProp.First, indexAndProp.Second, innerEventType, isMustCoerce, coerceToType); } else { inValue = new FilterForEvalEventPropForge( identNodeInner.ResolvedStreamName, identNodeInner.ResolvedPropertyName, identNodeInner.ExprEvaluatorIdent, isMustCoerce, coerceToType); } listofValues.Add(inValue); } } } // Fallback if not all values in the in-node can be resolved to properties or constants if (listofValues.Count == expectedNumberOfConstants) { return new FilterSpecParamInForge(lookupable, op, listofValues); } return null; }