@ -150,6 +150,8 @@ extern bool optimize_bounded_sort;
static int GUC_check_errcode_value ;
static int GUC_check_errcode_value ;
static List * reserved_class_prefix = NIL ;
/* global variables for check hook support */
/* global variables for check hook support */
char * GUC_check_errmsg_string ;
char * GUC_check_errmsg_string ;
char * GUC_check_errdetail_string ;
char * GUC_check_errdetail_string ;
@ -5590,18 +5592,44 @@ find_option(const char *name, bool create_placeholders, bool skip_errors,
* doesn ' t contain a separator , don ' t assume that it was meant to be a
* doesn ' t contain a separator , don ' t assume that it was meant to be a
* placeholder .
* placeholder .
*/
*/
if ( strchr ( name , GUC_QUALIFIER_SEPARATOR ) ! = NULL )
const char * sep = strchr ( name , GUC_QUALIFIER_SEPARATOR ) ;
if ( sep ! = NULL )
{
{
if ( valid_custom_variable_name ( name ) )
size_t classLen = sep - name ;
return add_placeholder_variable ( name , elevel ) ;
ListCell * lc ;
/* A special error message seems desirable here */
if ( ! skip_errors )
/* The name must be syntactically acceptable ... */
ereport ( elevel ,
if ( ! valid_custom_variable_name ( name ) )
( errcode ( ERRCODE_INVALID_NAME ) ,
{
errmsg ( " invalid configuration parameter name \" %s \" " ,
if ( ! skip_errors )
name ) ,
ereport ( elevel ,
errdetail ( " Custom parameter names must be two or more simple identifiers separated by dots. " ) ) ) ;
( errcode ( ERRCODE_INVALID_NAME ) ,
return NULL ;
errmsg ( " invalid configuration parameter name \" %s \" " ,
name ) ,
errdetail ( " Custom parameter names must be two or more simple identifiers separated by dots. " ) ) ) ;
return NULL ;
}
/* ... and it must not match any previously-reserved prefix */
foreach ( lc , reserved_class_prefix )
{
const char * rcprefix = lfirst ( lc ) ;
if ( strlen ( rcprefix ) = = classLen & &
strncmp ( name , rcprefix , classLen ) = = 0 )
{
if ( ! skip_errors )
ereport ( elevel ,
( errcode ( ERRCODE_INVALID_NAME ) ,
errmsg ( " invalid configuration parameter name \" %s \" " ,
name ) ,
errdetail ( " \" %s \" is a reserved prefix. " ,
rcprefix ) ) ) ;
return NULL ;
}
}
/* OK, create it */
return add_placeholder_variable ( name , elevel ) ;
}
}
}
}
@ -9355,15 +9383,26 @@ DefineCustomEnumVariable(const char *name,
}
}
/*
/*
* Mark the given GUC prefix as " reserved " .
*
* This deletes any existing placeholders matching the prefix ,
* and then prevents new ones from being created .
* Extensions should call this after they ' ve defined all of their custom
* Extensions should call this after they ' ve defined all of their custom
* GUCs , to help catch misspelled config - file entries .
* GUCs , to help catch misspelled config - file entries .
*/
*/
void
void
EmitWarningsOnPlaceholders ( const char * className )
MarkGUCPrefixReserved ( const char * className )
{
{
int classLen = strlen ( className ) ;
int classLen = strlen ( className ) ;
int i ;
int i ;
MemoryContext oldcontext ;
/*
* Check for existing placeholders . We must actually remove invalid
* placeholders , else future parallel worker startups will fail . ( We
* don ' t bother trying to free associated memory , since this shouldn ' t
* happen often . )
*/
for ( i = 0 ; i < num_guc_variables ; i + + )
for ( i = 0 ; i < num_guc_variables ; i + + )
{
{
struct config_generic * var = guc_variables [ i ] ;
struct config_generic * var = guc_variables [ i ] ;
@ -9373,11 +9412,21 @@ EmitWarningsOnPlaceholders(const char *className)
var - > name [ classLen ] = = GUC_QUALIFIER_SEPARATOR )
var - > name [ classLen ] = = GUC_QUALIFIER_SEPARATOR )
{
{
ereport ( WARNING ,
ereport ( WARNING ,
( errcode ( ERRCODE_UNDEFINED_OBJECT ) ,
( errcode ( ERRCODE_INVALID_NAME ) ,
errmsg ( " unrecognized configuration parameter \" %s \" " ,
errmsg ( " invalid configuration parameter name \" %s \" , removing it " ,
var - > name ) ) ) ;
var - > name ) ,
errdetail ( " \" %s \" is now a reserved prefix. " ,
className ) ) ) ;
num_guc_variables - - ;
memmove ( & guc_variables [ i ] , & guc_variables [ i + 1 ] ,
( num_guc_variables - i ) * sizeof ( struct config_generic * ) ) ;
}
}
}
}
/* And remember the name so we can prevent future mistakes. */
oldcontext = MemoryContextSwitchTo ( TopMemoryContext ) ;
reserved_class_prefix = lappend ( reserved_class_prefix , pstrdup ( className ) ) ;
MemoryContextSwitchTo ( oldcontext ) ;
}
}