@@ -433,7 +433,25 @@ static relopt_real realRelOpts[] =
433
433
{{NULL }}
434
434
};
435
435
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 [] =
437
455
{
438
456
{
439
457
{
@@ -442,10 +460,9 @@ static relopt_string stringRelOpts[] =
442
460
RELOPT_KIND_GIST ,
443
461
AccessExclusiveLock
444
462
},
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\"." )
449
466
},
450
467
{
451
468
{
@@ -454,15 +471,20 @@ static relopt_string stringRelOpts[] =
454
471
RELOPT_KIND_VIEW ,
455
472
AccessExclusiveLock
456
473
},
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\"." )
461
477
},
462
478
/* list terminator */
463
479
{{NULL }}
464
480
};
465
481
482
+ static relopt_string stringRelOpts [] =
483
+ {
484
+ /* list terminator */
485
+ {{NULL }}
486
+ };
487
+
466
488
static relopt_gen * * relOpts = NULL ;
467
489
static bits32 last_assigned_kind = RELOPT_KIND_LAST_DEFAULT ;
468
490
@@ -505,6 +527,12 @@ initialize_reloptions(void)
505
527
realRelOpts [i ].gen .lockmode ));
506
528
j ++ ;
507
529
}
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
+ }
508
536
for (i = 0 ; stringRelOpts [i ].gen .name ; i ++ )
509
537
{
510
538
Assert (DoLockModesConflict (stringRelOpts [i ].gen .lockmode ,
@@ -543,6 +571,14 @@ initialize_reloptions(void)
543
571
j ++ ;
544
572
}
545
573
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
+
546
582
for (i = 0 ; stringRelOpts [i ].gen .name ; i ++ )
547
583
{
548
584
relOpts [j ] = & stringRelOpts [i ].gen ;
@@ -641,6 +677,9 @@ allocate_reloption(bits32 kinds, int type, const char *name, const char *desc,
641
677
case RELOPT_TYPE_REAL :
642
678
size = sizeof (relopt_real );
643
679
break ;
680
+ case RELOPT_TYPE_ENUM :
681
+ size = sizeof (relopt_enum );
682
+ break ;
644
683
case RELOPT_TYPE_STRING :
645
684
size = sizeof (relopt_string );
646
685
break ;
@@ -661,6 +700,13 @@ allocate_reloption(bits32 kinds, int type, const char *name, const char *desc,
661
700
newoption -> type = type ;
662
701
newoption -> lockmode = lockmode ;
663
702
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
+
664
710
MemoryContextSwitchTo (oldcxt );
665
711
666
712
return newoption ;
@@ -721,6 +767,34 @@ add_real_reloption(bits32 kinds, const char *name, const char *desc, double defa
721
767
add_reloption ((relopt_gen * ) newoption );
722
768
}
723
769
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
+
724
798
/*
725
799
* add_string_reloption
726
800
* Add a new string reloption
@@ -1237,6 +1311,37 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len,
1237
1311
optreal -> min , optreal -> max )));
1238
1312
}
1239
1313
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 ;
1240
1345
case RELOPT_TYPE_STRING :
1241
1346
{
1242
1347
relopt_string * optstring = (relopt_string * ) option -> gen ;
@@ -1330,6 +1435,11 @@ fillRelOptions(void *rdopts, Size basesize,
1330
1435
options [i ].values .real_val :
1331
1436
((relopt_real * ) options [i ].gen )-> default_val ;
1332
1437
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 ;
1333
1443
case RELOPT_TYPE_STRING :
1334
1444
optstring = (relopt_string * ) options [i ].gen ;
1335
1445
if (options [i ].isset )
@@ -1446,8 +1556,8 @@ view_reloptions(Datum reloptions, bool validate)
1446
1556
static const relopt_parse_elt tab [] = {
1447
1557
{"security_barrier" , RELOPT_TYPE_BOOL ,
1448
1558
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 )}
1451
1561
};
1452
1562
1453
1563
options = parseRelOptions (reloptions , validate , RELOPT_KIND_VIEW , & numoptions );
0 commit comments