| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more contributor license |
| * agreements. See the NOTICE file distributed with this work for additional information regarding |
| * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the License. You may obtain a |
| * copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License |
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| * or implied. See the License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package org.apache.geode.cache.query.internal; |
| |
| import static org.assertj.core.api.Assertions.assertThat; |
| import static org.assertj.core.api.Assertions.assertThatCode; |
| import static org.assertj.core.api.Assertions.assertThatThrownBy; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.when; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.SortedMap; |
| import java.util.TreeMap; |
| |
| import junitparams.JUnitParamsRunner; |
| import junitparams.Parameters; |
| import org.junit.Before; |
| import org.junit.Ignore; |
| import org.junit.Test; |
| import org.junit.experimental.categories.Category; |
| import org.junit.runner.RunWith; |
| |
| import org.apache.geode.cache.query.QueryInvalidException; |
| import org.apache.geode.cache.query.internal.parse.OQLLexerTokenTypes; |
| import org.apache.geode.cache.query.security.MethodInvocationAuthorizer; |
| import org.apache.geode.internal.cache.InternalCache; |
| import org.apache.geode.test.junit.categories.OQLQueryTest; |
| |
| @Category(OQLQueryTest.class) |
| @RunWith(JUnitParamsRunner.class) |
| public class QCompilerTest { |
| private QueryExecutionContext context; |
| |
| @Before |
| public void setUp() { |
| InternalCache mockCache = mock(InternalCache.class); |
| when(mockCache.getQueryService()).thenReturn(mock(InternalQueryService.class)); |
| when(mockCache.getQueryService().getMethodInvocationAuthorizer()) |
| .thenReturn(mock(MethodInvocationAuthorizer.class)); |
| |
| context = new QueryExecutionContext(null, mockCache); |
| } |
| |
| @Test |
| public void testStringConditioningForLike_1() { |
| String s1 = "abc%"; |
| StringBuffer buffer = new StringBuffer(s1); |
| CompiledLike cl = new CompiledLike(null, null); |
| int wildCardPosition = cl.checkIfSargableAndRemoveEscapeChars(context, buffer); |
| assertThat(wildCardPosition).isEqualTo(3); |
| assertThat(buffer.toString()).isEqualTo(s1); |
| |
| s1 = "abc\\%abc"; |
| buffer = new StringBuffer(s1); |
| wildCardPosition = cl.checkIfSargableAndRemoveEscapeChars(context, buffer); |
| assertThat(wildCardPosition).isEqualTo(-1); |
| assertThat(buffer.toString()).isEqualTo("abc%abc"); |
| |
| s1 = "abc\\\\%abc"; |
| buffer = new StringBuffer(s1); |
| wildCardPosition = cl.checkIfSargableAndRemoveEscapeChars(context, buffer); |
| assertThat(wildCardPosition).isEqualTo(4); |
| assertThat(buffer.toString()).isEqualTo("abc\\%abc"); |
| |
| s1 = "abc\\\\\\%abc"; |
| buffer = new StringBuffer(s1); |
| wildCardPosition = cl.checkIfSargableAndRemoveEscapeChars(context, buffer); |
| assertThat(wildCardPosition).isEqualTo(-1); |
| assertThat(buffer.toString()).isEqualTo("abc\\%abc"); |
| |
| s1 = "%"; |
| buffer = new StringBuffer(s1); |
| wildCardPosition = cl.checkIfSargableAndRemoveEscapeChars(context, buffer); |
| assertThat(wildCardPosition).isEqualTo(0); |
| assertThat(buffer.toString()).isEqualTo(s1); |
| |
| s1 = "%abc"; |
| buffer = new StringBuffer(s1); |
| wildCardPosition = cl.checkIfSargableAndRemoveEscapeChars(context, buffer); |
| assertThat(wildCardPosition).isEqualTo(0); |
| assertThat(buffer.toString()).isEqualTo("%abc"); |
| |
| s1 = "%%abc"; |
| buffer = new StringBuffer(s1); |
| wildCardPosition = cl.checkIfSargableAndRemoveEscapeChars(context, buffer); |
| assertThat(wildCardPosition).isEqualTo(0); |
| assertThat(buffer.toString()).isEqualTo("%%abc"); |
| |
| s1 = "%\\%abc"; |
| buffer = new StringBuffer(s1); |
| wildCardPosition = cl.checkIfSargableAndRemoveEscapeChars(context, buffer); |
| assertThat(wildCardPosition).isEqualTo(0); |
| assertThat(buffer.toString()).isEqualTo("%\\%abc"); |
| |
| s1 = "_abc"; |
| buffer = new StringBuffer(s1); |
| |
| wildCardPosition = cl.checkIfSargableAndRemoveEscapeChars(context, buffer); |
| assertThat(wildCardPosition).isEqualTo(0); |
| assertThat(buffer.toString()).isEqualTo("_abc"); |
| |
| s1 = "\\_abc"; |
| buffer = new StringBuffer(s1); |
| |
| wildCardPosition = cl.checkIfSargableAndRemoveEscapeChars(context, buffer); |
| assertThat(wildCardPosition).isEqualTo(-1); |
| assertThat(buffer.toString()).isEqualTo("_abc"); |
| |
| s1 = "ab\\%c%d"; |
| buffer = new StringBuffer(s1); |
| |
| wildCardPosition = cl.checkIfSargableAndRemoveEscapeChars(context, buffer); |
| assertThat(wildCardPosition).isEqualTo(4); |
| assertThat(buffer.toString()).isEqualTo("ab%c%d"); |
| |
| s1 = "ab\\__d"; |
| buffer = new StringBuffer(s1); |
| |
| wildCardPosition = cl.checkIfSargableAndRemoveEscapeChars(context, buffer); |
| assertThat(wildCardPosition).isEqualTo(3); |
| assertThat(buffer.toString()).isEqualTo("ab__d"); |
| } |
| |
| @Test |
| public void testSargableRange() { |
| String pattern = "abc"; |
| CompiledLiteral literal = new CompiledLiteral(pattern); |
| CompiledID cid = new CompiledID("val"); |
| CompiledLike cl = new CompiledLike(cid, literal); |
| CompiledComparison[] cc = cl.getRangeIfSargable(context, cid, pattern); |
| assertThat(cc.length).isEqualTo(1); |
| |
| ArrayList cv = (ArrayList) cc[0].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo(pattern); |
| assertThat(cc[0].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_EQ); |
| |
| pattern = "ab%"; |
| literal = new CompiledLiteral(pattern); |
| cl = new CompiledLike(cid, literal); |
| cc = cl.getRangeIfSargable(context, cid, pattern); |
| assertThat(cc.length).isEqualTo(2); |
| |
| cv = (ArrayList) cc[0].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo("ab"); |
| assertThat(cc[0].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_GE); |
| |
| cv = (ArrayList) cc[1].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo("ac"); |
| assertThat(cc[1].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_LT); |
| |
| pattern = "a%c"; |
| literal = new CompiledLiteral(pattern); |
| cl = new CompiledLike(cid, literal); |
| cc = cl.getRangeIfSargable(context, cid, pattern); |
| assertThat(cc.length).isEqualTo(3); |
| |
| cv = (ArrayList) cc[0].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo("a"); |
| assertThat(cc[0].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_GE); |
| |
| cv = (ArrayList) cc[1].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo("b"); |
| assertThat(cc[1].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_LT); |
| |
| assertThat(cc[2]).isEqualTo(cl); |
| |
| pattern = "%bc"; |
| literal = new CompiledLiteral(pattern); |
| cl = new CompiledLike(cid, literal); |
| cc = cl.getRangeIfSargable(context, cid, pattern); |
| assertThat(cc.length).isEqualTo(2); |
| |
| cv = (ArrayList) cc[0].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo(""); |
| assertThat(cc[0].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_GE); |
| |
| assertThat(cc[1]).isEqualTo(cl); |
| |
| pattern = "ab_"; |
| literal = new CompiledLiteral(pattern); |
| cl = new CompiledLike(cid, literal); |
| cc = cl.getRangeIfSargable(context, cid, pattern); |
| assertThat(cc.length).isEqualTo(3); |
| |
| cv = (ArrayList) cc[0].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo("ab"); |
| assertThat(cc[0].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_GE); |
| |
| cv = (ArrayList) cc[1].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo("ac"); |
| assertThat(cc[1].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_LT); |
| |
| assertThat(cc[2]).isEqualTo(cl); |
| |
| pattern = "_bc"; |
| literal = new CompiledLiteral(pattern); |
| cl = new CompiledLike(cid, literal); |
| cc = cl.getRangeIfSargable(context, cid, pattern); |
| assertThat(cc.length).isEqualTo(2); |
| |
| cv = (ArrayList) cc[0].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo(""); |
| assertThat(cc[0].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_GE); |
| |
| assertThat(cc[1]).isEqualTo(cl); |
| |
| pattern = "a_c"; |
| literal = new CompiledLiteral(pattern); |
| cl = new CompiledLike(cid, literal); |
| cc = cl.getRangeIfSargable(context, cid, pattern); |
| assertThat(cc.length).isEqualTo(3); |
| |
| cv = (ArrayList) cc[0].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo("a"); |
| assertThat(cc[0].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_GE); |
| |
| cv = (ArrayList) cc[1].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo("b"); |
| assertThat(cc[1].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_LT); |
| |
| assertThat(cc[2]).isEqualTo(cl); |
| |
| pattern = "_b%"; |
| literal = new CompiledLiteral(pattern); |
| cl = new CompiledLike(cid, literal); |
| cc = cl.getRangeIfSargable(context, cid, pattern); |
| assertThat(cc.length).isEqualTo(2); |
| |
| cv = (ArrayList) cc[0].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo(""); |
| assertThat(cc[0].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_GE); |
| |
| assertThat(cc[1]).isEqualTo(cl); |
| |
| pattern = "a\\%bc"; |
| literal = new CompiledLiteral(pattern); |
| cl = new CompiledLike(cid, literal); |
| cc = cl.getRangeIfSargable(context, cid, pattern); |
| assertThat(cc.length).isEqualTo(1); |
| |
| cv = (ArrayList) cc[0].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo("a%bc"); |
| assertThat(cc[0].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_EQ); |
| |
| pattern = "ab%"; |
| literal = new CompiledLiteral(pattern); |
| cl = new CompiledLike(cid, literal); |
| cl.negate(); |
| cc = cl.getRangeIfSargable(context, cid, pattern); |
| assertThat(cc.length).isEqualTo(2); |
| |
| cv = (ArrayList) cc[0].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo("ab"); |
| assertThat(cc[0].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_GE); |
| |
| cv = (ArrayList) cc[1].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo("ac"); |
| assertThat(cc[1].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_LT); |
| |
| pattern = "a%c"; |
| literal = new CompiledLiteral(pattern); |
| cl = new CompiledLike(cid, literal); |
| cl.negate(); |
| cc = cl.getRangeIfSargable(context, cid, pattern); |
| assertThat(cc.length).isEqualTo(2); |
| |
| cv = (ArrayList) cc[0].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo(""); |
| assertThat(cc[0].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_GE); |
| |
| assertThat(cc[1]).isEqualTo(cl); |
| |
| pattern = "a_"; |
| literal = new CompiledLiteral(pattern); |
| cl = new CompiledLike(cid, literal); |
| cl.negate(); |
| cc = cl.getRangeIfSargable(context, cid, pattern); |
| assertThat(cc.length).isEqualTo(2); |
| |
| cv = (ArrayList) cc[0].getChildren(); |
| assertThat(cv.get(0)).isInstanceOf(CompiledID.class); |
| assertThat(((CompiledID) cv.get(0)).getId()).isEqualTo("val"); |
| assertThat(cv.get(1)).isInstanceOf(CompiledLiteral.class); |
| assertThat(((CompiledLiteral) cv.get(1))._obj).isEqualTo(""); |
| assertThat(cc[0].getOperator()).isEqualTo(OQLLexerTokenTypes.TOK_GE); |
| |
| assertThat(cc[1]).isEqualTo(cl); |
| } |
| |
| /** |
| * This test is no more valid. From 6.6 Like is enhanced to support special chars (% and _) at any |
| * place in the string pattern. With this the Like predicate is not transformed to |
| * compiled-junction with > and < operator. |
| */ |
| @Ignore |
| @Test |
| public void testStringConditioningForLike_2() { |
| CompiledValue var = new CompiledPath(new CompiledID("p"), "ID"); |
| String s1 = "abc%"; |
| CompiledLiteral literal = new CompiledLiteral(s1); |
| QCompiler compiler = new QCompiler(); |
| CompiledValue result = compiler.createCompiledValueForLikePredicate(var, literal); |
| validationHelperForCompiledJunction((CompiledJunction) result, "abc", "abd"); |
| |
| s1 = "abc\\\\%"; |
| literal = new CompiledLiteral(s1); |
| compiler = new QCompiler(); |
| result = compiler.createCompiledValueForLikePredicate(var, literal); |
| validationHelperForCompiledJunction((CompiledJunction) result, "abc\\\\", "abc\\]"); |
| |
| s1 = "abc" + new String(new char[] {(char) 255, '%'}); |
| literal = new CompiledLiteral(s1); |
| compiler = new QCompiler(); |
| result = compiler.createCompiledValueForLikePredicate(var, literal); |
| String lowerBoundKey = "abc" + new String(new char[] {(char) 255}); |
| validationHelperForCompiledJunction((CompiledJunction) result, lowerBoundKey, "abd"); |
| |
| s1 = "abc" |
| + new String(new char[] {(char) 255, (char) 255, (char) 255, (char) 255, (char) 255, '%'}); |
| literal = new CompiledLiteral(s1); |
| compiler = new QCompiler(); |
| result = compiler.createCompiledValueForLikePredicate(var, literal); |
| lowerBoundKey = |
| "abc" + new String(new char[] {(char) 255, (char) 255, (char) 255, (char) 255, (char) 255}); |
| validationHelperForCompiledJunction((CompiledJunction) result, lowerBoundKey, "abd"); |
| |
| s1 = "%"; |
| literal = new CompiledLiteral(s1); |
| compiler = new QCompiler(); |
| result = compiler.createCompiledValueForLikePredicate(var, literal); |
| assertThat(result).isInstanceOf(CompiledComparison.class); |
| CompiledComparison cc = (CompiledComparison) result; |
| assertThat(cc.reflectOnOperator((CompiledValue) cc.getChildren().get(1))) |
| .isEqualTo(OQLLexerTokenTypes.TOK_GE); |
| assertThat(((CompiledLiteral) cc.getChildren().get(1))._obj).isEqualTo(""); |
| } |
| |
| private void validationHelperForCompiledJunction(CompiledJunction result, String lowerBoundKey, |
| String upperBoundKey) { |
| assertThat(result.getOperator()).isEqualTo(OQLLexerTokenTypes.LITERAL_and); |
| List list = result.getChildren(); |
| CompiledComparison lowerBound = (CompiledComparison) list.get(0); |
| CompiledComparison upperBound = (CompiledComparison) list.get(1); |
| assertThat(lowerBound.reflectOnOperator((CompiledValue) lowerBound.getChildren().get(1))) |
| .isEqualTo(OQLLexerTokenTypes.TOK_GE); |
| assertThat(upperBound.reflectOnOperator((CompiledValue) upperBound.getChildren().get(1))) |
| .isEqualTo(OQLLexerTokenTypes.TOK_LT); |
| assertThat(((CompiledLiteral) lowerBound.getChildren().get(1))._obj).isEqualTo(lowerBoundKey); |
| assertThat(((CompiledLiteral) upperBound.getChildren().get(1))._obj).isEqualTo(upperBoundKey); |
| } |
| |
| @Test |
| public void testLowestString() { |
| SortedMap<String, String> map = new TreeMap<>(); |
| map.put("ab", "value"); |
| map.put("z", "value"); |
| map.put("v", "value"); |
| SortedMap returnMap = map.tailMap(CompiledLike.LOWEST_STRING); |
| assertThat(returnMap.size()).isEqualTo(3); |
| } |
| |
| @Test |
| public void testBoundaryChar() { |
| String s1 = "!"; |
| String s2 = "9"; |
| String s3 = "A"; |
| String s4 = "["; |
| String s5 = "a"; |
| String s6 = "{"; |
| String s7 = new String(new char[] {(char) 255}); |
| assertThat(s2.compareTo(s1) > 0).isTrue(); |
| assertThat(s3.compareTo(s2) > 0).isTrue(); |
| assertThat(s4.compareTo(s3) > 0).isTrue(); |
| assertThat(s5.compareTo(s4) > 0).isTrue(); |
| assertThat(s6.compareTo(s5) > 0).isTrue(); |
| assertThat(s7.compareTo(s6) > 0).isTrue(); |
| } |
| |
| @Test |
| @Parameters({"MIN", "MAX", "AVG", "SUM", "COUNT"}) |
| public void parsingShouldSucceedWhenAggregatesAreUsedAsPartOfTheWhereClauseWithinAnInnerSelectQuery( |
| String function) { |
| String[] queries = new String[] { |
| "SELECT * FROM /region WHERE id IN (SELECT " + function + "(id) FROM /region)", |
| "SELECT COUNT(id), status FROM /region WHERE id IN (SELECT " + function |
| + "(id) FROM /region) GROUP BY status", |
| |
| "SELECT * FROM /region WHERE id = ELEMENT(SELECT " + function + "(id) FROM /region)", |
| "SELECT * FROM /region WHERE id < ELEMENT(SELECT " + function + "(id) FROM /region)", |
| "SELECT * FROM /region WHERE id > ELEMENT(SELECT " + function + "(id) FROM /region)", |
| "SELECT * FROM /region WHERE id <> ELEMENT(SELECT " + function + "(id) FROM /region)", |
| |
| "SELECT COUNT(id), status FROM /region WHERE id = ELEMENT(SELECT " + function |
| + "(id) FROM /region) GROUP BY status", |
| "SELECT COUNT(id), status FROM /region WHERE id < ELEMENT(SELECT " + function |
| + "(id) FROM /region) GROUP BY status", |
| "SELECT COUNT(id), status FROM /region WHERE id > ELEMENT(SELECT " + function |
| + "(id) FROM /region) GROUP BY status", |
| "SELECT COUNT(id), status FROM /region WHERE id <> ELEMENT(SELECT " + function |
| + "(id) FROM /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 /region WHERE " + function + "(id) > 0", |
| "SELECT COUNT(id), status FROM /region WHERE " + function + "(id) > 0 GROUP BY status", |
| "SELECT * FROM /region WHERE " + function + "(id) > 0 OR id < 0", |
| "SELECT COUNT(id), status FROM /region WHERE " + function |
| + "(id) > 0 OR id < 0 GROUP BY status", |
| "SELECT * FROM /region WHERE id > 0 AND " + function + "(id) > 0", |
| "SELECT COUNT(id), status FROM /region WHERE id > 0 AND " + function |
| + "(id) > 0 GROUP BY status", |
| "SELECT * FROM /region WHERE " + function + "(id) < ELEMENT(SELECT " + function |
| + "(id) FROM /region)", |
| "SELECT COUNT(id), status FROM /region WHERE " + function + "(id) < ELEMENT(SELECT " |
| + function + "(id) FROM /region) GROUP BY status", |
| "SELECT * FROM /region WHERE id > ELEMENT(SELECT id FROM /region WHERE " + function |
| + "(id) > 0)", |
| "SELECT id, status FROM /region WHERE id > ELEMENT(SELECT id FROM /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"); |
| } |
| } |
| } |