Skip to content

Extend the EET DML oracle to UPDATE support - #1357

Merged
mrigger merged 4 commits into
mainfrom
feature/eet-update
Aug 12, 2026
Merged

Extend the EET DML oracle to UPDATE support#1357
mrigger merged 4 commits into
mainfrom
feature/eet-update

Conversation

@tlmorgan24

Copy link
Copy Markdown
Collaborator

The EET DML oracle (EETDMLOracle) previously transformed only DELETE statements. This PR adds UPDATE to the same oracle. The key difference from DELETE is that UPDATE has two kinds of transformable expression (the WHERE predicate and each SET value expression) rather than one.

Comparing which rows are affected is no longer enough (two runs could change the same rows but write different values, which we would want to flag as a bug). The comparison is therefore upgraded to a full post-image (for each surviving row, its identifier together with every content column's value). This covers both UPDATE and DELETE statements, subsuming DELETE's previous surviving-row-set comparison. It will also, with small additions, be able to cover INSERT statements, which will be added next.

Effort has been made to make the logs for reported bugs clear, showing the post-image discrepancy of the relevant rows. Test case reduction is left to a later PR.

@tlmorgan24
tlmorgan24 requested a review from mrigger August 8, 2026 06:32
String originalStatement;
String transformedStatement;
if (Randomly.getBoolean()) {
// UPDATE also transforms the written values: each SET value expression is transformed in a scalar context.

Copy link
Copy Markdown
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 nice to have a method whose name would make the two options immediately clear. However, I assume that is not straightforward given the two return values?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in latest push. To get around the two-return-values issue, I created a simple StatementPair class, which the methods return instances of

}
while (result.next()) {
List<String> row = new ArrayList<>(columnCount);
for (int i = 1; i <= columnCount; i++) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just to double-check, starting from 1 here is intended?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, result.getString(i) uses JDBC ResultSet indexing, which is 1-based

SQLQueryAdapter q = new SQLQueryAdapter(selectStatement, errors, true,
state.getOptions().canonicalizeSqlString());
SQLancerResultSet result = null;
try {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We could subsequently think whether we can extract such low-level result handling logic to a more high-level API.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, this would be cleaner, I will take note of it for a future PR

private static Map<String, List<String>> indexByRowId(List<List<String>> image) {
Map<String, List<String>> byRowId = new LinkedHashMap<>();
for (List<String> row : image) {
byRowId.put(row.get(0), row);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

could we have a named constant, similar to the existing ROW_ID_COLUMN? This would make it clearer what part of the code relies on this assumption.

@tlmorgan24 tlmorgan24 Aug 12, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in latest push. Instead of using an additional named constant, I ended up designing it so that everything is derived from the existing ROW_ID_COLUMN

@mrigger mrigger left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, thanks!

@mrigger
mrigger merged commit 41550d1 into main Aug 12, 2026
47 of 50 checks passed
@mrigger
mrigger deleted the feature/eet-update branch August 12, 2026 15:14
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