Hi Michael, v17 applies to master (6a1c1102c4), builds warning-free, and make check-world passes here. Three small patches attached: 0001 applies to master, 0002 and 0003 on top of 0005.
1. The 8-byte counter survives standby promotion and crash recovery, which the tests of cb298616463d do not cover; 0001 adds the standby case to 004_timeline_switch.pl. Primary counter set to 4295067296 (2^32 + 100000), base backup, then 20000 values into an oid8 table, so the standby sees the counter only through XLOG_NEXTOID records. After promotion and 3000 more values, next_oid is 4295100064; the same after killing the primary with an immediate shutdown and restarting it. All 23000 values read back equal on both nodes, chunk_ids 4295067301 to 4295094871, all distinct. 2. pg_upgrade works both ways that matter: a v17 cluster with oid8 tables and the counter past 2^32 comes out usable, and a 16beta2 cluster comes out with its oid TOAST tables intact and able to add oid8 ones. v17 to v17: NextOID 4295067406 before and after, then 120 more rows into an oid8 and an oid table, 120 new distinct IDs each. 16beta2 to v17: an external and a compressed TOAST table stay oid, reads and inserts work, verify_heapam() finds nothing, an oid8 table created next to them works, and a plain dump restores with the same chunk_id types. 3. Logical decoding of oid8 values past 2^32 works, but no test in 0004 would catch it if it broke; 0002 adds one that does. Publisher and subscriber in one cluster, counter past 2^32, two rows with 9000-byte values, one then updated on a non-TOAST column, one given a new value: the subscriber ends with the same lengths and md5s, chunk_ids 4295067317 and 4295067319. The toast.sql additions in 0004 run with a young counter, so their IDs fit in 4 bytes and a chunk_id read as an Oid still matches. 0002 moves the counter past 2^32 in 006_logical_decoding.pl and decodes one oid8 value; with the chunk_id read the way it was before v14 the row comes out as data[text]:unchanged-toast-datum, with v17 it passes. 4. A rewrite after ALTER TABLE SET (toast_value_type) keeps the TOAST table's type either way, as Bharath concluded from the code. VACUUM FULL, CLUSTER, REPACK, SET UNLOGGED and SET LOGGED, on an oid table switched to oid8 and on an oid8 table with IDs past 2^32 switched to oid: chunk_id type unchanged, 50 of 50 values intact, verify_heapam() and bt_index_check() clean after each. Only a TOAST table created afterwards (ADD COLUMN on a table that had none, CREATE TABLE AS) picks up the new value. 5. For oid8 tables the -o docs are incomplete: a lost pg_control moves the counter backwards by itself, and the value to set, which the docs say there is no easy way to find, is one query away. 0003 says so under -o, and adds that the reloption has to be given on every partition (the reloptions test checks that a partitioned table rejects it; I checked that a partition created without it gets an oid TOAST table). Rare case: pg_control lost, cluster brought back with pg_resetwal -f as documented, the OID counter comes back as the guess, 10000. On a fresh cluster with 1000 values in an oid8 table (chunk_ids 16394 to 17393) and 1000 in an oid table, the oid table takes new rows as before and inserts into the oid8 table fail with ERROR: duplicate key value violates unique constraint "pg_toast_16384_index" each failed statement moving the counter by one, so a thousand failures before it comes back on its own. SELECT max(chunk_id) on the oid8 TOAST table gave 17393; pg_resetwal -o 17394 put it back to work. Regards, Rui
0001-Check-that-a-promoted-standby-keeps-the-8-byte-OID-c.patch
Description: Binary data
0002-Decode-an-oid8-TOAST-value-with-an-ID-past-2-32.patch
Description: Binary data
0003-Document-two-things-about-toast_value_type-oid8.patch
Description: Binary data
