=== Applying patches on top of PostgreSQL commit ID 7dcea51c2a4dcf7c512bbd4f618d1d3620f9d3d7 === /etc/rc.d/jail: WARNING: Per-jail configuration via jail_* variables is obsolete. Please consider migrating to /etc/jail.conf. Fri Sep 12 17:37:19 UTC 2025 On branch cf/4688 nothing to commit, working tree clean === using 'git am' to apply patch ./v-13-0001-New-options-engine.patch === Applying: 1/1] New options engine Using index info to reconstruct a base tree... M contrib/dblink/dblink.c M contrib/file_fdw/file_fdw.c M contrib/postgres_fdw/option.c M doc/src/sgml/indexam.sgml M src/backend/access/brin/brin.c M src/backend/access/common/reloptions.c M src/backend/access/gist/gist.c M src/backend/access/gist/gistutil.c M src/backend/access/nbtree/nbtree.c M src/backend/access/nbtree/nbtutils.c M src/backend/access/spgist/spgutils.c M src/backend/commands/createas.c M src/backend/commands/foreigncmds.c M src/backend/commands/indexcmds.c M src/backend/commands/tablecmds.c M src/backend/commands/tablespace.c M src/backend/foreign/foreign.c M src/backend/parser/parse_utilcmd.c M src/backend/tcop/utility.c M src/backend/utils/cache/attoptcache.c M src/backend/utils/cache/relcache.c M src/include/access/amapi.h M src/include/access/nbtree.h M src/include/access/reloptions.h M src/include/access/spgist_private.h Falling back to patching base and 3-way merge... Auto-merging src/include/access/spgist_private.h Auto-merging src/include/access/reloptions.h CONFLICT (content): Merge conflict in src/include/access/reloptions.h Auto-merging src/include/access/nbtree.h Auto-merging src/include/access/amapi.h Auto-merging src/backend/utils/cache/relcache.c Auto-merging src/backend/utils/cache/attoptcache.c Auto-merging src/backend/tcop/utility.c Auto-merging src/backend/parser/parse_utilcmd.c Auto-merging src/backend/foreign/foreign.c Auto-merging src/backend/commands/tablespace.c Auto-merging src/backend/commands/tablecmds.c Auto-merging src/backend/commands/indexcmds.c Auto-merging src/backend/commands/foreigncmds.c Auto-merging src/backend/commands/createas.c Auto-merging src/backend/access/spgist/spgutils.c Auto-merging src/backend/access/nbtree/nbtutils.c CONFLICT (content): Merge conflict in src/backend/access/nbtree/nbtutils.c Auto-merging src/backend/access/nbtree/nbtree.c Auto-merging src/backend/access/gist/gistutil.c Auto-merging src/backend/access/gist/gist.c Auto-merging src/backend/access/common/reloptions.c CONFLICT (content): Merge conflict in src/backend/access/common/reloptions.c Auto-merging src/backend/access/brin/brin.c Auto-merging doc/src/sgml/indexam.sgml Auto-merging contrib/postgres_fdw/option.c Auto-merging contrib/file_fdw/file_fdw.c Auto-merging contrib/dblink/dblink.c error: Failed to merge in the changes. hint: Use 'git am --show-current-patch=diff' to see the failed patch Patch failed at 0001 1/1] New options engine When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". Unstaged changes after reset: M contrib/bloom/bloom.h M contrib/bloom/blutils.c M contrib/dblink/dblink.c M contrib/file_fdw/file_fdw.c M contrib/postgres_fdw/option.c M contrib/test_decoding/expected/twophase.out M doc/src/sgml/indexam.sgml M src/backend/access/brin/brin.c M src/backend/access/common/Makefile M src/backend/access/common/meson.build M src/backend/access/common/reloptions.c M src/backend/access/gin/ginutil.c M src/backend/access/gist/gist.c M src/backend/access/gist/gistutil.c M src/backend/access/hash/hash.c M src/backend/access/hash/hashutil.c M src/backend/access/nbtree/nbtree.c M src/backend/access/nbtree/nbtutils.c M src/backend/access/spgist/spgutils.c M src/backend/commands/createas.c M src/backend/commands/foreigncmds.c M src/backend/commands/indexcmds.c M src/backend/commands/tablecmds.c M src/backend/commands/tablespace.c M src/backend/foreign/foreign.c M src/backend/parser/parse_utilcmd.c M src/backend/tcop/utility.c M src/backend/utils/cache/attoptcache.c M src/backend/utils/cache/relcache.c M src/backend/utils/cache/spccache.c M src/include/access/amapi.h M src/include/access/brin.h M src/include/access/brin_internal.h M src/include/access/gin_private.h M src/include/access/gist_private.h M src/include/access/hash.h M src/include/access/nbtree.h M src/include/access/reloptions.h M src/include/access/spgist.h M src/include/access/spgist_private.h M src/include/commands/tablecmds.h M src/test/modules/dummy_index_am/dummy_index_am.c M src/test/modules/test_oat_hooks/expected/alter_table.out M src/test/regress/expected/reloptions.out M src/test/regress/sql/reloptions.sql Removing src/backend/access/common/options.c Removing src/include/access/options.h === using patch(1) to apply patch ./v-13-0001-New-options-engine.patch === patching file contrib/bloom/bloom.h patching file contrib/bloom/blutils.c patching file contrib/dblink/dblink.c Hunk #1 succeeded at 1929 (offset -7 lines). patching file contrib/file_fdw/file_fdw.c Hunk #1 succeeded at 206 (offset 3 lines). patching file contrib/postgres_fdw/option.c Hunk #1 succeeded at 65 (offset -5 lines). patching file contrib/test_decoding/expected/twophase.out patching file doc/src/sgml/indexam.sgml patching file src/backend/access/brin/brin.c Hunk #5 succeeded at 2997 (offset -1 lines). patching file src/backend/access/common/Makefile patching file src/backend/access/common/meson.build patching file src/backend/access/common/options.c patching file src/backend/access/common/reloptions.c Hunk #4 FAILED at 89. Hunk #5 succeeded at 496 (offset -8 lines). Hunk #6 succeeded at 505 (offset -8 lines). Hunk #7 succeeded at 517 (offset -8 lines). Hunk #8 succeeded at 532 (offset -8 lines). Hunk #9 succeeded at 542 (offset -8 lines). Hunk #10 succeeded at 557 (offset -8 lines). Hunk #11 succeeded at 567 (offset -8 lines). Hunk #12 FAILED at 613. Hunk #13 succeeded at 871 (offset 1 line). Hunk #14 FAILED at 890. Hunk #15 FAILED at 1442. Hunk #16 succeeded at 1616 (offset 13 lines). 4 out of 16 hunks FAILED -- saving rejects to file src/backend/access/common/reloptions.c.rej patching file src/backend/access/gin/ginutil.c patching file src/backend/access/gist/gist.c patching file src/backend/access/gist/gistutil.c patching file src/backend/access/hash/hash.c patching file src/backend/access/hash/hashutil.c patching file src/backend/access/nbtree/nbtree.c Hunk #2 succeeded at 152 (offset 14 lines). Hunk #3 succeeded at 168 (offset 14 lines). Hunk #4 succeeded at 1796 (offset 240 lines). patching file src/backend/access/nbtree/nbtutils.c Hunk #1 FAILED at 18. Hunk #2 succeeded at 3644 (offset 929 lines). 1 out of 2 hunks FAILED -- saving rejects to file src/backend/access/nbtree/nbtutils.c.rej patching file src/backend/access/spgist/spgutils.c patching file src/backend/commands/createas.c patching file src/backend/commands/foreigncmds.c Hunk #1 succeeded at 123 (offset 11 lines). patching file src/backend/commands/indexcmds.c Hunk #2 succeeded at 570 (offset -1 lines). Hunk #3 succeeded at 893 (offset -1 lines). Hunk #4 succeeded at 908 (offset -1 lines). Hunk #5 succeeded at 2248 (offset 1 line). patching file src/backend/commands/tablecmds.c Hunk #2 succeeded at 782 (offset 30 lines). Hunk #3 succeeded at 930 (offset 30 lines). Hunk #4 succeeded at 4573 (offset 32 lines). Hunk #5 succeeded at 4615 (offset 32 lines). Hunk #6 succeeded at 4836 (offset 32 lines). Hunk #7 succeeded at 9075 (offset 107 lines). Hunk #8 succeeded at 16645 (offset 699 lines). Hunk #9 succeeded at 16680 (offset 699 lines). Hunk #10 succeeded at 16722 (offset 699 lines). Hunk #11 succeeded at 16818 (offset 699 lines). patching file src/backend/commands/tablespace.c patching file src/backend/foreign/foreign.c Hunk #1 succeeded at 81 (offset 1 line). Hunk #2 succeeded at 168 (offset 1 line). Hunk #3 succeeded at 240 (offset 1 line). Hunk #4 succeeded at 277 (offset 1 line). Hunk #5 succeeded at 310 (offset 1 line). Hunk #6 succeeded at 527 (offset 1 line). Hunk #7 succeeded at 625 (offset 1 line). patching file src/backend/parser/parse_utilcmd.c Hunk #1 succeeded at 1932 (offset 7 lines). Hunk #2 succeeded at 1996 (offset 7 lines). patching file src/backend/tcop/utility.c Hunk #1 succeeded at 1149 (offset -10 lines). Hunk #2 succeeded at 1173 (offset -10 lines). Hunk #3 succeeded at 1292 (offset -9 lines). patching file src/backend/utils/cache/attoptcache.c patching file src/backend/utils/cache/relcache.c patching file src/backend/utils/cache/spccache.c patching file src/include/access/amapi.h Hunk #3 succeeded at 300 (offset 1 line). patching file src/include/access/brin.h patching file src/include/access/brin_internal.h patching file src/include/access/gin_private.h patching file src/include/access/gist_private.h patching file src/include/access/hash.h patching file src/include/access/nbtree.h Hunk #1 succeeded at 1333 (offset 26 lines). patching file src/include/access/options.h patching file src/include/access/reloptions.h Hunk #2 FAILED at 20. Hunk #3 succeeded at 218 (offset 13 lines). Hunk #4 FAILED at 214. 2 out of 4 hunks FAILED -- saving rejects to file src/include/access/reloptions.h.rej patching file src/include/access/spgist.h patching file src/include/access/spgist_private.h Hunk #1 succeeded at 532 (offset 2 lines). patching file src/include/commands/tablecmds.h patching file src/test/modules/dummy_index_am/dummy_index_am.c patching file src/test/modules/test_oat_hooks/expected/alter_table.out patching file src/test/regress/expected/reloptions.out patching file src/test/regress/sql/reloptions.sql Unstaged changes after reset: M contrib/bloom/bloom.h M contrib/bloom/blutils.c M contrib/dblink/dblink.c M contrib/file_fdw/file_fdw.c M contrib/postgres_fdw/option.c M contrib/test_decoding/expected/twophase.out M doc/src/sgml/indexam.sgml M src/backend/access/brin/brin.c M src/backend/access/common/Makefile M src/backend/access/common/meson.build M src/backend/access/common/reloptions.c M src/backend/access/gin/ginutil.c M src/backend/access/gist/gist.c M src/backend/access/gist/gistutil.c M src/backend/access/hash/hash.c M src/backend/access/hash/hashutil.c M src/backend/access/nbtree/nbtree.c M src/backend/access/nbtree/nbtutils.c M src/backend/access/spgist/spgutils.c M src/backend/commands/createas.c M src/backend/commands/foreigncmds.c M src/backend/commands/indexcmds.c M src/backend/commands/tablecmds.c M src/backend/commands/tablespace.c M src/backend/foreign/foreign.c M src/backend/parser/parse_utilcmd.c M src/backend/tcop/utility.c M src/backend/utils/cache/attoptcache.c M src/backend/utils/cache/relcache.c M src/backend/utils/cache/spccache.c M src/include/access/amapi.h M src/include/access/brin.h M src/include/access/brin_internal.h M src/include/access/gin_private.h M src/include/access/gist_private.h M src/include/access/hash.h M src/include/access/nbtree.h M src/include/access/reloptions.h M src/include/access/spgist.h M src/include/access/spgist_private.h M src/include/commands/tablecmds.h M src/test/modules/dummy_index_am/dummy_index_am.c M src/test/modules/test_oat_hooks/expected/alter_table.out M src/test/regress/expected/reloptions.out M src/test/regress/sql/reloptions.sql Removing src/backend/access/common/options.c Removing src/backend/access/common/reloptions.c.rej Removing src/backend/access/nbtree/nbtutils.c.rej Removing src/include/access/options.h Removing src/include/access/reloptions.h.rej === using 'git apply' to apply patch ./v-13-0001-New-options-engine.patch === Applied patch to 'contrib/bloom/bloom.h' cleanly. Applied patch to 'contrib/bloom/blutils.c' cleanly. Applied patch to 'contrib/dblink/dblink.c' cleanly. Applied patch to 'contrib/file_fdw/file_fdw.c' cleanly. Applied patch to 'contrib/postgres_fdw/option.c' cleanly. Applied patch to 'contrib/test_decoding/expected/twophase.out' cleanly. Applied patch to 'doc/src/sgml/indexam.sgml' cleanly. Applied patch to 'src/backend/access/brin/brin.c' cleanly. Applied patch to 'src/backend/access/common/Makefile' cleanly. Applied patch to 'src/backend/access/common/meson.build' cleanly. Falling back to direct application... Applied patch to 'src/backend/access/common/reloptions.c' with conflicts. Applied patch to 'src/backend/access/gin/ginutil.c' cleanly. Applied patch to 'src/backend/access/gist/gist.c' cleanly. Applied patch to 'src/backend/access/gist/gistutil.c' cleanly. Applied patch to 'src/backend/access/hash/hash.c' cleanly. Applied patch to 'src/backend/access/hash/hashutil.c' cleanly. Applied patch to 'src/backend/access/nbtree/nbtree.c' cleanly. Applied patch to 'src/backend/access/nbtree/nbtutils.c' with conflicts. Applied patch to 'src/backend/access/spgist/spgutils.c' cleanly. Applied patch to 'src/backend/commands/createas.c' cleanly. Applied patch to 'src/backend/commands/foreigncmds.c' cleanly. Applied patch to 'src/backend/commands/indexcmds.c' cleanly. Applied patch to 'src/backend/commands/tablecmds.c' cleanly. Applied patch to 'src/backend/commands/tablespace.c' cleanly. Applied patch to 'src/backend/foreign/foreign.c' cleanly. Applied patch to 'src/backend/parser/parse_utilcmd.c' cleanly. Applied patch to 'src/backend/tcop/utility.c' cleanly. Applied patch to 'src/backend/utils/cache/attoptcache.c' cleanly. Applied patch to 'src/backend/utils/cache/relcache.c' cleanly. Applied patch to 'src/backend/utils/cache/spccache.c' cleanly. Applied patch to 'src/include/access/amapi.h' cleanly. Applied patch to 'src/include/access/brin.h' cleanly. Applied patch to 'src/include/access/brin_internal.h' cleanly. Applied patch to 'src/include/access/gin_private.h' cleanly. Applied patch to 'src/include/access/gist_private.h' cleanly. Applied patch to 'src/include/access/hash.h' cleanly. Applied patch to 'src/include/access/nbtree.h' cleanly. Falling back to direct application... Applied patch to 'src/include/access/reloptions.h' with conflicts. Applied patch to 'src/include/access/spgist.h' cleanly. Applied patch to 'src/include/access/spgist_private.h' cleanly. Applied patch to 'src/include/commands/tablecmds.h' cleanly. Applied patch to 'src/test/modules/dummy_index_am/dummy_index_am.c' cleanly. Applied patch to 'src/test/modules/test_oat_hooks/expected/alter_table.out' cleanly. Applied patch to 'src/test/regress/expected/reloptions.out' cleanly. Applied patch to 'src/test/regress/sql/reloptions.sql' cleanly. U src/backend/access/common/reloptions.c U src/backend/access/nbtree/nbtutils.c U src/include/access/reloptions.h diff --cc src/backend/access/common/reloptions.c index 0af3fea68fa,45e8eaaee25..00000000000 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@@ -91,400 -89,8 +89,403 @@@ * value has no effect until the next VACUUM, so no need for stronger lock. */ ++<<<<<<< ours +static relopt_bool boolRelOpts[] = +{ + { + { + "autosummarize", + "Enables automatic summarization on this BRIN index", + RELOPT_KIND_BRIN, + AccessExclusiveLock + }, + false + }, + { + { + "autovacuum_enabled", + "Enables autovacuum in this relation", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + true + }, + { + { + "user_catalog_table", + "Declare a table as an additional catalog table, e.g. for the purpose of logical replication", + RELOPT_KIND_HEAP, + AccessExclusiveLock + }, + false + }, + { + { + "fastupdate", + "Enables \"fast update\" feature for this GIN index", + RELOPT_KIND_GIN, + AccessExclusiveLock + }, + true + }, + { + { + "security_barrier", + "View acts as a row security barrier", + RELOPT_KIND_VIEW, + AccessExclusiveLock + }, + false + }, + { + { + "security_invoker", + "Privileges on underlying relations are checked as the invoking user, not the view owner", + RELOPT_KIND_VIEW, + AccessExclusiveLock + }, + false + }, + { + { + "vacuum_truncate", + "Enables vacuum to truncate empty pages at the end of this table", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + true + }, + { + { + "deduplicate_items", + "Enables \"deduplicate items\" feature for this btree index", + RELOPT_KIND_BTREE, + ShareUpdateExclusiveLock /* since it applies only to later + * inserts */ + }, + true + }, + /* list terminator */ + {{NULL}} +}; + +static relopt_int intRelOpts[] = +{ + { + { + "fillfactor", + "Packs table pages only to this percentage", + RELOPT_KIND_HEAP, + ShareUpdateExclusiveLock /* since it applies only to later + * inserts */ + }, + HEAP_DEFAULT_FILLFACTOR, HEAP_MIN_FILLFACTOR, 100 + }, + { + { + "fillfactor", + "Packs btree index pages only to this percentage", + RELOPT_KIND_BTREE, + ShareUpdateExclusiveLock /* since it applies only to later + * inserts */ + }, + BTREE_DEFAULT_FILLFACTOR, BTREE_MIN_FILLFACTOR, 100 + }, + { + { + "fillfactor", + "Packs hash index pages only to this percentage", + RELOPT_KIND_HASH, + ShareUpdateExclusiveLock /* since it applies only to later + * inserts */ + }, + HASH_DEFAULT_FILLFACTOR, HASH_MIN_FILLFACTOR, 100 + }, + { + { + "fillfactor", + "Packs gist index pages only to this percentage", + RELOPT_KIND_GIST, + ShareUpdateExclusiveLock /* since it applies only to later + * inserts */ + }, + GIST_DEFAULT_FILLFACTOR, GIST_MIN_FILLFACTOR, 100 + }, + { + { + "fillfactor", + "Packs spgist index pages only to this percentage", + RELOPT_KIND_SPGIST, + ShareUpdateExclusiveLock /* since it applies only to later + * inserts */ + }, + SPGIST_DEFAULT_FILLFACTOR, SPGIST_MIN_FILLFACTOR, 100 + }, + { + { + "autovacuum_vacuum_threshold", + "Minimum number of tuple updates or deletes prior to vacuum", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + -1, 0, INT_MAX + }, + { + { + "autovacuum_vacuum_max_threshold", + "Maximum number of tuple updates or deletes prior to vacuum", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + -2, -1, INT_MAX + }, + { + { + "autovacuum_vacuum_insert_threshold", + "Minimum number of tuple inserts prior to vacuum, or -1 to disable insert vacuums", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + -2, -1, INT_MAX + }, + { + { + "autovacuum_analyze_threshold", + "Minimum number of tuple inserts, updates or deletes prior to analyze", + RELOPT_KIND_HEAP, + ShareUpdateExclusiveLock + }, + -1, 0, INT_MAX + }, + { + { + "autovacuum_vacuum_cost_limit", + "Vacuum cost amount available before napping, for autovacuum", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + -1, 1, 10000 + }, + { + { + "autovacuum_freeze_min_age", + "Minimum age at which VACUUM should freeze a table row, for autovacuum", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + -1, 0, 1000000000 + }, + { + { + "autovacuum_multixact_freeze_min_age", + "Minimum multixact age at which VACUUM should freeze a row multixact's, for autovacuum", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + -1, 0, 1000000000 + }, + { + { + "autovacuum_freeze_max_age", + "Age at which to autovacuum a table to prevent transaction ID wraparound", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + -1, 100000, 2000000000 + }, + { + { + "autovacuum_multixact_freeze_max_age", + "Multixact age at which to autovacuum a table to prevent multixact wraparound", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + -1, 10000, 2000000000 + }, + { + { + "autovacuum_freeze_table_age", + "Age at which VACUUM should perform a full table sweep to freeze row versions", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, -1, 0, 2000000000 + }, + { + { + "autovacuum_multixact_freeze_table_age", + "Age of multixact at which VACUUM should perform a full table sweep to freeze row versions", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, -1, 0, 2000000000 + }, + { + { + "log_autovacuum_min_duration", + "Sets the minimum execution time above which autovacuum actions will be logged", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + -1, -1, INT_MAX + }, + { + { + "toast_tuple_target", + "Sets the target tuple length at which external columns will be toasted", + RELOPT_KIND_HEAP, + ShareUpdateExclusiveLock + }, + TOAST_TUPLE_TARGET, 128, TOAST_TUPLE_TARGET_MAIN + }, + { + { + "pages_per_range", + "Number of pages that each page range covers in a BRIN index", + RELOPT_KIND_BRIN, + AccessExclusiveLock + }, 128, 1, 131072 + }, + { + { + "gin_pending_list_limit", + "Maximum size of the pending list for this GIN index, in kilobytes.", + RELOPT_KIND_GIN, + AccessExclusiveLock + }, + -1, 64, MAX_KILOBYTES + }, + { + { + "effective_io_concurrency", + "Number of simultaneous requests that can be handled efficiently by the disk subsystem.", + RELOPT_KIND_TABLESPACE, + ShareUpdateExclusiveLock + }, + -1, 0, MAX_IO_CONCURRENCY + }, + { + { + "maintenance_io_concurrency", + "Number of simultaneous requests that can be handled efficiently by the disk subsystem for maintenance work.", + RELOPT_KIND_TABLESPACE, + ShareUpdateExclusiveLock + }, + -1, 0, MAX_IO_CONCURRENCY + }, + { + { + "parallel_workers", + "Number of parallel processes that can be used per executor node for this relation.", + RELOPT_KIND_HEAP, + ShareUpdateExclusiveLock + }, + -1, 0, 1024 + }, + + /* list terminator */ + {{NULL}} +}; + +static relopt_real realRelOpts[] = +{ + { + { + "autovacuum_vacuum_cost_delay", + "Vacuum cost delay in milliseconds, for autovacuum", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + -1, 0.0, 100.0 + }, + { + { + "autovacuum_vacuum_scale_factor", + "Number of tuple updates or deletes prior to vacuum as a fraction of reltuples", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + -1, 0.0, 100.0 + }, + { + { + "autovacuum_vacuum_insert_scale_factor", + "Number of tuple inserts prior to vacuum as a fraction of reltuples", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + -1, 0.0, 100.0 + }, + { + { + "autovacuum_analyze_scale_factor", + "Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples", + RELOPT_KIND_HEAP, + ShareUpdateExclusiveLock + }, + -1, 0.0, 100.0 + }, + { + { + "vacuum_max_eager_freeze_failure_rate", + "Fraction of pages in a relation vacuum can scan and fail to freeze before disabling eager scanning.", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + -1, 0.0, 1.0 + }, + + { + { + "seq_page_cost", + "Sets the planner's estimate of the cost of a sequentially fetched disk page.", + RELOPT_KIND_TABLESPACE, + ShareUpdateExclusiveLock + }, + -1, 0.0, DBL_MAX + }, + { + { + "random_page_cost", + "Sets the planner's estimate of the cost of a nonsequentially fetched disk page.", + RELOPT_KIND_TABLESPACE, + ShareUpdateExclusiveLock + }, + -1, 0.0, DBL_MAX + }, + { + { + "n_distinct", + "Sets the planner's estimate of the number of distinct values appearing in a column (excluding child relations).", + RELOPT_KIND_ATTRIBUTE, + ShareUpdateExclusiveLock + }, + 0, -1.0, DBL_MAX + }, + { + { + "n_distinct_inherited", + "Sets the planner's estimate of the number of distinct values appearing in a column (including child relations).", + RELOPT_KIND_ATTRIBUTE, + ShareUpdateExclusiveLock + }, + 0, -1.0, DBL_MAX + }, + { + { + "vacuum_cleanup_index_scale_factor", + "Deprecated B-Tree parameter.", + RELOPT_KIND_BTREE, + ShareUpdateExclusiveLock + }, + -1, 0.0, 1e10 + }, + /* list terminator */ + {{NULL}} +}; + ++======= ++>>>>>>> theirs /* values from StdRdOptIndexCleanup */ - static relopt_enum_elt_def StdRdOptIndexCleanupValues[] = + static opt_enum_elt_def StdRdOptIndexCleanupValues[] = { {"auto", STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO}, {"on", STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON}, @@@ -1131,256 -213,8 +608,261 @@@ add_local_string_reloption(local_relopt validate_string_relopt validator, fill_string_relopt filler, int offset) { ++<<<<<<< ours + relopt_string *newoption = init_string_reloption(RELOPT_KIND_LOCAL, + name, desc, + default_val, + validator, filler, + 0); + + add_local_reloption(relopts, (relopt_gen *) newoption, offset); +} + +/* + * Transform a relation options list (list of DefElem) into the text array + * format that is kept in pg_class.reloptions, including only those options + * that are in the passed namespace. The output values do not include the + * namespace. + * + * This is used for three cases: CREATE TABLE/INDEX, ALTER TABLE SET, and + * ALTER TABLE RESET. In the ALTER cases, oldOptions is the existing + * reloptions value (possibly NULL), and we replace or remove entries + * as needed. + * + * If acceptOidsOff is true, then we allow oids = false, but throw error when + * on. This is solely needed for backwards compatibility. + * + * Note that this is not responsible for determining whether the options + * are valid, but it does check that namespaces for all the options given are + * listed in validnsps. The NULL namespace is always valid and need not be + * explicitly listed. Passing a NULL pointer means that only the NULL + * namespace is valid. + * + * Both oldOptions and the result are text arrays (or NULL for "default"), + * but we declare them as Datums to avoid including array.h in reloptions.h. + */ +Datum +transformRelOptions(Datum oldOptions, List *defList, const char *nameSpace, + const char *const validnsps[], bool acceptOidsOff, bool isReset) +{ + Datum result; + ArrayBuildState *astate; + ListCell *cell; + + /* no change if empty list */ + if (defList == NIL) + return oldOptions; + + /* We build new array using accumArrayResult */ + astate = NULL; + + /* Copy any oldOptions that aren't to be replaced */ + if (PointerIsValid(DatumGetPointer(oldOptions))) + { + ArrayType *array = DatumGetArrayTypeP(oldOptions); + Datum *oldoptions; + int noldoptions; + int i; + + deconstruct_array_builtin(array, TEXTOID, &oldoptions, NULL, &noldoptions); + + for (i = 0; i < noldoptions; i++) + { + char *text_str = VARDATA(DatumGetPointer(oldoptions[i])); + int text_len = VARSIZE(DatumGetPointer(oldoptions[i])) - VARHDRSZ; + + /* Search for a match in defList */ + foreach(cell, defList) + { + DefElem *def = (DefElem *) lfirst(cell); + int kw_len; + + /* ignore if not in the same namespace */ + if (nameSpace == NULL) + { + if (def->defnamespace != NULL) + continue; + } + else if (def->defnamespace == NULL) + continue; + else if (strcmp(def->defnamespace, nameSpace) != 0) + continue; + + kw_len = strlen(def->defname); + if (text_len > kw_len && text_str[kw_len] == '=' && + strncmp(text_str, def->defname, kw_len) == 0) + break; + } + if (!cell) + { + /* No match, so keep old option */ + astate = accumArrayResult(astate, oldoptions[i], + false, TEXTOID, + CurrentMemoryContext); + } + } + } + + /* + * If CREATE/SET, add new options to array; if RESET, just check that the + * user didn't say RESET (option=val). (Must do this because the grammar + * doesn't enforce it.) + */ + foreach(cell, defList) + { + DefElem *def = (DefElem *) lfirst(cell); + + if (isReset) + { + if (def->arg != NULL) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("RESET must not include values for parameters"))); + } + else + { + const char *name; + const char *value; + text *t; + Size len; + + /* + * Error out if the namespace is not valid. A NULL namespace is + * always valid. + */ + if (def->defnamespace != NULL) + { + bool valid = false; + int i; + + if (validnsps) + { + for (i = 0; validnsps[i]; i++) + { + if (strcmp(def->defnamespace, validnsps[i]) == 0) + { + valid = true; + break; + } + } + } + + if (!valid) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("unrecognized parameter namespace \"%s\"", + def->defnamespace))); + } + + /* ignore if not in the same namespace */ + if (nameSpace == NULL) + { + if (def->defnamespace != NULL) + continue; + } + else if (def->defnamespace == NULL) + continue; + else if (strcmp(def->defnamespace, nameSpace) != 0) + continue; + + /* + * Flatten the DefElem into a text string like "name=arg". If we + * have just "name", assume "name=true" is meant. Note: the + * namespace is not output. + */ + name = def->defname; + if (def->arg != NULL) + value = defGetString(def); + else + value = "true"; + + /* Insist that name not contain "=", else "a=b=c" is ambiguous */ + if (strchr(name, '=') != NULL) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid option name \"%s\": must not contain \"=\"", + name))); + + /* + * This is not a great place for this test, but there's no other + * convenient place to filter the option out. As WITH (oids = + * false) will be removed someday, this seems like an acceptable + * amount of ugly. + */ + if (acceptOidsOff && def->defnamespace == NULL && + strcmp(name, "oids") == 0) + { + if (defGetBoolean(def)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("tables declared WITH OIDS are not supported"))); + /* skip over option, reloptions machinery doesn't know it */ + continue; + } + + len = VARHDRSZ + strlen(name) + 1 + strlen(value); + /* +1 leaves room for sprintf's trailing null */ + t = (text *) palloc(len + 1); + SET_VARSIZE(t, len); + sprintf(VARDATA(t), "%s=%s", name, value); + + astate = accumArrayResult(astate, PointerGetDatum(t), + false, TEXTOID, + CurrentMemoryContext); + } + } + + if (astate) + result = makeArrayResult(astate, CurrentMemoryContext); + else + result = (Datum) 0; + + return result; +} + + +/* + * Convert the text-array format of reloptions into a List of DefElem. + * This is the inverse of transformRelOptions(). + */ +List * +untransformRelOptions(Datum options) +{ + List *result = NIL; + ArrayType *array; + Datum *optiondatums; + int noptions; + int i; + + /* Nothing to do if no options */ + if (!PointerIsValid(DatumGetPointer(options))) + return result; + + array = DatumGetArrayTypeP(options); + + deconstruct_array_builtin(array, TEXTOID, &optiondatums, NULL, &noptions); + + for (i = 0; i < noptions; i++) + { + char *s; + char *p; + Node *val = NULL; + + s = TextDatumGetCString(optiondatums[i]); + p = strchr(s, '='); + if (p) + { + *p++ = '\0'; + val = (Node *) makeString(p); + } + result = lappend(result, makeDefElem(s, val, -1)); + } + + return result; ++======= + optionsSpecSetAddString(relopts->spec_set, name, desc, NoLock, offset, + NULL, default_val, validator, filler); ++>>>>>>> theirs } /* @@@ -1443,57 -286,13 +934,63 @@@ extractRelOptions(HeapTuple tuple, Tupl return options; } - static void - parseRelOptionsInternal(Datum options, bool validate, - relopt_value *reloptions, int numoptions) + void + oid_postvalidate(option_value *value) { ++<<<<<<< ours + ArrayType *array = DatumGetArrayTypeP(options); + Datum *optiondatums; + int noptions; + int i; + + deconstruct_array_builtin(array, TEXTOID, &optiondatums, NULL, &noptions); + + for (i = 0; i < noptions; i++) + { + char *text_str = VARDATA(DatumGetPointer(optiondatums[i])); + int text_len = VARSIZE(DatumGetPointer(optiondatums[i])) - VARHDRSZ; + int j; + + /* Search for a match in reloptions */ + for (j = 0; j < numoptions; j++) + { + int kw_len = reloptions[j].gen->namelen; + + if (text_len > kw_len && text_str[kw_len] == '=' && + strncmp(text_str, reloptions[j].gen->name, kw_len) == 0) + { + parse_one_reloption(&reloptions[j], text_str, text_len, + validate); + break; + } + } + + if (j >= numoptions && validate) + { + char *s; + char *p; + + s = TextDatumGetCString(optiondatums[i]); + p = strchr(s, '='); + if (p) + *p = '\0'; + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("unrecognized parameter \"%s\"", s))); + } + } + + /* It's worth avoiding memory leaks in this function */ + pfree(optiondatums); + + if (((void *) array) != DatumGetPointer(options)) + pfree(array); ++======= + if (value->values.bool_val) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("tables declared WITH OIDS are not supported"))); ++>>>>>>> theirs } /* @@@ -1582,393 -534,64 +1232,210 @@@ get_heap_relopt_spec_set(void } /* - * Subroutine for parseRelOptions, to parse and validate a single option's - * value + * These toast options are can't be set via SQL, but we should set them + * to their defaults in binary representation, to make postgres work properly */ static void - parse_one_reloption(relopt_value *option, char *text_str, int text_len, - bool validate) + toast_options_postprocess(void *data, bool validate) { - char *value; - int value_len; - bool parsed; - bool nofree = false; - - if (option->isset && validate) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("parameter \"%s\" specified more than once", - option->gen->name))); - - value_len = text_len - option->gen->namelen - 1; - value = (char *) palloc(value_len + 1); - memcpy(value, text_str + option->gen->namelen + 1, value_len); - value[value_len] = '\0'; - - switch (option->gen->type) + if (data) { - case RELOPT_TYPE_BOOL: - { - parsed = parse_bool(value, &option->values.bool_val); - if (validate && !parsed) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid value for boolean option \"%s\": %s", - option->gen->name, value))); - } - break; - case RELOPT_TYPE_INT: - { - relopt_int *optint = (relopt_int *) option->gen; - - parsed = parse_int(value, &option->values.int_val, 0, NULL); - if (validate && !parsed) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid value for integer option \"%s\": %s", - option->gen->name, value))); - if (validate && (option->values.int_val < optint->min || - option->values.int_val > optint->max)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("value %s out of bounds for option \"%s\"", - value, option->gen->name), - errdetail("Valid values are between \"%d\" and \"%d\".", - optint->min, optint->max))); - } - break; - case RELOPT_TYPE_REAL: - { - relopt_real *optreal = (relopt_real *) option->gen; + StdRdOptions *toast_options = (StdRdOptions *) data; - parsed = parse_real(value, &option->values.real_val, 0, NULL); - if (validate && !parsed) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid value for floating point option \"%s\": %s", - option->gen->name, value))); - if (validate && (option->values.real_val < optreal->min || - option->values.real_val > optreal->max)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("value %s out of bounds for option \"%s\"", - value, option->gen->name), - errdetail("Valid values are between \"%f\" and \"%f\".", - optreal->min, optreal->max))); - } - break; - case RELOPT_TYPE_ENUM: - { - relopt_enum *optenum = (relopt_enum *) option->gen; - relopt_enum_elt_def *elt; - - parsed = false; - for (elt = optenum->members; elt->string_val; elt++) - { - if (pg_strcasecmp(value, elt->string_val) == 0) - { - option->values.enum_val = elt->symbol_val; - parsed = true; - break; - } - } - if (validate && !parsed) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid value for enum option \"%s\": %s", - option->gen->name, value), - optenum->detailmsg ? - errdetail_internal("%s", _(optenum->detailmsg)) : 0)); - - /* - * If value is not among the allowed string values, but we are - * not asked to validate, just use the default numeric value. - */ - if (!parsed) - option->values.enum_val = optenum->default_val; - } - break; - case RELOPT_TYPE_STRING: - { - relopt_string *optstring = (relopt_string *) option->gen; - - option->values.string_val = value; - nofree = true; - if (validate && optstring->validate_cb) - (optstring->validate_cb) (value); - parsed = true; - } - break; - default: - elog(ERROR, "unsupported reloption type %d", option->gen->type); - parsed = true; /* quiet compiler */ - break; + toast_options->fillfactor = 100; + toast_options->autovacuum.analyze_threshold = -1; + toast_options->autovacuum.analyze_scale_factor = -1; } - - if (parsed) - option->isset = true; - if (!nofree) - pfree(value); } - /* - * Given the result from parseRelOptions, allocate a struct that's of the - * specified base size plus any extra space that's needed for string variables. - * - * "base" should be sizeof(struct) of the reloptions struct (StdRdOptions or - * equivalent). - */ - static void * - allocateReloptStruct(Size base, relopt_value *options, int numoptions) + static options_spec_set *toast_relopt_spec_set = NULL; + options_spec_set * + get_toast_relopt_spec_set(void) { - Size size = base; - int i; - - for (i = 0; i < numoptions; i++) - { - relopt_value *optval = &options[i]; - - if (optval->gen->type == RELOPT_TYPE_STRING) - { - relopt_string *optstr = (relopt_string *) optval->gen; + if (toast_relopt_spec_set) + return toast_relopt_spec_set; - if (optstr->fill_cb) - { - const char *val = optval->isset ? optval->values.string_val : - optstr->default_isnull ? NULL : optstr->default_val; - - size += optstr->fill_cb(val, NULL); - } - else - size += GET_STRING_RELOPTION_LEN(*optval) + 1; - } - } - - return palloc0(size); - } - - /* - * Given the result of parseRelOptions and a parsing table, fill in the - * struct (previously allocated with allocateReloptStruct) with the parsed - * values. - * - * rdopts is the pointer to the allocated struct to be filled. - * basesize is the sizeof(struct) that was passed to allocateReloptStruct. - * options, of length numoptions, is parseRelOptions' output. - * elems, of length numelems, is the table describing the allowed options. - * When validate is true, it is expected that all options appear in elems. - */ - static void - fillRelOptions(void *rdopts, Size basesize, - relopt_value *options, int numoptions, - bool validate, - const relopt_parse_elt *elems, int numelems) - { - int i; - int offset = basesize; - - for (i = 0; i < numoptions; i++) - { - int j; - bool found = false; + toast_relopt_spec_set = get_stdrd_relopt_spec_set(false); + toast_relopt_spec_set->postprocess_fun = toast_options_postprocess; ++<<<<<<< ours + for (j = 0; j < numelems; j++) + { + if (strcmp(options[i].gen->name, elems[j].optname) == 0) + { + relopt_string *optstring; + char *itempos = ((char *) rdopts) + elems[j].offset; + char *string_val; + + /* + * If isset_offset is provided, store whether the reloption is + * set there. + */ + if (elems[j].isset_offset > 0) + { + char *setpos = ((char *) rdopts) + elems[j].isset_offset; + + *(bool *) setpos = options[i].isset; + } + + switch (options[i].gen->type) + { + case RELOPT_TYPE_BOOL: + *(bool *) itempos = options[i].isset ? + options[i].values.bool_val : + ((relopt_bool *) options[i].gen)->default_val; + break; + case RELOPT_TYPE_INT: + *(int *) itempos = options[i].isset ? + options[i].values.int_val : + ((relopt_int *) options[i].gen)->default_val; + break; + case RELOPT_TYPE_REAL: + *(double *) itempos = options[i].isset ? + options[i].values.real_val : + ((relopt_real *) options[i].gen)->default_val; + break; + case RELOPT_TYPE_ENUM: + *(int *) itempos = options[i].isset ? + options[i].values.enum_val : + ((relopt_enum *) options[i].gen)->default_val; + break; + case RELOPT_TYPE_STRING: + optstring = (relopt_string *) options[i].gen; + if (options[i].isset) + string_val = options[i].values.string_val; + else if (!optstring->default_isnull) + string_val = optstring->default_val; + else + string_val = NULL; + + if (optstring->fill_cb) + { + Size size = + optstring->fill_cb(string_val, + (char *) rdopts + offset); + + if (size) + { + *(int *) itempos = offset; + offset += size; + } + else + *(int *) itempos = 0; + } + else if (string_val == NULL) + *(int *) itempos = 0; + else + { + strcpy((char *) rdopts + offset, string_val); + *(int *) itempos = offset; + offset += strlen(string_val) + 1; + } + break; + default: + elog(ERROR, "unsupported reloption type %d", + options[i].gen->type); + break; + } + found = true; + break; + } + } + if (validate && !found) + elog(ERROR, "reloption \"%s\" not found in parse table", + options[i].gen->name); + } + SET_VARSIZE(rdopts, offset); ++======= + return toast_relopt_spec_set; ++>>>>>>> theirs } /* - * Option parser for anything that uses StdRdOptions. + * Do not allow to set any option on partitioned table */ - bytea * - default_reloptions(Datum reloptions, bool validate, relopt_kind kind) + static void + partitioned_options_postprocess(void *data, bool validate) { ++<<<<<<< ours + static const relopt_parse_elt tab[] = { + {"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)}, + {"autovacuum_enabled", RELOPT_TYPE_BOOL, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, enabled)}, + {"autovacuum_vacuum_threshold", RELOPT_TYPE_INT, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_threshold)}, + {"autovacuum_vacuum_max_threshold", RELOPT_TYPE_INT, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_max_threshold)}, + {"autovacuum_vacuum_insert_threshold", RELOPT_TYPE_INT, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_ins_threshold)}, + {"autovacuum_analyze_threshold", RELOPT_TYPE_INT, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_threshold)}, + {"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_limit)}, + {"autovacuum_freeze_min_age", RELOPT_TYPE_INT, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_min_age)}, + {"autovacuum_freeze_max_age", RELOPT_TYPE_INT, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_max_age)}, + {"autovacuum_freeze_table_age", RELOPT_TYPE_INT, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_table_age)}, + {"autovacuum_multixact_freeze_min_age", RELOPT_TYPE_INT, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, multixact_freeze_min_age)}, + {"autovacuum_multixact_freeze_max_age", RELOPT_TYPE_INT, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, multixact_freeze_max_age)}, + {"autovacuum_multixact_freeze_table_age", RELOPT_TYPE_INT, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, multixact_freeze_table_age)}, + {"log_autovacuum_min_duration", RELOPT_TYPE_INT, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, log_min_duration)}, + {"toast_tuple_target", RELOPT_TYPE_INT, + offsetof(StdRdOptions, toast_tuple_target)}, + {"autovacuum_vacuum_cost_delay", RELOPT_TYPE_REAL, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_delay)}, + {"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_scale_factor)}, + {"autovacuum_vacuum_insert_scale_factor", RELOPT_TYPE_REAL, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_ins_scale_factor)}, + {"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_scale_factor)}, + {"user_catalog_table", RELOPT_TYPE_BOOL, + offsetof(StdRdOptions, user_catalog_table)}, + {"parallel_workers", RELOPT_TYPE_INT, + offsetof(StdRdOptions, parallel_workers)}, + {"vacuum_index_cleanup", RELOPT_TYPE_ENUM, + offsetof(StdRdOptions, vacuum_index_cleanup)}, + {"vacuum_truncate", RELOPT_TYPE_BOOL, + offsetof(StdRdOptions, vacuum_truncate), offsetof(StdRdOptions, vacuum_truncate_set)}, + {"vacuum_max_eager_freeze_failure_rate", RELOPT_TYPE_REAL, + offsetof(StdRdOptions, vacuum_max_eager_freeze_failure_rate)} + }; + + return (bytea *) build_reloptions(reloptions, validate, kind, + sizeof(StdRdOptions), + tab, lengthof(tab)); ++======= + if (data && validate) + ereport(ERROR, + errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot specify storage parameters for a partitioned table"), + errhint("Specify storage parameters for its leaf partitions instead.")); ++>>>>>>> theirs } - /* - * build_reloptions - * - * Parses "reloptions" provided by the caller, returning them in a - * structure containing the parsed options. The parsing is done with - * the help of a parsing table describing the allowed options, defined - * by "relopt_elems" of length "num_relopt_elems". - * - * "validate" must be true if reloptions value is freshly built by - * transformRelOptions(), as opposed to being read from the catalog, in which - * case the values contained in it must already be valid. - * - * NULL is returned if the passed-in options did not match any of the options - * in the parsing table, unless validate is true in which case an error would - * be reported. - */ - void * - build_reloptions(Datum reloptions, bool validate, - relopt_kind kind, - Size relopt_struct_size, - const relopt_parse_elt *relopt_elems, - int num_relopt_elems) - { - int numoptions; - relopt_value *options; - void *rdopts; - /* parse options specific to given relation option kind */ - options = parseRelOptions(reloptions, validate, kind, &numoptions); - Assert(numoptions <= num_relopt_elems); + static options_spec_set *partitioned_relopt_spec_set = NULL; - /* if none set, we're done */ - if (numoptions == 0) - { - Assert(options == NULL); - return NULL; - } - - /* allocate and fill the structure */ - rdopts = allocateReloptStruct(relopt_struct_size, options, numoptions); - fillRelOptions(rdopts, relopt_struct_size, options, numoptions, - validate, relopt_elems, num_relopt_elems); + options_spec_set * + get_partitioned_relopt_spec_set(void) + { + if (partitioned_relopt_spec_set) + return partitioned_relopt_spec_set; + partitioned_relopt_spec_set = get_stdrd_relopt_spec_set(true); - pfree(options); + /* No options for now, so Spec Set is empty */ + partitioned_relopt_spec_set->postprocess_fun = + partitioned_options_postprocess; - return rdopts; + return partitioned_relopt_spec_set; } /* @@@ -1979,36 -602,41 +1446,48 @@@ void * build_local_reloptions(local_relopts *relopts, Datum options, bool validate) { - int noptions = list_length(relopts->options); - relopt_parse_elt *elems = palloc(sizeof(*elems) * noptions); - relopt_value *vals; void *opts; - int i = 0; ListCell *lc; + List *values; - foreach(lc, relopts->options) + values = optionsTextArrayToRawValues(options); + values = optionsParseRawValues(values, relopts->spec_set, validate); + opts = optionsValuesToBytea(values, relopts->spec_set); + + /* + * Kind of ugly conversion here for backward compatibility. Would be + * removed while moving opclass options to options.c API + */ + + if (validate && relopts->validators) { - local_relopt *opt = lfirst(lc); + int val_count = list_length(values); + int i; + option_value *val_array; ++<<<<<<< ours + elems[i].optname = opt->option->name; + elems[i].opttype = opt->option->type; + elems[i].offset = opt->offset; + elems[i].isset_offset = 0; /* not supported for local relopts yet */ ++======= + val_array = palloc(sizeof(option_value) * val_count); ++>>>>>>> theirs - i++; - } + i = 0; + foreach(lc, values) + { + option_value *val = lfirst(lc); - vals = parseLocalRelOptions(relopts, options, validate); - opts = allocateReloptStruct(relopts->relopt_struct_size, vals, noptions); - fillRelOptions(opts, relopts->relopt_struct_size, vals, noptions, validate, - elems, noptions); + memcpy(&(val_array[i]), val, sizeof(option_value)); + i++; + } - if (validate) foreach(lc, relopts->validators) - ((relopts_validator) lfirst(lc)) (opts, vals, noptions); + ((relopts_validator) lfirst(lc)) (opts, val_array, val_count); - if (elems) - pfree(elems); + pfree(val_array); + } return opts; } diff --cc src/backend/access/nbtree/nbtutils.c index edfea2acaff,28a3c0be76b..00000000000 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@@ -18,7 -18,7 +18,11 @@@ #include #include "access/nbtree.h" ++<<<<<<< ours +#include "access/reloptions.h" ++======= + #include "storage/lock.h" ++>>>>>>> theirs #include "access/relscan.h" #include "commands/progress.h" #include "miscadmin.h" diff --cc src/include/access/reloptions.h index a604a4702c3,b42bb614e03..00000000000 --- a/src/include/access/reloptions.h +++ b/src/include/access/reloptions.h @@@ -28,151 -23,25 +23,67 @@@ /* reloption namespaces allowed for heaps -- currently only TOAST */ #define HEAP_RELOPT_NAMESPACES { "toast", NULL } - /* generic struct to hold shared data */ - typedef struct relopt_gen - { - const char *name; /* must be first (used as list termination - * marker) */ - const char *desc; - bits32 kinds; - LOCKMODE lockmode; - int namelen; - relopt_type type; - } relopt_gen; - - /* holds a parsed value */ - typedef struct relopt_value - { - relopt_gen *gen; - bool isset; - union - { - bool bool_val; - int int_val; - double real_val; - int enum_val; - char *string_val; /* allocated separately */ - } values; - } relopt_value; - - /* reloptions records for specific variable types */ - typedef struct relopt_bool - { - relopt_gen gen; - bool default_val; - } relopt_bool; - - typedef struct relopt_int - { - relopt_gen gen; - int default_val; - int min; - int max; - } relopt_int; - - typedef struct relopt_real - { - relopt_gen gen; - double default_val; - double min; - double max; - } relopt_real; - /* - * relopt_enum_elt_def -- One member of the array of acceptable values - * of an enum reloption. + * backward compatibility aliases so local reloption code of custom validator + * can work. */ - typedef struct relopt_enum_elt_def - { - const char *string_val; - int symbol_val; - } relopt_enum_elt_def; + typedef option_value relopt_value; + typedef fill_string_option fill_string_relopt; + typedef validate_string_option validate_string_relopt; + #define GET_STRING_RELOPTION(optstruct, member) \ + GET_STRING_OPTION(optstruct, member) - typedef struct relopt_enum - { - relopt_gen gen; - relopt_enum_elt_def *members; - int default_val; - const char *detailmsg; - /* null-terminated array of members */ - } relopt_enum; - /* validation routines for strings */ - typedef void (*validate_string_relopt) (const char *value); - typedef Size (*fill_string_relopt) (const char *value, void *ptr); + /* + * relopts_validator functions is left for backward compatibility for using + * with local reloptions. Should not be used elsewhere + */ /* validation routine for the whole option set */ ++<<<<<<< ours +typedef void (*relopts_validator) (void *parsed_options, relopt_value *vals, int nvals); + +typedef struct relopt_string +{ + relopt_gen gen; + int default_len; + bool default_isnull; + validate_string_relopt validate_cb; + fill_string_relopt fill_cb; + char *default_val; +} relopt_string; + +/* This is the table datatype for build_reloptions() */ +typedef struct +{ + const char *optname; /* option's name */ + relopt_type opttype; /* option's datatype */ + int offset; /* offset of field in result struct */ + + /* + * isset_offset is an optional offset of a field in the result struct that + * stores whether the option is explicitly set for the relation or if it + * just picked up the default value. In most cases, this can be + * accomplished by giving the reloption a special out-of-range default + * value (e.g., some integer reloptions use -2), but this isn't always + * possible. For example, a Boolean reloption cannot be given an + * out-of-range default, so we need another way to discover the source of + * its value. This offset is only used if given a value greater than + * zero. + */ + int isset_offset; +} relopt_parse_elt; + +/* Local reloption definition */ +typedef struct local_relopt +{ + relopt_gen *option; /* option definition */ + int offset; /* offset of parsed value in bytea structure */ +} local_relopt; ++======= + typedef void (*relopts_validator) (void *parsed_options, relopt_value *vals, + int nvals); ++>>>>>>> theirs /* Structure to hold local reloption data for build_local_reloptions() */ typedef struct local_relopts @@@ -232,17 -75,8 +117,15 @@@ extern void add_local_string_reloption( validate_string_relopt validator, fill_string_relopt filler, int offset); ++<<<<<<< ours +extern Datum transformRelOptions(Datum oldOptions, List *defList, + const char *nameSpace, const char *const validnsps[], + bool acceptOidsOff, bool isReset); +extern List *untransformRelOptions(Datum options); ++======= ++>>>>>>> theirs extern bytea *extractRelOptions(HeapTuple tuple, TupleDesc tupdesc, - amoptions_function amoptions); - extern void *build_reloptions(Datum reloptions, bool validate, - relopt_kind kind, - Size relopt_struct_size, - const relopt_parse_elt *relopt_elems, - int num_relopt_elems); + amreloptspecset_function amoptions_def_set); extern void *build_local_reloptions(local_relopts *relopts, Datum options, bool validate);