/
NikolayIvkin
/
sqlancer2
Обзор
Документация
Войти
/
NikolayIvkin
/
sqlancer2
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/sqlancer/duckdb/test/DuckDBNoRECOracle.java
137 строк
6 KB
Patrick
Continuation of Reworking Connection to DB to support non-SQL connections
26 ноя 2020, 15:40
26 ноя 2020, 15:40
62e302e
Код
Авторство
О чём код?
package sqlancer.duckdb.test; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import sqlancer.IgnoreMeException; import sqlancer.Randomly; import sqlancer.SQLConnection; import sqlancer.common.ast.newast.ColumnReferenceNode; import sqlancer.common.ast.newast.NewPostfixTextNode; import sqlancer.common.ast.newast.Node; import sqlancer.common.ast.newast.TableReferenceNode; import sqlancer.common.oracle.NoRECBase; import sqlancer.common.oracle.TestOracle; import sqlancer.common.query.SQLQueryAdapter; import sqlancer.common.query.SQLancerResultSet; import sqlancer.duckdb.DuckDBErrors; import sqlancer.duckdb.DuckDBProvider.DuckDBGlobalState; import sqlancer.duckdb.DuckDBSchema; import sqlancer.duckdb.DuckDBSchema.DuckDBColumn; import sqlancer.duckdb.DuckDBSchema.DuckDBCompositeDataType; import sqlancer.duckdb.DuckDBSchema.DuckDBDataType; import sqlancer.duckdb.DuckDBSchema.DuckDBTable; import sqlancer.duckdb.DuckDBSchema.DuckDBTables; import sqlancer.duckdb.DuckDBToStringVisitor; import sqlancer.duckdb.ast.DuckDBExpression; import sqlancer.duckdb.ast.DuckDBJoin; import sqlancer.duckdb.ast.DuckDBSelect; import sqlancer.duckdb.gen.DuckDBExpressionGenerator; import sqlancer.duckdb.gen.DuckDBExpressionGenerator.DuckDBCastOperation; public class DuckDBNoRECOracle extends NoRECBase<DuckDBGlobalState> implements TestOracle { private final DuckDBSchema s; public DuckDBNoRECOracle(DuckDBGlobalState globalState) { super(globalState); this.s = globalState.getSchema(); DuckDBErrors.addExpressionErrors(errors); } @Override public void check() throws SQLException { DuckDBTables randomTables = s.getRandomTableNonEmptyTables(); List<DuckDBColumn> columns = randomTables.getColumns(); DuckDBExpressionGenerator gen = new DuckDBExpressionGenerator(state).setColumns(columns); Node<DuckDBExpression> randomWhereCondition = gen.generateExpression(); List<DuckDBTable> tables = randomTables.getTables(); List<TableReferenceNode<DuckDBExpression, DuckDBTable>> tableList = tables.stream() .map(t -> new TableReferenceNode<DuckDBExpression, DuckDBTable>(t)).collect(Collectors.toList()); List<Node<DuckDBExpression>> joins = DuckDBJoin.getJoins(tableList, state); int secondCount = getSecondQuery(tableList.stream().collect(Collectors.toList()), randomWhereCondition, joins); int firstCount = getFirstQueryCount(con, tableList.stream().collect(Collectors.toList()), columns, randomWhereCondition, joins); if (firstCount == -1 || secondCount == -1) { throw new IgnoreMeException(); } if (firstCount != secondCount) { throw new AssertionError( optimizedQueryString + "; -- " + firstCount + "\n" + unoptimizedQueryString + " -- " + secondCount); } } private int getSecondQuery(List<Node<DuckDBExpression>> tableList, Node<DuckDBExpression> randomWhereCondition, List<Node<DuckDBExpression>> joins) throws SQLException { DuckDBSelect select = new DuckDBSelect(); // select.setGroupByClause(groupBys); // DuckDBExpression isTrue = DuckDBPostfixOperation.create(randomWhereCondition, // PostfixOperator.IS_TRUE); Node<DuckDBExpression> asText = new NewPostfixTextNode<>(new DuckDBCastOperation( new NewPostfixTextNode<DuckDBExpression>(randomWhereCondition, " IS NOT NULL AND " + DuckDBToStringVisitor.asString(randomWhereCondition)), new DuckDBCompositeDataType(DuckDBDataType.INT, 8)), "as count"); select.setFetchColumns(Arrays.asList(asText)); select.setFromList(tableList); // select.setSelectType(SelectType.ALL); select.setJoinList(joins); int secondCount = 0; unoptimizedQueryString = "SELECT SUM(count) FROM (" + DuckDBToStringVisitor.asString(select) + ") as res"; errors.add("canceling statement due to statement timeout"); SQLQueryAdapter q = new SQLQueryAdapter(unoptimizedQueryString, errors); SQLancerResultSet rs; try { rs = q.executeAndGetLogged(state); } catch (Exception e) { throw new AssertionError(unoptimizedQueryString, e); } if (rs == null) { return -1; } if (rs.next()) { secondCount += rs.getLong(1); } rs.close(); return secondCount; } private int getFirstQueryCount(SQLConnection con, List<Node<DuckDBExpression>> tableList, List<DuckDBColumn> columns, Node<DuckDBExpression> randomWhereCondition, List<Node<DuckDBExpression>> joins) throws SQLException { DuckDBSelect select = new DuckDBSelect(); // select.setGroupByClause(groupBys); // DuckDBAggregate aggr = new DuckDBAggregate( List<Node<DuckDBExpression>> allColumns = columns.stream() .map((c) -> new ColumnReferenceNode<DuckDBExpression, DuckDBColumn>(c)).collect(Collectors.toList()); // DuckDBAggregateFunction.COUNT); // select.setFetchColumns(Arrays.asList(aggr)); select.setFetchColumns(allColumns); select.setFromList(tableList); select.setWhereClause(randomWhereCondition); if (Randomly.getBooleanWithSmallProbability()) { select.setOrderByExpressions(new DuckDBExpressionGenerator(state).setColumns(columns).generateOrderBys()); } // select.setSelectType(SelectType.ALL); select.setJoinList(joins); int firstCount = 0; try (Statement stat = con.createStatement()) { optimizedQueryString = DuckDBToStringVisitor.asString(select); if (options.logEachSelect()) { logger.writeCurrent(optimizedQueryString); } try (ResultSet rs = stat.executeQuery(optimizedQueryString)) { while (rs.next()) { firstCount++; } } } catch (SQLException e) { throw new IgnoreMeException(); } return firstCount; } }