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
Avoid using a cursor in plpgsql's RETURN QUERY statement.
plpgsql has always executed the query given in a RETURN QUERY commandby opening it as a cursor and then fetching a few rows at a time,which it turns around and dumps into the function's result tuplestore.The point of this was to keep from blowing out memory with an oversizedSPITupleTable result (note that while a tuplestore can spill tuplesto disk, SPITupleTable cannot). However, it's rather inefficient, bothbecause of extra data copying and because of executor entry/exitoverhead. In recent versions, a new performance problem has emerged:use of a cursor prevents use of a parallel plan for the executed query.We can improve matters by skipping use of a cursor and having theexecutor push result tuples directly into the function's resulttuplestore. However, a moderate amount of new infrastructure is neededto make that idea work:* We can use the existing tstoreReceiver.c DestReceiver code to funnelexecutor output to the tuplestore, but it has to be extended to supportplpgsql's requirement for possibly applying a tuple conversion map.* SPI needs to be extended to allow use of a caller-suppliedDestReceiver instead of its usual receiver that puts tuples intoa SPITupleTable. Two new API calls are needed to handle both theRETURN QUERY and RETURN QUERY EXECUTE cases.I also felt that I didn't want these new API calls to use the legacymethod of specifying query parameter values with "char" null flags(the old ' '/'n' convention); rather they should accept ParamListInfoobjects containing the parameter type and value info. This requireda bit of additional new infrastructure since we didn't yet have anyparse analysis callback that would interpret $N parameter symbolsaccording to type data supplied in a ParamListInfo. There seems to beno harm in letting makeParamList install that callback by default,rather than leaving a new ParamListInfo's parserSetup hook as NULL.(Indeed, as of HEAD, I couldn't find anyplace that was using theparserSetup field at all; plpgsql was using parserSetupArg for itsown purposes, but parserSetup seemed to be write-only.)We can actually get plpgsql out of the business of using legacy nullflags altogether, and using ParamListInfo instead of its ad-hocPreparedParamsData structure; but this requires inventing one moreSPI API call that can replace SPI_cursor_open_with_args. That seemsworth doing, though.SPI_execute_with_args and SPI_cursor_open_with_args are now unusedanywhere in the core PG distribution. Perhaps someday we coulddeprecate/remove them. But cleaning up the crufty bits of the SPIAPI is a task for a different patch.Per bug #16040 from Jeremy Smith. This is unfortunately too invasive toconsider back-patching. Patch by me; thanks to Hamid Akhtar for review.Discussion:https://postgr.es/m/16040-eaacad11fecfb198@postgresql.org