LCOV - differential code coverage report
Current view: top level - src/backend/access/common - reloptions.c (source / functions) Coverage Total Hit UNC UBC GNC CBC DCB
Current: f76c13edadc2b319036e0d238703ed56bb23f934 vs 9e17d25e79d4756be08b4a5521b4b58450217137 Lines: 90.7 % 659 598 5 56 68 530 3
Current Date: 2026-09-20 14:13:17 +0900 Functions: 91.5 % 47 43 4 6 37
Baseline: lcov-20260920-baseline Branches: 79.0 % 448 354 14 80 46 308
Baseline Date: 2026-09-20 14:13:13 +0900 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 92.9 % 70 65 5 65
(30,360] days: 90.8 % 65 59 6 3 56
(360..) days: 90.5 % 524 474 50 474
Function coverage date bins:
(7,30] days: 100.0 % 3 3 3
(30,360] days: 92.9 % 14 13 1 13
(360..) days: 90.0 % 30 27 3 3 24
Branch coverage date bins:
(7,30] days: 76.7 % 60 46 14 46
(30,360] days: 88.2 % 34 30 4 30
(360..) days: 78.5 % 354 278 76 278

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * reloptions.c
                                  4                 :                :  *    Core support for relation options (pg_class.reloptions)
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *
                                 10                 :                :  * IDENTIFICATION
                                 11                 :                :  *    src/backend/access/common/reloptions.c
                                 12                 :                :  *
                                 13                 :                :  *-------------------------------------------------------------------------
                                 14                 :                :  */
                                 15                 :                : 
                                 16                 :                : #include "postgres.h"
                                 17                 :                : 
                                 18                 :                : #include <float.h>
                                 19                 :                : 
                                 20                 :                : #include "access/gist_private.h"
                                 21                 :                : #include "access/hash.h"
                                 22                 :                : #include "access/heaptoast.h"
                                 23                 :                : #include "access/htup_details.h"
                                 24                 :                : #include "access/nbtree.h"
                                 25                 :                : #include "access/reloptions.h"
                                 26                 :                : #include "access/spgist_private.h"
                                 27                 :                : #include "catalog/pg_type.h"
                                 28                 :                : #include "commands/defrem.h"
                                 29                 :                : #include "commands/tablespace.h"
                                 30                 :                : #include "nodes/makefuncs.h"
                                 31                 :                : #include "storage/lock.h"
                                 32                 :                : #include "utils/array.h"
                                 33                 :                : #include "utils/attoptcache.h"
                                 34                 :                : #include "utils/builtins.h"
                                 35                 :                : #include "utils/guc.h"
                                 36                 :                : #include "utils/memutils.h"
                                 37                 :                : #include "utils/rel.h"
                                 38                 :                : 
                                 39                 :                : /*
                                 40                 :                :  * Contents of pg_class.reloptions
                                 41                 :                :  *
                                 42                 :                :  * To add an option:
                                 43                 :                :  *
                                 44                 :                :  * (i) decide on a type (bool, ternary, integer, real, enum, string), name,
                                 45                 :                :  * default value, upper and lower bounds (if applicable); for strings,
                                 46                 :                :  * consider a validation routine.
                                 47                 :                :  * (ii) add a record below (or use add_<type>_reloption).
                                 48                 :                :  * (iii) add it to the appropriate options struct (perhaps StdRdOptions)
                                 49                 :                :  * (iv) add it to the appropriate handling routine (perhaps
                                 50                 :                :  * default_reloptions)
                                 51                 :                :  * (v) make sure the lock level is set correctly for that operation
                                 52                 :                :  * (vi) don't forget to document the option
                                 53                 :                :  *
                                 54                 :                :  * From the user's point of view, a 'ternary' is exactly like a Boolean,
                                 55                 :                :  * so we don't document it separately.  On the implementation side, the
                                 56                 :                :  * handling code can detect the case where the option has not been set.
                                 57                 :                :  *
                                 58                 :                :  * The default choice for any new option should be AccessExclusiveLock.
                                 59                 :                :  * In some cases the lock level can be reduced from there, but the lock
                                 60                 :                :  * level chosen should always conflict with itself to ensure that multiple
                                 61                 :                :  * changes aren't lost when we attempt concurrent changes.
                                 62                 :                :  * The choice of lock level depends completely upon how that parameter
                                 63                 :                :  * is used within the server, not upon how and when you'd like to change it.
                                 64                 :                :  * Safety first. Existing choices are documented here, and elsewhere in
                                 65                 :                :  * backend code where the parameters are used.
                                 66                 :                :  *
                                 67                 :                :  * In general, anything that affects the results obtained from a SELECT must be
                                 68                 :                :  * protected by AccessExclusiveLock.
                                 69                 :                :  *
                                 70                 :                :  * Autovacuum related parameters can be set at ShareUpdateExclusiveLock
                                 71                 :                :  * since they are only used by the AV procs and don't change anything
                                 72                 :                :  * currently executing.
                                 73                 :                :  *
                                 74                 :                :  * Fillfactor can be set at ShareUpdateExclusiveLock because it applies only to
                                 75                 :                :  * subsequent changes made to data blocks, as documented in hio.c
                                 76                 :                :  *
                                 77                 :                :  * n_distinct options can be set at ShareUpdateExclusiveLock because they
                                 78                 :                :  * are only used during ANALYZE, which uses a ShareUpdateExclusiveLock,
                                 79                 :                :  * so the ANALYZE will not be affected by in-flight changes. Changing those
                                 80                 :                :  * values has no effect until the next ANALYZE, so no need for stronger lock.
                                 81                 :                :  *
                                 82                 :                :  * Planner-related parameters can be set at ShareUpdateExclusiveLock because
                                 83                 :                :  * they only affect planning and not the correctness of the execution. Plans
                                 84                 :                :  * cannot be changed in mid-flight, so changes here could not easily result in
                                 85                 :                :  * new improved plans in any case. So we allow existing queries to continue
                                 86                 :                :  * and existing plans to survive, a small price to pay for allowing better
                                 87                 :                :  * plans to be introduced concurrently without interfering with users.
                                 88                 :                :  *
                                 89                 :                :  * Setting parallel_workers at ShareUpdateExclusiveLock is safe, since it acts
                                 90                 :                :  * the same as max_parallel_workers_per_gather which is a USERSET parameter
                                 91                 :                :  * that doesn't affect existing plans or queries.
                                 92                 :                :  *
                                 93                 :                :  * vacuum_truncate can be set at ShareUpdateExclusiveLock because it
                                 94                 :                :  * is only used during VACUUM, which uses a ShareUpdateExclusiveLock,
                                 95                 :                :  * so the VACUUM will not be affected by in-flight changes. Changing its
                                 96                 :                :  * value has no effect until the next VACUUM, so no need for stronger lock.
                                 97                 :                :  */
                                 98                 :                : 
                                 99                 :                : static relopt_bool boolRelOpts[] =
                                100                 :                : {
                                101                 :                :     {
                                102                 :                :         {
                                103                 :                :             "autosummarize",
                                104                 :                :             "Enables automatic summarization on this BRIN index",
                                105                 :                :             RELOPT_KIND_BRIN,
                                106                 :                :             AccessExclusiveLock
                                107                 :                :         },
                                108                 :                :         false
                                109                 :                :     },
                                110                 :                :     {
                                111                 :                :         {
                                112                 :                :             "user_catalog_table",
                                113                 :                :             "Declare a table as an additional catalog table, e.g. for the purpose of logical replication",
                                114                 :                :             RELOPT_KIND_HEAP,
                                115                 :                :             AccessExclusiveLock
                                116                 :                :         },
                                117                 :                :         false
                                118                 :                :     },
                                119                 :                :     {
                                120                 :                :         {
                                121                 :                :             "fastupdate",
                                122                 :                :             "Enables \"fast update\" feature for this GIN index",
                                123                 :                :             RELOPT_KIND_GIN,
                                124                 :                :             AccessExclusiveLock
                                125                 :                :         },
                                126                 :                :         true
                                127                 :                :     },
                                128                 :                :     {
                                129                 :                :         {
                                130                 :                :             "security_barrier",
                                131                 :                :             "View acts as a row security barrier",
                                132                 :                :             RELOPT_KIND_VIEW,
                                133                 :                :             AccessExclusiveLock
                                134                 :                :         },
                                135                 :                :         false
                                136                 :                :     },
                                137                 :                :     {
                                138                 :                :         {
                                139                 :                :             "security_invoker",
                                140                 :                :             "Privileges on underlying relations are checked as the invoking user, not the view owner",
                                141                 :                :             RELOPT_KIND_VIEW,
                                142                 :                :             AccessExclusiveLock
                                143                 :                :         },
                                144                 :                :         false
                                145                 :                :     },
                                146                 :                :     {
                                147                 :                :         {
                                148                 :                :             "deduplicate_items",
                                149                 :                :             "Enables \"deduplicate items\" feature for this btree index",
                                150                 :                :             RELOPT_KIND_BTREE,
                                151                 :                :             ShareUpdateExclusiveLock    /* since it applies only to later
                                152                 :                :                                          * inserts */
                                153                 :                :         },
                                154                 :                :         true
                                155                 :                :     },
                                156                 :                :     /* list terminator */
                                157                 :                :     {{NULL}}
                                158                 :                : };
                                159                 :                : 
                                160                 :                : static relopt_ternary ternaryRelOpts[] =
                                161                 :                : {
                                162                 :                :     {
                                163                 :                :         {
                                164                 :                :             "autovacuum_enabled",
                                165                 :                :             "Enables autovacuum in this relation",
                                166                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                167                 :                :             ShareUpdateExclusiveLock
                                168                 :                :         }
                                169                 :                :     },
                                170                 :                :     {
                                171                 :                :         {
                                172                 :                :             "vacuum_truncate",
                                173                 :                :             "Enables vacuum to truncate empty pages at the end of this table",
                                174                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                175                 :                :             ShareUpdateExclusiveLock
                                176                 :                :         }
                                177                 :                :     },
                                178                 :                :     /* list terminator */
                                179                 :                :     {
                                180                 :                :         {
                                181                 :                :             NULL
                                182                 :                :         }
                                183                 :                :     }
                                184                 :                : };
                                185                 :                : 
                                186                 :                : static relopt_int intRelOpts[] =
                                187                 :                : {
                                188                 :                :     {
                                189                 :                :         {
                                190                 :                :             "fillfactor",
                                191                 :                :             "Packs table pages only to this percentage",
                                192                 :                :             RELOPT_KIND_HEAP,
                                193                 :                :             ShareUpdateExclusiveLock    /* since it applies only to later
                                194                 :                :                                          * inserts */
                                195                 :                :         },
                                196                 :                :         HEAP_DEFAULT_FILLFACTOR, HEAP_MIN_FILLFACTOR, 100
                                197                 :                :     },
                                198                 :                :     {
                                199                 :                :         {
                                200                 :                :             "fillfactor",
                                201                 :                :             "Packs btree index pages only to this percentage",
                                202                 :                :             RELOPT_KIND_BTREE,
                                203                 :                :             ShareUpdateExclusiveLock    /* since it applies only to later
                                204                 :                :                                          * inserts */
                                205                 :                :         },
                                206                 :                :         BTREE_DEFAULT_FILLFACTOR, BTREE_MIN_FILLFACTOR, 100
                                207                 :                :     },
                                208                 :                :     {
                                209                 :                :         {
                                210                 :                :             "fillfactor",
                                211                 :                :             "Packs hash index pages only to this percentage",
                                212                 :                :             RELOPT_KIND_HASH,
                                213                 :                :             ShareUpdateExclusiveLock    /* since it applies only to later
                                214                 :                :                                          * inserts */
                                215                 :                :         },
                                216                 :                :         HASH_DEFAULT_FILLFACTOR, HASH_MIN_FILLFACTOR, 100
                                217                 :                :     },
                                218                 :                :     {
                                219                 :                :         {
                                220                 :                :             "fillfactor",
                                221                 :                :             "Packs gist index pages only to this percentage",
                                222                 :                :             RELOPT_KIND_GIST,
                                223                 :                :             ShareUpdateExclusiveLock    /* since it applies only to later
                                224                 :                :                                          * inserts */
                                225                 :                :         },
                                226                 :                :         GIST_DEFAULT_FILLFACTOR, GIST_MIN_FILLFACTOR, 100
                                227                 :                :     },
                                228                 :                :     {
                                229                 :                :         {
                                230                 :                :             "fillfactor",
                                231                 :                :             "Packs spgist index pages only to this percentage",
                                232                 :                :             RELOPT_KIND_SPGIST,
                                233                 :                :             ShareUpdateExclusiveLock    /* since it applies only to later
                                234                 :                :                                          * inserts */
                                235                 :                :         },
                                236                 :                :         SPGIST_DEFAULT_FILLFACTOR, SPGIST_MIN_FILLFACTOR, 100
                                237                 :                :     },
                                238                 :                :     {
                                239                 :                :         {
                                240                 :                :             "autovacuum_parallel_workers",
                                241                 :                :             "Maximum number of parallel autovacuum workers that can be used for processing this table.",
                                242                 :                :             RELOPT_KIND_HEAP,
                                243                 :                :             ShareUpdateExclusiveLock
                                244                 :                :         },
                                245                 :                :         -1, -1, 1024
                                246                 :                :     },
                                247                 :                :     {
                                248                 :                :         {
                                249                 :                :             "autovacuum_vacuum_threshold",
                                250                 :                :             "Minimum number of tuple updates or deletes prior to vacuum",
                                251                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                252                 :                :             ShareUpdateExclusiveLock
                                253                 :                :         },
                                254                 :                :         -1, 0, INT_MAX
                                255                 :                :     },
                                256                 :                :     {
                                257                 :                :         {
                                258                 :                :             "autovacuum_vacuum_max_threshold",
                                259                 :                :             "Maximum number of tuple updates or deletes prior to vacuum",
                                260                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                261                 :                :             ShareUpdateExclusiveLock
                                262                 :                :         },
                                263                 :                :         -2, -1, INT_MAX
                                264                 :                :     },
                                265                 :                :     {
                                266                 :                :         {
                                267                 :                :             "autovacuum_vacuum_insert_threshold",
                                268                 :                :             "Minimum number of tuple inserts prior to vacuum, or -1 to disable insert vacuums",
                                269                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                270                 :                :             ShareUpdateExclusiveLock
                                271                 :                :         },
                                272                 :                :         -2, -1, INT_MAX
                                273                 :                :     },
                                274                 :                :     {
                                275                 :                :         {
                                276                 :                :             "autovacuum_analyze_threshold",
                                277                 :                :             "Minimum number of tuple inserts, updates or deletes prior to analyze",
                                278                 :                :             RELOPT_KIND_HEAP,
                                279                 :                :             ShareUpdateExclusiveLock
                                280                 :                :         },
                                281                 :                :         -1, 0, INT_MAX
                                282                 :                :     },
                                283                 :                :     {
                                284                 :                :         {
                                285                 :                :             "autovacuum_vacuum_cost_limit",
                                286                 :                :             "Vacuum cost amount available before napping, for autovacuum",
                                287                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                288                 :                :             ShareUpdateExclusiveLock
                                289                 :                :         },
                                290                 :                :         -1, 1, 10000
                                291                 :                :     },
                                292                 :                :     {
                                293                 :                :         {
                                294                 :                :             "autovacuum_freeze_min_age",
                                295                 :                :             "Minimum age at which VACUUM should freeze a table row, for autovacuum",
                                296                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                297                 :                :             ShareUpdateExclusiveLock
                                298                 :                :         },
                                299                 :                :         -1, 0, 1000000000
                                300                 :                :     },
                                301                 :                :     {
                                302                 :                :         {
                                303                 :                :             "autovacuum_multixact_freeze_min_age",
                                304                 :                :             "Minimum multixact age at which VACUUM should freeze a row multixact's, for autovacuum",
                                305                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                306                 :                :             ShareUpdateExclusiveLock
                                307                 :                :         },
                                308                 :                :         -1, 0, 1000000000
                                309                 :                :     },
                                310                 :                :     {
                                311                 :                :         {
                                312                 :                :             "autovacuum_freeze_max_age",
                                313                 :                :             "Age at which to autovacuum a table to prevent transaction ID wraparound",
                                314                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                315                 :                :             ShareUpdateExclusiveLock
                                316                 :                :         },
                                317                 :                :         -1, 100000, 2000000000
                                318                 :                :     },
                                319                 :                :     {
                                320                 :                :         {
                                321                 :                :             "autovacuum_multixact_freeze_max_age",
                                322                 :                :             "Multixact age at which to autovacuum a table to prevent multixact wraparound",
                                323                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                324                 :                :             ShareUpdateExclusiveLock
                                325                 :                :         },
                                326                 :                :         -1, 10000, 2000000000
                                327                 :                :     },
                                328                 :                :     {
                                329                 :                :         {
                                330                 :                :             "autovacuum_freeze_table_age",
                                331                 :                :             "Age at which VACUUM should perform a full table sweep to freeze row versions",
                                332                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                333                 :                :             ShareUpdateExclusiveLock
                                334                 :                :         }, -1, 0, 2000000000
                                335                 :                :     },
                                336                 :                :     {
                                337                 :                :         {
                                338                 :                :             "autovacuum_multixact_freeze_table_age",
                                339                 :                :             "Age of multixact at which VACUUM should perform a full table sweep to freeze row versions",
                                340                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                341                 :                :             ShareUpdateExclusiveLock
                                342                 :                :         }, -1, 0, 2000000000
                                343                 :                :     },
                                344                 :                :     {
                                345                 :                :         {
                                346                 :                :             "log_autovacuum_min_duration",
                                347                 :                :             "Sets the minimum execution time above which vacuum actions by autovacuum will be logged",
                                348                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                349                 :                :             ShareUpdateExclusiveLock
                                350                 :                :         },
                                351                 :                :         -2, -1, INT_MAX
                                352                 :                :     },
                                353                 :                :     {
                                354                 :                :         {
                                355                 :                :             "log_autoanalyze_min_duration",
                                356                 :                :             "Sets the minimum execution time above which analyze actions by autovacuum will be logged",
                                357                 :                :             RELOPT_KIND_HEAP,
                                358                 :                :             ShareUpdateExclusiveLock
                                359                 :                :         },
                                360                 :                :         -1, -1, INT_MAX
                                361                 :                :     },
                                362                 :                :     {
                                363                 :                :         {
                                364                 :                :             "toast_tuple_target",
                                365                 :                :             "Sets the target tuple length at which external columns will be toasted",
                                366                 :                :             RELOPT_KIND_HEAP,
                                367                 :                :             ShareUpdateExclusiveLock
                                368                 :                :         },
                                369                 :                :         TOAST_TUPLE_TARGET, 128, TOAST_TUPLE_TARGET_MAIN
                                370                 :                :     },
                                371                 :                :     {
                                372                 :                :         {
                                373                 :                :             "pages_per_range",
                                374                 :                :             "Number of pages that each page range covers in a BRIN index",
                                375                 :                :             RELOPT_KIND_BRIN,
                                376                 :                :             AccessExclusiveLock
                                377                 :                :         }, 128, 1, 131072
                                378                 :                :     },
                                379                 :                :     {
                                380                 :                :         {
                                381                 :                :             "gin_pending_list_limit",
                                382                 :                :             "Maximum size of the pending list for this GIN index, in kilobytes.",
                                383                 :                :             RELOPT_KIND_GIN,
                                384                 :                :             AccessExclusiveLock
                                385                 :                :         },
                                386                 :                :         -1, 64, MAX_KILOBYTES
                                387                 :                :     },
                                388                 :                :     {
                                389                 :                :         {
                                390                 :                :             "effective_io_concurrency",
                                391                 :                :             "Number of simultaneous requests that can be handled efficiently by the disk subsystem.",
                                392                 :                :             RELOPT_KIND_TABLESPACE,
                                393                 :                :             ShareUpdateExclusiveLock
                                394                 :                :         },
                                395                 :                :         -1, 0, MAX_IO_CONCURRENCY
                                396                 :                :     },
                                397                 :                :     {
                                398                 :                :         {
                                399                 :                :             "maintenance_io_concurrency",
                                400                 :                :             "Number of simultaneous requests that can be handled efficiently by the disk subsystem for maintenance work.",
                                401                 :                :             RELOPT_KIND_TABLESPACE,
                                402                 :                :             ShareUpdateExclusiveLock
                                403                 :                :         },
                                404                 :                :         -1, 0, MAX_IO_CONCURRENCY
                                405                 :                :     },
                                406                 :                :     {
                                407                 :                :         {
                                408                 :                :             "parallel_workers",
                                409                 :                :             "Number of parallel processes that can be used per executor node for this relation.",
                                410                 :                :             RELOPT_KIND_HEAP,
                                411                 :                :             ShareUpdateExclusiveLock
                                412                 :                :         },
                                413                 :                :         -1, 0, 1024
                                414                 :                :     },
                                415                 :                : 
                                416                 :                :     /* list terminator */
                                417                 :                :     {{NULL}}
                                418                 :                : };
                                419                 :                : 
                                420                 :                : static relopt_real realRelOpts[] =
                                421                 :                : {
                                422                 :                :     {
                                423                 :                :         {
                                424                 :                :             "autovacuum_vacuum_cost_delay",
                                425                 :                :             "Vacuum cost delay in milliseconds, for autovacuum",
                                426                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                427                 :                :             ShareUpdateExclusiveLock
                                428                 :                :         },
                                429                 :                :         -1, 0.0, 100.0
                                430                 :                :     },
                                431                 :                :     {
                                432                 :                :         {
                                433                 :                :             "autovacuum_vacuum_scale_factor",
                                434                 :                :             "Number of tuple updates or deletes prior to vacuum as a fraction of reltuples",
                                435                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                436                 :                :             ShareUpdateExclusiveLock
                                437                 :                :         },
                                438                 :                :         -1, 0.0, 100.0
                                439                 :                :     },
                                440                 :                :     {
                                441                 :                :         {
                                442                 :                :             "autovacuum_vacuum_insert_scale_factor",
                                443                 :                :             "Number of tuple inserts prior to vacuum as a fraction of reltuples",
                                444                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                445                 :                :             ShareUpdateExclusiveLock
                                446                 :                :         },
                                447                 :                :         -1, 0.0, 100.0
                                448                 :                :     },
                                449                 :                :     {
                                450                 :                :         {
                                451                 :                :             "autovacuum_analyze_scale_factor",
                                452                 :                :             "Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples",
                                453                 :                :             RELOPT_KIND_HEAP,
                                454                 :                :             ShareUpdateExclusiveLock
                                455                 :                :         },
                                456                 :                :         -1, 0.0, 100.0
                                457                 :                :     },
                                458                 :                :     {
                                459                 :                :         {
                                460                 :                :             "vacuum_max_eager_freeze_failure_rate",
                                461                 :                :             "Fraction of pages in a relation vacuum can scan and fail to freeze before disabling eager scanning.",
                                462                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                463                 :                :             ShareUpdateExclusiveLock
                                464                 :                :         },
                                465                 :                :         -1, 0.0, 1.0
                                466                 :                :     },
                                467                 :                : 
                                468                 :                :     {
                                469                 :                :         {
                                470                 :                :             "seq_page_cost",
                                471                 :                :             "Sets the planner's estimate of the cost of a sequentially fetched disk page.",
                                472                 :                :             RELOPT_KIND_TABLESPACE,
                                473                 :                :             ShareUpdateExclusiveLock
                                474                 :                :         },
                                475                 :                :         -1, 0.0, DBL_MAX
                                476                 :                :     },
                                477                 :                :     {
                                478                 :                :         {
                                479                 :                :             "random_page_cost",
                                480                 :                :             "Sets the planner's estimate of the cost of a nonsequentially fetched disk page.",
                                481                 :                :             RELOPT_KIND_TABLESPACE,
                                482                 :                :             ShareUpdateExclusiveLock
                                483                 :                :         },
                                484                 :                :         -1, 0.0, DBL_MAX
                                485                 :                :     },
                                486                 :                :     {
                                487                 :                :         {
                                488                 :                :             "n_distinct",
                                489                 :                :             "Sets the planner's estimate of the number of distinct values appearing in a column (excluding child relations).",
                                490                 :                :             RELOPT_KIND_ATTRIBUTE,
                                491                 :                :             ShareUpdateExclusiveLock
                                492                 :                :         },
                                493                 :                :         0, -1.0, DBL_MAX
                                494                 :                :     },
                                495                 :                :     {
                                496                 :                :         {
                                497                 :                :             "n_distinct_inherited",
                                498                 :                :             "Sets the planner's estimate of the number of distinct values appearing in a column (including child relations).",
                                499                 :                :             RELOPT_KIND_ATTRIBUTE,
                                500                 :                :             ShareUpdateExclusiveLock
                                501                 :                :         },
                                502                 :                :         0, -1.0, DBL_MAX
                                503                 :                :     },
                                504                 :                :     {
                                505                 :                :         {
                                506                 :                :             "vacuum_cleanup_index_scale_factor",
                                507                 :                :             "Deprecated B-Tree parameter.",
                                508                 :                :             RELOPT_KIND_BTREE,
                                509                 :                :             ShareUpdateExclusiveLock
                                510                 :                :         },
                                511                 :                :         -1, 0.0, 1e10
                                512                 :                :     },
                                513                 :                :     /* list terminator */
                                514                 :                :     {{NULL}}
                                515                 :                : };
                                516                 :                : 
                                517                 :                : /* values from StdRdOptIndexCleanup */
                                518                 :                : static relopt_enum_elt_def StdRdOptIndexCleanupValues[] =
                                519                 :                : {
                                520                 :                :     /* no value for NOT_SET */
                                521                 :                :     {"auto", STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO},
                                522                 :                :     {"on", STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON},
                                523                 :                :     {"off", STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF},
                                524                 :                :     {"true", STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON},
                                525                 :                :     {"false", STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF},
                                526                 :                :     {"yes", STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON},
                                527                 :                :     {"no", STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF},
                                528                 :                :     {"1", STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON},
                                529                 :                :     {"0", STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF},
                                530                 :                :     {(const char *) NULL}       /* list terminator */
                                531                 :                : };
                                532                 :                : 
                                533                 :                : /* values from GistOptBufferingMode */
                                534                 :                : static relopt_enum_elt_def gistBufferingOptValues[] =
                                535                 :                : {
                                536                 :                :     {"auto", GIST_OPTION_BUFFERING_AUTO},
                                537                 :                :     {"on", GIST_OPTION_BUFFERING_ON},
                                538                 :                :     {"off", GIST_OPTION_BUFFERING_OFF},
                                539                 :                :     {(const char *) NULL}       /* list terminator */
                                540                 :                : };
                                541                 :                : 
                                542                 :                : /* values from ViewOptCheckOption */
                                543                 :                : static relopt_enum_elt_def viewCheckOptValues[] =
                                544                 :                : {
                                545                 :                :     /* no value for NOT_SET */
                                546                 :                :     {"local", VIEW_OPTION_CHECK_OPTION_LOCAL},
                                547                 :                :     {"cascaded", VIEW_OPTION_CHECK_OPTION_CASCADED},
                                548                 :                :     {(const char *) NULL}       /* list terminator */
                                549                 :                : };
                                550                 :                : 
                                551                 :                : /* values from StdRdOptToastValueType */
                                552                 :                : static relopt_enum_elt_def StdRdOptToastValueTypes[] =
                                553                 :                : {
                                554                 :                :     /* no value for INVALID */
                                555                 :                :     {"oid", STDRD_OPTION_TOAST_VALUE_TYPE_OID},
                                556                 :                :     {"oid8", STDRD_OPTION_TOAST_VALUE_TYPE_OID8},
                                557                 :                :     {(const char *) NULL}       /* list terminator */
                                558                 :                : };
                                559                 :                : 
                                560                 :                : static relopt_enum enumRelOpts[] =
                                561                 :                : {
                                562                 :                :     {
                                563                 :                :         {
                                564                 :                :             "vacuum_index_cleanup",
                                565                 :                :             "Controls index vacuuming and index cleanup",
                                566                 :                :             RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
                                567                 :                :             ShareUpdateExclusiveLock
                                568                 :                :         },
                                569                 :                :         StdRdOptIndexCleanupValues,
                                570                 :                :         STDRD_OPTION_VACUUM_INDEX_CLEANUP_NOT_SET,
                                571                 :                :         gettext_noop("Valid values are \"on\", \"off\", and \"auto\".")
                                572                 :                :     },
                                573                 :                :     {
                                574                 :                :         {
                                575                 :                :             "toast_value_type",
                                576                 :                :             "Controls the attribute type of chunk_id at toast table creation",
                                577                 :                :             RELOPT_KIND_HEAP,
                                578                 :                :             ShareUpdateExclusiveLock
                                579                 :                :         },
                                580                 :                :         StdRdOptToastValueTypes,
                                581                 :                :         STDRD_OPTION_TOAST_VALUE_TYPE_OID,
                                582                 :                :         gettext_noop("Valid values are \"oid\" and \"oid8\".")
                                583                 :                :     },
                                584                 :                :     {
                                585                 :                :         {
                                586                 :                :             "buffering",
                                587                 :                :             "Enables buffering build for this GiST index",
                                588                 :                :             RELOPT_KIND_GIST,
                                589                 :                :             AccessExclusiveLock
                                590                 :                :         },
                                591                 :                :         gistBufferingOptValues,
                                592                 :                :         GIST_OPTION_BUFFERING_AUTO,
                                593                 :                :         gettext_noop("Valid values are \"on\", \"off\", and \"auto\".")
                                594                 :                :     },
                                595                 :                :     {
                                596                 :                :         {
                                597                 :                :             "check_option",
                                598                 :                :             "View has WITH CHECK OPTION defined (local or cascaded).",
                                599                 :                :             RELOPT_KIND_VIEW,
                                600                 :                :             AccessExclusiveLock
                                601                 :                :         },
                                602                 :                :         viewCheckOptValues,
                                603                 :                :         VIEW_OPTION_CHECK_OPTION_NOT_SET,
                                604                 :                :         gettext_noop("Valid values are \"local\" and \"cascaded\".")
                                605                 :                :     },
                                606                 :                :     /* list terminator */
                                607                 :                :     {{NULL}}
                                608                 :                : };
                                609                 :                : 
                                610                 :                : static relopt_string stringRelOpts[] =
                                611                 :                : {
                                612                 :                :     /* list terminator */
                                613                 :                :     {{NULL}}
                                614                 :                : };
                                615                 :                : 
                                616                 :                : static relopt_gen **relOpts = NULL;
                                617                 :                : static uint32 last_assigned_kind = RELOPT_KIND_LAST_DEFAULT;
                                618                 :                : 
                                619                 :                : static int  num_custom_options = 0;
                                620                 :                : static relopt_gen **custom_options = NULL;
                                621                 :                : static bool need_initialization = true;
                                622                 :                : 
                                623                 :                : static void initialize_reloptions(void);
                                624                 :                : static void parse_one_reloption(relopt_value *option, char *text_str,
                                625                 :                :                                 int text_len, bool validate);
                                626                 :                : 
                                627                 :                : /*
                                628                 :                :  * Get the length of a string reloption (either default or the user-defined
                                629                 :                :  * value).  This is used for allocation purposes when building a set of
                                630                 :                :  * relation options.
                                631                 :                :  */
                                632                 :                : #define GET_STRING_RELOPTION_LEN(option) \
                                633                 :                :     ((option).isset ? strlen((option).string_val) : \
                                634                 :                :      ((relopt_string *) (option).gen)->default_len)
                                635                 :                : 
                                636                 :                : #ifdef USE_ASSERT_CHECKING
                                637                 :                : /*
                                638                 :                :  * Verify that every option a TOAST table accepts defaults to a value the user
                                639                 :                :  * cannot set.  That way, we can tell whether a reloption is set on the TOAST
                                640                 :                :  * table or if we should pull the value from its main table.
                                641                 :                :  */
                                642                 :                : static void
   30 nathan@postgresql.or      643                 :GNC        4261 : assert_toast_defaults_unsettable(void)
                                644                 :                : {
                                645         [ +  + ]:         207637 :     for (int i = 0; relOpts[i]; i++)
                                646                 :                :     {
                                647                 :         203376 :         relopt_gen *gen = relOpts[i];
                                648                 :                : 
                                649         [ +  + ]:         203376 :         if ((gen->kinds & RELOPT_KIND_TOAST) == 0)
                                650                 :         126678 :             continue;
                                651                 :                : 
                                652                 :                :         /*
                                653                 :                :          * A TOAST table's value is filled in from its main table's at the
                                654                 :                :          * same offset in the same struct, so the option must be settable on a
                                655                 :                :          * heap too.
                                656                 :                :          */
                                657         [ -  + ]:          76698 :         Assert((gen->kinds & RELOPT_KIND_HEAP) != 0);
                                658                 :                : 
                                659   [ +  +  +  +  :          76698 :         switch (gen->type)
                                                 - ]
                                660                 :                :         {
                                661                 :           8522 :             case RELOPT_TYPE_TERNARY:
                                662                 :                : 
                                663                 :                :                 /*
                                664                 :                :                  * Ternaries carry no default, and parse_one_reloption() can
                                665                 :                :                  * only produce true or false, so PG_TERNARY_UNSET is already
                                666                 :                :                  * beyond a user's reach.
                                667                 :                :                  */
                                668                 :           8522 :                 break;
                                669                 :                : 
                                670                 :          46871 :             case RELOPT_TYPE_INT:
                                671                 :                :                 {
                                672                 :          46871 :                     relopt_int *optint = (relopt_int *) gen;
                                673                 :                : 
                                674   [ -  +  -  - ]:          46871 :                     Assert(optint->default_val < optint->min ||
                                675                 :                :                            optint->default_val > optint->max);
                                676                 :          46871 :                     break;
                                677                 :                :                 }
                                678                 :                : 
                                679                 :          17044 :             case RELOPT_TYPE_REAL:
                                680                 :                :                 {
                                681                 :          17044 :                     relopt_real *optreal = (relopt_real *) gen;
                                682                 :                : 
                                683   [ -  +  -  - ]:          17044 :                     Assert(optreal->default_val < optreal->min ||
                                684                 :                :                            optreal->default_val > optreal->max);
                                685                 :          17044 :                     break;
                                686                 :                :                 }
                                687                 :                : 
                                688                 :           4261 :             case RELOPT_TYPE_ENUM:
                                689                 :                :                 {
                                690                 :           4261 :                     relopt_enum *optenum = (relopt_enum *) gen;
                                691                 :                : 
                                692                 :           4261 :                     for (relopt_enum_elt_def *elt = optenum->members;
                                693         [ +  + ]:          42610 :                          elt->string_val; elt++)
                                694         [ -  + ]:          38349 :                         Assert(elt->symbol_val != optenum->default_val);
                                695                 :           4261 :                     break;
                                696                 :                :                 }
                                697                 :                : 
   30 nathan@postgresql.or      698                 :UNC           0 :             default:
                                699                 :                :                 /* Neither bools nor strings can express "unset". */
                                700                 :              0 :                 Assert(false);
                                701                 :                :         }
                                702                 :                :     }
   30 nathan@postgresql.or      703                 :GNC        4261 : }
                                704                 :                : #endif                          /* USE_ASSERT_CHECKING */
                                705                 :                : 
                                706                 :                : /*
                                707                 :                :  * initialize_reloptions
                                708                 :                :  *      initialization routine, must be called before parsing
                                709                 :                :  *
                                710                 :                :  * Initialize the relOpts array and fill each variable's type and name length.
                                711                 :                :  */
                                712                 :                : static void
 6467 alvherre@alvh.no-ip.      713                 :CBC        4261 : initialize_reloptions(void)
                                714                 :                : {
                                715                 :                :     int         i;
                                716                 :                :     int         j;
                                717                 :                : 
 6037 tgl@sss.pgh.pa.us         718                 :           4261 :     j = 0;
 6467 alvherre@alvh.no-ip.      719         [ +  + ]:          29827 :     for (i = 0; boolRelOpts[i].gen.name; i++)
                                720                 :                :     {
 4055 simon@2ndQuadrant.co      721         [ -  + ]:          25566 :         Assert(DoLockModesConflict(boolRelOpts[i].gen.lockmode,
                                722                 :                :                                    boolRelOpts[i].gen.lockmode));
 6467 alvherre@alvh.no-ip.      723                 :          25566 :         j++;
                                724                 :                :     }
  242 alvherre@kurilemu.de      725         [ +  + ]:          12783 :     for (i = 0; ternaryRelOpts[i].gen.name; i++)
                                726                 :                :     {
                                727         [ -  + ]:           8522 :         Assert(DoLockModesConflict(ternaryRelOpts[i].gen.lockmode,
                                728                 :                :                                    ternaryRelOpts[i].gen.lockmode));
                                729                 :           8522 :         j++;
                                730                 :                :     }
                                731                 :                : 
 6467 alvherre@alvh.no-ip.      732         [ +  + ]:         110786 :     for (i = 0; intRelOpts[i].gen.name; i++)
                                733                 :                :     {
 4055 simon@2ndQuadrant.co      734         [ -  + ]:         106525 :         Assert(DoLockModesConflict(intRelOpts[i].gen.lockmode,
                                735                 :                :                                    intRelOpts[i].gen.lockmode));
 6467 alvherre@alvh.no-ip.      736                 :         106525 :         j++;
                                737                 :                :     }
                                738         [ +  + ]:          46871 :     for (i = 0; realRelOpts[i].gen.name; i++)
                                739                 :                :     {
 4055 simon@2ndQuadrant.co      740         [ -  + ]:          42610 :         Assert(DoLockModesConflict(realRelOpts[i].gen.lockmode,
                                741                 :                :                                    realRelOpts[i].gen.lockmode));
 6467 alvherre@alvh.no-ip.      742                 :          42610 :         j++;
                                743                 :                :     }
 2552                           744         [ +  + ]:          21305 :     for (i = 0; enumRelOpts[i].gen.name; i++)
                                745                 :                :     {
                                746         [ -  + ]:          17044 :         Assert(DoLockModesConflict(enumRelOpts[i].gen.lockmode,
                                747                 :                :                                    enumRelOpts[i].gen.lockmode));
                                748                 :          17044 :         j++;
                                749                 :                :     }
 6467                           750         [ -  + ]:           4261 :     for (i = 0; stringRelOpts[i].gen.name; i++)
                                751                 :                :     {
 4055 simon@2ndQuadrant.co      752         [ #  # ]:UBC           0 :         Assert(DoLockModesConflict(stringRelOpts[i].gen.lockmode,
                                753                 :                :                                    stringRelOpts[i].gen.lockmode));
 6467 alvherre@alvh.no-ip.      754                 :              0 :         j++;
                                755                 :                :     }
 6467 alvherre@alvh.no-ip.      756                 :CBC        4261 :     j += num_custom_options;
                                757                 :                : 
                                758         [ -  + ]:           4261 :     if (relOpts)
 6467 alvherre@alvh.no-ip.      759                 :UBC           0 :         pfree(relOpts);
 6467 alvherre@alvh.no-ip.      760                 :CBC        8522 :     relOpts = MemoryContextAlloc(TopMemoryContext,
                                761                 :           4261 :                                  (j + 1) * sizeof(relopt_gen *));
                                762                 :                : 
                                763                 :           4261 :     j = 0;
                                764         [ +  + ]:          29827 :     for (i = 0; boolRelOpts[i].gen.name; i++)
                                765                 :                :     {
                                766                 :          25566 :         relOpts[j] = &boolRelOpts[i].gen;
                                767                 :          25566 :         relOpts[j]->type = RELOPT_TYPE_BOOL;
                                768                 :          25566 :         relOpts[j]->namelen = strlen(relOpts[j]->name);
                                769                 :          25566 :         j++;
                                770                 :                :     }
                                771                 :                : 
  242 alvherre@kurilemu.de      772         [ +  + ]:          12783 :     for (i = 0; ternaryRelOpts[i].gen.name; i++)
                                773                 :                :     {
                                774                 :           8522 :         relOpts[j] = &ternaryRelOpts[i].gen;
                                775                 :           8522 :         relOpts[j]->type = RELOPT_TYPE_TERNARY;
                                776                 :           8522 :         relOpts[j]->namelen = strlen(relOpts[j]->name);
                                777                 :           8522 :         j++;
                                778                 :                :     }
                                779                 :                : 
 6467 alvherre@alvh.no-ip.      780         [ +  + ]:         110786 :     for (i = 0; intRelOpts[i].gen.name; i++)
                                781                 :                :     {
                                782                 :         106525 :         relOpts[j] = &intRelOpts[i].gen;
                                783                 :         106525 :         relOpts[j]->type = RELOPT_TYPE_INT;
                                784                 :         106525 :         relOpts[j]->namelen = strlen(relOpts[j]->name);
                                785                 :         106525 :         j++;
                                786                 :                :     }
                                787                 :                : 
                                788         [ +  + ]:          46871 :     for (i = 0; realRelOpts[i].gen.name; i++)
                                789                 :                :     {
                                790                 :          42610 :         relOpts[j] = &realRelOpts[i].gen;
                                791                 :          42610 :         relOpts[j]->type = RELOPT_TYPE_REAL;
                                792                 :          42610 :         relOpts[j]->namelen = strlen(relOpts[j]->name);
                                793                 :          42610 :         j++;
                                794                 :                :     }
                                795                 :                : 
 2552                           796         [ +  + ]:          21305 :     for (i = 0; enumRelOpts[i].gen.name; i++)
                                797                 :                :     {
                                798                 :          17044 :         relOpts[j] = &enumRelOpts[i].gen;
                                799                 :          17044 :         relOpts[j]->type = RELOPT_TYPE_ENUM;
                                800                 :          17044 :         relOpts[j]->namelen = strlen(relOpts[j]->name);
                                801                 :          17044 :         j++;
                                802                 :                :     }
                                803                 :                : 
 6467                           804         [ -  + ]:           4261 :     for (i = 0; stringRelOpts[i].gen.name; i++)
                                805                 :                :     {
 6467 alvherre@alvh.no-ip.      806                 :UBC           0 :         relOpts[j] = &stringRelOpts[i].gen;
                                807                 :              0 :         relOpts[j]->type = RELOPT_TYPE_STRING;
                                808                 :              0 :         relOpts[j]->namelen = strlen(relOpts[j]->name);
                                809                 :              0 :         j++;
                                810                 :                :     }
                                811                 :                : 
 6467 alvherre@alvh.no-ip.      812         [ +  + ]:CBC        7370 :     for (i = 0; i < num_custom_options; i++)
                                813                 :                :     {
                                814                 :           3109 :         relOpts[j] = custom_options[i];
                                815                 :           3109 :         j++;
                                816                 :                :     }
                                817                 :                : 
                                818                 :                :     /* add a list terminator */
                                819                 :           4261 :     relOpts[j] = NULL;
                                820                 :                : 
                                821                 :                :     /* flag the work is complete */
 6037 tgl@sss.pgh.pa.us         822                 :           4261 :     need_initialization = false;
                                823                 :                : 
                                824                 :                : #ifdef USE_ASSERT_CHECKING
   30 nathan@postgresql.or      825                 :GNC        4261 :     assert_toast_defaults_unsettable();
                                826                 :                : #endif
 6467 alvherre@alvh.no-ip.      827                 :CBC        4261 : }
                                828                 :                : 
                                829                 :                : /*
                                830                 :                :  * add_reloption_kind
                                831                 :                :  *      Create a new relopt_kind value, to be used in custom reloptions by
                                832                 :                :  *      user-defined AMs.
                                833                 :                :  */
                                834                 :                : relopt_kind
                                835                 :             96 : add_reloption_kind(void)
                                836                 :                : {
                                837                 :                :     /* don't hand out the last bit so that the enum's behavior is portable */
                                838         [ -  + ]:             96 :     if (last_assigned_kind >= RELOPT_KIND_MAX)
 6467 alvherre@alvh.no-ip.      839         [ #  # ]:UBC           0 :         ereport(ERROR,
                                840                 :                :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                841                 :                :                  errmsg("user-defined relation parameter types limit exceeded")));
 6378 alvherre@alvh.no-ip.      842                 :CBC          96 :     last_assigned_kind <<= 1;
 6328 tgl@sss.pgh.pa.us         843                 :             96 :     return (relopt_kind) last_assigned_kind;
                                844                 :                : }
                                845                 :                : 
                                846                 :                : /*
                                847                 :                :  * add_reloption
                                848                 :                :  *      Add an already-created custom reloption to the list, and recompute the
                                849                 :                :  *      main parser table.
                                850                 :                :  */
                                851                 :                : static void
 6467 alvherre@alvh.no-ip.      852                 :           3142 : add_reloption(relopt_gen *newoption)
                                853                 :                : {
                                854                 :                :     static int  max_custom_options = 0;
                                855                 :                : 
                                856         [ +  + ]:           3142 :     if (num_custom_options >= max_custom_options)
                                857                 :                :     {
                                858                 :                :         MemoryContext oldcxt;
                                859                 :                : 
                                860                 :            381 :         oldcxt = MemoryContextSwitchTo(TopMemoryContext);
                                861                 :                : 
                                862         [ +  + ]:            381 :         if (max_custom_options == 0)
                                863                 :                :         {
                                864                 :             96 :             max_custom_options = 8;
   34 michael@paquier.xyz       865                 :GNC          96 :             custom_options = palloc_array(relopt_gen *, max_custom_options);
                                866                 :                :         }
                                867                 :                :         else
                                868                 :                :         {
 6467 alvherre@alvh.no-ip.      869                 :CBC         285 :             max_custom_options *= 2;
   34 michael@paquier.xyz       870                 :GNC         285 :             custom_options = repalloc_array(custom_options, relopt_gen *, max_custom_options);
                                871                 :                :         }
 6467 alvherre@alvh.no-ip.      872                 :CBC         381 :         MemoryContextSwitchTo(oldcxt);
                                873                 :                :     }
                                874                 :           3142 :     custom_options[num_custom_options++] = newoption;
                                875                 :                : 
                                876                 :           3142 :     need_initialization = true;
                                877                 :           3142 : }
                                878                 :                : 
                                879                 :                : /*
                                880                 :                :  * init_local_reloptions
                                881                 :                :  *      Initialize local reloptions that will parsed into bytea structure of
                                882                 :                :  *      'relopt_struct_size'.
                                883                 :                :  */
                                884                 :                : void
 1462 pg@bowt.ie                885                 :           3808 : init_local_reloptions(local_relopts *relopts, Size relopt_struct_size)
                                886                 :                : {
                                887                 :           3808 :     relopts->options = NIL;
                                888                 :           3808 :     relopts->validators = NIL;
                                889                 :           3808 :     relopts->relopt_struct_size = relopt_struct_size;
 2365 akorotkov@postgresql      890                 :           3808 : }
                                891                 :                : 
                                892                 :                : /*
                                893                 :                :  * register_reloptions_validator
                                894                 :                :  *      Register custom validation callback that will be called at the end of
                                895                 :                :  *      build_local_reloptions().
                                896                 :                :  */
                                897                 :                : void
 1462 pg@bowt.ie                898                 :             14 : register_reloptions_validator(local_relopts *relopts, relopts_validator validator)
                                899                 :                : {
                                900                 :             14 :     relopts->validators = lappend(relopts->validators, validator);
 2365 akorotkov@postgresql      901                 :             14 : }
                                902                 :                : 
                                903                 :                : /*
                                904                 :                :  * add_local_reloption
                                905                 :                :  *      Add an already-created custom reloption to the local list.
                                906                 :                :  */
                                907                 :                : static void
                                908                 :           2492 : add_local_reloption(local_relopts *relopts, relopt_gen *newoption, int offset)
                                909                 :                : {
  284 michael@paquier.xyz       910                 :           2492 :     local_relopt *opt = palloc_object(local_relopt);
                                911                 :                : 
 2365 akorotkov@postgresql      912         [ -  + ]:           2492 :     Assert(offset < relopts->relopt_struct_size);
                                913                 :                : 
                                914                 :           2492 :     opt->option = newoption;
                                915                 :           2492 :     opt->offset = offset;
                                916                 :                : 
                                917                 :           2492 :     relopts->options = lappend(relopts->options, opt);
                                918                 :           2492 : }
                                919                 :                : 
                                920                 :                : /*
                                921                 :                :  * allocate_reloption
                                922                 :                :  *      Allocate a new reloption and initialize the type-agnostic fields
                                923                 :                :  *      (for types other than string)
                                924                 :                :  */
                                925                 :                : static relopt_gen *
  174 nathan@postgresql.or      926                 :           5634 : allocate_reloption(uint32 kinds, int type, const char *name, const char *desc,
                                927                 :                :                    LOCKMODE lockmode)
                                928                 :                : {
                                929                 :                :     MemoryContext oldcxt;
                                930                 :                :     size_t      size;
                                931                 :                :     relopt_gen *newoption;
                                932                 :                : 
 2365 akorotkov@postgresql      933         [ +  + ]:           5634 :     if (kinds != RELOPT_KIND_LOCAL)
                                934                 :           3142 :         oldcxt = MemoryContextSwitchTo(TopMemoryContext);
                                935                 :                :     else
                                936                 :           2492 :         oldcxt = NULL;
                                937                 :                : 
 6467 alvherre@alvh.no-ip.      938   [ +  +  +  +  :           5634 :     switch (type)
                                           +  +  - ]
                                939                 :                :     {
                                940                 :              1 :         case RELOPT_TYPE_BOOL:
                                941                 :              1 :             size = sizeof(relopt_bool);
                                942                 :              1 :             break;
  242 alvherre@kurilemu.de      943                 :              1 :         case RELOPT_TYPE_TERNARY:
                                944                 :              1 :             size = sizeof(relopt_ternary);
                                945                 :              1 :             break;
 6467 alvherre@alvh.no-ip.      946                 :           4452 :         case RELOPT_TYPE_INT:
                                947                 :           4452 :             size = sizeof(relopt_int);
                                948                 :           4452 :             break;
                                949                 :           1177 :         case RELOPT_TYPE_REAL:
                                950                 :           1177 :             size = sizeof(relopt_real);
                                951                 :           1177 :             break;
 2552                           952                 :              1 :         case RELOPT_TYPE_ENUM:
                                953                 :              1 :             size = sizeof(relopt_enum);
                                954                 :              1 :             break;
 5521 heikki.linnakangas@i      955                 :              2 :         case RELOPT_TYPE_STRING:
                                956                 :              2 :             size = sizeof(relopt_string);
                                957                 :              2 :             break;
 6467 alvherre@alvh.no-ip.      958                 :UBC           0 :         default:
 4067 tgl@sss.pgh.pa.us         959         [ #  # ]:              0 :             elog(ERROR, "unsupported reloption type %d", type);
                                960                 :                :             return NULL;        /* keep compiler quiet */
                                961                 :                :     }
                                962                 :                : 
 6467 alvherre@alvh.no-ip.      963                 :CBC        5634 :     newoption = palloc(size);
                                964                 :                : 
                                965                 :           5634 :     newoption->name = pstrdup(name);
                                966         [ +  + ]:           5634 :     if (desc)
                                967                 :           5633 :         newoption->desc = pstrdup(desc);
                                968                 :                :     else
                                969                 :              1 :         newoption->desc = NULL;
 6378                           970                 :           5634 :     newoption->kinds = kinds;
 6467                           971                 :           5634 :     newoption->namelen = strlen(name);
                                972                 :           5634 :     newoption->type = type;
 2552 michael@paquier.xyz       973                 :           5634 :     newoption->lockmode = lockmode;
                                974                 :                : 
 2365 akorotkov@postgresql      975         [ +  + ]:           5634 :     if (oldcxt != NULL)
                                976                 :           3142 :         MemoryContextSwitchTo(oldcxt);
                                977                 :                : 
 6467 alvherre@alvh.no-ip.      978                 :           5634 :     return newoption;
                                979                 :                : }
                                980                 :                : 
                                981                 :                : /*
                                982                 :                :  * init_bool_reloption
                                983                 :                :  *      Allocate and initialize a new boolean reloption
                                984                 :                :  */
                                985                 :                : static relopt_bool *
  174 nathan@postgresql.or      986                 :              1 : init_bool_reloption(uint32 kinds, const char *name, const char *desc,
                                987                 :                :                     bool default_val, LOCKMODE lockmode)
                                988                 :                : {
                                989                 :                :     relopt_bool *newoption;
                                990                 :                : 
 6378 alvherre@alvh.no-ip.      991                 :              1 :     newoption = (relopt_bool *) allocate_reloption(kinds, RELOPT_TYPE_BOOL,
                                992                 :                :                                                    name, desc, lockmode);
 6467                           993                 :              1 :     newoption->default_val = default_val;
                                994                 :                : 
 2365 akorotkov@postgresql      995                 :              1 :     return newoption;
                                996                 :                : }
                                997                 :                : 
                                998                 :                : /*
                                999                 :                :  * add_bool_reloption
                               1000                 :                :  *      Add a new boolean reloption
                               1001                 :                :  */
                               1002                 :                : void
  174 nathan@postgresql.or     1003                 :              1 : add_bool_reloption(uint32 kinds, const char *name, const char *desc,
                               1004                 :                :                    bool default_val, LOCKMODE lockmode)
                               1005                 :                : {
 2365 akorotkov@postgresql     1006                 :              1 :     relopt_bool *newoption = init_bool_reloption(kinds, name, desc,
                               1007                 :                :                                                  default_val, lockmode);
                               1008                 :                : 
 6467 alvherre@alvh.no-ip.     1009                 :              1 :     add_reloption((relopt_gen *) newoption);
                               1010                 :              1 : }
                               1011                 :                : 
                               1012                 :                : /*
                               1013                 :                :  * add_local_bool_reloption
                               1014                 :                :  *      Add a new boolean local reloption
                               1015                 :                :  *
                               1016                 :                :  * 'offset' is offset of bool-typed field.
                               1017                 :                :  */
                               1018                 :                : void
 2365 akorotkov@postgresql     1019                 :UBC           0 : add_local_bool_reloption(local_relopts *relopts, const char *name,
                               1020                 :                :                          const char *desc, bool default_val, int offset)
                               1021                 :                : {
                               1022                 :              0 :     relopt_bool *newoption = init_bool_reloption(RELOPT_KIND_LOCAL,
                               1023                 :                :                                                  name, desc,
                               1024                 :                :                                                  default_val, 0);
                               1025                 :                : 
                               1026                 :              0 :     add_local_reloption(relopts, (relopt_gen *) newoption, offset);
                               1027                 :              0 : }
                               1028                 :                : 
                               1029                 :                : /*
                               1030                 :                :  * init_ternary_reloption
                               1031                 :                :  *      Allocate and initialize a new ternary reloption
                               1032                 :                :  */
                               1033                 :                : static relopt_ternary *
  174 nathan@postgresql.or     1034                 :CBC           1 : init_ternary_reloption(uint32 kinds, const char *name, const char *desc,
                               1035                 :                :                        LOCKMODE lockmode)
                               1036                 :                : {
                               1037                 :                :     relopt_ternary *newoption;
                               1038                 :                : 
                               1039                 :                :     newoption = (relopt_ternary *)
  242 alvherre@kurilemu.de     1040                 :              1 :         allocate_reloption(kinds, RELOPT_TYPE_TERNARY, name, desc, lockmode);
                               1041                 :                : 
                               1042                 :              1 :     return newoption;
                               1043                 :                : }
                               1044                 :                : 
                               1045                 :                : /*
                               1046                 :                :  * add_ternary_reloption
                               1047                 :                :  *      Add a new ternary reloption
                               1048                 :                :  */
                               1049                 :                : void
  174 nathan@postgresql.or     1050                 :              1 : add_ternary_reloption(uint32 kinds, const char *name, const char *desc,
                               1051                 :                :                       LOCKMODE lockmode)
                               1052                 :                : {
                               1053                 :                :     relopt_ternary *newoption;
                               1054                 :                : 
                               1055                 :                :     newoption =
  242 alvherre@kurilemu.de     1056                 :              1 :         init_ternary_reloption(kinds, name, desc, lockmode);
                               1057                 :                : 
                               1058                 :              1 :     add_reloption((relopt_gen *) newoption);
                               1059                 :              1 : }
                               1060                 :                : 
                               1061                 :                : /*
                               1062                 :                :  * add_local_ternary_reloption
                               1063                 :                :  *      Add a new ternary local reloption
                               1064                 :                :  *
                               1065                 :                :  * 'offset' is offset of ternary-typed field.
                               1066                 :                :  */
                               1067                 :                : void
  242 alvherre@kurilemu.de     1068                 :UBC           0 : add_local_ternary_reloption(local_relopts *relopts, const char *name,
                               1069                 :                :                             const char *desc, int offset)
                               1070                 :                : {
                               1071                 :                :     relopt_ternary *newoption;
                               1072                 :                : 
                               1073                 :                :     newoption =
                               1074                 :              0 :         init_ternary_reloption(RELOPT_KIND_LOCAL, name, desc, 0);
                               1075                 :                : 
                               1076                 :              0 :     add_local_reloption(relopts, (relopt_gen *) newoption, offset);
                               1077                 :              0 : }
                               1078                 :                : 
                               1079                 :                : /*
                               1080                 :                :  * init_real_reloption
                               1081                 :                :  *      Allocate and initialize a new integer reloption
                               1082                 :                :  */
                               1083                 :                : static relopt_int *
  174 nathan@postgresql.or     1084                 :CBC        4452 : init_int_reloption(uint32 kinds, const char *name, const char *desc,
                               1085                 :                :                    int default_val, int min_val, int max_val,
                               1086                 :                :                    LOCKMODE lockmode)
                               1087                 :                : {
                               1088                 :                :     relopt_int *newoption;
                               1089                 :                : 
 6378 alvherre@alvh.no-ip.     1090                 :           4452 :     newoption = (relopt_int *) allocate_reloption(kinds, RELOPT_TYPE_INT,
                               1091                 :                :                                                   name, desc, lockmode);
 6467                          1092                 :           4452 :     newoption->default_val = default_val;
                               1093                 :           4452 :     newoption->min = min_val;
                               1094                 :           4452 :     newoption->max = max_val;
                               1095                 :                : 
 2365 akorotkov@postgresql     1096                 :           4452 :     return newoption;
                               1097                 :                : }
                               1098                 :                : 
                               1099                 :                : /*
                               1100                 :                :  * add_int_reloption
                               1101                 :                :  *      Add a new integer reloption
                               1102                 :                :  */
                               1103                 :                : void
  174 nathan@postgresql.or     1104                 :           3136 : add_int_reloption(uint32 kinds, const char *name, const char *desc, int default_val,
                               1105                 :                :                   int min_val, int max_val, LOCKMODE lockmode)
                               1106                 :                : {
 2365 akorotkov@postgresql     1107                 :           3136 :     relopt_int *newoption = init_int_reloption(kinds, name, desc,
                               1108                 :                :                                                default_val, min_val,
                               1109                 :                :                                                max_val, lockmode);
                               1110                 :                : 
 6467 alvherre@alvh.no-ip.     1111                 :           3136 :     add_reloption((relopt_gen *) newoption);
                               1112                 :           3136 : }
                               1113                 :                : 
                               1114                 :                : /*
                               1115                 :                :  * add_local_int_reloption
                               1116                 :                :  *      Add a new local integer reloption
                               1117                 :                :  *
                               1118                 :                :  * 'offset' is offset of int-typed field.
                               1119                 :                :  */
                               1120                 :                : void
 2365 akorotkov@postgresql     1121                 :           1316 : add_local_int_reloption(local_relopts *relopts, const char *name,
                               1122                 :                :                         const char *desc, int default_val, int min_val,
                               1123                 :                :                         int max_val, int offset)
                               1124                 :                : {
                               1125                 :           1316 :     relopt_int *newoption = init_int_reloption(RELOPT_KIND_LOCAL,
                               1126                 :                :                                                name, desc, default_val,
                               1127                 :                :                                                min_val, max_val, 0);
                               1128                 :                : 
                               1129                 :           1316 :     add_local_reloption(relopts, (relopt_gen *) newoption, offset);
                               1130                 :           1316 : }
                               1131                 :                : 
                               1132                 :                : /*
                               1133                 :                :  * init_real_reloption
                               1134                 :                :  *      Allocate and initialize a new real reloption
                               1135                 :                :  */
                               1136                 :                : static relopt_real *
  174 nathan@postgresql.or     1137                 :           1177 : init_real_reloption(uint32 kinds, const char *name, const char *desc,
                               1138                 :                :                     double default_val, double min_val, double max_val,
                               1139                 :                :                     LOCKMODE lockmode)
                               1140                 :                : {
                               1141                 :                :     relopt_real *newoption;
                               1142                 :                : 
 6378 alvherre@alvh.no-ip.     1143                 :           1177 :     newoption = (relopt_real *) allocate_reloption(kinds, RELOPT_TYPE_REAL,
                               1144                 :                :                                                    name, desc, lockmode);
 6467                          1145                 :           1177 :     newoption->default_val = default_val;
                               1146                 :           1177 :     newoption->min = min_val;
                               1147                 :           1177 :     newoption->max = max_val;
                               1148                 :                : 
 2365 akorotkov@postgresql     1149                 :           1177 :     return newoption;
                               1150                 :                : }
                               1151                 :                : 
                               1152                 :                : /*
                               1153                 :                :  * add_real_reloption
                               1154                 :                :  *      Add a new float reloption
                               1155                 :                :  */
                               1156                 :                : void
  174 nathan@postgresql.or     1157                 :              1 : add_real_reloption(uint32 kinds, const char *name, const char *desc,
                               1158                 :                :                    double default_val, double min_val, double max_val,
                               1159                 :                :                    LOCKMODE lockmode)
                               1160                 :                : {
 2365 akorotkov@postgresql     1161                 :              1 :     relopt_real *newoption = init_real_reloption(kinds, name, desc,
                               1162                 :                :                                                  default_val, min_val,
                               1163                 :                :                                                  max_val, lockmode);
                               1164                 :                : 
 6467 alvherre@alvh.no-ip.     1165                 :              1 :     add_reloption((relopt_gen *) newoption);
                               1166                 :              1 : }
                               1167                 :                : 
                               1168                 :                : /*
                               1169                 :                :  * add_local_real_reloption
                               1170                 :                :  *      Add a new local float reloption
                               1171                 :                :  *
                               1172                 :                :  * 'offset' is offset of double-typed field.
                               1173                 :                :  */
                               1174                 :                : void
 2365 akorotkov@postgresql     1175                 :           1176 : add_local_real_reloption(local_relopts *relopts, const char *name,
                               1176                 :                :                          const char *desc, double default_val,
                               1177                 :                :                          double min_val, double max_val, int offset)
                               1178                 :                : {
                               1179                 :           1176 :     relopt_real *newoption = init_real_reloption(RELOPT_KIND_LOCAL,
                               1180                 :                :                                                  name, desc,
                               1181                 :                :                                                  default_val, min_val,
                               1182                 :                :                                                  max_val, 0);
                               1183                 :                : 
                               1184                 :           1176 :     add_local_reloption(relopts, (relopt_gen *) newoption, offset);
                               1185                 :           1176 : }
                               1186                 :                : 
                               1187                 :                : /*
                               1188                 :                :  * init_enum_reloption
                               1189                 :                :  *      Allocate and initialize a new enum reloption
                               1190                 :                :  */
                               1191                 :                : static relopt_enum *
  174 nathan@postgresql.or     1192                 :              1 : init_enum_reloption(uint32 kinds, const char *name, const char *desc,
                               1193                 :                :                     relopt_enum_elt_def *members, int default_val,
                               1194                 :                :                     const char *detailmsg, LOCKMODE lockmode)
                               1195                 :                : {
                               1196                 :                :     relopt_enum *newoption;
                               1197                 :                : 
 2365 akorotkov@postgresql     1198                 :              1 :     newoption = (relopt_enum *) allocate_reloption(kinds, RELOPT_TYPE_ENUM,
                               1199                 :                :                                                    name, desc, lockmode);
                               1200                 :              1 :     newoption->members = members;
                               1201                 :              1 :     newoption->default_val = default_val;
                               1202                 :              1 :     newoption->detailmsg = detailmsg;
                               1203                 :                : 
                               1204                 :              1 :     return newoption;
                               1205                 :                : }
                               1206                 :                : 
                               1207                 :                : 
                               1208                 :                : /*
                               1209                 :                :  * add_enum_reloption
                               1210                 :                :  *      Add a new enum reloption
                               1211                 :                :  *
                               1212                 :                :  * The members array must have a terminating NULL entry.
                               1213                 :                :  *
                               1214                 :                :  * The detailmsg is shown when unsupported values are passed, and has this
                               1215                 :                :  * form:   "Valid values are \"foo\", \"bar\", and \"bar\"."
                               1216                 :                :  *
                               1217                 :                :  * The members array and detailmsg are not copied -- caller must ensure that
                               1218                 :                :  * they are valid throughout the life of the process.
                               1219                 :                :  */
                               1220                 :                : void
  174 nathan@postgresql.or     1221                 :              1 : add_enum_reloption(uint32 kinds, const char *name, const char *desc,
                               1222                 :                :                    relopt_enum_elt_def *members, int default_val,
                               1223                 :                :                    const char *detailmsg, LOCKMODE lockmode)
                               1224                 :                : {
 2365 akorotkov@postgresql     1225                 :              1 :     relopt_enum *newoption = init_enum_reloption(kinds, name, desc,
                               1226                 :                :                                                  members, default_val,
                               1227                 :                :                                                  detailmsg, lockmode);
                               1228                 :                : 
 2552 alvherre@alvh.no-ip.     1229                 :              1 :     add_reloption((relopt_gen *) newoption);
                               1230                 :              1 : }
                               1231                 :                : 
                               1232                 :                : /*
                               1233                 :                :  * add_local_enum_reloption
                               1234                 :                :  *      Add a new local enum reloption
                               1235                 :                :  *
                               1236                 :                :  * 'offset' is offset of int-typed field.
                               1237                 :                :  */
                               1238                 :                : void
 2365 akorotkov@postgresql     1239                 :UBC           0 : add_local_enum_reloption(local_relopts *relopts, const char *name,
                               1240                 :                :                          const char *desc, relopt_enum_elt_def *members,
                               1241                 :                :                          int default_val, const char *detailmsg, int offset)
                               1242                 :                : {
                               1243                 :              0 :     relopt_enum *newoption = init_enum_reloption(RELOPT_KIND_LOCAL,
                               1244                 :                :                                                  name, desc,
                               1245                 :                :                                                  members, default_val,
                               1246                 :                :                                                  detailmsg, 0);
                               1247                 :                : 
                               1248                 :              0 :     add_local_reloption(relopts, (relopt_gen *) newoption, offset);
                               1249                 :              0 : }
                               1250                 :                : 
                               1251                 :                : /*
                               1252                 :                :  * init_string_reloption
                               1253                 :                :  *      Allocate and initialize a new string reloption
                               1254                 :                :  */
                               1255                 :                : static relopt_string *
  174 nathan@postgresql.or     1256                 :CBC           2 : init_string_reloption(uint32 kinds, const char *name, const char *desc,
                               1257                 :                :                       const char *default_val,
                               1258                 :                :                       validate_string_relopt validator,
                               1259                 :                :                       fill_string_relopt filler,
                               1260                 :                :                       LOCKMODE lockmode)
                               1261                 :                : {
                               1262                 :                :     relopt_string *newoption;
                               1263                 :                : 
                               1264                 :                :     /* make sure the validator/default combination is sane */
 5521 heikki.linnakangas@i     1265         [ +  - ]:              2 :     if (validator)
                               1266                 :              2 :         (validator) (default_val);
                               1267                 :                : 
                               1268                 :              2 :     newoption = (relopt_string *) allocate_reloption(kinds, RELOPT_TYPE_STRING,
                               1269                 :                :                                                      name, desc, lockmode);
 6464 alvherre@alvh.no-ip.     1270                 :              2 :     newoption->validate_cb = validator;
 2365 akorotkov@postgresql     1271                 :              2 :     newoption->fill_cb = filler;
 6467 alvherre@alvh.no-ip.     1272         [ +  + ]:              2 :     if (default_val)
                               1273                 :                :     {
 2365 akorotkov@postgresql     1274         [ -  + ]:              1 :         if (kinds == RELOPT_KIND_LOCAL)
 2365 akorotkov@postgresql     1275                 :UBC           0 :             newoption->default_val = strdup(default_val);
                               1276                 :                :         else
 2365 akorotkov@postgresql     1277                 :CBC           1 :             newoption->default_val = MemoryContextStrdup(TopMemoryContext, default_val);
 5521 heikki.linnakangas@i     1278                 :              1 :         newoption->default_len = strlen(default_val);
 6467 alvherre@alvh.no-ip.     1279                 :              1 :         newoption->default_isnull = false;
                               1280                 :                :     }
                               1281                 :                :     else
                               1282                 :                :     {
 5521 heikki.linnakangas@i     1283                 :              1 :         newoption->default_val = "";
 6467 alvherre@alvh.no-ip.     1284                 :              1 :         newoption->default_len = 0;
                               1285                 :              1 :         newoption->default_isnull = true;
                               1286                 :                :     }
                               1287                 :                : 
 2365 akorotkov@postgresql     1288                 :              2 :     return newoption;
                               1289                 :                : }
                               1290                 :                : 
                               1291                 :                : /*
                               1292                 :                :  * add_string_reloption
                               1293                 :                :  *      Add a new string reloption
                               1294                 :                :  *
                               1295                 :                :  * "validator" is an optional function pointer that can be used to test the
                               1296                 :                :  * validity of the values.  It must elog(ERROR) when the argument string is
                               1297                 :                :  * not acceptable for the variable.  Note that the default value must pass
                               1298                 :                :  * the validation.
                               1299                 :                :  */
                               1300                 :                : void
  174 nathan@postgresql.or     1301                 :              2 : add_string_reloption(uint32 kinds, const char *name, const char *desc,
                               1302                 :                :                      const char *default_val, validate_string_relopt validator,
                               1303                 :                :                      LOCKMODE lockmode)
                               1304                 :                : {
 2365 akorotkov@postgresql     1305                 :              2 :     relopt_string *newoption = init_string_reloption(kinds, name, desc,
                               1306                 :                :                                                      default_val,
                               1307                 :                :                                                      validator, NULL,
                               1308                 :                :                                                      lockmode);
                               1309                 :                : 
 6467 alvherre@alvh.no-ip.     1310                 :              2 :     add_reloption((relopt_gen *) newoption);
                               1311                 :              2 : }
                               1312                 :                : 
                               1313                 :                : /*
                               1314                 :                :  * add_local_string_reloption
                               1315                 :                :  *      Add a new local string reloption
                               1316                 :                :  *
                               1317                 :                :  * 'offset' is offset of int-typed field that will store offset of string value
                               1318                 :                :  * in the resulting bytea structure.
                               1319                 :                :  */
                               1320                 :                : void
 2365 akorotkov@postgresql     1321                 :UBC           0 : add_local_string_reloption(local_relopts *relopts, const char *name,
                               1322                 :                :                            const char *desc, const char *default_val,
                               1323                 :                :                            validate_string_relopt validator,
                               1324                 :                :                            fill_string_relopt filler, int offset)
                               1325                 :                : {
                               1326                 :              0 :     relopt_string *newoption = init_string_reloption(RELOPT_KIND_LOCAL,
                               1327                 :                :                                                      name, desc,
                               1328                 :                :                                                      default_val,
                               1329                 :                :                                                      validator, filler,
                               1330                 :                :                                                      0);
                               1331                 :                : 
                               1332                 :              0 :     add_local_reloption(relopts, (relopt_gen *) newoption, offset);
                               1333                 :              0 : }
                               1334                 :                : 
                               1335                 :                : /*
                               1336                 :                :  * Transform a relation options list (list of DefElem) into the text array
                               1337                 :                :  * format that is kept in pg_class.reloptions, including only those options
                               1338                 :                :  * that are in the passed namespace.  The output values do not include the
                               1339                 :                :  * namespace.
                               1340                 :                :  *
                               1341                 :                :  * This is used for three cases: CREATE TABLE/INDEX, ALTER TABLE SET, and
                               1342                 :                :  * ALTER TABLE RESET.  In the ALTER cases, oldOptions is the existing
                               1343                 :                :  * reloptions value (possibly NULL), and we replace or remove entries
                               1344                 :                :  * as needed.
                               1345                 :                :  *
                               1346                 :                :  * If acceptOidsOff is true, then we allow oids = false, but throw error when
                               1347                 :                :  * on. This is solely needed for backwards compatibility.
                               1348                 :                :  *
                               1349                 :                :  * Note that this is not responsible for determining whether the options
                               1350                 :                :  * are valid, but it does check that namespaces for all the options given are
                               1351                 :                :  * listed in validnsps.  The NULL namespace is always valid and need not be
                               1352                 :                :  * explicitly listed.  Passing a NULL pointer means that only the NULL
                               1353                 :                :  * namespace is valid.
                               1354                 :                :  *
                               1355                 :                :  * Both oldOptions and the result are text arrays (or NULL for "default"),
                               1356                 :                :  * but we declare them as Datums to avoid including array.h in reloptions.h.
                               1357                 :                :  */
                               1358                 :                : Datum
  410 nathan@postgresql.or     1359                 :CBC       86186 : transformRelOptions(Datum oldOptions, List *defList, const char *nameSpace,
                               1360                 :                :                     const char *const validnsps[], bool acceptOidsOff, bool isReset)
                               1361                 :                : {
                               1362                 :                :     Datum       result;
                               1363                 :                :     ArrayBuildState *astate;
                               1364                 :                :     ListCell   *cell;
                               1365                 :                : 
                               1366                 :                :     /* no change if empty list */
 7384 tgl@sss.pgh.pa.us        1367         [ +  + ]:          86186 :     if (defList == NIL)
                               1368                 :          83403 :         return oldOptions;
                               1369                 :                : 
                               1370                 :                :     /* We build new array using accumArrayResult */
                               1371                 :           2783 :     astate = NULL;
                               1372                 :                : 
                               1373                 :                :     /* Copy any oldOptions that aren't to be replaced */
  361 peter@eisentraut.org     1374         [ +  + ]:           2783 :     if (DatumGetPointer(oldOptions) != NULL)
                               1375                 :                :     {
 7291 bruce@momjian.us         1376                 :            276 :         ArrayType  *array = DatumGetArrayTypeP(oldOptions);
                               1377                 :                :         Datum      *oldoptions;
                               1378                 :                :         int         noldoptions;
                               1379                 :                :         int         i;
                               1380                 :                : 
 1542 peter@eisentraut.org     1381                 :            276 :         deconstruct_array_builtin(array, TEXTOID, &oldoptions, NULL, &noldoptions);
                               1382                 :                : 
 7384 tgl@sss.pgh.pa.us        1383         [ +  + ]:            703 :         for (i = 0; i < noldoptions; i++)
                               1384                 :                :         {
  411 peter@eisentraut.org     1385                 :            427 :             char       *text_str = VARDATA(DatumGetPointer(oldoptions[i]));
                               1386                 :            427 :             int         text_len = VARSIZE(DatumGetPointer(oldoptions[i])) - VARHDRSZ;
                               1387                 :                : 
                               1388                 :                :             /* Search for a match in defList */
 7384 tgl@sss.pgh.pa.us        1389   [ +  -  +  +  :            642 :             foreach(cell, defList)
                                              +  + ]
                               1390                 :                :             {
 6310 bruce@momjian.us         1391                 :            462 :                 DefElem    *def = (DefElem *) lfirst(cell);
                               1392                 :                :                 int         kw_len;
                               1393                 :                : 
                               1394                 :                :                 /* ignore if not in the same namespace */
  410 nathan@postgresql.or     1395         [ +  + ]:            462 :                 if (nameSpace == NULL)
                               1396                 :                :                 {
 6378 tgl@sss.pgh.pa.us        1397         [ -  + ]:            430 :                     if (def->defnamespace != NULL)
 6439 alvherre@alvh.no-ip.     1398                 :UBC           0 :                         continue;
                               1399                 :                :                 }
 6378 tgl@sss.pgh.pa.us        1400         [ +  + ]:CBC          32 :                 else if (def->defnamespace == NULL)
 6439 alvherre@alvh.no-ip.     1401                 :             20 :                     continue;
  410 nathan@postgresql.or     1402         [ -  + ]:             12 :                 else if (strcmp(def->defnamespace, nameSpace) != 0)
 6439 alvherre@alvh.no-ip.     1403                 :UBC           0 :                     continue;
                               1404                 :                : 
 6378 tgl@sss.pgh.pa.us        1405                 :CBC         442 :                 kw_len = strlen(def->defname);
 7384                          1406   [ +  +  +  + ]:            442 :                 if (text_len > kw_len && text_str[kw_len] == '=' &&
 3159                          1407         [ +  + ]:            260 :                     strncmp(text_str, def->defname, kw_len) == 0)
 7384                          1408                 :            247 :                     break;
                               1409                 :                :             }
                               1410         [ +  + ]:            427 :             if (!cell)
                               1411                 :                :             {
                               1412                 :                :                 /* No match, so keep old option */
                               1413                 :            180 :                 astate = accumArrayResult(astate, oldoptions[i],
                               1414                 :                :                                           false, TEXTOID,
                               1415                 :                :                                           CurrentMemoryContext);
                               1416                 :                :             }
                               1417                 :                :         }
                               1418                 :                :     }
                               1419                 :                : 
                               1420                 :                :     /*
                               1421                 :                :      * If CREATE/SET, add new options to array; if RESET, just check that the
                               1422                 :                :      * user didn't say RESET (option=val).  (Must do this because the grammar
                               1423                 :                :      * doesn't enforce it.)
                               1424                 :                :      */
                               1425   [ +  -  +  +  :           5833 :     foreach(cell, defList)
                                              +  + ]
                               1426                 :                :     {
 6310 bruce@momjian.us         1427                 :           3074 :         DefElem    *def = (DefElem *) lfirst(cell);
                               1428                 :                : 
 7384 tgl@sss.pgh.pa.us        1429         [ +  + ]:           3074 :         if (isReset)
                               1430                 :                :         {
                               1431         [ +  + ]:            196 :             if (def->arg != NULL)
                               1432         [ +  - ]:              8 :                 ereport(ERROR,
                               1433                 :                :                         (errcode(ERRCODE_SYNTAX_ERROR),
                               1434                 :                :                          errmsg("RESET must not include values for parameters")));
                               1435                 :                :         }
                               1436                 :                :         else
                               1437                 :                :         {
                               1438                 :                :             const char *name;
                               1439                 :                :             const char *value;
                               1440                 :                :             text       *t;
                               1441                 :                :             Size        len;
                               1442                 :                : 
                               1443                 :                :             /*
                               1444                 :                :              * Error out if the namespace is not valid.  A NULL namespace is
                               1445                 :                :              * always valid.
                               1446                 :                :              */
 6378                          1447         [ +  + ]:           2878 :             if (def->defnamespace != NULL)
                               1448                 :                :             {
 6310 bruce@momjian.us         1449                 :             96 :                 bool        valid = false;
                               1450                 :                :                 int         i;
                               1451                 :                : 
 6439 alvherre@alvh.no-ip.     1452         [ +  + ]:             96 :                 if (validnsps)
                               1453                 :                :                 {
                               1454         [ +  + ]:             96 :                     for (i = 0; validnsps[i]; i++)
                               1455                 :                :                     {
 3159 tgl@sss.pgh.pa.us        1456         [ +  + ]:             92 :                         if (strcmp(def->defnamespace, validnsps[i]) == 0)
                               1457                 :                :                         {
 6439 alvherre@alvh.no-ip.     1458                 :             88 :                             valid = true;
                               1459                 :             88 :                             break;
                               1460                 :                :                         }
                               1461                 :                :                     }
                               1462                 :                :                 }
                               1463                 :                : 
                               1464         [ +  + ]:             96 :                 if (!valid)
                               1465         [ +  - ]:              8 :                     ereport(ERROR,
                               1466                 :                :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1467                 :                :                              errmsg("unrecognized parameter namespace \"%s\"",
                               1468                 :                :                                     def->defnamespace)));
                               1469                 :                :             }
                               1470                 :                : 
                               1471                 :                :             /* ignore if not in the same namespace */
  410 nathan@postgresql.or     1472         [ +  + ]:           2870 :             if (nameSpace == NULL)
                               1473                 :                :             {
 6378 tgl@sss.pgh.pa.us        1474         [ +  + ]:           2041 :                 if (def->defnamespace != NULL)
 6439 alvherre@alvh.no-ip.     1475                 :             44 :                     continue;
                               1476                 :                :             }
 6378 tgl@sss.pgh.pa.us        1477         [ +  + ]:            829 :             else if (def->defnamespace == NULL)
 6439 alvherre@alvh.no-ip.     1478                 :            785 :                 continue;
  410 nathan@postgresql.or     1479         [ -  + ]:             44 :             else if (strcmp(def->defnamespace, nameSpace) != 0)
 7384 tgl@sss.pgh.pa.us        1480                 :UBC           0 :                 continue;
                               1481                 :                : 
                               1482                 :                :             /*
                               1483                 :                :              * Flatten the DefElem into a text string like "name=arg". If we
                               1484                 :                :              * have just "name", assume "name=true" is meant.  Note: the
                               1485                 :                :              * namespace is not output.
                               1486                 :                :              */
  475 tgl@sss.pgh.pa.us        1487                 :CBC        2041 :             name = def->defname;
 7384                          1488         [ +  + ]:           2041 :             if (def->arg != NULL)
 6378                          1489                 :           1792 :                 value = defGetString(def);
                               1490                 :                :             else
 7384                          1491                 :            249 :                 value = "true";
                               1492                 :                : 
                               1493                 :                :             /* Insist that name not contain "=", else "a=b=c" is ambiguous */
  475                          1494         [ -  + ]:           2041 :             if (strchr(name, '=') != NULL)
  475 tgl@sss.pgh.pa.us        1495         [ #  # ]:UBC           0 :                 ereport(ERROR,
                               1496                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1497                 :                :                          errmsg("invalid option name \"%s\": must not contain \"=\"",
                               1498                 :                :                                 name)));
                               1499                 :                : 
                               1500                 :                :             /*
                               1501                 :                :              * This is not a great place for this test, but there's no other
                               1502                 :                :              * convenient place to filter the option out. As WITH (oids =
                               1503                 :                :              * false) will be removed someday, this seems like an acceptable
                               1504                 :                :              * amount of ugly.
                               1505                 :                :              */
 2861 andres@anarazel.de       1506   [ +  +  +  + ]:CBC        2041 :             if (acceptOidsOff && def->defnamespace == NULL &&
  475 tgl@sss.pgh.pa.us        1507         [ +  + ]:           1090 :                 strcmp(name, "oids") == 0)
                               1508                 :                :             {
 2861 andres@anarazel.de       1509         [ +  + ]:             12 :                 if (defGetBoolean(def))
                               1510         [ +  - ]:              8 :                     ereport(ERROR,
                               1511                 :                :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               1512                 :                :                              errmsg("tables declared WITH OIDS are not supported")));
                               1513                 :                :                 /* skip over option, reloptions machinery doesn't know it */
                               1514                 :              4 :                 continue;
                               1515                 :                :             }
                               1516                 :                : 
  475 tgl@sss.pgh.pa.us        1517                 :           2029 :             len = VARHDRSZ + strlen(name) + 1 + strlen(value);
                               1518                 :                :             /* +1 leaves room for sprintf's trailing null */
 7384                          1519                 :           2029 :             t = (text *) palloc(len + 1);
 7145                          1520                 :           2029 :             SET_VARSIZE(t, len);
  475                          1521                 :           2029 :             sprintf(VARDATA(t), "%s=%s", name, value);
                               1522                 :                : 
 7384                          1523                 :           2029 :             astate = accumArrayResult(astate, PointerGetDatum(t),
                               1524                 :                :                                       false, TEXTOID,
                               1525                 :                :                                       CurrentMemoryContext);
                               1526                 :                :         }
                               1527                 :                :     }
                               1528                 :                : 
                               1529         [ +  + ]:           2759 :     if (astate)
                               1530                 :           1907 :         result = makeArrayResult(astate, CurrentMemoryContext);
                               1531                 :                :     else
                               1532                 :            852 :         result = (Datum) 0;
                               1533                 :                : 
                               1534                 :           2759 :     return result;
                               1535                 :                : }
                               1536                 :                : 
                               1537                 :                : 
                               1538                 :                : /*
                               1539                 :                :  * Convert the text-array format of reloptions into a List of DefElem.
                               1540                 :                :  * This is the inverse of transformRelOptions().
                               1541                 :                :  */
                               1542                 :                : List *
 6868                          1543                 :          17421 : untransformRelOptions(Datum options)
                               1544                 :                : {
                               1545                 :          17421 :     List       *result = NIL;
                               1546                 :                :     ArrayType  *array;
                               1547                 :                :     Datum      *optiondatums;
                               1548                 :                :     int         noptions;
                               1549                 :                :     int         i;
                               1550                 :                : 
                               1551                 :                :     /* Nothing to do if no options */
  361 peter@eisentraut.org     1552         [ +  + ]:          17421 :     if (DatumGetPointer(options) == NULL)
 6868 tgl@sss.pgh.pa.us        1553                 :           3030 :         return result;
                               1554                 :                : 
                               1555                 :          14391 :     array = DatumGetArrayTypeP(options);
                               1556                 :                : 
 1542 peter@eisentraut.org     1557                 :          14391 :     deconstruct_array_builtin(array, TEXTOID, &optiondatums, NULL, &noptions);
                               1558                 :                : 
 6868 tgl@sss.pgh.pa.us        1559         [ +  + ]:          43309 :     for (i = 0; i < noptions; i++)
                               1560                 :                :     {
                               1561                 :                :         char       *s;
                               1562                 :                :         char       *p;
                               1563                 :          28918 :         Node       *val = NULL;
                               1564                 :                : 
 6753                          1565                 :          28918 :         s = TextDatumGetCString(optiondatums[i]);
 6868                          1566                 :          28918 :         p = strchr(s, '=');
                               1567         [ +  - ]:          28918 :         if (p)
                               1568                 :                :         {
                               1569                 :          28918 :             *p++ = '\0';
 1468 alvherre@alvh.no-ip.     1570                 :          28918 :             val = (Node *) makeString(p);
                               1571                 :                :         }
                               1572                 :          28918 :         result = lappend(result, makeDefElem(s, val, -1));
                               1573                 :                :     }
                               1574                 :                : 
 6868 tgl@sss.pgh.pa.us        1575                 :          14391 :     return result;
                               1576                 :                : }
                               1577                 :                : 
                               1578                 :                : /*
                               1579                 :                :  * Extract and parse reloptions from a pg_class tuple.
                               1580                 :                :  *
                               1581                 :                :  * This is a low-level routine, expected to be used by relcache code and
                               1582                 :                :  * callers that do not have a table's relcache entry (e.g. autovacuum).  For
                               1583                 :                :  * other uses, consider grabbing the rd_options pointer from the relcache entry
                               1584                 :                :  * instead.
                               1585                 :                :  *
                               1586                 :                :  * tupdesc is pg_class' tuple descriptor.  amoptions is a pointer to the index
                               1587                 :                :  * AM's options parser function in the case of a tuple corresponding to an
                               1588                 :                :  * index, or NULL otherwise.
                               1589                 :                :  */
                               1590                 :                : bytea *
 3899                          1591                 :         976337 : extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
                               1592                 :                :                   amoptions_function amoptions)
                               1593                 :                : {
                               1594                 :                :     bytea      *options;
                               1595                 :                :     bool        isnull;
                               1596                 :                :     Datum       datum;
                               1597                 :                :     Form_pg_class classForm;
                               1598                 :                : 
 6446 alvherre@alvh.no-ip.     1599                 :         976337 :     datum = fastgetattr(tuple,
                               1600                 :                :                         Anum_pg_class_reloptions,
                               1601                 :                :                         tupdesc,
                               1602                 :                :                         &isnull);
                               1603         [ +  + ]:         976337 :     if (isnull)
                               1604                 :         963627 :         return NULL;
                               1605                 :                : 
                               1606                 :          12710 :     classForm = (Form_pg_class) GETSTRUCT(tuple);
                               1607                 :                : 
                               1608                 :                :     /* Parse into appropriate format; don't error out here */
                               1609   [ +  -  +  +  :          12710 :     switch (classForm->relkind)
                                              -  - ]
                               1610                 :                :     {
                               1611                 :           9577 :         case RELKIND_RELATION:
                               1612                 :                :         case RELKIND_TOASTVALUE:
                               1613                 :                :         case RELKIND_MATVIEW:
  892 akorotkov@postgresql     1614                 :           9577 :             options = heap_reloptions(classForm->relkind, datum, false);
 6446 alvherre@alvh.no-ip.     1615                 :           9577 :             break;
 2502 michael@paquier.xyz      1616                 :UBC           0 :         case RELKIND_PARTITIONED_TABLE:
                               1617                 :              0 :             options = partitioned_table_reloptions(datum, false);
                               1618                 :              0 :             break;
 4451 alvherre@alvh.no-ip.     1619                 :CBC        1503 :         case RELKIND_VIEW:
                               1620                 :           1503 :             options = view_reloptions(datum, false);
                               1621                 :           1503 :             break;
 6446                          1622                 :           1630 :         case RELKIND_INDEX:
                               1623                 :                :         case RELKIND_PARTITIONED_INDEX:
                               1624                 :           1630 :             options = index_reloptions(amoptions, datum, false);
                               1625                 :           1630 :             break;
 5741 rhaas@postgresql.org     1626                 :UBC           0 :         case RELKIND_FOREIGN_TABLE:
                               1627                 :              0 :             options = NULL;
                               1628                 :              0 :             break;
 6446 alvherre@alvh.no-ip.     1629                 :              0 :         default:
                               1630                 :              0 :             Assert(false);      /* can't get here */
                               1631                 :                :             options = NULL;     /* keep compiler quiet */
                               1632                 :                :             break;
                               1633                 :                :     }
                               1634                 :                : 
 6446 alvherre@alvh.no-ip.     1635                 :CBC       12710 :     return options;
                               1636                 :                : }
                               1637                 :                : 
                               1638                 :                : static void
 2365 akorotkov@postgresql     1639                 :          14804 : parseRelOptionsInternal(Datum options, bool validate,
                               1640                 :                :                         relopt_value *reloptions, int numoptions)
                               1641                 :                : {
                               1642                 :          14804 :     ArrayType  *array = DatumGetArrayTypeP(options);
                               1643                 :                :     Datum      *optiondatums;
                               1644                 :                :     int         noptions;
                               1645                 :                :     int         i;
                               1646                 :                : 
 1542 peter@eisentraut.org     1647                 :          14804 :     deconstruct_array_builtin(array, TEXTOID, &optiondatums, NULL, &noptions);
                               1648                 :                : 
 2365 akorotkov@postgresql     1649         [ +  + ]:          31154 :     for (i = 0; i < noptions; i++)
                               1650                 :                :     {
  411 peter@eisentraut.org     1651                 :          16571 :         char       *text_str = VARDATA(DatumGetPointer(optiondatums[i]));
                               1652                 :          16571 :         int         text_len = VARSIZE(DatumGetPointer(optiondatums[i])) - VARHDRSZ;
                               1653                 :                :         int         j;
                               1654                 :                : 
                               1655                 :                :         /* Search for a match in reloptions */
 2365 akorotkov@postgresql     1656         [ +  + ]:         102351 :         for (j = 0; j < numoptions; j++)
                               1657                 :                :         {
                               1658                 :         102287 :             int         kw_len = reloptions[j].gen->namelen;
                               1659                 :                : 
                               1660   [ +  +  +  + ]:         102287 :             if (text_len > kw_len && text_str[kw_len] == '=' &&
                               1661         [ +  + ]:          24198 :                 strncmp(text_str, reloptions[j].gen->name, kw_len) == 0)
                               1662                 :                :             {
                               1663                 :          16507 :                 parse_one_reloption(&reloptions[j], text_str, text_len,
                               1664                 :                :                                     validate);
                               1665                 :          16338 :                 break;
                               1666                 :                :             }
                               1667                 :                :         }
                               1668                 :                : 
                               1669   [ +  +  +  + ]:          16402 :         if (j >= numoptions && validate)
                               1670                 :                :         {
                               1671                 :                :             char       *s;
                               1672                 :                :             char       *p;
                               1673                 :                : 
                               1674                 :             52 :             s = TextDatumGetCString(optiondatums[i]);
                               1675                 :             52 :             p = strchr(s, '=');
                               1676         [ +  - ]:             52 :             if (p)
                               1677                 :             52 :                 *p = '\0';
                               1678         [ +  - ]:             52 :             ereport(ERROR,
                               1679                 :                :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1680                 :                :                      errmsg("unrecognized parameter \"%s\"", s)));
                               1681                 :                :         }
                               1682                 :                :     }
                               1683                 :                : 
                               1684                 :                :     /* It's worth avoiding memory leaks in this function */
                               1685                 :          14583 :     pfree(optiondatums);
                               1686                 :                : 
                               1687         [ +  + ]:          14583 :     if (((void *) array) != DatumGetPointer(options))
                               1688                 :          12833 :         pfree(array);
                               1689                 :          14583 : }
                               1690                 :                : 
                               1691                 :                : /*
                               1692                 :                :  * Interpret reloptions that are given in text-array format.
                               1693                 :                :  *
                               1694                 :                :  * options is a reloption text array as constructed by transformRelOptions.
                               1695                 :                :  * kind specifies the family of options to be processed.
                               1696                 :                :  *
                               1697                 :                :  * The return value is a relopt_value * array on which the options actually
                               1698                 :                :  * set in the options array are marked with isset=true.  The length of this
                               1699                 :                :  * array is returned in *numrelopts.  Options not set are also present in the
                               1700                 :                :  * array; this is so that the caller can easily locate the default values.
                               1701                 :                :  *
                               1702                 :                :  * If there are no options of the given kind, numrelopts is set to 0 and NULL
                               1703                 :                :  * is returned (unless options are illegally supplied despite none being
                               1704                 :                :  * defined, in which case an error occurs).
                               1705                 :                :  *
                               1706                 :                :  * Note: values of type int, bool and real are allocated as part of the
                               1707                 :                :  * returned array.  Values of type string are allocated separately and must
                               1708                 :                :  * be freed by the caller.
                               1709                 :                :  */
                               1710                 :                : static relopt_value *
 6467 alvherre@alvh.no-ip.     1711                 :          72802 : parseRelOptions(Datum options, bool validate, relopt_kind kind,
                               1712                 :                :                 int *numrelopts)
                               1713                 :                : {
 3460 rhaas@postgresql.org     1714                 :          72802 :     relopt_value *reloptions = NULL;
 6467 alvherre@alvh.no-ip.     1715                 :          72802 :     int         numoptions = 0;
                               1716                 :                :     int         i;
                               1717                 :                :     int         j;
                               1718                 :                : 
                               1719         [ +  + ]:          72802 :     if (need_initialization)
                               1720                 :           4248 :         initialize_reloptions();
                               1721                 :                : 
                               1722                 :                :     /* Build a list of expected options, based on kind */
                               1723                 :                : 
                               1724         [ +  + ]:        3499598 :     for (i = 0; relOpts[i]; i++)
 6378                          1725         [ +  + ]:        3426796 :         if (relOpts[i]->kinds & kind)
 6467                          1726                 :        1395524 :             numoptions++;
                               1727                 :                : 
 3460 rhaas@postgresql.org     1728         [ +  - ]:          72802 :     if (numoptions > 0)
                               1729                 :                :     {
   34 michael@paquier.xyz      1730                 :GNC       72802 :         reloptions = palloc_array(relopt_value, numoptions);
                               1731                 :                : 
 3460 rhaas@postgresql.org     1732         [ +  + ]:CBC     3499598 :         for (i = 0, j = 0; relOpts[i]; i++)
                               1733                 :                :         {
                               1734         [ +  + ]:        3426796 :             if (relOpts[i]->kinds & kind)
                               1735                 :                :             {
                               1736                 :        1395524 :                 reloptions[j].gen = relOpts[i];
                               1737                 :        1395524 :                 reloptions[j].isset = false;
                               1738                 :        1395524 :                 j++;
                               1739                 :                :             }
                               1740                 :                :         }
                               1741                 :                :     }
                               1742                 :                : 
                               1743                 :                :     /* Done if no options */
  361 peter@eisentraut.org     1744         [ +  + ]:          72802 :     if (DatumGetPointer(options) != NULL)
 2365 akorotkov@postgresql     1745                 :          14525 :         parseRelOptionsInternal(options, validate, reloptions, numoptions);
                               1746                 :                : 
                               1747                 :          72634 :     *numrelopts = numoptions;
                               1748                 :          72634 :     return reloptions;
                               1749                 :                : }
                               1750                 :                : 
                               1751                 :                : /* Parse local unregistered options. */
                               1752                 :                : static relopt_value *
                               1753                 :           1904 : parseLocalRelOptions(local_relopts *relopts, Datum options, bool validate)
                               1754                 :                : {
                               1755                 :           1904 :     int         nopts = list_length(relopts->options);
  284 michael@paquier.xyz      1756                 :           1904 :     relopt_value *values = palloc_array(relopt_value, nopts);
                               1757                 :                :     ListCell   *lc;
 2365 akorotkov@postgresql     1758                 :           1904 :     int         i = 0;
                               1759                 :                : 
                               1760   [ +  -  +  +  :           4396 :     foreach(lc, relopts->options)
                                              +  + ]
                               1761                 :                :     {
                               1762                 :           2492 :         local_relopt *opt = lfirst(lc);
                               1763                 :                : 
                               1764                 :           2492 :         values[i].gen = opt->option;
                               1765                 :           2492 :         values[i].isset = false;
                               1766                 :                : 
                               1767                 :           2492 :         i++;
                               1768                 :                :     }
                               1769                 :                : 
                               1770         [ +  + ]:           1904 :     if (options != (Datum) 0)
                               1771                 :            279 :         parseRelOptionsInternal(options, validate, values, nopts);
                               1772                 :                : 
                               1773                 :           1851 :     return values;
                               1774                 :                : }
                               1775                 :                : 
                               1776                 :                : /*
                               1777                 :                :  * Subroutine for parseRelOptions, to parse and validate a single option's
                               1778                 :                :  * value
                               1779                 :                :  */
                               1780                 :                : static void
 6467 alvherre@alvh.no-ip.     1781                 :          16507 : parse_one_reloption(relopt_value *option, char *text_str, int text_len,
                               1782                 :                :                     bool validate)
                               1783                 :                : {
                               1784                 :                :     char       *value;
                               1785                 :                :     int         value_len;
                               1786                 :                :     bool        parsed;
                               1787                 :          16507 :     bool        nofree = false;
                               1788                 :                : 
                               1789   [ +  +  +  + ]:          16507 :     if (option->isset && validate)
                               1790         [ +  - ]:              8 :         ereport(ERROR,
                               1791                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1792                 :                :                  errmsg("parameter \"%s\" specified more than once",
                               1793                 :                :                         option->gen->name)));
                               1794                 :                : 
                               1795                 :          16499 :     value_len = text_len - option->gen->namelen - 1;
                               1796                 :          16499 :     value = (char *) palloc(value_len + 1);
                               1797                 :          16499 :     memcpy(value, text_str + option->gen->namelen + 1, value_len);
                               1798                 :          16499 :     value[value_len] = '\0';
                               1799                 :                : 
                               1800   [ +  +  +  +  :          16499 :     switch (option->gen->type)
                                           +  +  - ]
                               1801                 :                :     {
                               1802                 :           2235 :         case RELOPT_TYPE_BOOL:
                               1803                 :                :             {
  241 alvherre@kurilemu.de     1804                 :           2235 :                 parsed = parse_bool(value, &option->bool_val);
 6467 alvherre@alvh.no-ip.     1805   [ +  +  +  + ]:           2235 :                 if (validate && !parsed)
                               1806         [ +  - ]:             11 :                     ereport(ERROR,
                               1807                 :                :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1808                 :                :                              errmsg("invalid value for boolean option \"%s\": %s",
                               1809                 :                :                                     option->gen->name, value)));
                               1810                 :                :             }
                               1811                 :           2224 :             break;
  242 alvherre@kurilemu.de     1812                 :           6138 :         case RELOPT_TYPE_TERNARY:
                               1813                 :                :             {
                               1814                 :                :                 bool        b;
                               1815                 :                : 
                               1816                 :           6138 :                 parsed = parse_bool(value, &b);
  241                          1817                 :           6138 :                 option->ternary_val = b ? PG_TERNARY_TRUE :
                               1818                 :                :                     PG_TERNARY_FALSE;
  242                          1819   [ +  +  +  + ]:           6138 :                 if (validate && !parsed)
                               1820         [ +  - ]:             15 :                     ereport(ERROR,
                               1821                 :                :                             errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1822                 :                :                             errmsg("invalid value for boolean option \"%s\": %s",
                               1823                 :                :                                    option->gen->name, value));
                               1824                 :                :             }
                               1825                 :           6123 :             break;
 6467 alvherre@alvh.no-ip.     1826                 :           6315 :         case RELOPT_TYPE_INT:
                               1827                 :                :             {
 6310 bruce@momjian.us         1828                 :           6315 :                 relopt_int *optint = (relopt_int *) option->gen;
                               1829                 :                : 
  241 alvherre@kurilemu.de     1830                 :           6315 :                 parsed = parse_int(value, &option->int_val, 0, NULL);
 6467 alvherre@alvh.no-ip.     1831   [ +  +  +  + ]:           6315 :                 if (validate && !parsed)
                               1832         [ +  - ]:             14 :                     ereport(ERROR,
                               1833                 :                :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1834                 :                :                              errmsg("invalid value for integer option \"%s\": %s",
                               1835                 :                :                                     option->gen->name, value)));
  241 alvherre@kurilemu.de     1836   [ +  +  +  + ]:           6301 :                 if (validate && (option->int_val < optint->min ||
                               1837         [ +  + ]:            590 :                                  option->int_val > optint->max))
 6467 alvherre@alvh.no-ip.     1838         [ +  - ]:             75 :                     ereport(ERROR,
                               1839                 :                :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1840                 :                :                              errmsg("value %s out of bounds for option \"%s\"",
                               1841                 :                :                                     value, option->gen->name),
                               1842                 :                :                              errdetail("Valid values are between \"%d\" and \"%d\".",
                               1843                 :                :                                        optint->min, optint->max)));
                               1844                 :                :             }
                               1845                 :           6226 :             break;
                               1846                 :            324 :         case RELOPT_TYPE_REAL:
                               1847                 :                :             {
 6310 bruce@momjian.us         1848                 :            324 :                 relopt_real *optreal = (relopt_real *) option->gen;
                               1849                 :                : 
  241 alvherre@kurilemu.de     1850                 :            324 :                 parsed = parse_real(value, &option->real_val, 0, NULL);
 6467 alvherre@alvh.no-ip.     1851   [ +  +  +  + ]:            324 :                 if (validate && !parsed)
                               1852         [ +  - ]:             10 :                     ereport(ERROR,
                               1853                 :                :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1854                 :                :                              errmsg("invalid value for floating point option \"%s\": %s",
                               1855                 :                :                                     option->gen->name, value)));
  241 alvherre@kurilemu.de     1856   [ +  +  +  + ]:            314 :                 if (validate && (option->real_val < optreal->min ||
                               1857         [ +  + ]:            110 :                                  option->real_val > optreal->max))
 6467 alvherre@alvh.no-ip.     1858         [ +  - ]:             20 :                     ereport(ERROR,
                               1859                 :                :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1860                 :                :                              errmsg("value %s out of bounds for option \"%s\"",
                               1861                 :                :                                     value, option->gen->name),
                               1862                 :                :                              errdetail("Valid values are between \"%f\" and \"%f\".",
                               1863                 :                :                                        optreal->min, optreal->max)));
                               1864                 :                :             }
                               1865                 :            294 :             break;
 2552                          1866                 :           1393 :         case RELOPT_TYPE_ENUM:
                               1867                 :                :             {
                               1868                 :           1393 :                 relopt_enum *optenum = (relopt_enum *) option->gen;
                               1869                 :                :                 relopt_enum_elt_def *elt;
                               1870                 :                : 
                               1871                 :           1393 :                 parsed = false;
                               1872         [ +  + ]:           2711 :                 for (elt = optenum->members; elt->string_val; elt++)
                               1873                 :                :                 {
                               1874         [ +  + ]:           2695 :                     if (pg_strcasecmp(value, elt->string_val) == 0)
                               1875                 :                :                     {
  241 alvherre@kurilemu.de     1876                 :           1377 :                         option->enum_val = elt->symbol_val;
 2552 alvherre@alvh.no-ip.     1877                 :           1377 :                         parsed = true;
                               1878                 :           1377 :                         break;
                               1879                 :                :                     }
                               1880                 :                :                 }
                               1881   [ +  +  +  + ]:           1393 :                 if (validate && !parsed)
                               1882   [ +  -  +  - ]:             16 :                     ereport(ERROR,
                               1883                 :                :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1884                 :                :                              errmsg("invalid value for enum option \"%s\": %s",
                               1885                 :                :                                     option->gen->name, value),
                               1886                 :                :                              optenum->detailmsg ?
                               1887                 :                :                              errdetail_internal("%s", _(optenum->detailmsg)) : 0));
                               1888                 :                : 
                               1889                 :                :                 /*
                               1890                 :                :                  * If value is not among the allowed string values, but we are
                               1891                 :                :                  * not asked to validate, just use the default numeric value.
                               1892                 :                :                  */
                               1893         [ -  + ]:           1377 :                 if (!parsed)
  241 alvherre@kurilemu.de     1894                 :UBC           0 :                     option->enum_val = optenum->default_val;
                               1895                 :                :             }
 2552 alvherre@alvh.no-ip.     1896                 :CBC        1377 :             break;
 6467                          1897                 :             94 :         case RELOPT_TYPE_STRING:
                               1898                 :                :             {
 6310 bruce@momjian.us         1899                 :             94 :                 relopt_string *optstring = (relopt_string *) option->gen;
                               1900                 :                : 
  241 alvherre@kurilemu.de     1901                 :             94 :                 option->string_val = value;
 6464 alvherre@alvh.no-ip.     1902                 :             94 :                 nofree = true;
 6460                          1903   [ +  +  +  - ]:             94 :                 if (validate && optstring->validate_cb)
                               1904                 :             32 :                     (optstring->validate_cb) (value);
 6464                          1905                 :             94 :                 parsed = true;
                               1906                 :                :             }
 6467                          1907                 :             94 :             break;
 6467 alvherre@alvh.no-ip.     1908                 :UBC           0 :         default:
                               1909         [ #  # ]:              0 :             elog(ERROR, "unsupported reloption type %d", option->gen->type);
                               1910                 :                :             parsed = true;      /* quiet compiler */
                               1911                 :                :             break;
                               1912                 :                :     }
                               1913                 :                : 
 6467 alvherre@alvh.no-ip.     1914         [ +  - ]:CBC       16338 :     if (parsed)
                               1915                 :          16338 :         option->isset = true;
                               1916         [ +  + ]:          16338 :     if (!nofree)
                               1917                 :          16244 :         pfree(value);
                               1918                 :          16338 : }
                               1919                 :                : 
                               1920                 :                : /*
                               1921                 :                :  * Given the result from parseRelOptions, allocate a struct that's of the
                               1922                 :                :  * specified base size plus any extra space that's needed for string variables.
                               1923                 :                :  *
                               1924                 :                :  * "base" should be sizeof(struct) of the reloptions struct (StdRdOptions or
                               1925                 :                :  * equivalent).
                               1926                 :                :  */
                               1927                 :                : static void *
 6460                          1928                 :          74485 : allocateReloptStruct(Size base, relopt_value *options, int numoptions)
                               1929                 :                : {
 6310 bruce@momjian.us         1930                 :          74485 :     Size        size = base;
                               1931                 :                :     int         i;
                               1932                 :                : 
 6460 alvherre@alvh.no-ip.     1933         [ +  + ]:        1470100 :     for (i = 0; i < numoptions; i++)
                               1934                 :                :     {
 2365 akorotkov@postgresql     1935                 :        1395615 :         relopt_value *optval = &options[i];
                               1936                 :                : 
                               1937         [ +  + ]:        1395615 :         if (optval->gen->type == RELOPT_TYPE_STRING)
                               1938                 :                :         {
                               1939                 :            134 :             relopt_string *optstr = (relopt_string *) optval->gen;
                               1940                 :                : 
                               1941         [ -  + ]:            134 :             if (optstr->fill_cb)
                               1942                 :                :             {
  241 alvherre@kurilemu.de     1943         [ #  # ]:UBC           0 :                 const char *val = optval->isset ? optval->string_val :
 1220 tgl@sss.pgh.pa.us        1944         [ #  # ]:              0 :                     optstr->default_isnull ? NULL : optstr->default_val;
                               1945                 :                : 
 2365 akorotkov@postgresql     1946                 :              0 :                 size += optstr->fill_cb(val, NULL);
                               1947                 :                :             }
                               1948                 :                :             else
 2365 akorotkov@postgresql     1949         [ +  + ]:CBC         134 :                 size += GET_STRING_RELOPTION_LEN(*optval) + 1;
                               1950                 :                :         }
                               1951                 :                :     }
                               1952                 :                : 
 6460 alvherre@alvh.no-ip.     1953                 :          74485 :     return palloc0(size);
                               1954                 :                : }
                               1955                 :                : 
                               1956                 :                : /*
                               1957                 :                :  * Given the result of parseRelOptions and a parsing table, fill in the
                               1958                 :                :  * struct (previously allocated with allocateReloptStruct) with the parsed
                               1959                 :                :  * values.
                               1960                 :                :  *
                               1961                 :                :  * rdopts is the pointer to the allocated struct to be filled.
                               1962                 :                :  * basesize is the sizeof(struct) that was passed to allocateReloptStruct.
                               1963                 :                :  * options, of length numoptions, is parseRelOptions' output.
                               1964                 :                :  * elems, of length numelems, is the table describing the allowed options.
                               1965                 :                :  * When validate is true, it is expected that all options appear in elems.
                               1966                 :                :  */
                               1967                 :                : static void
 6390 tgl@sss.pgh.pa.us        1968                 :          74485 : fillRelOptions(void *rdopts, Size basesize,
                               1969                 :                :                relopt_value *options, int numoptions,
                               1970                 :                :                bool validate,
                               1971                 :                :                const relopt_parse_elt *elems, int numelems)
                               1972                 :                : {
                               1973                 :                :     int         i;
 6310 bruce@momjian.us         1974                 :          74485 :     int         offset = basesize;
                               1975                 :                : 
 6460 alvherre@alvh.no-ip.     1976         [ +  + ]:        1470100 :     for (i = 0; i < numoptions; i++)
                               1977                 :                :     {
                               1978                 :                :         int         j;
 6310 bruce@momjian.us         1979                 :        1395615 :         bool        found = false;
                               1980                 :                : 
 6460 alvherre@alvh.no-ip.     1981         [ +  - ]:       18904417 :         for (j = 0; j < numelems; j++)
                               1982                 :                :         {
 3159 tgl@sss.pgh.pa.us        1983         [ +  + ]:       18904417 :             if (strcmp(options[i].gen->name, elems[j].optname) == 0)
                               1984                 :                :             {
                               1985                 :                :                 relopt_string *optstring;
 6310 bruce@momjian.us         1986                 :        1395615 :                 char       *itempos = ((char *) rdopts) + elems[j].offset;
                               1987                 :                :                 char       *string_val;
                               1988                 :                : 
 6460 alvherre@alvh.no-ip.     1989   [ +  +  +  +  :        1395615 :                 switch (options[i].gen->type)
                                           +  +  - ]
                               1990                 :                :                 {
                               1991                 :          58302 :                     case RELOPT_TYPE_BOOL:
                               1992                 :         116604 :                         *(bool *) itempos = options[i].isset ?
  241 alvherre@kurilemu.de     1993                 :           2223 :                             options[i].bool_val :
 6460 alvherre@alvh.no-ip.     1994         [ +  + ]:          58302 :                             ((relopt_bool *) options[i].gen)->default_val;
                               1995                 :          58302 :                         break;
  242 alvherre@kurilemu.de     1996                 :         117189 :                     case RELOPT_TYPE_TERNARY:
                               1997                 :         234378 :                         *(pg_ternary *) itempos = options[i].isset ?
  241                          1998         [ +  + ]:         117189 :                             options[i].ternary_val : PG_TERNARY_UNSET;
  242                          1999                 :         117189 :                         break;
 6460 alvherre@alvh.no-ip.     2000                 :         847863 :                     case RELOPT_TYPE_INT:
                               2001                 :        1695726 :                         *(int *) itempos = options[i].isset ?
  241 alvherre@kurilemu.de     2002         [ +  + ]:         847863 :                             options[i].int_val :
 6460 alvherre@alvh.no-ip.     2003                 :         841654 :                             ((relopt_int *) options[i].gen)->default_val;
                               2004                 :         847863 :                         break;
                               2005                 :         268631 :                     case RELOPT_TYPE_REAL:
                               2006                 :         537262 :                         *(double *) itempos = options[i].isset ?
  241 alvherre@kurilemu.de     2007         [ +  + ]:         268631 :                             options[i].real_val :
 6460 alvherre@alvh.no-ip.     2008                 :         268346 :                             ((relopt_real *) options[i].gen)->default_val;
                               2009                 :         268631 :                         break;
 2552                          2010                 :         103496 :                     case RELOPT_TYPE_ENUM:
                               2011                 :         206992 :                         *(int *) itempos = options[i].isset ?
  241 alvherre@kurilemu.de     2012         [ +  + ]:         103496 :                             options[i].enum_val :
 2552 alvherre@alvh.no-ip.     2013                 :         102119 :                             ((relopt_enum *) options[i].gen)->default_val;
                               2014                 :         103496 :                         break;
 6460                          2015                 :            134 :                     case RELOPT_TYPE_STRING:
                               2016                 :            134 :                         optstring = (relopt_string *) options[i].gen;
                               2017         [ +  + ]:            134 :                         if (options[i].isset)
  241 alvherre@kurilemu.de     2018                 :             92 :                             string_val = options[i].string_val;
 6460 alvherre@alvh.no-ip.     2019         [ +  + ]:             42 :                         else if (!optstring->default_isnull)
                               2020                 :             18 :                             string_val = optstring->default_val;
                               2021                 :                :                         else
                               2022                 :             24 :                             string_val = NULL;
                               2023                 :                : 
 2365 akorotkov@postgresql     2024         [ -  + ]:            134 :                         if (optstring->fill_cb)
                               2025                 :                :                         {
                               2026                 :                :                             Size        size =
 1220 tgl@sss.pgh.pa.us        2027                 :UBC           0 :                                 optstring->fill_cb(string_val,
                               2028                 :                :                                                    (char *) rdopts + offset);
                               2029                 :                : 
 2365 akorotkov@postgresql     2030         [ #  # ]:              0 :                             if (size)
                               2031                 :                :                             {
                               2032                 :              0 :                                 *(int *) itempos = offset;
                               2033                 :              0 :                                 offset += size;
                               2034                 :                :                             }
                               2035                 :                :                             else
                               2036                 :              0 :                                 *(int *) itempos = 0;
                               2037                 :                :                         }
 2365 akorotkov@postgresql     2038         [ +  + ]:CBC         134 :                         else if (string_val == NULL)
 6460 alvherre@alvh.no-ip.     2039                 :             24 :                             *(int *) itempos = 0;
                               2040                 :                :                         else
                               2041                 :                :                         {
                               2042                 :            110 :                             strcpy((char *) rdopts + offset, string_val);
                               2043                 :            110 :                             *(int *) itempos = offset;
                               2044                 :            110 :                             offset += strlen(string_val) + 1;
                               2045                 :                :                         }
                               2046                 :            134 :                         break;
 6460 alvherre@alvh.no-ip.     2047                 :UBC           0 :                     default:
 4067 tgl@sss.pgh.pa.us        2048         [ #  # ]:              0 :                         elog(ERROR, "unsupported reloption type %d",
                               2049                 :                :                              options[i].gen->type);
                               2050                 :                :                         break;
                               2051                 :                :                 }
 6460 alvherre@alvh.no-ip.     2052                 :CBC     1395615 :                 found = true;
                               2053                 :        1395615 :                 break;
                               2054                 :                :             }
                               2055                 :                :         }
 2805 tgl@sss.pgh.pa.us        2056   [ +  +  -  + ]:        1395615 :         if (validate && !found)
 6390 tgl@sss.pgh.pa.us        2057         [ #  # ]:UBC           0 :             elog(ERROR, "reloption \"%s\" not found in parse table",
                               2058                 :                :                  options[i].gen->name);
                               2059                 :                :     }
 6460 alvherre@alvh.no-ip.     2060                 :CBC       74485 :     SET_VARSIZE(rdopts, offset);
                               2061                 :          74485 : }
                               2062                 :                : 
                               2063                 :                : 
                               2064                 :                : /*
                               2065                 :                :  * Parse table for StdRdOptions.
                               2066                 :                :  */
                               2067                 :                : static const relopt_parse_elt stdRdOptionsTab[] = {
                               2068                 :                :     {"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)},
                               2069                 :                :     {"autovacuum_enabled", RELOPT_TYPE_TERNARY,
                               2070                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, enabled)},
                               2071                 :                :     {"autovacuum_parallel_workers", RELOPT_TYPE_INT,
                               2072                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, autovacuum_parallel_workers)},
                               2073                 :                :     {"autovacuum_vacuum_threshold", RELOPT_TYPE_INT,
                               2074                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_threshold)},
                               2075                 :                :     {"autovacuum_vacuum_max_threshold", RELOPT_TYPE_INT,
                               2076                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_max_threshold)},
                               2077                 :                :     {"autovacuum_vacuum_insert_threshold", RELOPT_TYPE_INT,
                               2078                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_ins_threshold)},
                               2079                 :                :     {"autovacuum_analyze_threshold", RELOPT_TYPE_INT,
                               2080                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_threshold)},
                               2081                 :                :     {"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT,
                               2082                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_limit)},
                               2083                 :                :     {"autovacuum_freeze_min_age", RELOPT_TYPE_INT,
                               2084                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_min_age)},
                               2085                 :                :     {"autovacuum_freeze_max_age", RELOPT_TYPE_INT,
                               2086                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_max_age)},
                               2087                 :                :     {"autovacuum_freeze_table_age", RELOPT_TYPE_INT,
                               2088                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_table_age)},
                               2089                 :                :     {"autovacuum_multixact_freeze_min_age", RELOPT_TYPE_INT,
                               2090                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, multixact_freeze_min_age)},
                               2091                 :                :     {"autovacuum_multixact_freeze_max_age", RELOPT_TYPE_INT,
                               2092                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, multixact_freeze_max_age)},
                               2093                 :                :     {"autovacuum_multixact_freeze_table_age", RELOPT_TYPE_INT,
                               2094                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, multixact_freeze_table_age)},
                               2095                 :                :     {"log_autovacuum_min_duration", RELOPT_TYPE_INT,
                               2096                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, log_vacuum_min_duration)},
                               2097                 :                :     {"log_autoanalyze_min_duration", RELOPT_TYPE_INT,
                               2098                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, log_analyze_min_duration)},
                               2099                 :                :     {"toast_tuple_target", RELOPT_TYPE_INT,
                               2100                 :                :     offsetof(StdRdOptions, toast_tuple_target)},
                               2101                 :                :     {"toast_value_type", RELOPT_TYPE_ENUM,
                               2102                 :                :     offsetof(StdRdOptions, toast_value_type)},
                               2103                 :                :     {"autovacuum_vacuum_cost_delay", RELOPT_TYPE_REAL,
                               2104                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_delay)},
                               2105                 :                :     {"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL,
                               2106                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_scale_factor)},
                               2107                 :                :     {"autovacuum_vacuum_insert_scale_factor", RELOPT_TYPE_REAL,
                               2108                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_ins_scale_factor)},
                               2109                 :                :     {"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,
                               2110                 :                :     offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_scale_factor)},
                               2111                 :                :     {"user_catalog_table", RELOPT_TYPE_BOOL,
                               2112                 :                :     offsetof(StdRdOptions, user_catalog_table)},
                               2113                 :                :     {"parallel_workers", RELOPT_TYPE_INT,
                               2114                 :                :     offsetof(StdRdOptions, parallel_workers)},
                               2115                 :                :     {"vacuum_index_cleanup", RELOPT_TYPE_ENUM,
                               2116                 :                :     offsetof(StdRdOptions, vacuum_index_cleanup)},
                               2117                 :                :     {"vacuum_truncate", RELOPT_TYPE_TERNARY,
                               2118                 :                :     offsetof(StdRdOptions, vacuum_truncate)},
                               2119                 :                :     {"vacuum_max_eager_freeze_failure_rate", RELOPT_TYPE_REAL,
                               2120                 :                :     offsetof(StdRdOptions, vacuum_max_eager_freeze_failure_rate)}
                               2121                 :                : };
                               2122                 :                : 
                               2123                 :                : /*
                               2124                 :                :  * Option parser for anything that uses StdRdOptions.
                               2125                 :                :  */
                               2126                 :                : bytea *
 6467                          2127                 :          58637 : default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
                               2128                 :                : {
 2511 michael@paquier.xyz      2129                 :          58637 :     return (bytea *) build_reloptions(reloptions, validate, kind,
                               2130                 :                :                                       sizeof(StdRdOptions),
                               2131                 :                :                                       stdRdOptionsTab,
                               2132                 :                :                                       lengthof(stdRdOptionsTab));
                               2133                 :                : }
                               2134                 :                : 
                               2135                 :                : /*
                               2136                 :                :  * find_reloption
                               2137                 :                :  *      Look up a reloption of the given kind by name.
                               2138                 :                :  *
                               2139                 :                :  * Returns NULL if no such option can be set on relations of that kind.  Note
                               2140                 :                :  * that names are unique only within a kind; "fillfactor", for example, is
                               2141                 :                :  * declared separately for heaps and for several index access methods.
                               2142                 :                :  */
                               2143                 :                : static relopt_gen *
   27 nathan@postgresql.or     2144                 :GNC         756 : find_reloption(const char *name, relopt_kind kind)
                               2145                 :                : {
                               2146         [ -  + ]:            756 :     if (need_initialization)
   27 nathan@postgresql.or     2147                 :UNC           0 :         initialize_reloptions();
                               2148                 :                : 
   27 nathan@postgresql.or     2149         [ +  + ]:GNC       24136 :     for (int i = 0; relOpts[i]; i++)
                               2150                 :                :     {
                               2151         [ +  + ]:          23884 :         if ((relOpts[i]->kinds & kind) != 0 &&
                               2152         [ +  + ]:           9324 :             strcmp(relOpts[i]->name, name) == 0)
                               2153                 :            504 :             return relOpts[i];
                               2154                 :                :     }
                               2155                 :                : 
                               2156                 :            252 :     return NULL;
                               2157                 :                : }
                               2158                 :                : 
                               2159                 :                : /*
                               2160                 :                :  * merge_toast_reloptions
                               2161                 :                :  *      Fill in a TOAST table's unset options from its main table's.
                               2162                 :                :  *
                               2163                 :                :  * Any option that may be set on a TOAST table but was not is taken from
                               2164                 :                :  * main_opts.  Either argument may be NULL; if both are, NULL is returned.
                               2165                 :                :  * Otherwise, the options to use are returned.
                               2166                 :                :  *
                               2167                 :                :  * An option counts as unset while it still holds the default declared for it
                               2168                 :                :  * above, which works because nothing a TOAST table accepts has a default the
                               2169                 :                :  * user could also set (see assert_toast_defaults_unsettable()).
                               2170                 :                :  *
                               2171                 :                :  * If the return value is not NULL, it is palloc'd.
                               2172                 :                :  */
                               2173                 :                : StdRdOptions *
                               2174                 :          26011 : merge_toast_reloptions(const StdRdOptions *toast_opts,
                               2175                 :                :                        const StdRdOptions *main_opts)
                               2176                 :                : {
                               2177                 :                :     StdRdOptions *ret;
                               2178                 :                : 
                               2179                 :                :     /* if both arguments are NULL, return NULL */
                               2180   [ +  +  +  + ]:          26011 :     if (toast_opts == NULL && main_opts == NULL)
                               2181                 :          25414 :         return NULL;
                               2182                 :                : 
                               2183                 :                :     /* if one argument is NULL, return the non-NULL one */
                               2184                 :            597 :     ret = palloc_object(StdRdOptions);
                               2185   [ +  +  +  + ]:            597 :     if (toast_opts == NULL || main_opts == NULL)
                               2186                 :                :     {
                               2187         [ +  + ]:            569 :         memcpy(ret, main_opts ? main_opts : toast_opts, sizeof(StdRdOptions));
                               2188                 :            569 :         return ret;
                               2189                 :                :     }
                               2190                 :                : 
                               2191                 :                :     /* replace unset TOAST relopts with the main table's */
                               2192                 :             28 :     memcpy(ret, toast_opts, sizeof(StdRdOptions));
                               2193         [ +  + ]:            784 :     for (int i = 0; i < lengthof(stdRdOptionsTab); i++)
                               2194                 :                :     {
                               2195                 :            756 :         const relopt_parse_elt *elem = &stdRdOptionsTab[i];
                               2196                 :                :         relopt_gen *gen;
                               2197                 :                :         char       *toast_val;
                               2198                 :                :         const char *main_val;
                               2199                 :                : 
                               2200                 :                :         /* skip anything that cannot be set on a TOAST table */
                               2201                 :            756 :         gen = find_reloption(elem->optname, RELOPT_KIND_TOAST);
                               2202         [ +  + ]:            756 :         if (gen == NULL)
                               2203                 :            252 :             continue;
                               2204                 :                : 
                               2205                 :            504 :         toast_val = (char *) ret + elem->offset;
                               2206                 :            504 :         main_val = (const char *) main_opts + elem->offset;
                               2207                 :                : 
                               2208   [ +  +  +  +  :            504 :         switch (gen->type)
                                                 - ]
                               2209                 :                :         {
                               2210                 :             56 :             case RELOPT_TYPE_TERNARY:
                               2211         [ +  + ]:             56 :                 if (*(pg_ternary *) toast_val == PG_TERNARY_UNSET)
                               2212                 :             41 :                     *(pg_ternary *) toast_val = *(const pg_ternary *) main_val;
                               2213                 :             56 :                 break;
                               2214                 :                : 
                               2215                 :            308 :             case RELOPT_TYPE_INT:
                               2216         [ +  - ]:            308 :                 if (*(int *) toast_val == ((relopt_int *) gen)->default_val)
                               2217                 :            308 :                     *(int *) toast_val = *(const int *) main_val;
                               2218                 :            308 :                 break;
                               2219                 :                : 
                               2220                 :            112 :             case RELOPT_TYPE_REAL:
                               2221         [ +  + ]:            112 :                 if (*(double *) toast_val == ((relopt_real *) gen)->default_val)
                               2222                 :            109 :                     *(double *) toast_val = *(const double *) main_val;
                               2223                 :            112 :                 break;
                               2224                 :                : 
                               2225                 :             28 :             case RELOPT_TYPE_ENUM:
                               2226         [ +  + ]:             28 :                 if (*(int *) toast_val == ((relopt_enum *) gen)->default_val)
                               2227                 :             16 :                     *(int *) toast_val = *(const int *) main_val;
                               2228                 :             28 :                 break;
                               2229                 :                : 
   27 nathan@postgresql.or     2230                 :UNC           0 :             default:
                               2231         [ #  # ]:              0 :                 elog(ERROR, "reloption \"%s\" has a type a TOAST table cannot inherit",
                               2232                 :                :                      elem->optname);
                               2233                 :                :         }
                               2234                 :                :     }
                               2235                 :                : 
   27 nathan@postgresql.or     2236                 :GNC          28 :     return ret;
                               2237                 :                : }
                               2238                 :                : 
                               2239                 :                : /*
                               2240                 :                :  * build_reloptions
                               2241                 :                :  *
                               2242                 :                :  * Parses "reloptions" provided by the caller, returning them in a
                               2243                 :                :  * structure containing the parsed options.  The parsing is done with
                               2244                 :                :  * the help of a parsing table describing the allowed options, defined
                               2245                 :                :  * by "relopt_elems" of length "num_relopt_elems".
                               2246                 :                :  *
                               2247                 :                :  * "validate" must be true if reloptions value is freshly built by
                               2248                 :                :  * transformRelOptions(), as opposed to being read from the catalog, in which
                               2249                 :                :  * case the values contained in it must already be valid.
                               2250                 :                :  *
                               2251                 :                :  * NULL is returned if the passed-in options did not match any of the options
                               2252                 :                :  * in the parsing table, unless validate is true in which case an error would
                               2253                 :                :  * be reported.
                               2254                 :                :  */
                               2255                 :                : void *
 2511 michael@paquier.xyz      2256                 :CBC       72802 : build_reloptions(Datum reloptions, bool validate,
                               2257                 :                :                  relopt_kind kind,
                               2258                 :                :                  Size relopt_struct_size,
                               2259                 :                :                  const relopt_parse_elt *relopt_elems,
                               2260                 :                :                  int num_relopt_elems)
                               2261                 :                : {
                               2262                 :                :     int         numoptions;
                               2263                 :                :     relopt_value *options;
                               2264                 :                :     void       *rdopts;
                               2265                 :                : 
                               2266                 :                :     /* parse options specific to given relation option kind */
 6467 alvherre@alvh.no-ip.     2267                 :          72802 :     options = parseRelOptions(reloptions, validate, kind, &numoptions);
 2511 michael@paquier.xyz      2268         [ -  + ]:          72634 :     Assert(numoptions <= num_relopt_elems);
                               2269                 :                : 
                               2270                 :                :     /* if none set, we're done */
 6467 alvherre@alvh.no-ip.     2271         [ -  + ]:          72634 :     if (numoptions == 0)
                               2272                 :                :     {
 2511 michael@paquier.xyz      2273         [ #  # ]:UBC           0 :         Assert(options == NULL);
 7384 tgl@sss.pgh.pa.us        2274                 :              0 :         return NULL;
                               2275                 :                :     }
                               2276                 :                : 
                               2277                 :                :     /* allocate and fill the structure */
 2511 michael@paquier.xyz      2278                 :CBC       72634 :     rdopts = allocateReloptStruct(relopt_struct_size, options, numoptions);
                               2279                 :          72634 :     fillRelOptions(rdopts, relopt_struct_size, options, numoptions,
                               2280                 :                :                    validate, relopt_elems, num_relopt_elems);
                               2281                 :                : 
 6467 alvherre@alvh.no-ip.     2282                 :          72634 :     pfree(options);
                               2283                 :                : 
 2511 michael@paquier.xyz      2284                 :          72634 :     return rdopts;
                               2285                 :                : }
                               2286                 :                : 
                               2287                 :                : /*
                               2288                 :                :  * Parse local options, allocate a bytea struct that's of the specified
                               2289                 :                :  * 'base_size' plus any extra space that's needed for string variables,
                               2290                 :                :  * fill its option's fields located at the given offsets and return it.
                               2291                 :                :  */
                               2292                 :                : void *
 2365 akorotkov@postgresql     2293                 :           1904 : build_local_reloptions(local_relopts *relopts, Datum options, bool validate)
                               2294                 :                : {
                               2295                 :           1904 :     int         noptions = list_length(relopts->options);
  284 michael@paquier.xyz      2296                 :           1904 :     relopt_parse_elt *elems = palloc_array(relopt_parse_elt, noptions);
                               2297                 :                :     relopt_value *vals;
                               2298                 :                :     void       *opts;
 2365 akorotkov@postgresql     2299                 :           1904 :     int         i = 0;
                               2300                 :                :     ListCell   *lc;
                               2301                 :                : 
                               2302   [ +  -  +  +  :           4396 :     foreach(lc, relopts->options)
                                              +  + ]
                               2303                 :                :     {
                               2304                 :           2492 :         local_relopt *opt = lfirst(lc);
                               2305                 :                : 
                               2306                 :           2492 :         elems[i].optname = opt->option->name;
                               2307                 :           2492 :         elems[i].opttype = opt->option->type;
                               2308                 :           2492 :         elems[i].offset = opt->offset;
                               2309                 :                : 
                               2310                 :           2492 :         i++;
                               2311                 :                :     }
                               2312                 :                : 
                               2313                 :           1904 :     vals = parseLocalRelOptions(relopts, options, validate);
                               2314                 :           1851 :     opts = allocateReloptStruct(relopts->relopt_struct_size, vals, noptions);
                               2315                 :           1851 :     fillRelOptions(opts, relopts->relopt_struct_size, vals, noptions, validate,
                               2316                 :                :                    elems, noptions);
                               2317                 :                : 
 1246                          2318         [ +  + ]:           1851 :     if (validate)
                               2319   [ +  +  +  +  :            412 :         foreach(lc, relopts->validators)
                                              +  + ]
                               2320                 :              3 :             ((relopts_validator) lfirst(lc)) (opts, vals, noptions);
                               2321                 :                : 
 2365                          2322         [ +  - ]:           1850 :     if (elems)
                               2323                 :           1850 :         pfree(elems);
                               2324                 :                : 
                               2325                 :           1850 :     return opts;
                               2326                 :                : }
                               2327                 :                : 
                               2328                 :                : /*
                               2329                 :                :  * Option parser for partitioned tables
                               2330                 :                :  */
                               2331                 :                : bytea *
 2502 michael@paquier.xyz      2332                 :           3383 : partitioned_table_reloptions(Datum reloptions, bool validate)
                               2333                 :                : {
 1411 tgl@sss.pgh.pa.us        2334   [ +  -  +  + ]:           3383 :     if (validate && reloptions)
                               2335         [ +  - ]:             12 :         ereport(ERROR,
                               2336                 :                :                 errcode(ERRCODE_WRONG_OBJECT_TYPE),
                               2337                 :                :                 errmsg("cannot specify storage parameters for a partitioned table"),
                               2338                 :                :                 errhint("Specify storage parameters for its leaf partitions instead."));
                               2339                 :           3371 :     return NULL;
                               2340                 :                : }
                               2341                 :                : 
                               2342                 :                : /*
                               2343                 :                :  * Option parser for views
                               2344                 :                :  */
                               2345                 :                : bytea *
 4451 alvherre@alvh.no-ip.     2346                 :          12080 : view_reloptions(Datum reloptions, bool validate)
                               2347                 :                : {
                               2348                 :                :     static const relopt_parse_elt tab[] = {
                               2349                 :                :         {"security_barrier", RELOPT_TYPE_BOOL,
                               2350                 :                :         offsetof(ViewOptions, security_barrier)},
                               2351                 :                :         {"security_invoker", RELOPT_TYPE_BOOL,
                               2352                 :                :         offsetof(ViewOptions, security_invoker)},
                               2353                 :                :         {"check_option", RELOPT_TYPE_ENUM,
                               2354                 :                :         offsetof(ViewOptions, check_option)}
                               2355                 :                :     };
                               2356                 :                : 
 2511 michael@paquier.xyz      2357                 :          12080 :     return (bytea *) build_reloptions(reloptions, validate,
                               2358                 :                :                                       RELOPT_KIND_VIEW,
                               2359                 :                :                                       sizeof(ViewOptions),
                               2360                 :                :                                       tab, lengthof(tab));
                               2361                 :                : }
                               2362                 :                : 
                               2363                 :                : /*
                               2364                 :                :  * Parse options for heaps, views and toast tables.
                               2365                 :                :  */
                               2366                 :                : bytea *
  892 akorotkov@postgresql     2367                 :          62513 : heap_reloptions(char relkind, Datum reloptions, bool validate)
                               2368                 :                : {
                               2369                 :                :     StdRdOptions *rdopts;
                               2370                 :                : 
 6378 alvherre@alvh.no-ip.     2371      [ +  +  + ]:          62513 :     switch (relkind)
                               2372                 :                :     {
                               2373                 :          25877 :         case RELKIND_TOASTVALUE:
                               2374                 :                :             rdopts = (StdRdOptions *)
 5949 itagaki.takahiro@gma     2375                 :          25877 :                 default_reloptions(reloptions, validate, RELOPT_KIND_TOAST);
                               2376         [ +  - ]:          25869 :             if (rdopts != NULL)
                               2377                 :                :             {
                               2378                 :                :                 /* adjust default-only parameters for TOAST relations */
                               2379                 :          25869 :                 rdopts->fillfactor = 100;
  892 akorotkov@postgresql     2380                 :          25869 :                 rdopts->autovacuum.analyze_threshold = -1;
                               2381                 :          25869 :                 rdopts->autovacuum.analyze_scale_factor = -1;
                               2382                 :                :             }
 5949 itagaki.takahiro@gma     2383                 :          25869 :             return (bytea *) rdopts;
 6378 alvherre@alvh.no-ip.     2384                 :          32760 :         case RELKIND_RELATION:
                               2385                 :                :         case RELKIND_MATVIEW:
  892 akorotkov@postgresql     2386                 :          32760 :             return default_reloptions(reloptions, validate, RELOPT_KIND_HEAP);
 6378 alvherre@alvh.no-ip.     2387                 :           3876 :         default:
                               2388                 :                :             /* other relkinds are not supported */
                               2389                 :           3876 :             return NULL;
                               2390                 :                :     }
                               2391                 :                : }
                               2392                 :                : 
                               2393                 :                : 
                               2394                 :                : /*
                               2395                 :                :  * Parse options for indexes.
                               2396                 :                :  *
                               2397                 :                :  *  amoptions   index AM's option parser function
                               2398                 :                :  *  reloptions  options as text[] datum
                               2399                 :                :  *  validate    error flag
                               2400                 :                :  */
                               2401                 :                : bytea *
 3899 tgl@sss.pgh.pa.us        2402                 :          20702 : index_reloptions(amoptions_function amoptions, Datum reloptions, bool validate)
                               2403                 :                : {
                               2404         [ -  + ]:          20702 :     Assert(amoptions != NULL);
                               2405                 :                : 
                               2406                 :                :     /* Assume function is strict */
  361 peter@eisentraut.org     2407         [ +  + ]:          20702 :     if (DatumGetPointer(reloptions) == NULL)
 7384 tgl@sss.pgh.pa.us        2408                 :          18731 :         return NULL;
                               2409                 :                : 
 3899                          2410                 :           1971 :     return amoptions(reloptions, validate);
                               2411                 :                : }
                               2412                 :                : 
                               2413                 :                : /*
                               2414                 :                :  * Option parser for attribute reloptions
                               2415                 :                :  */
                               2416                 :                : bytea *
 6085 rhaas@postgresql.org     2417                 :             25 : attribute_reloptions(Datum reloptions, bool validate)
                               2418                 :                : {
                               2419                 :                :     static const relopt_parse_elt tab[] = {
                               2420                 :                :         {"n_distinct", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct)},
                               2421                 :                :         {"n_distinct_inherited", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct_inherited)}
                               2422                 :                :     };
                               2423                 :                : 
 2511 michael@paquier.xyz      2424                 :             25 :     return (bytea *) build_reloptions(reloptions, validate,
                               2425                 :                :                                       RELOPT_KIND_ATTRIBUTE,
                               2426                 :                :                                       sizeof(AttributeOpts),
                               2427                 :                :                                       tab, lengthof(tab));
                               2428                 :                : }
                               2429                 :                : 
                               2430                 :                : /*
                               2431                 :                :  * Option parser for tablespace reloptions
                               2432                 :                :  */
                               2433                 :                : bytea *
 6102 rhaas@postgresql.org     2434                 :             89 : tablespace_reloptions(Datum reloptions, bool validate)
                               2435                 :                : {
                               2436                 :                :     static const relopt_parse_elt tab[] = {
                               2437                 :                :         {"random_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, random_page_cost)},
                               2438                 :                :         {"seq_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, seq_page_cost)},
                               2439                 :                :         {"effective_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, effective_io_concurrency)},
                               2440                 :                :         {"maintenance_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, maintenance_io_concurrency)}
                               2441                 :                :     };
                               2442                 :                : 
 2511 michael@paquier.xyz      2443                 :             89 :     return (bytea *) build_reloptions(reloptions, validate,
                               2444                 :                :                                       RELOPT_KIND_TABLESPACE,
                               2445                 :                :                                       sizeof(TableSpaceOpts),
                               2446                 :                :                                       tab, lengthof(tab));
                               2447                 :                : }
                               2448                 :                : 
                               2449                 :                : /*
                               2450                 :                :  * Determine the required LOCKMODE from an option list.
                               2451                 :                :  *
                               2452                 :                :  * Called from AlterTableGetLockLevel(), see that function
                               2453                 :                :  * for a longer explanation of how this works.
                               2454                 :                :  */
                               2455                 :                : LOCKMODE
 4055 simon@2ndQuadrant.co     2456                 :            540 : AlterTableGetRelOptionsLockLevel(List *defList)
                               2457                 :                : {
 3755 rhaas@postgresql.org     2458                 :            540 :     LOCKMODE    lockmode = NoLock;
                               2459                 :                :     ListCell   *cell;
                               2460                 :                : 
 4055 simon@2ndQuadrant.co     2461         [ -  + ]:            540 :     if (defList == NIL)
 4055 simon@2ndQuadrant.co     2462                 :UBC           0 :         return AccessExclusiveLock;
                               2463                 :                : 
 4055 simon@2ndQuadrant.co     2464         [ +  + ]:CBC         540 :     if (need_initialization)
                               2465                 :             13 :         initialize_reloptions();
                               2466                 :                : 
                               2467   [ +  -  +  +  :           1105 :     foreach(cell, defList)
                                              +  + ]
                               2468                 :                :     {
 3755 rhaas@postgresql.org     2469                 :            565 :         DefElem    *def = (DefElem *) lfirst(cell);
                               2470                 :                :         int         i;
                               2471                 :                : 
 4055 simon@2ndQuadrant.co     2472         [ +  + ]:          27447 :         for (i = 0; relOpts[i]; i++)
                               2473                 :                :         {
 3159 tgl@sss.pgh.pa.us        2474                 :          26882 :             if (strncmp(relOpts[i]->name,
                               2475                 :          26882 :                         def->defname,
                               2476         [ +  + ]:          26882 :                         relOpts[i]->namelen + 1) == 0)
                               2477                 :                :             {
 4055 simon@2ndQuadrant.co     2478         [ +  + ]:            789 :                 if (lockmode < relOpts[i]->lockmode)
                               2479                 :            536 :                     lockmode = relOpts[i]->lockmode;
                               2480                 :                :             }
                               2481                 :                :         }
                               2482                 :                :     }
                               2483                 :                : 
                               2484                 :            540 :     return lockmode;
                               2485                 :                : }
        

Generated by: LCOV version 2.0-1