Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
107 changes: 107 additions & 0 deletions src/sqlancer/common/oracle/DQEBase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package sqlancer.common.oracle;

import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import sqlancer.MainOptions;
import sqlancer.SQLConnection;
import sqlancer.SQLGlobalState;
import sqlancer.common.query.ExpectedErrors;
import sqlancer.common.query.SQLQueryAdapter;
import sqlancer.common.query.SQLQueryError;
import sqlancer.common.schema.AbstractRelationalTable;

public abstract class DQEBase<S extends SQLGlobalState<?, ?>> {

public static final String COLUMN_ROWID = "rowId";
public static final String COLUMN_UPDATED = "updated";

protected final S state;
protected final ExpectedErrors selectExpectedErrors = new ExpectedErrors();
protected final ExpectedErrors updateExpectedErrors = new ExpectedErrors();
protected final ExpectedErrors deleteExpectedErrors = new ExpectedErrors();

// protected final Main.StateLogger logger;
protected final MainOptions options;
protected final SQLConnection con;

public DQEBase(S state) {
this.state = state;
this.con = state.getConnection();
// this.logger = state.getLogger();
this.options = state.getOptions();
}

public abstract void addAuxiliaryColumns(AbstractRelationalTable<?, ?, ?> table) throws SQLException;

public void dropAuxiliaryColumns(AbstractRelationalTable<?, ?, ?> table) throws SQLException {
String tableName = table.getName();
String dropColumnRowId = String.format("ALTER TABLE %s DROP COLUMN %s", tableName, COLUMN_ROWID);
new SQLQueryAdapter(dropColumnRowId).execute(state);
String dropColumnUpdated = String.format("ALTER TABLE %s DROP COLUMN %s", tableName, COLUMN_UPDATED);
new SQLQueryAdapter(dropColumnUpdated).execute(state);
}

public static class SQLQueryResult {

private final Map<AbstractRelationalTable<?, ?, ?>, Set<String>> accessedRows; // Table name with respect rows
private final List<SQLQueryError> queryErrors;

public SQLQueryResult(Map<AbstractRelationalTable<?, ?, ?>, Set<String>> accessedRows,
List<SQLQueryError> queryErrors) {
this.accessedRows = accessedRows;
this.queryErrors = queryErrors;
}

public Map<AbstractRelationalTable<?, ?, ?>, Set<String>> getAccessedRows() {
return accessedRows;
}

public List<SQLQueryError> getQueryErrors() {
return queryErrors;
}

public boolean hasEmptyErrors() {
return queryErrors.isEmpty();
}

public boolean hasErrors() {
return !hasEmptyErrors();
}

public boolean hasSameErrors(SQLQueryResult that) {
if (queryErrors.size() != that.getQueryErrors().size()) {
return false;
} else {
Collections.sort(queryErrors);
Collections.sort(that.getQueryErrors());
for (int i = 0; i < queryErrors.size(); i++) {
if (!queryErrors.get(i).equals(that.getQueryErrors().get(i))) {
return false;
}
}
}
return true;
}

public boolean hasAccessedRows() {
if (accessedRows.isEmpty()) {
return false;
}
for (Set<String> accessedRow : accessedRows.values()) {
if (!accessedRow.isEmpty()) {
return true;
}
}
return false;
}

public boolean hasSameAccessedRows(SQLQueryResult that) {
return accessedRows.equals(that.getAccessedRows());
}

}
}
111 changes: 111 additions & 0 deletions src/sqlancer/common/query/SQLQueryError.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package sqlancer.common.query;

import java.util.Objects;

public class SQLQueryError implements Comparable<SQLQueryError> {

public enum ErrorLevel {
WARNING, ERROR
}

private ErrorLevel level;
private int code;
private String message;

public void setLevel(String level) {
// value of is case-sensitive
this.level = ErrorLevel.valueOf(level.toUpperCase());
}

public void setCode(int code) {
this.code = code;
}

public void setMessage(String message) {
this.message = message;
}

public ErrorLevel getLevel() {
return level;
}

public int getCode() {
return code;
}

public String getMessage() {
return message;
}

public boolean hasSameLevel(SQLQueryError that) {
return Objects.equals(level, that.getLevel());
}

public boolean hasSameCodeAndMessage(SQLQueryError that) {
if (code != that.getCode()) {
return false;
}
return Objects.equals(message, that.getMessage());
}

@Override
public boolean equals(Object that) {
if (that == null) {
return false;
}
if (that instanceof SQLQueryError) {
SQLQueryError thatError = (SQLQueryError) that;
if (hasSameLevel(thatError) && hasSameCodeAndMessage(thatError)) {
return true;
}
}
return false;
}

@Override
public String toString() {
return String.format("Level: %s; Code: %d; Message: %s.", level, code, message);
}

@Override
public int compareTo(SQLQueryError that) {
if (code < that.getCode()) {
return -1;
} else if (code > that.getCode()) {
return 1;
}

if (level == null && that.getLevel() != null) {
return -1;
}
if (level != null && that.getLevel() == null) {
return 1;
}
if (level != null && that.getLevel() != null) {
int res = level.compareTo(that.getLevel());
if (res != 0) {
return res;
}
}

if (message == null && that.getMessage() != null) {
return -1;
}
if (message != null && that.getMessage() == null) {
return 1;
}
if (message != null && that.getMessage() != null) {
int res = message.compareTo(that.getMessage());
if (res != 0) {
return res;
}
}

return 0;
}

@Override
public int hashCode() {
return Objects.hash(level, code, message);
}
}