Skip to content

dolt sql -q/-f: EXECUTE of a prepared DML statement (UPDATE/INSERT) silently applies nothing #11345

Description

@maphew

Summary

In dolt sql -q / dolt sql -f (CLI batch mode, no server), EXECUTE of a prepared write statement (UPDATE, INSERT) reports success but applies nothing. Prepared reads (SELECT) execute and return results, and the identical statements run directly apply fine — so scripts using SET @sql = ...; PREPARE stmt FROM @sql; EXECUTE stmt (the standard MySQL idiom for conditional migrations) silently lose their writes.

Steps to reproduce

dolt init --name t --email t@t
dolt sql -q "CREATE TABLE t2 (id VARCHAR(64) PRIMARY KEY, val INT); INSERT INTO t2 VALUES ('a',1);"

# Prepared UPDATE: no error, no effect
dolt sql -q "PREPARE s FROM 'UPDATE t2 SET val=9 WHERE id=''a'''; EXECUTE s; DEALLOCATE PREPARE s;"
dolt sql -q "SELECT val FROM t2 WHERE id='a'" -r csv   # => 1  (expected 9)

# Same via a user variable (the conditional-migration idiom): same silent no-op
dolt sql -q "SET @sql='UPDATE t2 SET val=8 WHERE id=''a'''; PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;"
dolt sql -q "SELECT val FROM t2 WHERE id='a'" -r csv   # => 1  (expected 8)

# Prepared INSERT: same
dolt sql -q "PREPARE s FROM 'INSERT INTO t2 VALUES (''b'',2)'; EXECUTE s;"
dolt sql -q "SELECT COUNT(*) FROM t2" -r csv           # => 1  (expected 2)

# Controls: prepared SELECT works; direct UPDATE works
dolt sql -q "PREPARE s FROM 'SELECT COUNT(*) AS n FROM t2'; EXECUTE s;"   # returns a result
dolt sql -q "UPDATE t2 SET val=5 WHERE id='a';"
dolt sql -q "SELECT val FROM t2 WHERE id='a'" -r csv   # => 5

Expected

EXECUTE of a prepared DML statement applies the write (or errors); it must not report success while changing nothing.

Observed

No error, no warning, zero effect. Reproduced on dolt 2.2.0 and 2.2.2 (linux-amd64), fresh dolt init database, no sql-server involved.

Impact

We hit this via a schema-migration file using the SET @sql = IF(<condition>, '<UPDATE ...>', 'SELECT 1'); PREPARE/EXECUTE idiom, applied through dolt sql -f: the migration's direct statements applied and its prepared recompute silently didn't, leaving derived state (a blocked-flag column) zeroed. Because nothing errors, the corruption is invisible until downstream behavior breaks.

claude-fable-5-xhigh on behalf of maphew

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions