/************************************************************************************** * Copyright (C) 2008 EsperTech, Inc. All rights reserved. * * http://esper.codehaus.org * * http://www.espertech.com * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the GPL license * * a copy of which has been included with this distribution in the license.txt file. * **************************************************************************************/ package com.espertech.esper.epl.expression; import com.espertech.esper.util.JavaClassHelper; import com.espertech.esper.util.CoercionException; import com.espertech.esper.type.RelationalOpEnum; import java.util.Collection; import java.util.Map; /** * Factory for subselect evaluation strategies. */ public class SubselectEvalStrategyFactory { /** * Create a strategy. * @param subselectExpression expression node * @param isNot true if negated * @param isAll true for ALL * @param isAny true for ANY * @param relationalOp relational op, if any * @return strategy * @throws ExprValidationException if expression validation fails */ public static SubselectEvalStrategy createStrategy(ExprSubselectNode subselectExpression, boolean isNot, boolean isAll, boolean isAny, RelationalOpEnum relationalOp) throws ExprValidationException { if (subselectExpression.getChildNodes().size() != 1) { throw new ExprValidationException("The Subselect-IN requires 1 child expression"); } ExprNode valueExpr = subselectExpression.getChildNodes().get(0); // Must be the same boxed type returned by expressions under this Class typeOne = JavaClassHelper.getBoxedType(subselectExpression.getChildNodes().get(0).getExprEvaluator().getType()); // collections, array or map not supported if ((typeOne.isArray()) || (JavaClassHelper.isImplementsInterface(typeOne, Collection.class)) || (JavaClassHelper.isImplementsInterface(typeOne, Map.class))) { throw new ExprValidationException("Collection or array comparison is not allowed for the IN, ANY, SOME or ALL keywords"); } Class typeTwo; if (subselectExpression.getSelectClause() != null) { typeTwo = subselectExpression.getSelectClause()[0].getExprEvaluator().getType(); } else { typeTwo = subselectExpression.getRawEventType().getUnderlyingType(); } if (relationalOp != null) { if ((typeOne != String.class) || (typeTwo != String.class)) { if (!JavaClassHelper.isNumeric(typeOne)) { throw new ExprValidationException("Implicit conversion from datatype '" + typeOne.getSimpleName() + "' to numeric is not allowed"); } if (!JavaClassHelper.isNumeric(typeTwo)) { throw new ExprValidationException("Implicit conversion from datatype '" + typeTwo.getSimpleName() + "' to numeric is not allowed"); } } Class compareType = JavaClassHelper.getCompareToCoercionType(typeOne, typeTwo); RelationalOpEnum.Computer computer = relationalOp.getComputer(compareType, typeOne, typeTwo); ExprEvaluator selectClause = subselectExpression.getSelectClause() == null ? null : subselectExpression.getSelectClause()[0].getExprEvaluator(); ExprEvaluator filterExpr = subselectExpression.getFilterExpr(); if (isAny) { return new SubselectEvalStrategyRelOpAny(computer, valueExpr.getExprEvaluator(),selectClause ,filterExpr); } return new SubselectEvalStrategyRelOpAll(computer, valueExpr.getExprEvaluator(), selectClause, filterExpr); } // Get the common type such as Bool, String or Double and Long Class coercionType; boolean mustCoerce; try { coercionType = JavaClassHelper.getCompareToCoercionType(typeOne, typeTwo); } catch (CoercionException ex) { throw new ExprValidationException("Implicit conversion from datatype '" + typeTwo.getSimpleName() + "' to '" + typeOne.getSimpleName() + "' is not allowed"); } // Check if we need to coerce mustCoerce = false; if ((coercionType != JavaClassHelper.getBoxedType(typeOne)) || (coercionType != JavaClassHelper.getBoxedType(typeTwo))) { if (JavaClassHelper.isNumeric(coercionType)) { mustCoerce = true; } } ExprEvaluator value = valueExpr.getExprEvaluator(); ExprEvaluator select = subselectExpression.getSelectClause() == null ? null : subselectExpression.getSelectClause()[0].getExprEvaluator(); ExprEvaluator filter = subselectExpression.getFilterExpr() == null ? null : subselectExpression.getFilterExpr(); 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); } } }