Skip to content

Conversation

@DerZc
Copy link
Contributor

@DerZc DerZc commented Mar 22, 2025

Support CODDTest for SQLite. This is a sub-task of the larger implementation tracked in #1054.

Copy link
Contributor

@mrigger mrigger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, and sorry for the delay! I've added some improvement suggestions.

org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a temporary file, so we should avoid checking it in.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So sorry for this and I have addressed this now.

public void removeTable(T table) {
if (this.tables.contains(table)) {
this.tables.remove(table);
for (C c : table.getColumns()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it actually necessary to remove the columns?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's necessary for CODDTest. I introduced the removeTable method because, when using a join clause in the Original query, we need the same clause in the Auxiliary query. Since the Auxiliary query is generated first, the join clauses are fixed when generating the Original query. To avoid redundant tables in the FROM clause, I remove them accordingly.
While it's not essential to remove columns in CODDTest—since they're used to generate other expressions—it might still be better to do so. If removeTable is reused by other components, it could leave behind columns in WHERE or other clauses that no longer belong to any table.

}
}

public Boolean isContained(T table) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should return a primitive boolean value rather than an Object.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have addressed this.

public int maxNumIndexes = 20;

@Parameter(names = { "--coddtest-model" }, description = "Apply CODDTest on expression, subquery, or random")
public String coddTestModel = "random";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use an enum here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this will be better and I updated this.

sb.append(")");
}
if (!s.getGroupByClause().isEmpty()) {
if (s.getGroupByClause().size() > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep the isEmpty here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I honestly can't remember why I made that change at the time, even though they look the same. I have addressed this now.

return this.withClause;
}

public void replaceFromTable(String tableName, SQLite3Expression newFromExpression) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a short comment to explain this method would be helpful.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I add a short comment fot this method.

public enum SQLite3DataType {
NULL, INT, TEXT, REAL, NONE, BINARY;

public static SQLite3DataType getTypeFromName(String name) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could use the builtin enum functionality for that (valueOf).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to use valueOf but found some name are different from type, for example integer and INT

visit(vs.get(name).get(i));
sb.append(" AS ");
switch(vs.get(name).get(i).getDataType()) {
case BINARY:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to implement the cast string representation directly in the data type class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! I have addressed this.


@Override
public void visit(SQLite3ResultMap tableSummary) {
// we utlize CASE WHEN THEN END here
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utilize

}

@Override
public void visit(SQLite3ResultMap tableSummary) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we perhaps extract smaller method calls for readability?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the code handling cases where an expression returns no results under the current database state, since I now discard the expression when it has no results. To ensure safety in case this method is used by other components, I’ve updated it to throw an exception if the expression yields an empty result.

@DerZc
Copy link
Contributor Author

DerZc commented Apr 9, 2025

Thank you for your feedback! I’ll make these updates as soon as possible.

@DerZc DerZc force-pushed the coddtest_sqlite branch from 986dcd1 to 089d2d0 Compare April 10, 2025 10:58
@Parameter(names = { "--max-num-indexes" }, description = "The maximum number of indexes that can be created")
public int maxNumIndexes = 20;

public enum coddtest_model {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use Java naming conventions like "CODDTestModel" here and below: RANDOM, EXPRESSION, and SUBQUERY.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated!

sb.append(vs.get(name).get(i).getDataType().toString());
sb.append("))");
}
isFirstColumn = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this intended? I think this should be false?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So sorry I make an error here, and fix it now

}


public void addTable(T table) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, we would also add test cases later on for these new methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I add the unit tests for these new methods and an unit tests for SQLite3 CODDTest oracle.

errors.add("misuse of aggregate");
errors.add("misuse of window function");
errors.add("second argument to nth_value must be a positive integer");
errors.add("no such table");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's surprising that such an error could happen. Do you know why?

errors.add("no such table");
errors.add("no query solution");
errors.add("unable to use function MATCH in the requested context");
errors.add("[SQLITE_ERROR] SQL error or missing database (unrecognized token:");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this indicate a syntax error?

@mrigger
Copy link
Contributor

mrigger commented Apr 21, 2025

The CI tests currently fail (see mvn -B verify -DskipTests=true). After fixing them and checking that the CI tests run CODDTest, I think we can merge the PR. I find the test oracle implementation quite complex and think there would be room for simplifying it, but it would be better to first get the PR in.

@mrigger
Copy link
Contributor

mrigger commented Apr 23, 2025

Error: Failed to execute goal net.revelc.code.formatter:formatter-maven-plugin:2.20.0:validate (eclipseformat) on project sqlancer: File '/home/runner/work/sqlancer/sqlancer/src/sqlancer/hive/HiveToStringVisitor.java' has not been previously formatted. Please format file (for example by invoking mvn net.revelc.code.formatter:formatter-maven-plugin:2.20.0:format) and commit before running validation! -> [Help 1]

Strange, perhaps this is an issue that made it in with another PR. Could you please run mvn formatter:format nevertheless so that the general tests pass (again)?

@mrigger
Copy link
Contributor

mrigger commented Apr 23, 2025

For the tests to run, I think you'll need to add them here:

mvn -Dtest=TestSQLitePQS test
mvn -Dtest=TestSQLiteTLP test
mvn -Dtest=TestSQLiteNoREC test

Copy link
Contributor

@mrigger mrigger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, lgtm!

@mrigger mrigger merged commit 3d9a5cc into sqlancer:main Apr 24, 2025
17 of 26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants