Skip to content

Commit 546f7c2

Browse files
committed
Don't fail for bad GUCs in CREATE FUNCTION with check_function_bodies off.
The previous coding attempted to activate all the GUC settings specified in SET clauses, so that the function validator could operate in the GUC environment expected by the function body. However, this is problematic when restoring a dump, since the SET clauses might refer to database objects that don't exist yet. We already have the parameter check_function_bodies that's meant to prevent forward references in function definitions from breaking dumps, so let's change CREATE FUNCTION to not install the SET values if check_function_bodies is off. Authors of function validators were already advised not to make any "context sensitive" checks when check_function_bodies is off, if indeed they're checking anything at all in that mode. But extend the documentation to point out the GUC issue in particular. (Note that we still check the SET clauses to some extent; the behavior with !check_function_bodies is now approximately equivalent to what ALTER DATABASE/ROLE have been doing for awhile with context-dependent GUCs.) This problem can be demonstrated in all active branches, so back-patch all the way.
1 parent 0d3f440 commit 546f7c2

File tree

4 files changed

+63
-12
lines changed

4 files changed

+63
-12
lines changed

doc/src/sgml/plhandler.sgml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,13 @@ CREATE LANGUAGE plsample
200200
of having a validator is not to let the call handler omit checks, but
201201
to notify the user immediately if there are obvious errors in a
202202
<command>CREATE FUNCTION</> command.)
203+
While the choice of exactly what to check is mostly left to the
204+
discretion of the validator function, note that the core
205+
<command>CREATE FUNCTION</> code only executes <literal>SET</> clauses
206+
attached to a function when <varname>check_function_bodies</> is on.
207+
Therefore, checks whose results might be affected by GUC parameters
208+
definitely should be skipped when <varname>check_function_bodies</> is
209+
off, to avoid false failures when reloading a dump.
203210
</para>
204211

205212
<para>

src/backend/catalog/pg_proc.c

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -668,24 +668,34 @@ ProcedureCreate(const char *procedureName,
668668
/* Verify function body */
669669
if (OidIsValid(languageValidator))
670670
{
671-
ArrayType *set_items;
672-
int save_nestlevel;
671+
ArrayType *set_items = NULL;
672+
int save_nestlevel = 0;
673673

674674
/* Advance command counter so new tuple can be seen by validator */
675675
CommandCounterIncrement();
676676

677-
/* Set per-function configuration parameters */
678-
set_items = (ArrayType *) DatumGetPointer(proconfig);
679-
if (set_items) /* Need a new GUC nesting level */
677+
/*
678+
* Set per-function configuration parameters so that the validation is
679+
* done with the environment the function expects. However, if
680+
* check_function_bodies is off, we don't do this, because that would
681+
* create dump ordering hazards that pg_dump doesn't know how to deal
682+
* with. (For example, a SET clause might refer to a not-yet-created
683+
* text search configuration.) This means that the validator
684+
* shouldn't complain about anything that might depend on a GUC
685+
* parameter when check_function_bodies is off.
686+
*/
687+
if (check_function_bodies)
680688
{
681-
save_nestlevel = NewGUCNestLevel();
682-
ProcessGUCArray(set_items,
683-
(superuser() ? PGC_SUSET : PGC_USERSET),
684-
PGC_S_SESSION,
685-
GUC_ACTION_SAVE);
689+
set_items = (ArrayType *) DatumGetPointer(proconfig);
690+
if (set_items) /* Need a new GUC nesting level */
691+
{
692+
save_nestlevel = NewGUCNestLevel();
693+
ProcessGUCArray(set_items,
694+
(superuser() ? PGC_SUSET : PGC_USERSET),
695+
PGC_S_SESSION,
696+
GUC_ACTION_SAVE);
697+
}
686698
}
687-
else
688-
save_nestlevel = 0; /* keep compiler quiet */
689699

690700
OidFunctionCall1(languageValidator, ObjectIdGetDatum(retval));
691701

src/test/regress/expected/guc.out

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,3 +718,19 @@ select myfunc(1), current_setting('work_mem');
718718
2MB | 2MB
719719
(1 row)
720720

721+
-- Normally, CREATE FUNCTION should complain about invalid values in
722+
-- function SET options; but not if check_function_bodies is off,
723+
-- because that creates ordering hazards for pg_dump
724+
create function func_with_bad_set() returns int as $$ select 1 $$
725+
language sql
726+
set default_text_search_config = no_such_config;
727+
NOTICE: text search configuration "no_such_config" does not exist
728+
ERROR: invalid value for parameter "default_text_search_config": "no_such_config"
729+
set check_function_bodies = off;
730+
create function func_with_bad_set() returns int as $$ select 1 $$
731+
language sql
732+
set default_text_search_config = no_such_config;
733+
NOTICE: text search configuration "no_such_config" does not exist
734+
select func_with_bad_set();
735+
ERROR: invalid value for parameter "default_text_search_config": "no_such_config"
736+
reset check_function_bodies;

src/test/regress/sql/guc.sql

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,21 @@ set work_mem = '1MB';
257257
select myfunc(0);
258258
select current_setting('work_mem');
259259
select myfunc(1), current_setting('work_mem');
260+
261+
-- Normally, CREATE FUNCTION should complain about invalid values in
262+
-- function SET options; but not if check_function_bodies is off,
263+
-- because that creates ordering hazards for pg_dump
264+
265+
create function func_with_bad_set() returns int as $$ select 1 $$
266+
language sql
267+
set default_text_search_config = no_such_config;
268+
269+
set check_function_bodies = off;
270+
271+
create function func_with_bad_set() returns int as $$ select 1 $$
272+
language sql
273+
set default_text_search_config = no_such_config;
274+
275+
select func_with_bad_set();
276+
277+
reset check_function_bodies;

0 commit comments

Comments
 (0)