QCompiler implements OQLLexerTokenTypes { public CompiledValue compileQuery(String oqlSource) { try { OQLLexer lexer = new OQLLexer(new StringReader(oqlSource)); OQLParser parser = new OQLParser(lexer); parser.setASTNodeClass("org.apache.geode.cache.query.internal.parse.ASTUnsupported"); parser.queryProgram(); GemFireAST n = (GemFireAST) parser.getAST(); n.compile(this); } catch (Exception ex) { throw new QueryInvalidException( String.format("Syntax error in query: %s", ex.getMessage()), ex); } Assert.assertTrue(stackSize() == 1, "stack size = " + stackSize()); return (CompiledValue) pop(); } QCompiler();  QCompiler(boolean isForIndexCompilation); CompiledValue compileQuery(String oqlSource); List compileFromClause(String fromClause); List compileProjectionAttributes(String projectionAttributes); void compileOrederByClause(int numOfChildren); void compileGroupByClause(int numOfChildren); void compileSortCriteria(String sortCriterion); void compileLimit(String limitNum); void compileImports(String imports); void select(Map<Integer, Object> queryComponents); void projection(); void aggregateFunction(CompiledValue expr, int aggFuncType, boolean distinctOnly); void iteratorDef(); void undefinedExpr(boolean is_defined); void function(int function, int numOfChildren); void inExpr(); void constructObject(Class clazz); void pushId(String id); void pushRegion(String regionPath); void appendPathComponent(String id); void pushBindArgument(int i); void pushLiteral(Object obj); void pushNull(); void combine(int num); void methodInvocation(); void indexOp(); void like(); void compare(int opKind); void mod(); void arithmetic(int opKind); void or(int numTerms); void and(int numTerms); void not(); void unaryMinus(); void typecast(); ObjectType assembleType(); void traceRequest(); boolean isTraceRequested(); void setHint(int numOfChildren); void setHintIdentifier(String text); void importName(String qualifiedName, String asName); Object pop(); void push(Object obj); int stackSize(); ObjectType resolveType(String typeName);  }
@Test @Parameters({"MIN", "MAX", "AVG", "SUM", "COUNT"}) public void parsingShouldSucceedWhenAggregatesAreUsedAsPartOfTheWhereClauseWithinAnInnerSelectQuery( String function) { String[] queries = new String[] { "SELECT * FROM " + SEPARATOR + "region WHERE id IN (SELECT " + function + "(id) FROM " + SEPARATOR + "region)", "SELECT COUNT(id), status FROM " + SEPARATOR + "region WHERE id IN (SELECT " + function + "(id) FROM " + SEPARATOR + "region) GROUP BY status", "SELECT * FROM " + SEPARATOR + "region WHERE id = ELEMENT(SELECT " + function + "(id) FROM " + SEPARATOR + "region)", "SELECT * FROM " + SEPARATOR + "region WHERE id < ELEMENT(SELECT " + function + "(id) FROM " + SEPARATOR + "region)", "SELECT * FROM " + SEPARATOR + "region WHERE id > ELEMENT(SELECT " + function + "(id) FROM " + SEPARATOR + "region)", "SELECT * FROM " + SEPARATOR + "region WHERE id <> ELEMENT(SELECT " + function + "(id) FROM " + SEPARATOR + "region)", "SELECT COUNT(id), status FROM " + SEPARATOR + "region WHERE id = ELEMENT(SELECT " + function + "(id) FROM " + SEPARATOR + "region) GROUP BY status", "SELECT COUNT(id), status FROM " + SEPARATOR + "region WHERE id < ELEMENT(SELECT " + function + "(id) FROM " + SEPARATOR + "region) GROUP BY status", "SELECT COUNT(id), status FROM " + SEPARATOR + "region WHERE id > ELEMENT(SELECT " + function + "(id) FROM " + SEPARATOR + "region) GROUP BY status", "SELECT COUNT(id), status FROM " + SEPARATOR + "region WHERE id <> ELEMENT(SELECT " + function + "(id) FROM " + SEPARATOR + "region) GROUP BY status", }; for (String queryString : queries) { QCompiler compiler = new QCompiler(); assertThatCode(() -> compiler.compileQuery(queryString)) .as(String.format("Query parsing failed for %s but should have succeeded.", queryString)) .doesNotThrowAnyException(); } }
@Test @Parameters({"MIN", "MAX", "AVG", "SUM", "COUNT"}) public void parsingShouldThrowExceptionWhenAggregatesAreUsedAsPartOfTheWhereClauseWithoutAnInnerSelectQuery( String function) { String[] queries = new String[] { "SELECT * FROM " + SEPARATOR + "region WHERE " + function + "(id) > 0", "SELECT COUNT(id), status FROM " + SEPARATOR + "region WHERE " + function + "(id) > 0 GROUP BY status", "SELECT * FROM " + SEPARATOR + "region WHERE " + function + "(id) > 0 OR id < 0", "SELECT COUNT(id), status FROM " + SEPARATOR + "region WHERE " + function + "(id) > 0 OR id < 0 GROUP BY status", "SELECT * FROM " + SEPARATOR + "region WHERE id > 0 AND " + function + "(id) > 0", "SELECT COUNT(id), status FROM " + SEPARATOR + "region WHERE id > 0 AND " + function + "(id) > 0 GROUP BY status", "SELECT * FROM " + SEPARATOR + "region WHERE " + function + "(id) < ELEMENT(SELECT " + function + "(id) FROM " + SEPARATOR + "region)", "SELECT COUNT(id), status FROM " + SEPARATOR + "region WHERE " + function + "(id) < ELEMENT(SELECT " + function + "(id) FROM " + SEPARATOR + "region) GROUP BY status", "SELECT * FROM " + SEPARATOR + "region WHERE id > ELEMENT(SELECT id FROM " + SEPARATOR + "region WHERE " + function + "(id) > 0)", "SELECT id, status FROM " + SEPARATOR + "region WHERE id > ELEMENT(SELECT id FROM " + SEPARATOR + "region WHERE " + function + "(id) > 0)" }; for (String queryString : queries) { QCompiler compiler = new QCompiler(); assertThatThrownBy(() -> compiler.compileQuery(queryString)) .as(String.format("Query parsing succeeded for %s but should have failed.", queryString)) .isInstanceOf(QueryInvalidException.class) .hasMessageContaining("Aggregate functions can not be used as part of the WHERE clause"); } }