step Exec to completion for SQLITE_ROW
The exec path treated SQLITE_ROW identically to SQLITE_DONE, calling newResult after a single step.
For DML with RETURNING clauses that affect multiple rows, this meant the statement was never stepped to completion, causing sqlite3_changes() to return stale counts.
Continue stepping until SQLITE_DONE before reading the result.
This could manifest as a performance regression: we're doing strictly more work by draining all the rows instead of abandoning them. But as Russ Cox says, I can make anything fast if it doesn't need to be correct.
This brings this Exec implementation in line with C sqlite3_exec in several ways:
-
Row draining: C sqlite3_exec loops sqlite3_step until rc != SQLITE_ROW, then finalizes.
-
Result after completion: C sqlite3_exec does finalize-after-loop.
-
Unconditional drain: C sqlite3_exec with a NULL callback still steps through every row.
-
Partial commit on interruption: C returns SQLITE_ABORT if the callback returns non-zero mid-drain, but already-stepped rows stay committed. (Use an explicit transaction for atomicity.)
-
Multi-statement iteration: C's outer loop prepares and fully steps each sub-statement.