@@ -433,7 +433,25 @@ static relopt_real realRelOpts[] =
433433 {{NULL }}
434434};
435435
436- static relopt_string stringRelOpts [] =
436+ /* values from GistOptBufferingMode */
437+ relopt_enum_elt_def gistBufferingOptValues [] =
438+ {
439+ {"auto" , GIST_OPTION_BUFFERING_AUTO },
440+ {"on" , GIST_OPTION_BUFFERING_ON },
441+ {"off" , GIST_OPTION_BUFFERING_OFF },
442+ {(const char * ) NULL } /* list terminator */
443+ };
444+
445+ /* values from ViewOptCheckOption */
446+ relopt_enum_elt_def viewCheckOptValues [] =
447+ {
448+ /* no value for NOT_SET */
449+ {"local" , VIEW_OPTION_CHECK_OPTION_LOCAL },
450+ {"cascaded" , VIEW_OPTION_CHECK_OPTION_CASCADED },
451+ {(const char * ) NULL } /* list terminator */
452+ };
453+
454+ static relopt_enum enumRelOpts [] =
437455{
438456 {
439457 {
@@ -442,10 +460,9 @@ static relopt_string stringRelOpts[] =
442460 RELOPT_KIND_GIST ,
443461 AccessExclusiveLock
444462 },
445- 4 ,
446- false,
447- gistValidateBufferingOption ,
448- "auto"
463+ gistBufferingOptValues ,
464+ GIST_OPTION_BUFFERING_AUTO ,
465+ gettext_noop ("Valid values are \"on\", \"off\", and \"auto\"." )
449466 },
450467 {
451468 {
@@ -454,15 +471,20 @@ static relopt_string stringRelOpts[] =
454471 RELOPT_KIND_VIEW ,
455472 AccessExclusiveLock
456473 },
457- 0 ,
458- true,
459- validateWithCheckOption ,
460- NULL
474+ viewCheckOptValues ,
475+ VIEW_OPTION_CHECK_OPTION_NOT_SET ,
476+ gettext_noop ("Valid values are \"local\" and \"cascaded\"." )
461477 },
462478 /* list terminator */
463479 {{NULL }}
464480};
465481
482+ static relopt_string stringRelOpts [] =
483+ {
484+ /* list terminator */
485+ {{NULL }}
486+ };
487+
466488static relopt_gen * * relOpts = NULL ;
467489static bits32 last_assigned_kind = RELOPT_KIND_LAST_DEFAULT ;
468490
@@ -505,6 +527,12 @@ initialize_reloptions(void)
505527 realRelOpts [i ].gen .lockmode ));
506528 j ++ ;
507529 }
530+ for (i = 0 ; enumRelOpts [i ].gen .name ; i ++ )
531+ {
532+ Assert (DoLockModesConflict (enumRelOpts [i ].gen .lockmode ,
533+ enumRelOpts [i ].gen .lockmode ));
534+ j ++ ;
535+ }
508536 for (i = 0 ; stringRelOpts [i ].gen .name ; i ++ )
509537 {
510538 Assert (DoLockModesConflict (stringRelOpts [i ].gen .lockmode ,
@@ -543,6 +571,14 @@ initialize_reloptions(void)
543571 j ++ ;
544572 }
545573
574+ for (i = 0 ; enumRelOpts [i ].gen .name ; i ++ )
575+ {
576+ relOpts [j ] = & enumRelOpts [i ].gen ;
577+ relOpts [j ]-> type = RELOPT_TYPE_ENUM ;
578+ relOpts [j ]-> namelen = strlen (relOpts [j ]-> name );
579+ j ++ ;
580+ }
581+
546582 for (i = 0 ; stringRelOpts [i ].gen .name ; i ++ )
547583 {
548584 relOpts [j ] = & stringRelOpts [i ].gen ;
@@ -641,6 +677,9 @@ allocate_reloption(bits32 kinds, int type, const char *name, const char *desc,
641677 case RELOPT_TYPE_REAL :
642678 size = sizeof (relopt_real );
643679 break ;
680+ case RELOPT_TYPE_ENUM :
681+ size = sizeof (relopt_enum );
682+ break ;
644683 case RELOPT_TYPE_STRING :
645684 size = sizeof (relopt_string );
646685 break ;
@@ -661,6 +700,13 @@ allocate_reloption(bits32 kinds, int type, const char *name, const char *desc,
661700 newoption -> type = type ;
662701 newoption -> lockmode = lockmode ;
663702
703+ /*
704+ * Set the default lock mode for this option. There is no actual way
705+ * for a module to enforce it when declaring a custom relation option,
706+ * so just use the highest level, which is safe for all cases.
707+ */
708+ newoption -> lockmode = AccessExclusiveLock ;
709+
664710 MemoryContextSwitchTo (oldcxt );
665711
666712 return newoption ;
@@ -721,6 +767,34 @@ add_real_reloption(bits32 kinds, const char *name, const char *desc, double defa
721767 add_reloption ((relopt_gen * ) newoption );
722768}
723769
770+ /*
771+ * add_enum_reloption
772+ * Add a new enum reloption
773+ *
774+ * The members array must have a terminating NULL entry.
775+ *
776+ * The detailmsg is shown when unsupported values are passed, and has this
777+ * form: "Valid values are \"foo\", \"bar\", and \"bar\"."
778+ *
779+ * The members array and detailmsg are not copied -- caller must ensure that
780+ * they are valid throughout the life of the process.
781+ */
782+ void
783+ add_enum_reloption (bits32 kinds , const char * name , const char * desc ,
784+ relopt_enum_elt_def * members , int default_val ,
785+ const char * detailmsg , LOCKMODE lockmode )
786+ {
787+ relopt_enum * newoption ;
788+
789+ newoption = (relopt_enum * ) allocate_reloption (kinds , RELOPT_TYPE_ENUM ,
790+ name , desc , lockmode );
791+ newoption -> members = members ;
792+ newoption -> default_val = default_val ;
793+ newoption -> detailmsg = detailmsg ;
794+
795+ add_reloption ((relopt_gen * ) newoption );
796+ }
797+
724798/*
725799 * add_string_reloption
726800 * Add a new string reloption
@@ -1237,6 +1311,37 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len,
12371311 optreal -> min , optreal -> max )));
12381312 }
12391313 break ;
1314+ case RELOPT_TYPE_ENUM :
1315+ {
1316+ relopt_enum * optenum = (relopt_enum * ) option -> gen ;
1317+ relopt_enum_elt_def * elt ;
1318+
1319+ parsed = false;
1320+ for (elt = optenum -> members ; elt -> string_val ; elt ++ )
1321+ {
1322+ if (pg_strcasecmp (value , elt -> string_val ) == 0 )
1323+ {
1324+ option -> values .enum_val = elt -> symbol_val ;
1325+ parsed = true;
1326+ break ;
1327+ }
1328+ }
1329+ if (validate && !parsed )
1330+ ereport (ERROR ,
1331+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1332+ errmsg ("invalid value for enum option \"%s\": %s" ,
1333+ option -> gen -> name , value ),
1334+ optenum -> detailmsg ?
1335+ errdetail_internal ("%s" , _ (optenum -> detailmsg )) : 0 ));
1336+
1337+ /*
1338+ * If value is not among the allowed string values, but we are
1339+ * not asked to validate, just use the default numeric value.
1340+ */
1341+ if (!parsed )
1342+ option -> values .enum_val = optenum -> default_val ;
1343+ }
1344+ break ;
12401345 case RELOPT_TYPE_STRING :
12411346 {
12421347 relopt_string * optstring = (relopt_string * ) option -> gen ;
@@ -1330,6 +1435,11 @@ fillRelOptions(void *rdopts, Size basesize,
13301435 options [i ].values .real_val :
13311436 ((relopt_real * ) options [i ].gen )-> default_val ;
13321437 break ;
1438+ case RELOPT_TYPE_ENUM :
1439+ * (int * ) itempos = options [i ].isset ?
1440+ options [i ].values .enum_val :
1441+ ((relopt_enum * ) options [i ].gen )-> default_val ;
1442+ break ;
13331443 case RELOPT_TYPE_STRING :
13341444 optstring = (relopt_string * ) options [i ].gen ;
13351445 if (options [i ].isset )
@@ -1446,8 +1556,8 @@ view_reloptions(Datum reloptions, bool validate)
14461556 static const relopt_parse_elt tab [] = {
14471557 {"security_barrier" , RELOPT_TYPE_BOOL ,
14481558 offsetof(ViewOptions , security_barrier )},
1449- {"check_option" , RELOPT_TYPE_STRING ,
1450- offsetof(ViewOptions , check_option_offset )}
1559+ {"check_option" , RELOPT_TYPE_ENUM ,
1560+ offsetof(ViewOptions , check_option )}
14511561 };
14521562
14531563 options = parseRelOptions (reloptions , validate , RELOPT_KIND_VIEW , & numoptions );
0 commit comments