I was glancing through the SET documentation and am not 100% sure I grok the special case of SET followed by SET LOCAL (I'm about to go glance through the code).
The effects of SET LOCAL last only till the end of the current transaction, whether committed or not. A special case is SET followed by SET LOCAL within a single transaction: the SET LOCAL value will be seen until the end of the transaction, but afterwards (if the transaction is committed) the SET value will take effect.
https://www.postgresql.org/docs/current/sql-set.html
I tracked it down, I was missing the implicit concept that SET means SET SESSION, e.g.
begin;
-- this persists post transaction, assuming commit
set session statement_timeout to '10s';
-- this lives for the life of the transaction
set local statement_timeout to '10s';
-- do other awesome things
commit;
It made a bit more sense reading the GUC variable values
Saving/Restoring GUC Variable Values
Prior values of configuration variables must be remembered in order to deal with several special cases: RESET (a/k/a SET TO DEFAULT), rollback of SET on transaction abort, rollback of SET LOCAL at transaction end (either commit or abort), and save/restore around a function that has a SET option. RESET is defined as selecting the value that would be effective had there never been any SET commands in the current session.
To handle these cases we must keep track of many distinct values for each variable. The primary values are:
actual variable contents always the current effective value
reset_val the value to use for RESET
(Each GUC entry also has a boot_val which is the wired-in default value. This is assigned to the reset_val and the actual variable during InitializeGUCOptions(). The boot_val is also consulted to restore the correct reset_val if SIGHUP processing discovers that a variable formerly specified in postgresql.conf is no longer set there.)
In addition to the primary values, there is a stack of former effective values that might need to be restored in future. Stacking and unstacking is controlled by the GUC "nest level", which is zero when outside any transaction, one at top transaction level, and incremented for each open subtransaction or function call with a SET option. A stack entry is made whenever a GUC variable is first modified at a given nesting level. (Note: the reset_val need not be stacked because it is only changed by non-transactional operations.)
A stack entry has a state, a prior value of the GUC variable, a remembered source of that prior value, and depending on the state may also have a "masked" value. The masked value is needed when SET followed by SET LOCAL occur at the same nest level: the SET's value is masked but must be remembered to restore after transaction commit.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With