An index-only scan fills its result slot from the HeapTuple an index AM returns in scan->xs_hitup by deforming it with the virtual slot's tuple descriptor. But the index AM formed that tuple with its own descriptor, scan->xs_hitupdesc, and the two may disagree about tuple layout. While each individual column's data *is* binary compatible, that doesn't ensure that each "described tuple shape" has compatible alignment.
This is a bug. All stable releases are affected. Attached bugfix teaches nodeIndexonlyscan.c to deform using the authoritative xs_hitupdesc descriptor used by the index AM, rather than assuming that the descriptor used by the scan's virtual slot is 100% compatible with xs_hitupdesc. The patch includes a test case demonstrating a query where this leads to incorrect behavior when scanning a multicolumn GiST index. Without the fix the executor gets confused about where the second index column begins, leading to a spurious error (e.g., "ERROR: type with OID nnnnn does not exist"). I haven't investigated whether the consequences could be worse than just an error. FWIW I discovered this bug when I wondered why the code in question didn't already work this way. I was trying to simplify my own patch that moves this functionality out of the core executor and into a table AM helper function (needed for the index prefetching work). The core executor already uses scandesc->xs_itupdesc for scandesc->xs_itup, so why doesn't it also use scandesc->xs_hitupdesc for scandesc->xs_hitup? I initially thought the bugfix's approach was just simpler, but subsequently realized it was actually necessary for correctness in certain edge cases. -- Peter Geoghegan
v1-0001-Fix-index-only-scan-misreading-GiST-fetch-tuples.patch
Description: Binary data
