The ONE place a session GUC is written.
A setting can be changed three ways, and PostgreSQL treats them as
the same act: SET timezone = 'Europe/Berlin', SELECT set_config('timezone', 'Europe/Berlin', false) as a statement of
its own, and the same call inside a larger query. All three arrived
here by separate routes, and two of them honoured search_path and
silently dropped every other setting -- so SET timezone moved
timestamptz output and set_config('timezone', …) did not, from one
session, with SHOW timezone agreeing with whichever had run last.
current_setting had the mirror-image bug on the READ side and its
fix left a comment claiming set_config already wrote the session
state. It did not. One writer is the only version of this that stays
true, so the parse-and-store for every GUC that changes how we
execute lives in set-setting! and nowhere else.
A setting we do not model is NOT an error: asyncpg toggles jit
around its type introspection and reads the result back, so an
unrecognised name is accepted and echoed by the caller. This
function reports whether it recognised the name; it never throws for
an unknown one, only for a known one given a bad value.
The ONE place a session GUC is written.
A setting can be changed three ways, and PostgreSQL treats them as
the same act: `SET timezone = 'Europe/Berlin'`, `SELECT
set_config('timezone', 'Europe/Berlin', false)` as a statement of
its own, and the same call inside a larger query. All three arrived
here by separate routes, and two of them honoured `search_path` and
silently dropped every other setting -- so `SET timezone` moved
timestamptz output and `set_config('timezone', …)` did not, from one
session, with `SHOW timezone` agreeing with whichever had run last.
`current_setting` had the mirror-image bug on the READ side and its
fix left a comment claiming `set_config` already wrote the session
state. It did not. One writer is the only version of this that stays
true, so the parse-and-store for every GUC that changes how we
execute lives in `set-setting!` and nowhere else.
A setting we do not model is NOT an error: asyncpg toggles `jit`
around its type introspection and reads the result back, so an
unrecognised name is accepted and echoed by the caller. This
function reports whether it recognised the name; it never throws for
an unknown one, only for a known one given a bad value.(normalize-search-path values)Split, trim and unquote a SET search_path value list.
Split, trim and unquote a SET search_path value list.
(read-setting session-state name)One GUC as text, exactly as SHOW reports it, or nil when we neither
model nor default it. The session's own value wins over the default.
This is the READ half of the pair: set-setting! writes, this reads,
and set_config needs both because PostgreSQL answers it with the
value the setting now has.
One GUC as text, exactly as `SHOW` reports it, or nil when we neither model nor default it. The session's own value wins over the default. This is the READ half of the pair: `set-setting!` writes, this reads, and `set_config` needs both because PostgreSQL answers it with the value the setting now has.
(reset-setting! session-state name)Clear one GUC, returning it to its compiled-in default. Returns true when the name is one we model.
This is what RESET <var> does, and also what set_config(name, NULL, …) does: guc.c's set_config_by_name passes a NULL value
straight to set_config_option, where it means "reset to default".
Clear one GUC, returning it to its compiled-in default. Returns true when the name is one we model. This is what `RESET <var>` does, and also what `set_config(name, NULL, …)` does: `guc.c`'s `set_config_by_name` passes a NULL value straight to `set_config_option`, where it means "reset to default".
(set-setting! session-state name values)Apply one session GUC. name is the setting as written (folded
here), values the raw value strings -- one for set_config, one or
more for a SET with a value list.
Returns true when the name is one we model and the value was stored, false otherwise. Throws 22023 for a recognised setting given a value it cannot take.
A single NULL value RESETS the setting, which is what PostgreSQL's
set_config(name, NULL, …) does.
set_config's third argument asks for the change to last only to
the end of the transaction. We do not model transaction-local
settings -- SET LOCAL is not distinguished either -- so the change
is applied to the session and outlives the transaction. Stated once
here rather than silently in two places.
Apply one session GUC. `name` is the setting as written (folded here), `values` the raw value strings -- one for `set_config`, one or more for a `SET` with a value list. Returns true when the name is one we model and the value was stored, false otherwise. Throws 22023 for a recognised setting given a value it cannot take. A single NULL value RESETS the setting, which is what PostgreSQL's `set_config(name, NULL, …)` does. `set_config`'s third argument asks for the change to last only to the end of the transaction. We do not model transaction-local settings -- `SET LOCAL` is not distinguished either -- so the change is applied to the session and outlives the transaction. Stated once here rather than silently in two places.
Every GUC we model, by its folded name, to the session-state key it
writes. One table so that writing a setting and resetting it cannot
name different things -- SET and RESET <var> each carried their
own copy of these names, which is the shape the set_config bug
grew out of.
RESET ALL is NOT driven from here: it clears a wider set
(server/session-guc-keys), including the datahike.* temporal vars
and statement_timeout, which are written on their own paths.
Every GUC we model, by its folded name, to the session-state key it writes. One table so that writing a setting and resetting it cannot name different things -- `SET` and `RESET <var>` each carried their own copy of these names, which is the shape the `set_config` bug grew out of. `RESET ALL` is NOT driven from here: it clears a wider set (`server/session-guc-keys`), including the datahike.* temporal vars and statement_timeout, which are written on their own paths.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |