/**
* Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com)
*
* Licensed 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 com.linkedin.pinot.pql.parsers;
import com.linkedin.pinot.common.request.FilterOperator;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.linkedin.pinot.common.request.BrokerRequest;
import com.linkedin.pinot.common.request.GroupBy;
import com.linkedin.pinot.pql.parsers.pql2.ast.TopAstNode;
/**
* Some tests for the PQL 2 compiler.
*/
public class Pql2CompilerTest {
@Test
public void testQuotedStrings() {
Pql2Compiler compiler = new Pql2Compiler();
// Two single quotes in a single quoted string
BrokerRequest brokerRequest = compiler.compileToBrokerRequest(
"select * from vegetables where origin = 'Martha''s Vineyard'");
Assert.assertEquals(brokerRequest.getFilterQuery().getValue().get(0), "Martha's Vineyard");
brokerRequest = compiler.compileToBrokerRequest(
"select * from vegetables where origin = 'Martha\"\"s Vineyard'");
Assert.assertEquals(brokerRequest.getFilterQuery().getValue().get(0), "Martha\"\"s Vineyard");
brokerRequest = compiler.compileToBrokerRequest(
"select * from vegetables where origin = \"Martha\"\"s Vineyard\"");
Assert.assertEquals(brokerRequest.getFilterQuery().getValue().get(0), "Martha\"s Vineyard");
brokerRequest = compiler.compileToBrokerRequest(
"select * from vegetables where origin = \"Martha''s Vineyard\"");
Assert.assertEquals(brokerRequest.getFilterQuery().getValue().get(0), "Martha''s Vineyard");
}
@Test
public void testDuplicateClauses() {
Pql2Compiler compiler = new Pql2Compiler();
assertCompilationFails(compiler, "select top 5 count(*) from a top 8");
assertCompilationFails(compiler, "select count(*) from a where a = 1 limit 5 where b = 2");
assertCompilationFails(compiler, "select count(*) from a group by b limit 5 group by b");
assertCompilationFails(compiler, "select count(*) from a having sum(a) = 8 limit 5 having sum(a) = 9");
assertCompilationFails(compiler, "select count(*) from a order by b limit 5 order by c");
assertCompilationFails(compiler, "select count(*) from a limit 5 limit 5");
}
@Test
public void testTopZero() throws Exception {
Pql2Compiler compiler = new Pql2Compiler();
testTopZeroFor(compiler, "select count(*) from someTable where c = 5 group by X top 0", TopAstNode.DEFAULT_TOP_N, false);
testTopZeroFor(compiler, "select count(*) from someTable where c = 5 group by X top 1", 1, false);
testTopZeroFor(compiler, "select count(*) from someTable where c = 5 group by X top -1", TopAstNode.DEFAULT_TOP_N, true);
}
private void assertCompilationFails(Pql2Compiler compiler, String query) {
try {
compiler.compileToBrokerRequest(query);
} catch (Pql2CompilationException e) {
// Expected
return;
}
Assert.fail("Query " + query + " compiled successfully but was expected to fail compilation");
}
private void testTopZeroFor(Pql2Compiler compiler, String s, final int expectedTopN, boolean parseException) throws Exception {
BrokerRequest req;
try {
req = compiler.compileToBrokerRequest(s);
} catch (Pql2CompilationException e) {
if (parseException) {
return;
}
throw e;
}
Assert.assertTrue(req.isSetGroupBy());
GroupBy groupBy = req.getGroupBy();
Assert.assertTrue(groupBy.isSetTopN());
Assert.assertEquals(expectedTopN, groupBy.getTopN());
}
@Test
public void testRejectInvalidLexerToken() {
assertCompilationFails(new Pql2Compiler(), "select foo from bar where baz ?= 2");
assertCompilationFails(new Pql2Compiler(), "select foo from bar where baz =! 2");
}
@Test
public void testRejectInvalidParses() {
assertCompilationFails(new Pql2Compiler(), "select foo from bar where baz < > 2");
assertCompilationFails(new Pql2Compiler(), "select foo from bar where baz ! = 2");
}
@Test
public void testParseExceptionHasCharacterPosition() {
Pql2Compiler compiler = new Pql2Compiler();
final String query = "select foo from bar where baz ? 2";
try {
compiler.compileToBrokerRequest(query);
} catch (Pql2CompilationException e) {
// Expected
Assert.assertTrue(e.getMessage().startsWith("1:30: "), "Compilation exception should contain line and character for error message. Error message is " + e.getMessage());
return;
}
Assert.fail("Query " + query + " compiled successfully but was expected to fail compilation");
}
@Test
public void testCStyleInequalityOperator() {
Pql2Compiler compiler = new Pql2Compiler();
BrokerRequest brokerRequest = compiler.compileToBrokerRequest(
"select * from vegetables where name != 'Brussels sprouts'");
Assert.assertEquals(brokerRequest.getFilterQuery().getOperator(), FilterOperator.NOT);
}
}