You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A DELETE whose qual deletes another row of the same columnar table fails: 'attempted to update invisible tuple' #1394
A columnar DELETE fails when its qual calls a function that deletes another row of the same table. Heap deletes both.
CREATEFUNCTIONg(i int, t text) RETURNS int LANGUAGE plpgsql AS $$
BEGIN EXECUTE format('DELETE FROM %s WHERE id = %s', t, i +1); RETURN 1; END $$;
CREATETABLEu (id int, v int) USING pgcolumnar;
INSERT INTO u SELECT g, 0FROM generate_series(1, 20) g;
DELETEFROM u WHERE id % 2=0AND g(id, 'u') IS NOT NULL;
-- columnar: ERROR: attempted to update invisible tuple-- heap: DELETE 10, and 1 row is left
Measured on PG16, on #1364's tree (192d51b). No subtransaction is involved. The same error also appears when the inner DELETE runs in a plpgsql EXCEPTION block, which is how I found it (#1360).
Why (from reading the code; the fix will confirm it)
The outer DELETE buffers a mark for row 2.
For row 4, the function's DELETE starts a scan. Scan start flushes the buffered marks, so PgColumnarUpsertDeleteVector updates the group's delete_vector row in command k.
When that inner statement ends, its own mark (row 5, same row group) is flushed in the same command k. The upsert finds the row version written in step 2 (SnapshotSelf sees it) and updates it.
heap_update refuses a tuple whose cmin is not below the current command id (TM_Invisible), hence "attempted to update invisible tuple".
The comment on delete_vector_flush_buffer assumes each chunk group is upserted once per command. A scan-start flush followed by a statement-end flush in the same command breaks that.
Proposed fix
In the upsert, when the existing version was written by the current command, advance the command counter before updating it. Red first: the reproduction above as an arm comparing columnar with heap, in both twins.
Activity
fix: a DELETE whose qual deletes another row of the same table no lon…
fix: a DELETE whose qual deletes another row of the same table no lon…
Merge pull request #1396 from commandprompt/fix/1394-double-upsert