Skip to content

Sync with upstream #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
3095ec5
Add TLPWhereGenerator interface
malwaregarry Apr 11, 2024
307713a
Add generic TLPWhere oracle
malwaregarry Apr 11, 2024
6e42048
Implement TLPWhereGenerator interfaces for SQLite3
malwaregarry Apr 11, 2024
17f7d3e
Use generic TLPWhere oracle for SQLite3
malwaregarry Apr 11, 2024
3989d76
[Databend] Refactor tests
malwaregarry Jun 29, 2024
37de4a2
[Databend] Update to v1.2.542
malwaregarry Jun 29, 2024
92fb688
Remove duplicated logs in NoREC oracle (#953)
malwaregarry Jul 8, 2024
2269032
Merge pull request #952 from malwaregarry/databend-ci2
mrigger Jul 8, 2024
3981bee
Merge pull request #942 from malwaregarry/sqlite-tlp-where
mrigger Jul 8, 2024
852c1e4
[ClickHouse] Added pattern for changed error message (#955)
qoega Jul 15, 2024
ec00b2d
Avoid storage parameters during CREATE TABLE for partitioned tables (…
robins Jul 16, 2024
6d2b92a
Review feedback
2010YOUY01 Jul 16, 2024
e18707e
Merge pull request #954 from 2010YOUY01/datafusion-init
mrigger Jul 16, 2024
0316c1c
Ensure INHERITS() only uses tables (not views)
robins Jul 17, 2024
cc189b4
Revert "Ensure INHERITS() only uses tables (not views)"
robins Jul 17, 2024
96adb54
Ensure INHERITS() only uses tables (not views)
robins Jul 17, 2024
c247c88
Merge pull request #957 from robins/inherits_should_only_use_tables
mrigger Jul 17, 2024
51e7ae8
Another fix
qoega Jul 18, 2024
7274143
Merge pull request #958 from qoega/qoega-patch-2
mrigger Jul 18, 2024
bb53912
Merge remote-tracking branch 'upstream/main'
2010YOUY01 Jul 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/sqlancer/clickhouse/ClickHouseErrors.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ public static List<String> getExpectedExpressionErrors() {
"Positional argument numeric constant expression is not representable as",
"Positional argument must be constant with numeric type", " is out of bounds. Expected in range",
"with constants is not supported. (INVALID_JOIN_ON_EXPRESSION)",
"Unexpected inf or nan to integer conversion", "Unsigned type must not contain",
"Cannot get JOIN keys from JOIN ON section", "Unexpected inf or nan to integer conversion",
"Cannot determine join keys in", "Unsigned type must not contain",
"Unexpected inf or nan to integer conversion",

// The way we generate JOINs we can have ambiguous left table column without
Expand Down
27 changes: 27 additions & 0 deletions src/sqlancer/common/gen/PartitionGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package sqlancer.common.gen;

import sqlancer.common.ast.newast.Expression;
import sqlancer.common.schema.AbstractTableColumn;

public interface PartitionGenerator<E extends Expression<C>, C extends AbstractTableColumn<?, ?>> {

/**
* Negates a predicate (i.e., uses a NOT operator).
*
* @param predicate
* the boolean predicate.
*
* @return the negated predicate.
*/
E negatePredicate(E predicate);

/**
* Checks if an expression evaluates to NULL (i.e., implements the IS NULL operator).
*
* @param expr
* the expression
*
* @return an expression that checks whether the expression evaluates to NULL.
*/
E isNull(E expr);
}
28 changes: 28 additions & 0 deletions src/sqlancer/common/gen/TLPWhereGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package sqlancer.common.gen;

import java.util.List;

import sqlancer.common.ast.newast.Expression;
import sqlancer.common.ast.newast.Join;
import sqlancer.common.ast.newast.Select;
import sqlancer.common.schema.AbstractTable;
import sqlancer.common.schema.AbstractTableColumn;
import sqlancer.common.schema.AbstractTables;

public interface TLPWhereGenerator<S extends Select<J, E, T, C>, J extends Join<E, T, C>, E extends Expression<C>, T extends AbstractTable<C, ?, ?>, C extends AbstractTableColumn<?, ?>>
extends PartitionGenerator<E, C> {

TLPWhereGenerator<S, J, E, T, C> setTablesAndColumns(AbstractTables<T, C> tables);

E generateBooleanExpression();

S generateSelect();

List<J> getRandomJoinClauses();

List<E> getTableRefs();

List<E> generateFetchColumns(boolean shouldCreateDummy);

List<E> generateOrderBys();
}
8 changes: 0 additions & 8 deletions src/sqlancer/common/oracle/NoRECOracle.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,6 @@ public Reproducer<G> getLastReproducer() {
private int countRows(String queryString, ExpectedErrors errors, SQLGlobalState<?, ?> state) {
SQLQueryAdapter q = new SQLQueryAdapter(queryString, errors);

if (state.getOptions().logEachSelect()) {
state.getLogger().writeCurrent(queryString);
}

int count = 0;
try (SQLancerResultSet rs = q.executeAndGet(state)) {
if (rs == null) {
Expand All @@ -151,10 +147,6 @@ private int countRows(String queryString, ExpectedErrors errors, SQLGlobalState<

private int extractCounts(String queryString, ExpectedErrors errors, SQLGlobalState<?, ?> state) {
SQLQueryAdapter q = new SQLQueryAdapter(queryString, errors);
if (state.getOptions().logEachSelect()) {
state.getLogger().writeCurrent(queryString);
}

int count = 0;
try (SQLancerResultSet rs = q.executeAndGet(state)) {
if (rs == null) {
Expand Down
84 changes: 84 additions & 0 deletions src/sqlancer/common/oracle/TLPWhereOracle.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package sqlancer.common.oracle;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import sqlancer.ComparatorHelper;
import sqlancer.Randomly;
import sqlancer.SQLGlobalState;
import sqlancer.common.ast.newast.Expression;
import sqlancer.common.ast.newast.Join;
import sqlancer.common.ast.newast.Select;
import sqlancer.common.gen.TLPWhereGenerator;
import sqlancer.common.query.ExpectedErrors;
import sqlancer.common.schema.AbstractSchema;
import sqlancer.common.schema.AbstractTable;
import sqlancer.common.schema.AbstractTableColumn;
import sqlancer.common.schema.AbstractTables;

public class TLPWhereOracle<Z extends Select<J, E, T, C>, J extends Join<E, T, C>, E extends Expression<C>, S extends AbstractSchema<?, T>, T extends AbstractTable<C, ?, ?>, C extends AbstractTableColumn<?, ?>, G extends SQLGlobalState<?, S>>
implements TestOracle<G> {

private final G state;

private TLPWhereGenerator<Z, J, E, T, C> gen;
private final ExpectedErrors errors;

private String generatedQueryString;

public TLPWhereOracle(G state, TLPWhereGenerator<Z, J, E, T, C> gen, ExpectedErrors expectedErrors) {
if (state == null || gen == null || expectedErrors == null) {
throw new IllegalArgumentException("Null variables used to initialize test oracle.");
}
this.state = state;
this.gen = gen;
this.errors = expectedErrors;
}

@Override
public void check() throws SQLException {
S s = state.getSchema();
AbstractTables<T, C> targetTables = TestOracleUtils.getRandomTableNonEmptyTables(s);
gen = gen.setTablesAndColumns(targetTables);

Select<J, E, T, C> select = gen.generateSelect();

boolean shouldCreateDummy = true;
select.setFetchColumns(gen.generateFetchColumns(shouldCreateDummy));
select.setJoinClauses(gen.getRandomJoinClauses());
select.setFromList(gen.getTableRefs());
select.setWhereClause(null);

String originalQueryString = select.asString();
generatedQueryString = originalQueryString;
List<String> firstResultSet = ComparatorHelper.getResultSetFirstColumnAsString(originalQueryString, errors,
state);

boolean orderBy = Randomly.getBooleanWithSmallProbability();
if (orderBy) {
select.setOrderByClauses(gen.generateOrderBys());
}

TestOracleUtils.PredicateVariants<E, C> predicates = TestOracleUtils.initializeTernaryPredicateVariants(gen,
gen.generateBooleanExpression());
select.setWhereClause(predicates.predicate);
String firstQueryString = select.asString();
select.setWhereClause(predicates.negatedPredicate);
String secondQueryString = select.asString();
select.setWhereClause(predicates.isNullPredicate);
String thirdQueryString = select.asString();

List<String> combinedString = new ArrayList<>();
List<String> secondResultSet = ComparatorHelper.getCombinedResultSet(firstQueryString, secondQueryString,
thirdQueryString, combinedString, !orderBy, state, errors);

ComparatorHelper.assumeResultSetsAreEqual(firstResultSet, secondResultSet, originalQueryString, combinedString,
state);
}

@Override
public String getLastQueryString() {
return generatedQueryString;
}
}
33 changes: 33 additions & 0 deletions src/sqlancer/common/oracle/TestOracleUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import sqlancer.IgnoreMeException;
import sqlancer.Randomly;
import sqlancer.common.ast.newast.Expression;
import sqlancer.common.gen.PartitionGenerator;
import sqlancer.common.schema.AbstractSchema;
import sqlancer.common.schema.AbstractTable;
import sqlancer.common.schema.AbstractTableColumn;
Expand All @@ -12,11 +14,42 @@ public final class TestOracleUtils {
private TestOracleUtils() {
}

public static final class PredicateVariants<E extends Expression<C>, C extends AbstractTableColumn<?, ?>> {
public E predicate;
public E negatedPredicate;
public E isNullPredicate;

PredicateVariants(E predicate, E negatedPredicate, E isNullPredicate) {
this.predicate = predicate;
this.negatedPredicate = negatedPredicate;
this.isNullPredicate = isNullPredicate;
}
}

public static <T extends AbstractTable<C, ?, ?>, C extends AbstractTableColumn<?, ?>> AbstractTables<T, C> getRandomTableNonEmptyTables(
AbstractSchema<?, T> schema) {
if (schema.getDatabaseTables().isEmpty()) {
throw new IgnoreMeException();
}
return new AbstractTables<>(Randomly.nonEmptySubset(schema.getDatabaseTables()));
}

public static <E extends Expression<C>, T extends AbstractTable<C, ?, ?>, C extends AbstractTableColumn<?, ?>> PredicateVariants<E, C> initializeTernaryPredicateVariants(
PartitionGenerator<E, C> gen, E predicate) {
if (gen == null) {
throw new IllegalStateException();
}
if (predicate == null) {
throw new IllegalStateException();
}
E negatedPredicate = gen.negatePredicate(predicate);
if (negatedPredicate == null) {
throw new IllegalStateException();
}
E isNullPredicate = gen.isNull(predicate);
if (isNullPredicate == null) {
throw new IllegalStateException();
}
return new PredicateVariants<>(predicate, negatedPredicate, isNullPredicate);
}
}
7 changes: 3 additions & 4 deletions src/sqlancer/datafusion/DataFusionProvider.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package sqlancer.datafusion;

import static java.lang.System.exit;
import static sqlancer.datafusion.DataFusionUtil.DataFusionLogger.DataFusionLogType.DML;
import static sqlancer.datafusion.DataFusionUtil.dfAssert;
import static sqlancer.datafusion.DataFusionUtil.displayTables;

import java.sql.Connection;
Expand Down Expand Up @@ -52,13 +52,12 @@ public void generateDatabase(DataFusionGlobalState globalState) throws Exception
List<DataFusionTable> allTables = globalState.getSchema().getDatabaseTables();
List<String> allTablesName = allTables.stream().map(t -> t.getName()).collect(Collectors.toList());
if (allTablesName.isEmpty()) {
System.out.println("Generate database failed");
exit(1);
dfAssert(false, "Generate Database failed.");
}

// Randomly insert some data into existing tables
for (DataFusionTable table : allTables) {
int nInsertQuery = globalState.getRandomly().getInteger(0, 8); // [0, 10)
int nInsertQuery = globalState.getRandomly().getInteger(0, globalState.getOptions().getMaxNumberInserts());

for (int i = 0; i < nInsertQuery; i++) {
SQLQueryAdapter insertQuery = null;
Expand Down
25 changes: 11 additions & 14 deletions src/sqlancer/datafusion/DataFusionUtil.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package sqlancer.datafusion;

import static java.lang.System.exit;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
Expand Down Expand Up @@ -66,11 +64,15 @@ public static String displayTables(DataFusionGlobalState state, List<String> fro
return resultStringBuilder.toString();
}

// During development, you might want to manually let this function call exit(1) to fail fast
public static void dfAssert(boolean condition, String message) {
if (!condition) {
String methodName = Thread.currentThread().getStackTrace()[2].getMethodName();
System.err.println("DataFusion assertion failed in function '" + methodName + "': " + message);
exit(1);
// // Development mode assertion failure
// String methodName = Thread.currentThread().getStackTrace()[2]// .getMethodName();
// System.err.println("DataFusion assertion failed in function '" + methodName + "': " + message);
// exit(1);

throw new AssertionError(message);
}
}

Expand Down Expand Up @@ -149,9 +151,7 @@ public void appendToLog(DataFusionLogType logType, String logContent) {
try {
logFileWriter = new FileWriter(errorLogFile, true);
} catch (IOException e) {
System.out.println("Failed to create FileWriter for errorLogFIle");
e.printStackTrace();
exit(1);
dfAssert(false, "Failed to create FileWriter for errorLogFIle");
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedDateTime = LocalDateTime.now().format(formatter);
Expand All @@ -175,14 +175,11 @@ public void appendToLog(DataFusionLogType logType, String logContent) {
logFileWriter.write(logContent);
logFileWriter.flush();
} catch (IOException e) {
System.out.println("Failed to write to " + logType + " log: " + e.getMessage());
e.printStackTrace();
exit(1);
String err = "Failed to write to " + logType + " log: " + e.getMessage();
dfAssert(false, err);
}
} else {
System.out.println("appending to log failed");
Thread.currentThread().getStackTrace();
exit(1);
dfAssert(false, "appending to log failed");
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/sqlancer/datafusion/server/datafusion_server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ async-trait = "0.1.73"
bytes = "1.4"
chrono = { version = "0.4.34", default-features = false }
dashmap = "5.5.0"
# This version is for SQLancer CI run
datafusion = { version = "40.0.0" }
# datafusion = { git = "https://github.com/apache/datafusion.git", branch = "main"}
datafusion_dev = { package = "datafusion", git = "https://github.com/apache/datafusion.git", branch = "main", optional = true }
# Use following line if you want to test against the latest main branch of DataFusion
# datafusion = { git = "https://github.com/apache/datafusion.git", branch = "main" }
env_logger = "0.11"
futures = "0.3"
half = { version = "2.2.1", default-features = false }
Expand Down
6 changes: 4 additions & 2 deletions src/sqlancer/postgres/gen/PostgresTableGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ private void createStandard() throws AssertionError {
generateInherits();
generatePartitionBy();
generateUsing();
PostgresCommon.generateWith(sb, globalState, errors);
if (!isPartitionedTable) {
PostgresCommon.generateWith(sb, globalState, errors);
}
if (Randomly.getBoolean() && isTemporaryTable) {
sb.append(" ON COMMIT ");
sb.append(Randomly.fromOptions("PRESERVE ROWS", "DELETE ROWS", "DROP"));
Expand Down Expand Up @@ -205,7 +207,7 @@ private void generateUsing() {
}

private void generateInherits() {
if (Randomly.getBoolean() && !newSchema.getDatabaseTables().isEmpty()) {
if (Randomly.getBoolean() && !newSchema.getDatabaseTablesWithoutViews().isEmpty()) {
sb.append(" INHERITS(");
sb.append(newSchema.getDatabaseTablesRandomSubsetNotEmpty().stream().map(t -> t.getName())
.collect(Collectors.joining(", ")));
Expand Down
17 changes: 16 additions & 1 deletion src/sqlancer/sqlite3/gen/SQLite3ExpressionGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import sqlancer.Randomly;
import sqlancer.common.gen.ExpressionGenerator;
import sqlancer.common.gen.NoRECGenerator;
import sqlancer.common.gen.TLPWhereGenerator;
import sqlancer.common.schema.AbstractTables;
import sqlancer.sqlite3.SQLite3GlobalState;
import sqlancer.sqlite3.ast.SQLite3Aggregate;
Expand Down Expand Up @@ -50,7 +51,8 @@
import sqlancer.sqlite3.schema.SQLite3Schema.SQLite3Table;

public class SQLite3ExpressionGenerator implements ExpressionGenerator<SQLite3Expression>,
NoRECGenerator<SQLite3Select, Join, SQLite3Expression, SQLite3Table, SQLite3Column> {
NoRECGenerator<SQLite3Select, Join, SQLite3Expression, SQLite3Table, SQLite3Column>,
TLPWhereGenerator<SQLite3Select, Join, SQLite3Expression, SQLite3Table, SQLite3Column> {

private SQLite3RowValue rw;
private final SQLite3GlobalState globalState;
Expand Down Expand Up @@ -133,6 +135,7 @@ public static SQLite3Expression getRandomLiteralValue(SQLite3GlobalState globalS
return new SQLite3ExpressionGenerator(globalState).getRandomLiteralValueInternal(globalState.getRandomly());
}

@Override
public List<SQLite3Expression> generateOrderBys() {
List<SQLite3Expression> expressions = new ArrayList<>();
for (int i = 0; i < Randomly.smallNumber() + 1; i++) {
Expand Down Expand Up @@ -747,6 +750,18 @@ public List<SQLite3Expression> getTableRefs() {
return tableRefs;
}

@Override
public List<SQLite3Expression> generateFetchColumns(boolean shouldCreateDummy) {
List<SQLite3Expression> columns = new ArrayList<>();
if (shouldCreateDummy && Randomly.getBoolean()) {
columns.add(new SQLite3ColumnName(SQLite3Column.createDummy("*"), null));
} else {
columns = Randomly.nonEmptySubset(this.columns).stream().map(c -> new SQLite3ColumnName(c, null))
.collect(Collectors.toList());
}
return columns;
}

@Override
public String generateOptimizedQueryString(SQLite3Select select, SQLite3Expression whereCondition,
boolean shouldUseAggregate) {
Expand Down
Loading
Loading