@ -433,7 +433,25 @@ static relopt_real realRelOpts[] =
{ { NULL } }
} ;
static relopt_string stringRelOpts [ ] =
/* values from GistOptBufferingMode */
relopt_enum_elt_def gistBufferingOptValues [ ] =
{
{ " auto " , GIST_OPTION_BUFFERING_AUTO } ,
{ " on " , GIST_OPTION_BUFFERING_ON } ,
{ " off " , GIST_OPTION_BUFFERING_OFF } ,
{ ( const char * ) NULL } /* list terminator */
} ;
/* values from ViewOptCheckOption */
relopt_enum_elt_def viewCheckOptValues [ ] =
{
/* no value for NOT_SET */
{ " local " , VIEW_OPTION_CHECK_OPTION_LOCAL } ,
{ " cascaded " , VIEW_OPTION_CHECK_OPTION_CASCADED } ,
{ ( const char * ) NULL } /* list terminator */
} ;
static relopt_enum enumRelOpts [ ] =
{
{
{
@ -442,10 +460,9 @@ static relopt_string stringRelOpts[] =
RELOPT_KIND_GIST ,
AccessExclusiveLock
} ,
4 ,
false ,
gistValidateBufferingOption ,
" auto "
gistBufferingOptValues ,
GIST_OPTION_BUFFERING_AUTO ,
gettext_noop ( " Valid values are \" on \" , \" off \" , and \" auto \" . " )
} ,
{
{
@ -454,15 +471,20 @@ static relopt_string stringRelOpts[] =
RELOPT_KIND_VIEW ,
AccessExclusiveLock
} ,
0 ,
true ,
validateWithCheckOption ,
NULL
viewCheckOptValues ,
VIEW_OPTION_CHECK_OPTION_NOT_SET ,
gettext_noop ( " Valid values are \" local \" and \" cascaded \" . " )
} ,
/* list terminator */
{ { NULL } }
} ;
static relopt_string stringRelOpts [ ] =
{
/* list terminator */
{ { NULL } }
} ;
static relopt_gen * * relOpts = NULL ;
static bits32 last_assigned_kind = RELOPT_KIND_LAST_DEFAULT ;
@ -505,6 +527,12 @@ initialize_reloptions(void)
realRelOpts [ i ] . gen . lockmode ) ) ;
j + + ;
}
for ( i = 0 ; enumRelOpts [ i ] . gen . name ; i + + )
{
Assert ( DoLockModesConflict ( enumRelOpts [ i ] . gen . lockmode ,
enumRelOpts [ i ] . gen . lockmode ) ) ;
j + + ;
}
for ( i = 0 ; stringRelOpts [ i ] . gen . name ; i + + )
{
Assert ( DoLockModesConflict ( stringRelOpts [ i ] . gen . lockmode ,
@ -543,6 +571,14 @@ initialize_reloptions(void)
j + + ;
}
for ( i = 0 ; enumRelOpts [ i ] . gen . name ; i + + )
{
relOpts [ j ] = & enumRelOpts [ i ] . gen ;
relOpts [ j ] - > type = RELOPT_TYPE_ENUM ;
relOpts [ j ] - > namelen = strlen ( relOpts [ j ] - > name ) ;
j + + ;
}
for ( i = 0 ; stringRelOpts [ i ] . gen . name ; i + + )
{
relOpts [ j ] = & stringRelOpts [ i ] . gen ;
@ -641,6 +677,9 @@ allocate_reloption(bits32 kinds, int type, const char *name, const char *desc,
case RELOPT_TYPE_REAL :
size = sizeof ( relopt_real ) ;
break ;
case RELOPT_TYPE_ENUM :
size = sizeof ( relopt_enum ) ;
break ;
case RELOPT_TYPE_STRING :
size = sizeof ( relopt_string ) ;
break ;
@ -661,6 +700,13 @@ allocate_reloption(bits32 kinds, int type, const char *name, const char *desc,
newoption - > type = type ;
newoption - > lockmode = lockmode ;
/*
* Set the default lock mode for this option . There is no actual way
* for a module to enforce it when declaring a custom relation option ,
* so just use the highest level , which is safe for all cases .
*/
newoption - > lockmode = AccessExclusiveLock ;
MemoryContextSwitchTo ( oldcxt ) ;
return newoption ;
@ -721,6 +767,34 @@ add_real_reloption(bits32 kinds, const char *name, const char *desc, double defa
add_reloption ( ( relopt_gen * ) newoption ) ;
}
/*
* add_enum_reloption
* Add a new enum reloption
*
* The members array must have a terminating NULL entry .
*
* The detailmsg is shown when unsupported values are passed , and has this
* form : " Valid values are \" foo \" , \" bar \" , and \" bar \" . "
*
* The members array and detailmsg are not copied - - caller must ensure that
* they are valid throughout the life of the process .
*/
void
add_enum_reloption ( bits32 kinds , const char * name , const char * desc ,
relopt_enum_elt_def * members , int default_val ,
const char * detailmsg , LOCKMODE lockmode )
{
relopt_enum * newoption ;
newoption = ( relopt_enum * ) allocate_reloption ( kinds , RELOPT_TYPE_ENUM ,
name , desc , lockmode ) ;
newoption - > members = members ;
newoption - > default_val = default_val ;
newoption - > detailmsg = detailmsg ;
add_reloption ( ( relopt_gen * ) newoption ) ;
}
/*
* add_string_reloption
* Add a new string reloption
@ -1237,6 +1311,37 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len,
optreal - > min , optreal - > max ) ) ) ;
}
break ;
case RELOPT_TYPE_ENUM :
{
relopt_enum * optenum = ( relopt_enum * ) option - > gen ;
relopt_enum_elt_def * elt ;
parsed = false ;
for ( elt = optenum - > members ; elt - > string_val ; elt + + )
{
if ( pg_strcasecmp ( value , elt - > string_val ) = = 0 )
{
option - > values . enum_val = elt - > symbol_val ;
parsed = true ;
break ;
}
}
if ( validate & & ! parsed )
ereport ( ERROR ,
( errcode ( ERRCODE_INVALID_PARAMETER_VALUE ) ,
errmsg ( " invalid value for enum option \" %s \" : %s " ,
option - > gen - > name , value ) ,
optenum - > detailmsg ?
errdetail_internal ( " %s " , _ ( optenum - > detailmsg ) ) : 0 ) ) ;
/*
* If value is not among the allowed string values , but we are
* not asked to validate , just use the default numeric value .
*/
if ( ! parsed )
option - > values . enum_val = optenum - > default_val ;
}
break ;
case RELOPT_TYPE_STRING :
{
relopt_string * optstring = ( relopt_string * ) option - > gen ;
@ -1330,6 +1435,11 @@ fillRelOptions(void *rdopts, Size basesize,
options [ i ] . values . real_val :
( ( relopt_real * ) options [ i ] . gen ) - > default_val ;
break ;
case RELOPT_TYPE_ENUM :
* ( int * ) itempos = options [ i ] . isset ?
options [ i ] . values . enum_val :
( ( relopt_enum * ) options [ i ] . gen ) - > default_val ;
break ;
case RELOPT_TYPE_STRING :
optstring = ( relopt_string * ) options [ i ] . gen ;
if ( options [ i ] . isset )
@ -1446,8 +1556,8 @@ view_reloptions(Datum reloptions, bool validate)
static const relopt_parse_elt tab [ ] = {
{ " security_barrier " , RELOPT_TYPE_BOOL ,
offsetof ( ViewOptions , security_barrier ) } ,
{ " check_option " , RELOPT_TYPE_STRING ,
offsetof ( ViewOptions , check_option_offset ) }
{ " check_option " , RELOPT_TYPE_ENUM ,
offsetof ( ViewOptions , check_option ) }
} ;
options = parseRelOptions ( reloptions , validate , RELOPT_KIND_VIEW , & numoptions ) ;