diff --git a/parser/pom.xml b/parser/pom.xml
index 8af6dc0..3fead4f 100644
--- a/parser/pom.xml
+++ b/parser/pom.xml
@@ -30,6 +30,36 @@
testng
test
+
+
+ javax.validation
+ validation-api
+
+
+
+ com.facebook.airlift
+ configuration
+
+
+
+ com.facebook.airlift
+ log
+
+
+
+ com.facebook.airlift
+ bootstrap
+
+
+
+ com.google.inject
+ guice
+
+
+
+ com.google.guava
+ guava
+
diff --git a/parser/src/test/java/com/facebook/coresql/parser/TestSqlParser.java b/parser/src/test/java/com/facebook/coresql/parser/TestSqlParser.java
index 60cf8f3..eafe051 100644
--- a/parser/src/test/java/com/facebook/coresql/parser/TestSqlParser.java
+++ b/parser/src/test/java/com/facebook/coresql/parser/TestSqlParser.java
@@ -13,8 +13,11 @@
*/
package com.facebook.coresql.parser;
+import com.facebook.coresql.parser.sqllogictest.java.SqlLogicTest;
import org.testng.annotations.Test;
+import java.io.IOException;
+
import static com.facebook.coresql.parser.ParserHelper.parseStatement;
import static com.facebook.coresql.parser.Unparser.unparse;
import static org.testng.Assert.assertEquals;
@@ -66,4 +69,11 @@ public void parseUnparseTest()
assertEquals(sql.trim(), unparse(ast).trim());
}
}
+
+ @Test
+ public void sqlLogicTest()
+ throws IOException
+ {
+ SqlLogicTest.execute();
+ }
}
diff --git a/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/java/SqlLogicTest.java b/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/java/SqlLogicTest.java
new file mode 100644
index 0000000..c8cdfe9
--- /dev/null
+++ b/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/java/SqlLogicTest.java
@@ -0,0 +1,339 @@
+/*
+ * 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.facebook.coresql.parser.sqllogictest.java;
+
+import com.facebook.airlift.bootstrap.Bootstrap;
+import com.facebook.airlift.log.Logger;
+import com.facebook.coresql.parser.AstNode;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import static com.facebook.coresql.parser.ParserHelper.parseStatement;
+import static com.facebook.coresql.parser.Unparser.unparse;
+import static com.facebook.coresql.parser.sqllogictest.java.SqlLogicTest.CoreSqlParsingError.PARSING_ERROR;
+import static com.facebook.coresql.parser.sqllogictest.java.SqlLogicTest.CoreSqlParsingError.UNPARSED_DOES_NOT_MATCH_ORIGINAL_ERROR;
+import static com.facebook.coresql.parser.sqllogictest.java.SqlLogicTest.CoreSqlParsingError.UNPARSING_ERROR;
+import static com.facebook.coresql.parser.sqllogictest.java.SqlLogicTest.DatabaseDialect.ALL;
+import static java.lang.Math.min;
+import static java.nio.file.FileVisitResult.CONTINUE;
+import static java.nio.file.FileVisitResult.TERMINATE;
+import static java.nio.file.Files.createFile;
+import static java.nio.file.Files.isHidden;
+import static java.nio.file.Files.readAllLines;
+import static java.nio.file.Files.walkFileTree;
+import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.toList;
+
+public final class SqlLogicTest
+{
+ private static final String NAME_OF_RESULT_FILE = "sqllogictest_result.txt";
+ private static final Logger LOG = Logger.get(SqlLogicTest.class);
+
+ private final SqlLogicTestResult result;
+ private final FileVisitor fileVisitor;
+ private final Path testFilesRootPath;
+ private final Path resultPath;
+ private final DatabaseDialect databaseDialect;
+ private final int maxNumFilesToVisit;
+
+ enum CoreSqlParsingError
+ {
+ PARSING_ERROR,
+ UNPARSING_ERROR,
+ UNPARSED_DOES_NOT_MATCH_ORIGINAL_ERROR
+ }
+
+ enum DatabaseDialect
+ {
+ ALL,
+ ORACLE,
+ MYSQL,
+ MSSQL,
+ SQLITE,
+ POSTGRESQL
+ }
+
+ @Inject
+ public SqlLogicTest(SqlLogicTestConfig config)
+ {
+ this.testFilesRootPath = requireNonNull(config.getTestFilesRootPath(), "test files root path is null");
+ this.resultPath = requireNonNull(config.getResultPath(), "result path is null");
+ this.databaseDialect = requireNonNull(config.getDatabaseDialect(), "database dialect is null");
+ this.result = new SqlLogicTestResult(config.getDatabaseDialect());
+ this.fileVisitor = new SqlLogicTestFileVisitor();
+ this.maxNumFilesToVisit = config.getMaxNumFilesToVisit();
+ }
+
+ public static void execute()
+ throws IOException
+ {
+ Bootstrap app = new Bootstrap(new SqlLogicTestModule());
+
+ Injector injector = app
+ .doNotInitializeLogging()
+ .quiet()
+ .initialize();
+
+ injector.getInstance(SqlLogicTest.class).run();
+ }
+
+ private void run()
+ throws IOException
+ {
+ createFileForResult(resultPath);
+ walkFileTree(testFilesRootPath, fileVisitor);
+ writeTestResultToFile(result, resultPath);
+ }
+
+ private static void createFileForResult(Path resultPath)
+ throws IOException
+ {
+ try {
+ createFile(resultPath.resolve(NAME_OF_RESULT_FILE));
+ }
+ catch (FileAlreadyExistsException e) {
+ LOG.info("Result file already exists. We'll overwrite it with the new result.");
+ }
+ catch (IOException e) {
+ throw new IOException("Could not create the sqllogictest result file.", e);
+ }
+ }
+
+ private Optional checkStatementForParserError(String statement)
+ {
+ Optional ast = Optional.ofNullable(parseStatement(statement));
+ if (!ast.isPresent()) {
+ return Optional.of(PARSING_ERROR);
+ }
+ String unparsed;
+ try {
+ unparsed = unparse(ast.get());
+ }
+ catch (Exception e) {
+ return Optional.of(UNPARSING_ERROR);
+ }
+ if (!statement.trim().equals(unparsed.trim())) {
+ return Optional.of(UNPARSED_DOES_NOT_MATCH_ORIGINAL_ERROR);
+ }
+ return Optional.empty();
+ }
+
+ private static void writeTestResultToFile(SqlLogicTestResult result, Path resultPath)
+ {
+ try (PrintWriter writer = new PrintWriter(resultPath.resolve(NAME_OF_RESULT_FILE).toString())) {
+ for (SqlLogicTestStatement statement : result.getErroneousStatements()) {
+ writer.print(statement.getStatement() + " ----> " + statement.getError().get().name());
+ writer.println();
+ writer.println();
+ }
+ writer.println("===============================================");
+ writer.println("RESULT");
+ writer.println("===============================================");
+ writer.printf("Database dialect tested against: %s", result.getDatabaseDialect());
+ writer.println();
+ writer.printf("%d statements found, %d statements successfully parsed.", result.getNumStatementsFound(), result.getNumStatementsParsed());
+ writer.println();
+ writer.printf("%s%% of sqllogictest statements were successfully parsed.",
+ new DecimalFormat("#.##").format(result.getNumStatementsParsed() / (double) result.getNumStatementsFound() * 100));
+ }
+ catch (FileNotFoundException e) {
+ LOG.error(e, "Could not find the result file at the given location");
+ }
+ }
+
+ private boolean isLineBeforeStatement(String line)
+ {
+ return line.startsWith("statement ok") || line.startsWith("query");
+ }
+
+ private boolean statementIsAcceptableToCurrDialect(SqlLogicTestStatement sqlLogicTestStatement)
+ {
+ if (databaseDialect == ALL) {
+ return sqlLogicTestStatement.getSkipIfSet().isEmpty() && !sqlLogicTestStatement.getCurrStatementsOnlyIfDialect().isPresent();
+ }
+ if (sqlLogicTestStatement.getCurrStatementsOnlyIfDialect().isPresent() && sqlLogicTestStatement.getCurrStatementsOnlyIfDialect().get() != databaseDialect) {
+ return false;
+ }
+ return !sqlLogicTestStatement.getSkipIfSet().contains(databaseDialect);
+ }
+
+ private boolean isConditionalRecordLine(String line)
+ {
+ String[] splitLine = line.split(" ");
+ if (splitLine.length <= 1) {
+ return false;
+ }
+ String conditionalFlag = splitLine[0];
+ if (!conditionalFlag.equals("skipif") && !conditionalFlag.equals("onlyif")) {
+ return false;
+ }
+ String potentialDialect = splitLine[1];
+ try {
+ DatabaseDialect.valueOf(potentialDialect.toUpperCase());
+ }
+ catch (IllegalArgumentException e) {
+ LOG.debug("This line had a skip-if or only-if dialect that isn't supported: %s", line);
+ return false;
+ }
+ return true;
+ }
+
+ private void processConditionalRecordLine(String line, SqlLogicTestStatement.Builder builder)
+ {
+ String[] splitLine = line.split(" ");
+ if (splitLine.length <= 1) {
+ return;
+ }
+ String potentialDialect = splitLine[1];
+ DatabaseDialect dialect = DatabaseDialect.valueOf(potentialDialect.toUpperCase());
+ if (line.startsWith("onlyif")) {
+ builder.setOnlyIfDialect(dialect);
+ }
+ else if (line.startsWith("skipif")) {
+ builder.addDialectToSkipIfSet(dialect);
+ }
+ }
+
+ private static String getCleanedUpStatement(StringBuilder statement)
+ {
+ statement = new StringBuilder(statement.toString().trim());
+ if (statement.length() > 0 && !statement.toString().endsWith(";")) {
+ statement.append(";"); // This semi-colon is necessary for parsing.
+ }
+ return statement.toString();
+ }
+
+ private int getStartingIndexOfNextStatement(int currIdx, List statements)
+ {
+ while (currIdx < statements.size() && !statements.get(currIdx).equals("")) {
+ ++currIdx;
+ }
+ return currIdx;
+ }
+
+ private int getIndexOfNextDelimiter(int currIdx, List statements)
+ {
+ while (currIdx < statements.size() && !statements.get(currIdx).equals("----")) {
+ ++currIdx;
+ }
+ return currIdx;
+ }
+
+ private List> getListOfStatementsAsLines(List linesFromFile)
+ {
+ List> statementsAsListsOfLines = new ArrayList<>();
+ int currIdx = 0;
+ while (currIdx < linesFromFile.size()) {
+ if (isConditionalRecordLine(linesFromFile.get(currIdx)) || isLineBeforeStatement(linesFromFile.get(currIdx))) {
+ int startingIdxOfNextStatement = getStartingIndexOfNextStatement(currIdx, linesFromFile);
+ int endOfCurrStatement = min(startingIdxOfNextStatement, getIndexOfNextDelimiter(currIdx, linesFromFile));
+ statementsAsListsOfLines.add(linesFromFile.subList(currIdx, endOfCurrStatement));
+ currIdx = startingIdxOfNextStatement;
+ }
+ else {
+ ++currIdx;
+ }
+ }
+ return statementsAsListsOfLines;
+ }
+
+ private SqlLogicTestStatement buildSqlLogicTestStatementFromLines(List statementAsListsOfLines)
+ {
+ SqlLogicTestStatement.Builder builder = SqlLogicTestStatement.builder();
+ StringBuilder statement = new StringBuilder();
+ for (String line : statementAsListsOfLines) {
+ if (isConditionalRecordLine(line)) {
+ processConditionalRecordLine(line, builder);
+ }
+ else if (!isLineBeforeStatement(line)) {
+ statement.append(line);
+ }
+ }
+ String cleanStatement = getCleanedUpStatement(statement);
+ return builder.setStatement(cleanStatement).setError(checkStatementForParserError(cleanStatement)).build();
+ }
+
+ private List parseSqlLogicTestStatementsFromFile(Path file)
+ throws IOException
+ {
+ List lines = readAllLines(file);
+ List> statementsAsListsOfLines = getListOfStatementsAsLines(lines);
+ return statementsAsListsOfLines.stream()
+ .map(this::buildSqlLogicTestStatementFromLines)
+ .filter(this::statementIsAcceptableToCurrDialect)
+ .collect(toList());
+ }
+
+ private List getErroneousStatements(List testStatements)
+ {
+ return testStatements.stream()
+ .filter(statement -> checkStatementForParserError(statement.getStatement()).isPresent())
+ .collect(toList());
+ }
+
+ private class SqlLogicTestFileVisitor
+ implements FileVisitor
+ {
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
+ {
+ return CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ throws IOException
+ {
+ if (isHidden(file)) {
+ return CONTINUE;
+ }
+ if (result.getNumFilesVisited() >= maxNumFilesToVisit) {
+ return TERMINATE;
+ }
+ result.incrementNumFilesVisited();
+ List testStatements = parseSqlLogicTestStatementsFromFile(file);
+ result.incrementNumStatementsFound(testStatements.size());
+ List erroneousStatements = getErroneousStatements(testStatements);
+ result.addErroneousStatements(erroneousStatements);
+ return CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(Path file, IOException exception)
+ {
+ LOG.warn(exception, "Failed to access file: %s", file.toString());
+ return CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exception)
+ {
+ return CONTINUE;
+ }
+ }
+}
diff --git a/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/java/SqlLogicTestConfig.java b/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/java/SqlLogicTestConfig.java
new file mode 100644
index 0000000..a3b74ef
--- /dev/null
+++ b/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/java/SqlLogicTestConfig.java
@@ -0,0 +1,89 @@
+/*
+ * 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.facebook.coresql.parser.sqllogictest.java;
+
+import com.facebook.airlift.configuration.Config;
+import com.facebook.airlift.configuration.ConfigDescription;
+import com.facebook.coresql.parser.sqllogictest.java.SqlLogicTest.DatabaseDialect;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static com.facebook.coresql.parser.sqllogictest.java.SqlLogicTest.DatabaseDialect.ALL;
+
+public class SqlLogicTestConfig
+{
+ private Path testFilesRootPath = Paths.get("src/test/java/com/facebook/coresql/parser/sqllogictest/resources/tests");
+ private Path resultPath = Paths.get("src/test/java/com/facebook/coresql/parser/sqllogictest/resources");
+ private DatabaseDialect databaseDialect = ALL;
+ private int maxNumFilesToVisit = 10;
+
+ @Config("test-files-root-path")
+ public SqlLogicTestConfig setTestFilesRootPath(String testFilesRootPath)
+ {
+ this.testFilesRootPath = Paths.get(testFilesRootPath);
+ return this;
+ }
+
+ @NotNull
+ public Path getTestFilesRootPath()
+ {
+ return testFilesRootPath;
+ }
+
+ @Config("result-path")
+ public SqlLogicTestConfig setResultPath(String resultPath)
+ {
+ this.resultPath = Paths.get(resultPath);
+ return this;
+ }
+
+ @NotNull
+ public Path getResultPath()
+ {
+ return resultPath;
+ }
+
+ @Config("max-num-files-to-visit")
+ @ConfigDescription("The max number of test files to test against")
+ public SqlLogicTestConfig setMaxNumFilesToVisit(int maxNumFilesToVisit)
+ {
+ this.maxNumFilesToVisit = maxNumFilesToVisit;
+ return this;
+ }
+
+ @Min(1)
+ public int getMaxNumFilesToVisit()
+ {
+ return maxNumFilesToVisit;
+ }
+
+ @Config("database-dialect")
+ @ConfigDescription("The database dialect to filter test queries over")
+ public SqlLogicTestConfig setDatabaseDialect(DatabaseDialect databaseDialect)
+ {
+ this.databaseDialect = databaseDialect;
+ return this;
+ }
+
+ @NotNull
+ public DatabaseDialect getDatabaseDialect()
+ {
+ return databaseDialect;
+ }
+}
diff --git a/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/java/SqlLogicTestModule.java b/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/java/SqlLogicTestModule.java
new file mode 100644
index 0000000..682a896
--- /dev/null
+++ b/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/java/SqlLogicTestModule.java
@@ -0,0 +1,32 @@
+/*
+ * 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.facebook.coresql.parser.sqllogictest.java;
+
+import com.google.inject.Binder;
+import com.google.inject.Module;
+
+import static com.facebook.airlift.configuration.ConfigBinder.configBinder;
+import static com.google.inject.Scopes.SINGLETON;
+
+public class SqlLogicTestModule
+ implements Module
+{
+ @Override
+ public void configure(Binder binder)
+ {
+ configBinder(binder).bindConfig(SqlLogicTestConfig.class);
+ binder.bind(SqlLogicTest.class).in(SINGLETON);
+ }
+}
diff --git a/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/java/SqlLogicTestResult.java b/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/java/SqlLogicTestResult.java
new file mode 100644
index 0000000..602315b
--- /dev/null
+++ b/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/java/SqlLogicTestResult.java
@@ -0,0 +1,77 @@
+/*
+ * 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.facebook.coresql.parser.sqllogictest.java;
+
+import com.facebook.coresql.parser.sqllogictest.java.SqlLogicTest.DatabaseDialect;
+import com.google.common.collect.ImmutableList;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.Objects.requireNonNull;
+
+public class SqlLogicTestResult
+{
+ private final List erroneousStatements;
+ private final DatabaseDialect databaseDialect;
+ private int numFilesVisited;
+ private int numStatementsFound;
+
+ public SqlLogicTestResult(DatabaseDialect databaseDialect)
+ {
+ this.databaseDialect = requireNonNull(databaseDialect);
+ this.erroneousStatements = new ArrayList<>();
+ }
+
+ public DatabaseDialect getDatabaseDialect()
+ {
+ return databaseDialect;
+ }
+
+ public void addErroneousStatements(List erroneousStatements)
+ {
+ this.erroneousStatements.addAll(erroneousStatements);
+ }
+
+ public List getErroneousStatements()
+ {
+ return ImmutableList.copyOf(erroneousStatements);
+ }
+
+ public int getNumFilesVisited()
+ {
+ return numFilesVisited;
+ }
+
+ public void incrementNumFilesVisited()
+ {
+ numFilesVisited += 1;
+ }
+
+ public int getNumStatementsFound()
+ {
+ return numStatementsFound;
+ }
+
+ public void incrementNumStatementsFound(int incrementAmount)
+ {
+ this.numStatementsFound += incrementAmount;
+ }
+
+ public int getNumStatementsParsed()
+ {
+ return numStatementsFound - erroneousStatements.size();
+ }
+}
diff --git a/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/java/SqlLogicTestStatement.java b/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/java/SqlLogicTestStatement.java
new file mode 100644
index 0000000..cbb4ffa
--- /dev/null
+++ b/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/java/SqlLogicTestStatement.java
@@ -0,0 +1,106 @@
+/*
+ * 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.facebook.coresql.parser.sqllogictest.java;
+
+import com.facebook.coresql.parser.sqllogictest.java.SqlLogicTest.DatabaseDialect;
+
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+
+import static com.facebook.coresql.parser.sqllogictest.java.SqlLogicTest.CoreSqlParsingError;
+import static java.util.Objects.requireNonNull;
+
+public class SqlLogicTestStatement
+{
+ private final Optional onlyIfDialect;
+ private final Optional error;
+ private final Set skipIfSet;
+ private final String statement;
+
+ private SqlLogicTestStatement(Builder builder)
+ {
+ this.onlyIfDialect = builder.onlyIfDialect;
+ this.error = builder.error;
+ this.skipIfSet = builder.skipIfSet;
+ this.statement = builder.statement;
+ }
+
+ public static Builder builder()
+ {
+ return new Builder();
+ }
+
+ public Optional getCurrStatementsOnlyIfDialect()
+ {
+ return onlyIfDialect;
+ }
+
+ public Optional getError()
+ {
+ return error;
+ }
+
+ public Set getSkipIfSet()
+ {
+ return skipIfSet;
+ }
+
+ public String getStatement()
+ {
+ return statement;
+ }
+
+ public static class Builder
+ {
+ private Optional onlyIfDialect;
+ private Optional error;
+ private final Set skipIfSet;
+ private String statement;
+
+ public Builder()
+ {
+ this.onlyIfDialect = Optional.empty();
+ this.error = Optional.empty();
+ this.skipIfSet = new HashSet<>();
+ }
+
+ public SqlLogicTestStatement build()
+ {
+ return new SqlLogicTestStatement(this);
+ }
+
+ public void setOnlyIfDialect(DatabaseDialect onlyIfDialect)
+ {
+ this.onlyIfDialect = Optional.of(onlyIfDialect);
+ }
+
+ public void addDialectToSkipIfSet(DatabaseDialect dialect)
+ {
+ this.skipIfSet.add(requireNonNull(dialect));
+ }
+
+ public Builder setError(Optional error)
+ {
+ this.error = error;
+ return this;
+ }
+
+ public Builder setStatement(String statement)
+ {
+ this.statement = requireNonNull(statement);
+ return this;
+ }
+ }
+}
diff --git a/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/resources/config.properties b/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/resources/config.properties
new file mode 100644
index 0000000..8ee10e5
--- /dev/null
+++ b/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/resources/config.properties
@@ -0,0 +1,4 @@
+test-files-root-path=src/test/java/com/facebook/coresql/parser/sqllogictest/resources/tests
+result-path=src/test/java/com/facebook/coresql/parser/sqllogictest/resources
+max-num-files-to-visit=10
+database-dialect=ALL
diff --git a/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/resources/tests/select1.test b/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/resources/tests/select1.test
new file mode 100644
index 0000000..f265998
--- /dev/null
+++ b/parser/src/test/java/com/facebook/coresql/parser/sqllogictest/resources/tests/select1.test
@@ -0,0 +1,2007 @@
+statement ok
+CREATE TABLE t1(a INTEGER, b INTEGER, c INTEGER, d INTEGER, e INTEGER)
+
+statement ok
+INSERT INTO t1(e,c,b,d,a) VALUES(103,102,100,101,104)
+
+statement ok
+INSERT INTO t1(a,c,d,e,b) VALUES(107,106,108,109,105)
+
+statement ok
+INSERT INTO t1(e,d,b,a,c) VALUES(110,114,112,111,113)
+
+statement ok
+INSERT INTO t1(d,c,e,a,b) VALUES(116,119,117,115,118)
+
+statement ok
+INSERT INTO t1(c,d,b,e,a) VALUES(123,122,124,120,121)
+
+statement ok
+INSERT INTO t1(a,d,b,e,c) VALUES(127,128,129,126,125)
+
+statement ok
+INSERT INTO t1(e,c,a,d,b) VALUES(132,134,131,133,130)
+
+statement ok
+INSERT INTO t1(a,d,b,e,c) VALUES(138,136,139,135,137)
+
+statement ok
+INSERT INTO t1(e,c,d,a,b) VALUES(144,141,140,142,143)
+
+statement ok
+INSERT INTO t1(b,a,e,d,c) VALUES(145,149,146,148,147)
+
+statement ok
+INSERT INTO t1(b,c,a,d,e) VALUES(151,150,153,154,152)
+
+statement ok
+INSERT INTO t1(c,e,a,d,b) VALUES(155,157,159,156,158)
+
+statement ok
+INSERT INTO t1(c,b,a,d,e) VALUES(161,160,163,164,162)
+
+statement ok
+INSERT INTO t1(b,d,a,e,c) VALUES(167,169,168,165,166)
+
+statement ok
+INSERT INTO t1(d,b,c,e,a) VALUES(171,170,172,173,174)
+
+statement ok
+INSERT INTO t1(e,c,a,d,b) VALUES(177,176,179,178,175)
+
+statement ok
+INSERT INTO t1(b,e,a,d,c) VALUES(181,180,182,183,184)
+
+statement ok
+INSERT INTO t1(c,a,b,e,d) VALUES(187,188,186,189,185)
+
+statement ok
+INSERT INTO t1(d,b,c,e,a) VALUES(190,194,193,192,191)
+
+statement ok
+INSERT INTO t1(a,e,b,d,c) VALUES(199,197,198,196,195)
+
+statement ok
+INSERT INTO t1(b,c,d,a,e) VALUES(200,202,203,201,204)
+
+statement ok
+INSERT INTO t1(c,e,a,b,d) VALUES(208,209,205,206,207)
+
+statement ok
+INSERT INTO t1(c,e,a,d,b) VALUES(214,210,213,212,211)
+
+statement ok
+INSERT INTO t1(b,c,a,d,e) VALUES(218,215,216,217,219)
+
+statement ok
+INSERT INTO t1(b,e,d,a,c) VALUES(223,221,222,220,224)
+
+statement ok
+INSERT INTO t1(d,e,b,a,c) VALUES(226,227,228,229,225)
+
+statement ok
+INSERT INTO t1(a,c,b,e,d) VALUES(234,231,232,230,233)
+
+statement ok
+INSERT INTO t1(e,b,a,c,d) VALUES(237,236,239,235,238)
+
+statement ok
+INSERT INTO t1(e,c,b,a,d) VALUES(242,244,240,243,241)
+
+statement ok
+INSERT INTO t1(e,d,c,b,a) VALUES(246,248,247,249,245)
+
+query I nosort
+SELECT CASE WHEN c>(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END
+ FROM t1
+ ORDER BY 1
+----
+30 values hashing to 3c13dee48d9356ae19af2515e05e6b54
+
+query II nosort
+SELECT a+b*2+c*3+d*4+e*5,
+ (a+b+c+d+e)/5
+ FROM t1
+ ORDER BY 1,2
+----
+60 values hashing to 808146289313018fce25f1a280bd8c30
+
+query IIIII nosort
+SELECT a+b*2+c*3+d*4+e*5,
+ CASE WHEN ac OR ee
+ AND EXISTS(SELECT 1 FROM t1 AS x WHERE x.bc OR ec
+ AND c>d
+ ORDER BY 3,4,5,1,2,6
+----
+24 values hashing to 425542fc8d1ec04f89534ae98d59a74d
+
+query IIII nosort
+SELECT a+b*2+c*3+d*4,
+ CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END,
+ (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.d=d+2)
+ ORDER BY 4,2,1,3
+----
+60 values hashing to a2af299d7b2197866b7c8f6854b77ab5
+
+query I nosort
+SELECT CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END
+ FROM t1
+ ORDER BY 1
+----
+30 values hashing to f2bf77f8cfb62666ab72c866ed4d4f1a
+
+query I nosort
+SELECT (SELECT count(*) FROM t1 AS x WHERE x.bb-2 AND ad
+ ORDER BY 1
+----
+20 values hashing to 1d6b8ed1db696a5f1c8d126facddd077
+
+query IIIII nosort
+SELECT a,
+ (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.db
+ OR b>c
+ ORDER BY 1,4,3,2,5
+----
+145 values hashing to 65042db64d506f67a37c85f825cdd11f
+
+query IIIIIII nosort
+SELECT CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END,
+ CASE WHEN a(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ abs(b-c)
+ FROM t1
+ WHERE EXISTS(SELECT 1 FROM t1 AS x WHERE x.bc
+ OR d NOT BETWEEN 110 AND 150
+ ORDER BY 4,1,5,2,6,3,7
+----
+210 values hashing to a259991ed1248a55a07838ce36a7c257
+
+query IIIIII nosort
+SELECT CASE WHEN c>(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ CASE WHEN at1.c AND x.db
+ OR d NOT BETWEEN 110 AND 150
+ ORDER BY 5,3,6,1,2,4
+----
+180 values hashing to 631b9506abcdd5dcea64c7ed2a3799ed
+
+query IIIII nosort
+SELECT (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.dd
+ ORDER BY 3,5,4,1,2
+----
+125 values hashing to 58b4ab36ed442f3837188b38cd02486a
+
+query IIIIII nosort
+SELECT CASE WHEN c>(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ a-b,
+ abs(b-c),
+ c,
+ CASE WHEN ab
+ ORDER BY 5,4,6,2,1,7,3
+----
+133 values hashing to af6179f0918bfe7e3a9cd1940fbb3f75
+
+query II nosort
+SELECT a,
+ b
+ FROM t1
+ ORDER BY 1,2
+----
+60 values hashing to f88a6f6656b30fc5b3c4ede940008ff2
+
+query III nosort
+SELECT c,
+ a-b,
+ (SELECT count(*) FROM t1 AS x WHERE x.b(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ a+b*2+c*3+d*4+e*5,
+ abs(b-c),
+ b-c,
+ CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END,
+ a-b
+ FROM t1
+ WHERE b>c
+ AND a>b
+ AND d NOT BETWEEN 110 AND 150
+ ORDER BY 2,1,6,4,3,5
+----
+42 values hashing to 6921d8dad7855bee57bd82dfd5fcbabc
+
+query IIIIII nosort
+SELECT a+b*2+c*3+d*4+e*5,
+ abs(a),
+ b-c,
+ c-d,
+ CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END,
+ a
+ FROM t1
+ WHERE c BETWEEN b-2 AND d+2
+ OR e+d BETWEEN a+b-10 AND c+130
+ ORDER BY 1,5,4,2,6,3
+----
+144 values hashing to 1d2ad7123e951f275353001a6879b3c8
+
+query IIIIIII nosort
+SELECT CASE WHEN a(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ b-c,
+ a+b*2
+ FROM t1
+ ORDER BY 6,2,4,5,3,1
+----
+180 values hashing to 9fc96182924e07a6ffa415425e69adcf
+
+query IIIIIII nosort
+SELECT d-e,
+ abs(a),
+ b,
+ c-d,
+ a+b*2+c*3,
+ abs(b-c),
+ CASE WHEN ac OR ee
+ AND c>d
+ ORDER BY 1,3,7,5,2,6,4
+----
+42 values hashing to 1b3471ef4d294cdab97aa6e5eb44bdc6
+
+query IIIIIII nosort
+SELECT CASE WHEN a(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END
+ FROM t1
+ WHERE e+d BETWEEN a+b-10 AND c+130
+ AND c>d
+ ORDER BY 1
+----
+1000
+1180
+1240
+
+query IIIIIII nosort
+SELECT a+b*2+c*3,
+ abs(b-c),
+ CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END,
+ a,
+ a+b*2+c*3+d*4,
+ a+b*2,
+ (SELECT count(*) FROM t1 AS x WHERE x.bb-2 AND a(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ c,
+ CASE WHEN ae
+ AND (c<=d-2 OR c>=d+2)
+ AND b>c
+ ORDER BY 2,3,1,5,4
+----
+25 values hashing to d26c6a15ff9231615a949e9c2412fc2b
+
+query IIIIIII nosort
+SELECT a+b*2+c*3+d*4+e*5,
+ CASE WHEN a(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END
+ FROM t1
+ WHERE (e>c OR eb
+ ORDER BY 4,5,3,7,1,6,2
+----
+196 values hashing to 601e621103e91110c69c4545c08a48c1
+
+query IIIII nosort
+SELECT (SELECT count(*) FROM t1 AS x WHERE x.bt1.c AND x.dc OR eb
+ AND (a>b-2 AND ab
+ OR c BETWEEN b-2 AND d+2
+ OR c>d
+ ORDER BY 3,2,1,4,5
+----
+140 values hashing to dd6eae29e54f220617fca7f22df83acb
+
+query IIIIII nosort
+SELECT d,
+ a+b*2+c*3+d*4+e*5,
+ a+b*2+c*3,
+ c-d,
+ (a+b+c+d+e)/5,
+ a-b
+ FROM t1
+ ORDER BY 3,4,2,6,5,1
+----
+180 values hashing to 4cf6744bf5d3826cd98ad853eeb5beba
+
+query IIIIIII nosort
+SELECT CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END,
+ a+b*2+c*3+d*4+e*5,
+ (a+b+c+d+e)/5,
+ abs(b-c),
+ abs(a),
+ (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.d(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ b,
+ c,
+ e
+ FROM t1
+ WHERE b>c
+ ORDER BY 1,2,4,3,5
+----
+70 values hashing to f0e2146374bd151d6ede973c9ed1f2a5
+
+query IIIIII nosort
+SELECT a-b,
+ a,
+ a+b*2+c*3,
+ b,
+ d,
+ d-e
+ FROM t1
+ WHERE (e>a AND ec
+ ORDER BY 2,6,5,4,3,1
+----
+84 values hashing to 5e2c89b85bc66b196ff3083128f5a494
+
+query IIIII nosort
+SELECT b,
+ (a+b+c+d+e)/5,
+ CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END,
+ abs(b-c),
+ b-c
+ FROM t1
+ WHERE a>b
+ ORDER BY 2,5,3,4,1
+----
+95 values hashing to eae71ba4e872a3ba44a0ecd1bf870a3e
+
+query IIII nosort
+SELECT abs(b-c),
+ a,
+ a+b*2,
+ CASE WHEN ab-2 AND ad
+ ORDER BY 2,1,3
+----
+15 values hashing to 08fa8e3fd6a4743609ebd0354e659bba
+
+query IIII nosort
+SELECT a,
+ e,
+ CASE WHEN c>(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ a-b
+ FROM t1
+ ORDER BY 2,4,3,1
+----
+120 values hashing to c328c1a96813bf1072935593f41667ab
+
+query III nosort
+SELECT (a+b+c+d+e)/5,
+ e,
+ (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.dc OR et1.c AND x.de
+ OR (e>a AND eb
+ ORDER BY 1
+----
+23 values hashing to 58bbff23f68fc8cebb2a4c6436d0b04a
+
+query IIIIII nosort
+SELECT CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END,
+ (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.db-2 AND ad
+ AND a>b
+ AND (a>b-2 AND at1.c AND x.dc
+ AND (a>b-2 AND a(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ a+b*2+c*3+d*4+e*5,
+ d
+ FROM t1
+ WHERE d>e
+ OR (a>b-2 AND ad
+ ORDER BY 2,3,4,1
+----
+120 values hashing to d15570017ab0bf7eb3db1e803003e5f0
+
+query I nosort
+SELECT a+b*2+c*3
+ FROM t1
+ ORDER BY 1
+----
+30 values hashing to 20bb63abd067ae8ef5a05f08be3b6762
+
+query IIIII nosort
+SELECT CASE WHEN ae
+ ORDER BY 3,4,1,2,5
+----
+80 values hashing to dda48f2f14d6eef074c866167931274f
+
+query II nosort
+SELECT (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.dc
+ ORDER BY 1,2
+----
+28 values hashing to 2d23fde26e5c80f6eabca42e592bde71
+
+query IIIII nosort
+SELECT a+b*2+c*3+d*4+e*5,
+ a,
+ CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END,
+ a+b*2+c*3+d*4,
+ b-c
+ FROM t1
+ WHERE d>e
+ ORDER BY 4,1,5,3,2
+----
+80 values hashing to 36b0bd3c4a5efd58912d89eec64b42fe
+
+query III nosort
+SELECT a-b,
+ a+b*2+c*3+d*4,
+ (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.dc OR ec
+ AND d>e
+ ORDER BY 1
+----
+120
+126
+135
+152
+165
+230
+237
+246
+
+query II nosort
+SELECT b,
+ e
+ FROM t1
+ WHERE (c<=d-2 OR c>=d+2)
+ ORDER BY 2,1
+----
+30 values hashing to e2107ed9f44c1f14fa1a14b1818a2073
+
+query IIII nosort
+SELECT b-c,
+ d-e,
+ c-d,
+ a+b*2+c*3
+ FROM t1
+ ORDER BY 1,2,4,3
+----
+120 values hashing to d9fe6e44ef568e5ddcdd440b1c1058b2
+
+query II nosort
+SELECT abs(b-c),
+ CASE WHEN ac OR ec
+ OR (a>b-2 AND a(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ (SELECT count(*) FROM t1 AS x WHERE x.be
+ AND d NOT BETWEEN 110 AND 150
+ ORDER BY 5,3,1,4,2
+----
+50 values hashing to 0d42d0a09548edf4a343fe9e95c98b2c
+
+query IIIIII nosort
+SELECT (a+b+c+d+e)/5,
+ (SELECT count(*) FROM t1 AS x WHERE x.b(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ c-d,
+ a+b*2+c*3+d*4,
+ a+b*2+c*3+d*4+e*5
+ FROM t1
+ WHERE (e>a AND ed
+ ORDER BY 2,5,6,4,1,3
+----
+18 values hashing to 51c5d8e007a143cf3bf858945f677039
+
+query IIIIIII nosort
+SELECT (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.dc OR ea AND e=d+2)
+ AND (a>b-2 AND ab-2 AND ae
+ ORDER BY 1,2
+----
+30 values hashing to 841db017799a825a9fce9bcc940f7f96
+
+query I nosort
+SELECT b-c
+ FROM t1
+ ORDER BY 1
+----
+30 values hashing to 970be304ddec1d2bede8d8e2f14368c6
+
+query IIIIII nosort
+SELECT (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.dd
+ OR (a>b-2 AND ae
+ AND d NOT BETWEEN 110 AND 150
+ AND (e>a AND ee
+ OR c BETWEEN b-2 AND d+2
+ ORDER BY 2,1,4,3,5
+----
+115 values hashing to 05325b83edf1f52fb3d249495c4114e2
+
+query II nosort
+SELECT a-b,
+ CASE WHEN ac
+ AND (a>b-2 AND ac OR ec
+ ORDER BY 4,3,2,1
+----
+112 values hashing to 5ae5415105496a1711310d3c42176846
+
+query IIII nosort
+SELECT a+b*2+c*3+d*4,
+ (SELECT count(*) FROM t1 AS x WHERE x.bc
+ ORDER BY 2,4,3,1
+----
+56 values hashing to 5f4a5fcffe6f102f57b56bf2e339dd89
+
+query II nosort
+SELECT b,
+ abs(b-c)
+ FROM t1
+ WHERE c>d
+ AND a>b
+ AND EXISTS(SELECT 1 FROM t1 AS x WHERE x.bt1.c AND x.d(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ abs(b-c),
+ a+b*2+c*3+d*4+e*5,
+ CASE WHEN at1.c AND x.dc OR ec OR ee
+ OR c BETWEEN b-2 AND d+2
+ ORDER BY 3,2,1
+----
+90 values hashing to 27ca10878c9391decf14b1da14b81a1a
+
+query II nosort
+SELECT (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.da AND e=d+2)
+ OR e+d BETWEEN a+b-10 AND c+130
+ ORDER BY 2,1
+----
+38 values hashing to 6b17e3a64ebbafbdf4ec543abf34d414
+
+query III nosort
+SELECT (a+b+c+d+e)/5,
+ abs(a),
+ d
+ FROM t1
+ WHERE e+d BETWEEN a+b-10 AND c+130
+ AND (e>c OR ee
+ ORDER BY 4,5,3,6,2,1,7
+----
+112 values hashing to 056a2f68932723bbdeb9dc7c26e21ff8
+
+query IIIII nosort
+SELECT a,
+ d,
+ a+b*2+c*3+d*4+e*5,
+ a-b,
+ (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.db-2 AND ac
+ ORDER BY 1,3,5,4,2
+----
+140 values hashing to 3dfb60ce29bfaa3deb2c90771787ae28
+
+query IIIIIII nosort
+SELECT (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.d=d+2)
+ OR (e>a AND ee
+ ORDER BY 5,6,3,7,2,1,4
+----
+154 values hashing to 7be42f68cbfeb20d2a574569eabc62b8
+
+query IIIII nosort
+SELECT b-c,
+ c,
+ CASE WHEN c>(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ (SELECT count(*) FROM t1 AS x WHERE x.bd
+ OR (a>b-2 AND ac
+ ORDER BY 1,3,5,2,4
+----
+130 values hashing to 3872625fdb5d1bd8d2d87c61b2c5d2b9
+
+query IIIIIII nosort
+SELECT b-c,
+ CASE WHEN at1.c AND x.dc
+ OR d NOT BETWEEN 110 AND 150
+ OR (e>c OR et1.c AND x.d=d+2)
+ OR c>d
+ ORDER BY 1,3,2
+----
+81 values hashing to 3bd0cf1b195cb05eea3e0621c5a4f38e
+
+query II nosort
+SELECT CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END,
+ a+b*2+c*3
+ FROM t1
+ ORDER BY 2,1
+----
+60 values hashing to 1692ce3bd9941e0f21090da530fd3ed8
+
+query IIIIIII nosort
+SELECT a+b*2+c*3+d*4,
+ c,
+ CASE WHEN a=d+2)
+ ORDER BY 6,2,4,3,1,7,5
+----
+70 values hashing to e83d593c583f1a0cfb445b1c4ab673b7
+
+query IIIII nosort
+SELECT (a+b+c+d+e)/5,
+ a-b,
+ b,
+ a+b*2,
+ a
+ FROM t1
+ WHERE (a>b-2 AND ac OR ee
+ ORDER BY 4,2,5,3,1
+----
+25 values hashing to 4d716c3a4be4e2c0fcaeb771d9557147
+
+query IIIIII nosort
+SELECT CASE WHEN c>(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ d,
+ e,
+ c-d,
+ a+b*2+c*3+d*4,
+ CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END
+ FROM t1
+ WHERE c BETWEEN b-2 AND d+2
+ AND c>d
+ AND EXISTS(SELECT 1 FROM t1 AS x WHERE x.be
+ AND (e>a AND eb
+ OR c>d
+ ORDER BY 1,5,3,2,4
+----
+130 values hashing to 9873ab86b9fa0eef10810ba4277fd1bf
+
+query IIIIII nosort
+SELECT a+b*2+c*3+d*4+e*5,
+ a,
+ abs(a),
+ a-b,
+ d-e,
+ CASE WHEN c>(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END
+ FROM t1
+ WHERE EXISTS(SELECT 1 FROM t1 AS x WHERE x.bc
+ ORDER BY 4,6,3,1,5,2
+----
+84 values hashing to c1c96a830016492c89e9fe7b92275b24
+
+query II nosort
+SELECT a+b*2+c*3,
+ a
+ FROM t1
+ WHERE (e>c OR eb
+ ORDER BY 1,2
+----
+56 values hashing to fedff1b28e56669aacb1dc79b927abf9
+
+query III nosort
+SELECT CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END,
+ c-d,
+ a+b*2+c*3
+ FROM t1
+ WHERE (c<=d-2 OR c>=d+2)
+ AND (a>b-2 AND at1.c AND x.de
+ ORDER BY 4,2,1,5,3
+----
+80 values hashing to 06c104cf923af770f3cf98700c2428d0
+
+query I nosort
+SELECT e
+ FROM t1
+ ORDER BY 1
+----
+30 values hashing to 41762f74ba25ab0f9b0448f319f2f292
+
+query IIIIII nosort
+SELECT c-d,
+ b,
+ d,
+ a+b*2+c*3+d*4+e*5,
+ a+b*2,
+ (SELECT count(*) FROM t1 AS x WHERE x.bd
+ ORDER BY 4,3,5,6,2,1
+----
+84 values hashing to e1b8a5e4a3649a2976b00eaf0962058b
+
+query IIIII nosort
+SELECT abs(b-c),
+ c-d,
+ a,
+ CASE WHEN ac
+ ORDER BY 4,2,1,5,3
+----
+145 values hashing to d7e8eaed9394e826f4fdcccf068acdec
+
+query IIII nosort
+SELECT (SELECT count(*) FROM t1 AS x WHERE x.b(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ a+b*2+c*3
+ FROM t1
+ WHERE c>d
+ AND b>c
+ AND e+d BETWEEN a+b-10 AND c+130
+ ORDER BY 3,4,1,2
+----
+4
+1
+1240
+738
+
+query I nosort
+SELECT (a+b+c+d+e)/5
+ FROM t1
+ ORDER BY 1
+----
+30 values hashing to 8d2279ba80763220505cecac39786e90
+
+query IIIIII nosort
+SELECT a+b*2,
+ (a+b+c+d+e)/5,
+ (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.dd
+ ORDER BY 6,5,4,1,3,2
+----
+78 values hashing to f8b104ce0c1d6a8d02976b512c224c33
+
+query IIII nosort
+SELECT a+b*2+c*3+d*4,
+ CASE WHEN ac OR eb
+ OR EXISTS(SELECT 1 FROM t1 AS x WHERE x.be
+ ORDER BY 2,1,3,4
+----
+120 values hashing to 227ac1db8da88813615a7e008801fba7
+
+query III nosort
+SELECT (a+b+c+d+e)/5,
+ a+b*2,
+ (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.dc OR ec
+ ORDER BY 2,1,3
+----
+84 values hashing to aa77bd3dacaadb8d94850b7457313394
+
+query IIIIIII nosort
+SELECT abs(a),
+ d,
+ e,
+ a+b*2+c*3+d*4,
+ CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END,
+ b-c,
+ a
+ FROM t1
+ WHERE (a>b-2 AND ab-2 AND ac OR e=d+2)
+ ORDER BY 6,7,2,1,3,4,5
+----
+-3
+13
+1
+167
+1
+1000
+333
+
+query IIIII nosort
+SELECT (a+b+c+d+e)/5,
+ c-d,
+ CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END,
+ a+b*2+c*3,
+ d-e
+ FROM t1
+ WHERE a>b
+ AND c BETWEEN b-2 AND d+2
+ AND (a>b-2 AND at1.c AND x.dc
+ ORDER BY 3,5,4,2,6,7,1
+----
+196 values hashing to ce60e2883fe7a0c41c29c17e9b62bf51
+
+query IIIIII nosort
+SELECT (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.d(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ abs(a),
+ a+b*2+c*3+d*4+e*5,
+ d-e,
+ CASE WHEN ae
+ OR b>c
+ ORDER BY 2,3,1,5,4,6
+----
+150 values hashing to c31247552305ea7108b6c15517e4e50e
+
+query IIIIII nosort
+SELECT b-c,
+ a+b*2,
+ a,
+ (SELECT count(*) FROM t1 AS x WHERE x.ba AND e(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ a+b*2+c*3+d*4+e*5
+ FROM t1
+ WHERE (e>c OR ee
+ AND EXISTS(SELECT 1 FROM t1 AS x WHERE x.ba AND et1.c AND x.da AND ec OR e=d+2)
+ ORDER BY 1
+----
+3331
+
+query III nosort
+SELECT a+b*2+c*3+d*4,
+ b,
+ a-b
+ FROM t1
+ WHERE c>d
+ OR d>e
+ OR b>c
+ ORDER BY 3,1,2
+----
+84 values hashing to 35aa92c733c1c60fedff6d6a36a4e64f
+
+query I nosort
+SELECT a-b
+ FROM t1
+ ORDER BY 1
+----
+30 values hashing to c2001bebc4d3d2d6b01a5a50ce4282ca
+
+query IIII nosort
+SELECT e,
+ a+b*2+c*3+d*4+e*5,
+ CASE WHEN ab
+ OR c BETWEEN b-2 AND d+2
+ ORDER BY 3,2,4,1
+----
+104 values hashing to 57317371c67d5ca0360d9860ff06b5f6
+
+query IIIII nosort
+SELECT (SELECT count(*) FROM t1 AS x WHERE x.b(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ e,
+ CASE WHEN at1.c AND x.dc
+ ORDER BY 3,5,4,2,1
+----
+140 values hashing to db6ada3c6b4c6105c96c56f98bd679d1
+
+query II nosort
+SELECT b-c,
+ a+b*2+c*3+d*4+e*5
+ FROM t1
+ WHERE b>c
+ AND a>b
+ AND (e>a AND ec
+ AND a>b
+ ORDER BY 3,2,1
+----
+21 values hashing to 47e5ff2f412981bf5017a3fcd7dcbfce
+
+query IIIII nosort
+SELECT a+b*2+c*3,
+ d,
+ b-c,
+ (SELECT count(*) FROM t1 AS x WHERE x.bb-2 AND ac
+ AND c>d
+ ORDER BY 3,5,1,4,2
+----
+10 values hashing to f7cc18e47d7f1cfbd32b65f410f3661f
+
+query IIII nosort
+SELECT d-e,
+ (a+b+c+d+e)/5,
+ CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END,
+ d
+ FROM t1
+ WHERE (e>c OR e=d+2)
+ AND c>d
+ ORDER BY 2,1
+----
+12 values hashing to 536e87880b7535393cfec01b6b44b09e
+
+query I nosort
+SELECT CASE WHEN aa AND ee
+ AND (c<=d-2 OR c>=d+2)
+ ORDER BY 1
+----
+222
+
+query II nosort
+SELECT a-b,
+ b-c
+ FROM t1
+ WHERE b>c
+ AND d>e
+ AND c BETWEEN b-2 AND d+2
+ ORDER BY 2,1
+----
+14 values hashing to d2bcb971c3fe19befbef456f67ecb854
+
+query III nosort
+SELECT b,
+ d,
+ (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.dc
+ ORDER BY 1,2,3
+----
+42 values hashing to fdf2c9075b2487f82c8ad837755619d7
+
+query I nosort
+SELECT a+b*2+c*3+d*4+e*5
+ FROM t1
+ WHERE EXISTS(SELECT 1 FROM t1 AS x WHERE x.b(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ b-c,
+ a+b*2
+ FROM t1
+ WHERE EXISTS(SELECT 1 FROM t1 AS x WHERE x.b(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END
+ FROM t1
+ ORDER BY 1
+----
+30 values hashing to 3c13dee48d9356ae19af2515e05e6b54
+
+query II nosort
+SELECT a+b*2+c*3+d*4,
+ a+b*2+c*3
+ FROM t1
+ WHERE b>c
+ ORDER BY 1,2
+----
+28 values hashing to 7626a6dc10da4bbb0672aba278414d7f
+
+query IIIII nosort
+SELECT e,
+ a,
+ a+b*2+c*3,
+ b,
+ d
+ FROM t1
+ WHERE c>d
+ OR EXISTS(SELECT 1 FROM t1 AS x WHERE x.b(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END
+ FROM t1
+ WHERE a>b
+ ORDER BY 3,1,2
+----
+57 values hashing to e46ef205fe944f0d32288b2138a40f06
+
+query IIIII nosort
+SELECT abs(a),
+ (a+b+c+d+e)/5,
+ CASE a+1 WHEN b THEN 111 WHEN c THEN 222
+ WHEN d THEN 333 WHEN e THEN 444 ELSE 555 END,
+ a+b*2+c*3,
+ d-e
+ FROM t1
+ ORDER BY 3,1,2,5,4
+----
+150 values hashing to 34ca74f90850eff35ac3a230238544be
+
+query IIIII nosort
+SELECT (SELECT count(*) FROM t1 AS x WHERE x.c>t1.c AND x.db-2 AND ac
+ OR (a>b-2 AND at1.c AND x.d=d+2)
+ ORDER BY 1,3,2
+----
+45 values hashing to c5572ef5e70213b43133e2248770b61d
+
+query I nosort
+SELECT d
+ FROM t1
+ WHERE (e>a AND ec
+ AND d>e
+ ORDER BY 4,5,6,3,2,1
+----
+48 values hashing to 8b118828e8caafc9faa4a21d0f3f4ea5
+
+query I nosort
+SELECT a+b*2+c*3
+ FROM t1
+ WHERE c BETWEEN b-2 AND d+2
+ ORDER BY 1
+----
+22 values hashing to 5d0ecdbff39863d98aa5a23e0424ac1e
+
+query IIII nosort
+SELECT abs(b-c),
+ CASE WHEN c>(SELECT avg(c) FROM t1) THEN a*2 ELSE b*10 END,
+ b,
+ a
+ FROM t1
+ WHERE b>c
+ AND d>e
+ NON EXISTANT CLAUSE 4,1,3,2
+----
+32 values hashing to 3ff228db977b596ebd4901df4462b000
+
+query IIIIII nosort
+SELECT a+b*2+c*3+d*4,
+ (a+b+c+d+e)/5,
+ a,
+ abs(a),
+ c-d,
+ c
+ FROM t1
+ ORDER BY 2,5,4,6,3,1
+----
diff --git a/pom.xml b/pom.xml
index fad61bc..3a6732b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,6 +19,7 @@
${project.parent.basedir}
+ 0.198
@@ -27,6 +28,34 @@
rewriter
+
+
+
+ com.facebook.airlift
+ configuration
+ ${dep.airlift.version}
+
+
+
+ com.facebook.airlift
+ log
+ ${dep.airlift.version}
+
+
+
+ com.facebook.airlift
+ bootstrap
+ ${dep.airlift.version}
+
+
+
+ javax.validation
+ validation-api
+ 2.0.1.Final
+
+
+
+