Skip to content

Extend the EET DML oracle to INSERT support - #1358

Open
tlmorgan24 wants to merge 3 commits into
mainfrom
feature/eet-insert
Open

Extend the EET DML oracle to INSERT support#1358
tlmorgan24 wants to merge 3 commits into
mainfrom
feature/eet-insert

Conversation

@tlmorgan24

@tlmorgan24 tlmorgan24 commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

The EET DML oracle (EETDMLOracle) previously transformed DELETE and UPDATE statements. This PR adds INSERT to the same oracle.

The INSERT is generated in the INSERT ... SELECT form rather than INSERT ... VALUES. This is because, when a value expression is transformed, the transformer introduces equivalent sub-expressions that reference the table's columns (for example, the random predicate inside a CASE WHEN). Column references are legal in a SELECT but not in a VALUES clause, so a VALUES form would produce invalid SQL without additional workarounds. Note, this does NOT mean that the testing is limited to only insert column references. It can still insert new constants too. For example, INSERT INTO t (c1) SELECT (123) FROM t WHERE p would insert n rows with the constant 123, where n is the number of rows in t which satisfy p. So, the INSERT ... SELECT form is expected to stress the DBMS at least as much as the INSERT ... VALUES form would.

Because INSERT ... SELECT inserts one new row per source row, each new row needs an identifier so the two runs' states can be lined up. Although the existing rows are originally stamped with UUID(), this cannot be used for the inserted rows, because it would be non-deterministic across the two runs. The implementation chosen here for MySQL simply removes the four dashes from the existing row's rowid, using REPLACE(rowid, '-', ''). This is deterministic (both runs assign the same identifiers), unique per source row, and distinct from every existing identifier (a 32-character string never equals the 36-character source string). It also fits the existing identifier column without widening it.

@tlmorgan24
tlmorgan24 requested a review from mrigger August 13, 2026 05:59
@mrigger

mrigger commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

The INSERT is generated in the INSERT ... SELECT form rather than INSERT ... VALUES.

Just a quick check: assuming that this is a workaround, could we just set the column list in the generator temporarily to be empty? Not sure if I understood the problem correctly.

@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! Just waiting for a response to the other comment I just posted before merging.

@Override
public List<MySQLExpression> generateInsertValues() {
// One value per content column, in schema order (aligned with the INSERT column list). As with the normal
// INSERT workload, each value is an arbitrary expression (not type-matched to the column); any resulting

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.

Ah, I wasn't aware or forgot that the INSERT generator is untyped. Probably, it should be typed, as it would make it much more likely to generate meaningful databases. But, I guess that's for another PR.

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, FYI this isn't MySQL-specific, it is a similar story for most other weakly typed DBMSs

@tlmorgan24

Copy link
Copy Markdown
Collaborator Author

The INSERT is generated in the INSERT ... SELECT form rather than INSERT ... VALUES.

Just a quick check: assuming that this is a workaround, could we just set the column list in the generator temporarily to be empty? Not sure if I understood the problem correctly.

Yes, it is possible to implement INSERT ... VALUES. The decision was mainly which of the two to implement first, and the other could be a later PR. I ended up thinking that INSERT ... SELECT was a simpler initial implementation, as it slots into the UPDATE and DELETE path more naturally, using the same DMLStatementGenerator signature. It also offers more transformation points (values and predicate) than INSERT ... VALUES (values only), potentially stressing the DBMS more. That said, INSERT ... VALUES may use a different execution path than INSERT ... SELECT, so adding it would increase coverage.

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