/// <summary>Create a strategy. </summary> /// <param name="subselectExpression">expression node</param> /// <param name="isNot">true if negated</param> /// <param name="isAll">true for ALL</param> /// <param name="isAny">true for ANY</param> /// <param name="relationalOp">relational op, if any</param> /// <returns>strategy</returns> /// <throws>ExprValidationException if expression validation fails</throws> public static SubselectEvalStrategy CreateStrategy(ExprSubselectNode subselectExpression, bool isNot, bool isAll, bool isAny, RelationalOpEnum?relationalOp) { if (subselectExpression.ChildNodes.Length != 1) { throw new ExprValidationException("The Subselect-IN requires 1 child expression"); } ExprNode valueExpr = subselectExpression.ChildNodes[0]; // Must be the same boxed type returned by expressions under this Type typeOne = subselectExpression.ChildNodes[0].ExprEvaluator.ReturnType.GetBoxedType(); // collections, array or map not supported if ((typeOne.IsArray) || (typeOne.IsImplementsInterface(typeof(DataCollection))) || (typeOne.IsImplementsInterface(typeof(DataMap)))) { throw new ExprValidationException("Collection or array comparison is not allowed for the IN, ANY, SOME or ALL keywords"); } var typeTwo = subselectExpression.SelectClause != null ? subselectExpression.SelectClause[0].ExprEvaluator.ReturnType : subselectExpression.RawEventType.UnderlyingType; if (relationalOp != null) { if ((typeOne != typeof(String)) || (typeTwo != typeof(String))) { if (!typeOne.IsNumeric()) { throw new ExprValidationException(string.Format("Implicit conversion from datatype '{0}' to numeric is not allowed", typeOne.FullName)); } if (!typeTwo.IsNumeric()) { throw new ExprValidationException(string.Format("Implicit conversion from datatype '{0}' to numeric is not allowed", typeTwo.FullName)); } } Type compareType = typeOne.GetCompareToCoercionType(typeTwo); RelationalOpEnumExtensions.Computer computer = relationalOp.Value.GetComputer(compareType, typeOne, typeTwo); ExprEvaluator selectClause = subselectExpression.SelectClause == null ? null : subselectExpression.SelectClause[0].ExprEvaluator; ExprEvaluator filterExpr = subselectExpression.FilterExpr; if (isAny) { return(new SubselectEvalStrategyRelOpAny(computer, valueExpr.ExprEvaluator, selectClause, filterExpr)); } return(new SubselectEvalStrategyRelOpAll(computer, valueExpr.ExprEvaluator, selectClause, filterExpr)); } // Get the common type such as Bool, String or Double and Long Type coercionType; try { coercionType = typeOne.GetCompareToCoercionType(typeTwo); } catch (CoercionException) { throw new ExprValidationException(string.Format("Implicit conversion from datatype '{0}' to '{1}' is not allowed", typeTwo.FullName, typeOne.FullName)); } // Check if we need to coerce bool mustCoerce = false; if ((coercionType != typeOne.GetBoxedType()) || (coercionType != typeTwo.GetBoxedType())) { if (coercionType.IsNumeric()) { mustCoerce = true; } } var value = valueExpr.ExprEvaluator; var select = subselectExpression.SelectClause == null ? null : subselectExpression.SelectClause[0].ExprEvaluator; var filter = subselectExpression.FilterExpr; if (isAll) { return(new SubselectEvalStrategyEqualsAll(isNot, mustCoerce, coercionType, value, select, filter)); } else if (isAny) { return(new SubselectEvalStrategyEqualsAny(isNot, mustCoerce, coercionType, value, select, filter)); } else { return(new SubselectEvalStrategyEqualsIn(isNot, mustCoerce, coercionType, value, select, filter)); } }