Fix SQLITE_DONE leak in ClearMetadata that broke DELETE on long text metadata (#274)

vec0Update_Delete_ClearMetadata's long-text branch runs a DELETE via
sqlite3_step, which returns SQLITE_DONE (101) on success. The code
checked for failure but never normalized the success case to SQLITE_OK.
The function's epilogue returned SQLITE_DONE as-is, which the caller
(vec0Update_Delete) treated as an error, aborting the DELETE scan and
silently leaving rows behind.

- Normalize rc to SQLITE_OK after successful sqlite3_step in ClearMetadata
- Move sqlite3_finalize before the rc check (cleanup on all paths)
- Add test_delete_by_metadata_with_long_text regression test
- Update test_deletes snapshot (row 3 now correctly deleted)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alex Garcia 2026-03-30 16:36:30 -07:00
parent dfd8dc5290
commit 4f7a8e410d
3 changed files with 43 additions and 26 deletions

View file

@ -8944,11 +8944,17 @@ int vec0Update_Delete_ClearMetadata(vec0_vtab *p, int metadata_idx, i64 rowid, i
}
sqlite3_bind_int64(stmt, 1, rowid);
rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);
if(rc != SQLITE_DONE) {
rc = SQLITE_ERROR;
goto done;
}
sqlite3_finalize(stmt);
// Fix for https://github.com/asg017/sqlite-vec/issues/274
// sqlite3_step returns SQLITE_DONE (101) on DML success, but the
// `done:` epilogue treats anything other than SQLITE_OK as an error.
// Without this, SQLITE_DONE propagates up to vec0Update_Delete,
// which aborts the DELETE scan and silently drops remaining rows.
rc = SQLITE_OK;
}
break;
}