2006-07-04 00:45:41 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* reloptions.c
|
|
|
|
* Core support for relation options (pg_class.reloptions)
|
|
|
|
*
|
2023-01-02 21:00:37 +01:00
|
|
|
* Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
|
2006-07-04 00:45:41 +02:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/access/common/reloptions.c
|
2006-07-04 00:45:41 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "postgres.h"
|
|
|
|
|
2017-02-23 21:57:08 +01:00
|
|
|
#include <float.h>
|
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
#include "access/gist_private.h"
|
|
|
|
#include "access/hash.h"
|
2019-07-08 17:58:05 +02:00
|
|
|
#include "access/heaptoast.h"
|
2012-08-30 22:15:44 +02:00
|
|
|
#include "access/htup_details.h"
|
2009-01-05 18:14:28 +01:00
|
|
|
#include "access/nbtree.h"
|
2006-07-04 00:45:41 +02:00
|
|
|
#include "access/reloptions.h"
|
2019-11-25 01:40:53 +01:00
|
|
|
#include "access/spgist_private.h"
|
2006-07-04 00:45:41 +02:00
|
|
|
#include "catalog/pg_type.h"
|
|
|
|
#include "commands/defrem.h"
|
2010-01-05 22:54:00 +01:00
|
|
|
#include "commands/tablespace.h"
|
2013-07-18 23:10:16 +02:00
|
|
|
#include "commands/view.h"
|
2007-12-02 00:44:44 +01:00
|
|
|
#include "nodes/makefuncs.h"
|
2016-04-08 17:14:56 +02:00
|
|
|
#include "postmaster/postmaster.h"
|
2011-09-04 07:13:16 +02:00
|
|
|
#include "utils/array.h"
|
2010-01-22 17:40:19 +01:00
|
|
|
#include "utils/attoptcache.h"
|
2006-07-04 00:45:41 +02:00
|
|
|
#include "utils/builtins.h"
|
2011-09-04 07:13:16 +02:00
|
|
|
#include "utils/guc.h"
|
2009-01-05 18:14:28 +01:00
|
|
|
#include "utils/memutils.h"
|
2006-07-04 00:45:41 +02:00
|
|
|
#include "utils/rel.h"
|
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
/*
|
|
|
|
* Contents of pg_class.reloptions
|
|
|
|
*
|
|
|
|
* To add an option:
|
|
|
|
*
|
2009-01-12 22:02:15 +01:00
|
|
|
* (i) decide on a type (integer, real, bool, string), name, default value,
|
|
|
|
* upper and lower bounds (if applicable); for strings, consider a validation
|
|
|
|
* routine.
|
|
|
|
* (ii) add a record below (or use add_<type>_reloption).
|
|
|
|
* (iii) add it to the appropriate options struct (perhaps StdRdOptions)
|
|
|
|
* (iv) add it to the appropriate handling routine (perhaps
|
2009-01-05 18:14:28 +01:00
|
|
|
* default_reloptions)
|
2017-03-06 11:34:31 +01:00
|
|
|
* (v) make sure the lock level is set correctly for that operation
|
|
|
|
* (vi) don't forget to document the option
|
2009-01-05 18:14:28 +01:00
|
|
|
*
|
2017-03-06 11:34:31 +01:00
|
|
|
* The default choice for any new option should be AccessExclusiveLock.
|
|
|
|
* In some cases the lock level can be reduced from there, but the lock
|
|
|
|
* level chosen should always conflict with itself to ensure that multiple
|
|
|
|
* changes aren't lost when we attempt concurrent changes.
|
|
|
|
* The choice of lock level depends completely upon how that parameter
|
|
|
|
* is used within the server, not upon how and when you'd like to change it.
|
|
|
|
* Safety first. Existing choices are documented here, and elsewhere in
|
|
|
|
* backend code where the parameters are used.
|
|
|
|
*
|
|
|
|
* In general, anything that affects the results obtained from a SELECT must be
|
|
|
|
* protected by AccessExclusiveLock.
|
|
|
|
*
|
|
|
|
* Autovacuum related parameters can be set at ShareUpdateExclusiveLock
|
|
|
|
* since they are only used by the AV procs and don't change anything
|
|
|
|
* currently executing.
|
|
|
|
*
|
|
|
|
* Fillfactor can be set because it applies only to subsequent changes made to
|
2019-07-22 03:01:50 +02:00
|
|
|
* data blocks, as documented in hio.c
|
2017-03-06 11:34:31 +01:00
|
|
|
*
|
|
|
|
* n_distinct options can be set at ShareUpdateExclusiveLock because they
|
|
|
|
* are only used during ANALYZE, which uses a ShareUpdateExclusiveLock,
|
|
|
|
* so the ANALYZE will not be affected by in-flight changes. Changing those
|
2019-04-12 05:56:38 +02:00
|
|
|
* values has no effect until the next ANALYZE, so no need for stronger lock.
|
2017-03-06 11:34:31 +01:00
|
|
|
*
|
|
|
|
* Planner-related parameters can be set with ShareUpdateExclusiveLock because
|
|
|
|
* they only affect planning and not the correctness of the execution. Plans
|
|
|
|
* cannot be changed in mid-flight, so changes here could not easily result in
|
|
|
|
* new improved plans in any case. So we allow existing queries to continue
|
|
|
|
* and existing plans to survive, a small price to pay for allowing better
|
|
|
|
* plans to be introduced concurrently without interfering with users.
|
|
|
|
*
|
|
|
|
* Setting parallel_workers is safe, since it acts the same as
|
|
|
|
* max_parallel_workers_per_gather which is a USERSET parameter that doesn't
|
|
|
|
* affect existing plans or queries.
|
2019-04-08 09:43:57 +02:00
|
|
|
*
|
|
|
|
* vacuum_truncate can be set at ShareUpdateExclusiveLock because it
|
|
|
|
* is only used during VACUUM, which uses a ShareUpdateExclusiveLock,
|
|
|
|
* so the VACUUM will not be affected by in-flight changes. Changing its
|
2019-04-12 05:56:38 +02:00
|
|
|
* value has no effect until the next VACUUM, so no need for stronger lock.
|
2009-01-05 18:14:28 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
static relopt_bool boolRelOpts[] =
|
|
|
|
{
|
BRIN auto-summarization
Previously, only VACUUM would cause a page range to get initially
summarized by BRIN indexes, which for some use cases takes too much time
since the inserts occur. To avoid the delay, have brininsert request a
summarization run for the previous range as soon as the first tuple is
inserted into the first page of the next range. Autovacuum is in charge
of processing these requests, after doing all the regular vacuuming/
analyzing work on tables.
This doesn't impose any new tasks on autovacuum, because autovacuum was
already in charge of doing summarizations. The only actual effect is to
change the timing, i.e. that it occurs earlier. For this reason, we
don't go any great lengths to record these requests very robustly; if
they are lost because of a server crash or restart, they will happen at
a later time anyway.
Most of the new code here is in autovacuum, which can now be told about
"work items" to process. This can be used for other things such as GIN
pending list cleaning, perhaps visibility map bit setting, both of which
are currently invoked during vacuum, but do not really depend on vacuum
taking place.
The requests are at the page range level, a granularity for which we did
not have SQL-level access; we only had index-level summarization
requests via brin_summarize_new_values(). It seems reasonable to add
SQL-level access to range-level summarization too, so add a function
brin_summarize_range() to do that.
Authors: Álvaro Herrera, based on sketch from Simon Riggs.
Reviewed-by: Thomas Munro.
Discussion: https://postgr.es/m/20170301045823.vneqdqkmsd4as4ds@alvherre.pgsql
2017-04-01 19:00:53 +02:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"autosummarize",
|
|
|
|
"Enables automatic summarization on this BRIN index",
|
|
|
|
RELOPT_KIND_BRIN,
|
|
|
|
AccessExclusiveLock
|
|
|
|
},
|
|
|
|
false
|
|
|
|
},
|
2009-02-09 21:57:59 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"autovacuum_enabled",
|
|
|
|
"Enables autovacuum in this relation",
|
2021-08-16 23:27:52 +02:00
|
|
|
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
2015-08-14 15:19:28 +02:00
|
|
|
ShareUpdateExclusiveLock
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
|
|
|
true
|
|
|
|
},
|
2013-12-11 01:17:34 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"user_catalog_table",
|
|
|
|
"Declare a table as an additional catalog table, e.g. for the purpose of logical replication",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_HEAP,
|
|
|
|
AccessExclusiveLock
|
2013-12-11 01:17:34 +01:00
|
|
|
},
|
|
|
|
false
|
|
|
|
},
|
2009-03-24 21:17:18 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"fastupdate",
|
|
|
|
"Enables \"fast update\" feature for this GIN index",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_GIN,
|
|
|
|
AccessExclusiveLock
|
2009-03-24 21:17:18 +01:00
|
|
|
},
|
|
|
|
true
|
|
|
|
},
|
2011-12-22 22:15:57 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"security_barrier",
|
|
|
|
"View acts as a row security barrier",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_VIEW,
|
|
|
|
AccessExclusiveLock
|
2011-12-22 22:15:57 +01:00
|
|
|
},
|
|
|
|
false
|
|
|
|
},
|
2022-03-22 11:28:10 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"security_invoker",
|
|
|
|
"Privileges on underlying relations are checked as the invoking user, not the view owner",
|
|
|
|
RELOPT_KIND_VIEW,
|
|
|
|
AccessExclusiveLock
|
|
|
|
},
|
|
|
|
false
|
|
|
|
},
|
2019-04-08 09:43:57 +02:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"vacuum_truncate",
|
|
|
|
"Enables vacuum to truncate empty pages at the end of this table",
|
|
|
|
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
|
|
|
ShareUpdateExclusiveLock
|
|
|
|
},
|
|
|
|
true
|
|
|
|
},
|
Add deduplication to nbtree.
Deduplication reduces the storage overhead of duplicates in indexes that
use the standard nbtree index access method. The deduplication process
is applied lazily, after the point where opportunistic deletion of
LP_DEAD-marked index tuples occurs. Deduplication is only applied at
the point where a leaf page split would otherwise be required. New
posting list tuples are formed by merging together existing duplicate
tuples. The physical representation of the items on an nbtree leaf page
is made more space efficient by deduplication, but the logical contents
of the page are not changed. Even unique indexes make use of
deduplication as a way of controlling bloat from duplicates whose TIDs
point to different versions of the same logical table row.
The lazy approach taken by nbtree has significant advantages over a GIN
style eager approach. Most individual inserts of index tuples have
exactly the same overhead as before. The extra overhead of
deduplication is amortized across insertions, just like the overhead of
page splits. The key space of indexes works in the same way as it has
since commit dd299df8 (the commit that made heap TID a tiebreaker
column).
Testing has shown that nbtree deduplication can generally make indexes
with about 10 or 15 tuples for each distinct key value about 2.5X - 4X
smaller, even with single column integer indexes (e.g., an index on a
referencing column that accompanies a foreign key). The final size of
single column nbtree indexes comes close to the final size of a similar
contrib/btree_gin index, at least in cases where GIN's posting list
compression isn't very effective. This can significantly improve
transaction throughput, and significantly reduce the cost of vacuuming
indexes.
A new index storage parameter (deduplicate_items) controls the use of
deduplication. The default setting is 'on', so all new B-Tree indexes
automatically use deduplication where possible. This decision will be
reviewed at the end of the Postgres 13 beta period.
There is a regression of approximately 2% of transaction throughput with
synthetic workloads that consist of append-only inserts into a table
with several non-unique indexes, where all indexes have few or no
repeated values. The underlying issue is that cycles are wasted on
unsuccessful attempts at deduplicating items in non-unique indexes.
There doesn't seem to be a way around it short of disabling
deduplication entirely. Note that deduplication of items in unique
indexes is fairly well targeted in general, which avoids the problem
there (we can use a special heuristic to trigger deduplication passes in
unique indexes, since we're specifically targeting "version bloat").
Bump XLOG_PAGE_MAGIC because xl_btree_vacuum changed.
No bump in BTREE_VERSION, since the representation of posting list
tuples works in a way that's backwards compatible with version 4 indexes
(i.e. indexes built on PostgreSQL 12). However, users must still
REINDEX a pg_upgrade'd index to use deduplication, regardless of the
Postgres version they've upgraded from. This is the only way to set the
new nbtree metapage flag indicating that deduplication is generally
safe.
Author: Anastasia Lubennikova, Peter Geoghegan
Reviewed-By: Peter Geoghegan, Heikki Linnakangas
Discussion:
https://postgr.es/m/55E4051B.7020209@postgrespro.ru
https://postgr.es/m/4ab6e2db-bcee-f4cf-0916-3a06e6ccbb55@postgrespro.ru
2020-02-26 22:05:30 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"deduplicate_items",
|
|
|
|
"Enables \"deduplicate items\" feature for this btree index",
|
|
|
|
RELOPT_KIND_BTREE,
|
|
|
|
ShareUpdateExclusiveLock /* since it applies only to later
|
|
|
|
* inserts */
|
|
|
|
},
|
|
|
|
true
|
|
|
|
},
|
2009-01-05 18:14:28 +01:00
|
|
|
/* list terminator */
|
|
|
|
{{NULL}}
|
|
|
|
};
|
|
|
|
|
|
|
|
static relopt_int intRelOpts[] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"fillfactor",
|
|
|
|
"Packs table pages only to this percentage",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_HEAP,
|
2016-03-10 13:07:33 +01:00
|
|
|
ShareUpdateExclusiveLock /* since it applies only to later
|
|
|
|
* inserts */
|
2009-01-05 18:14:28 +01:00
|
|
|
},
|
2014-08-28 22:10:47 +02:00
|
|
|
HEAP_DEFAULT_FILLFACTOR, HEAP_MIN_FILLFACTOR, 100
|
2009-01-05 18:14:28 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"fillfactor",
|
|
|
|
"Packs btree index pages only to this percentage",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_BTREE,
|
2016-03-10 13:07:33 +01:00
|
|
|
ShareUpdateExclusiveLock /* since it applies only to later
|
|
|
|
* inserts */
|
2009-01-05 18:14:28 +01:00
|
|
|
},
|
2014-08-28 22:10:47 +02:00
|
|
|
BTREE_DEFAULT_FILLFACTOR, BTREE_MIN_FILLFACTOR, 100
|
2009-01-05 18:14:28 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"fillfactor",
|
|
|
|
"Packs hash index pages only to this percentage",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_HASH,
|
2016-03-10 13:07:33 +01:00
|
|
|
ShareUpdateExclusiveLock /* since it applies only to later
|
|
|
|
* inserts */
|
2009-01-05 18:14:28 +01:00
|
|
|
},
|
2014-08-28 22:10:47 +02:00
|
|
|
HASH_DEFAULT_FILLFACTOR, HASH_MIN_FILLFACTOR, 100
|
2009-01-05 18:14:28 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"fillfactor",
|
|
|
|
"Packs gist index pages only to this percentage",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_GIST,
|
2016-03-10 13:07:33 +01:00
|
|
|
ShareUpdateExclusiveLock /* since it applies only to later
|
|
|
|
* inserts */
|
2009-01-05 18:14:28 +01:00
|
|
|
},
|
2014-08-28 22:10:47 +02:00
|
|
|
GIST_DEFAULT_FILLFACTOR, GIST_MIN_FILLFACTOR, 100
|
2009-01-05 18:14:28 +01:00
|
|
|
},
|
2011-12-17 22:41:16 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"fillfactor",
|
|
|
|
"Packs spgist index pages only to this percentage",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_SPGIST,
|
2016-03-10 13:07:33 +01:00
|
|
|
ShareUpdateExclusiveLock /* since it applies only to later
|
|
|
|
* inserts */
|
2011-12-17 22:41:16 +01:00
|
|
|
},
|
2014-08-28 22:10:47 +02:00
|
|
|
SPGIST_DEFAULT_FILLFACTOR, SPGIST_MIN_FILLFACTOR, 100
|
2011-12-17 22:41:16 +01:00
|
|
|
},
|
2009-02-09 21:57:59 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"autovacuum_vacuum_threshold",
|
|
|
|
"Minimum number of tuple updates or deletes prior to vacuum",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
|
|
|
ShareUpdateExclusiveLock
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
2014-08-28 22:10:47 +02:00
|
|
|
-1, 0, INT_MAX
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
Trigger autovacuum based on number of INSERTs
Traditionally autovacuum has only ever invoked a worker based on the
estimated number of dead tuples in a table and for anti-wraparound
purposes. For the latter, with certain classes of tables such as
insert-only tables, anti-wraparound vacuums could be the first vacuum that
the table ever receives. This could often lead to autovacuum workers being
busy for extended periods of time due to having to potentially freeze
every page in the table. This could be particularly bad for very large
tables. New clusters, or recently pg_restored clusters could suffer even
more as many large tables may have the same relfrozenxid, which could
result in large numbers of tables requiring an anti-wraparound vacuum all
at once.
Here we aim to reduce the work required by anti-wraparound and aggressive
vacuums in general, by triggering autovacuum when the table has received
enough INSERTs. This is controlled by adding two new GUCs and reloptions;
autovacuum_vacuum_insert_threshold and
autovacuum_vacuum_insert_scale_factor. These work exactly the same as the
existing scale factor and threshold controls, only base themselves off the
number of inserts since the last vacuum, rather than the number of dead
tuples. New controls were added rather than reusing the existing
controls, to allow these new vacuums to be tuned independently and perhaps
even completely disabled altogether, which can be done by setting
autovacuum_vacuum_insert_threshold to -1.
We make no attempt to skip index cleanup operations on these vacuums as
they may trigger for an insert-mostly table which continually doesn't have
enough dead tuples to trigger an autovacuum for the purpose of removing
those dead tuples. If we were to skip cleaning the indexes in this case,
then it is possible for the index(es) to become bloated over time.
There are additional benefits to triggering autovacuums based on inserts,
as tables which never contain enough dead tuples to trigger an autovacuum
are now more likely to receive a vacuum, which can mark more of the table
as "allvisible" and encourage the query planner to make use of Index Only
Scans.
Currently, we still obey vacuum_freeze_min_age when triggering these new
autovacuums based on INSERTs. For large insert-only tables, it may be
beneficial to lower the table's autovacuum_freeze_min_age so that tuples
are eligible to be frozen sooner. Here we've opted not to zero that for
these types of vacuums, since the table may just be insert-mostly and we
may otherwise freeze tuples that are still destined to be updated or
removed in the near future.
There was some debate to what exactly the new scale factor and threshold
should default to. For now, these are set to 0.2 and 1000, respectively.
There may be some motivation to adjust these before the release.
Author: Laurenz Albe, Darafei Praliaskouski
Reviewed-by: Alvaro Herrera, Masahiko Sawada, Chris Travers, Andres Freund, Justin Pryzby
Discussion: https://postgr.es/m/CAC8Q8t%2Bj36G_bLF%3D%2B0iMo6jGNWnLnWb1tujXuJr-%2Bx8ZCCTqoQ%40mail.gmail.com
2020-03-28 07:20:12 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"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
|
|
|
|
},
|
2009-02-09 21:57:59 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"autovacuum_analyze_threshold",
|
|
|
|
"Minimum number of tuple inserts, updates or deletes prior to analyze",
|
2021-08-16 23:27:52 +02:00
|
|
|
RELOPT_KIND_HEAP,
|
2015-08-14 15:19:28 +02:00
|
|
|
ShareUpdateExclusiveLock
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
2014-08-28 22:10:47 +02:00
|
|
|
-1, 0, INT_MAX
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"autovacuum_vacuum_cost_limit",
|
|
|
|
"Vacuum cost amount available before napping, for autovacuum",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
|
|
|
ShareUpdateExclusiveLock
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
2014-08-28 22:10:47 +02:00
|
|
|
-1, 1, 10000
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"autovacuum_freeze_min_age",
|
|
|
|
"Minimum age at which VACUUM should freeze a table row, for autovacuum",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
|
|
|
ShareUpdateExclusiveLock
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
2014-08-28 22:10:47 +02:00
|
|
|
-1, 0, 1000000000
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
Separate multixact freezing parameters from xid's
Previously we were piggybacking on transaction ID parameters to freeze
multixacts; but since there isn't necessarily any relationship between
rates of Xid and multixact consumption, this turns out not to be a good
idea.
Therefore, we now have multixact-specific freezing parameters:
vacuum_multixact_freeze_min_age: when to remove multis as we come across
them in vacuum (default to 5 million, i.e. early in comparison to Xid's
default of 50 million)
vacuum_multixact_freeze_table_age: when to force whole-table scans
instead of scanning only the pages marked as not all visible in
visibility map (default to 150 million, same as for Xids). Whichever of
both which reaches the 150 million mark earlier will cause a whole-table
scan.
autovacuum_multixact_freeze_max_age: when for cause emergency,
uninterruptible whole-table scans (default to 400 million, double as
that for Xids). This means there shouldn't be more frequent emergency
vacuuming than previously, unless multixacts are being used very
rapidly.
Backpatch to 9.3 where multixacts were made to persist enough to require
freezing. To avoid an ABI break in 9.3, VacuumStmt has a couple of
fields in an unnatural place, and StdRdOptions is split in two so that
the newly added fields can go at the end.
Patch by me, reviewed by Robert Haas, with additional input from Andres
Freund and Tom Lane.
2014-02-13 23:30:30 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"autovacuum_multixact_freeze_min_age",
|
|
|
|
"Minimum multixact age at which VACUUM should freeze a row multixact's, for autovacuum",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
|
|
|
ShareUpdateExclusiveLock
|
Separate multixact freezing parameters from xid's
Previously we were piggybacking on transaction ID parameters to freeze
multixacts; but since there isn't necessarily any relationship between
rates of Xid and multixact consumption, this turns out not to be a good
idea.
Therefore, we now have multixact-specific freezing parameters:
vacuum_multixact_freeze_min_age: when to remove multis as we come across
them in vacuum (default to 5 million, i.e. early in comparison to Xid's
default of 50 million)
vacuum_multixact_freeze_table_age: when to force whole-table scans
instead of scanning only the pages marked as not all visible in
visibility map (default to 150 million, same as for Xids). Whichever of
both which reaches the 150 million mark earlier will cause a whole-table
scan.
autovacuum_multixact_freeze_max_age: when for cause emergency,
uninterruptible whole-table scans (default to 400 million, double as
that for Xids). This means there shouldn't be more frequent emergency
vacuuming than previously, unless multixacts are being used very
rapidly.
Backpatch to 9.3 where multixacts were made to persist enough to require
freezing. To avoid an ABI break in 9.3, VacuumStmt has a couple of
fields in an unnatural place, and StdRdOptions is split in two so that
the newly added fields can go at the end.
Patch by me, reviewed by Robert Haas, with additional input from Andres
Freund and Tom Lane.
2014-02-13 23:30:30 +01:00
|
|
|
},
|
2014-08-28 22:10:47 +02:00
|
|
|
-1, 0, 1000000000
|
Separate multixact freezing parameters from xid's
Previously we were piggybacking on transaction ID parameters to freeze
multixacts; but since there isn't necessarily any relationship between
rates of Xid and multixact consumption, this turns out not to be a good
idea.
Therefore, we now have multixact-specific freezing parameters:
vacuum_multixact_freeze_min_age: when to remove multis as we come across
them in vacuum (default to 5 million, i.e. early in comparison to Xid's
default of 50 million)
vacuum_multixact_freeze_table_age: when to force whole-table scans
instead of scanning only the pages marked as not all visible in
visibility map (default to 150 million, same as for Xids). Whichever of
both which reaches the 150 million mark earlier will cause a whole-table
scan.
autovacuum_multixact_freeze_max_age: when for cause emergency,
uninterruptible whole-table scans (default to 400 million, double as
that for Xids). This means there shouldn't be more frequent emergency
vacuuming than previously, unless multixacts are being used very
rapidly.
Backpatch to 9.3 where multixacts were made to persist enough to require
freezing. To avoid an ABI break in 9.3, VacuumStmt has a couple of
fields in an unnatural place, and StdRdOptions is split in two so that
the newly added fields can go at the end.
Patch by me, reviewed by Robert Haas, with additional input from Andres
Freund and Tom Lane.
2014-02-13 23:30:30 +01:00
|
|
|
},
|
2009-02-09 21:57:59 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"autovacuum_freeze_max_age",
|
|
|
|
"Age at which to autovacuum a table to prevent transaction ID wraparound",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
|
|
|
ShareUpdateExclusiveLock
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
2015-10-05 11:53:43 +02:00
|
|
|
-1, 100000, 2000000000
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
Separate multixact freezing parameters from xid's
Previously we were piggybacking on transaction ID parameters to freeze
multixacts; but since there isn't necessarily any relationship between
rates of Xid and multixact consumption, this turns out not to be a good
idea.
Therefore, we now have multixact-specific freezing parameters:
vacuum_multixact_freeze_min_age: when to remove multis as we come across
them in vacuum (default to 5 million, i.e. early in comparison to Xid's
default of 50 million)
vacuum_multixact_freeze_table_age: when to force whole-table scans
instead of scanning only the pages marked as not all visible in
visibility map (default to 150 million, same as for Xids). Whichever of
both which reaches the 150 million mark earlier will cause a whole-table
scan.
autovacuum_multixact_freeze_max_age: when for cause emergency,
uninterruptible whole-table scans (default to 400 million, double as
that for Xids). This means there shouldn't be more frequent emergency
vacuuming than previously, unless multixacts are being used very
rapidly.
Backpatch to 9.3 where multixacts were made to persist enough to require
freezing. To avoid an ABI break in 9.3, VacuumStmt has a couple of
fields in an unnatural place, and StdRdOptions is split in two so that
the newly added fields can go at the end.
Patch by me, reviewed by Robert Haas, with additional input from Andres
Freund and Tom Lane.
2014-02-13 23:30:30 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"autovacuum_multixact_freeze_max_age",
|
|
|
|
"Multixact age at which to autovacuum a table to prevent multixact wraparound",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
|
|
|
ShareUpdateExclusiveLock
|
Separate multixact freezing parameters from xid's
Previously we were piggybacking on transaction ID parameters to freeze
multixacts; but since there isn't necessarily any relationship between
rates of Xid and multixact consumption, this turns out not to be a good
idea.
Therefore, we now have multixact-specific freezing parameters:
vacuum_multixact_freeze_min_age: when to remove multis as we come across
them in vacuum (default to 5 million, i.e. early in comparison to Xid's
default of 50 million)
vacuum_multixact_freeze_table_age: when to force whole-table scans
instead of scanning only the pages marked as not all visible in
visibility map (default to 150 million, same as for Xids). Whichever of
both which reaches the 150 million mark earlier will cause a whole-table
scan.
autovacuum_multixact_freeze_max_age: when for cause emergency,
uninterruptible whole-table scans (default to 400 million, double as
that for Xids). This means there shouldn't be more frequent emergency
vacuuming than previously, unless multixacts are being used very
rapidly.
Backpatch to 9.3 where multixacts were made to persist enough to require
freezing. To avoid an ABI break in 9.3, VacuumStmt has a couple of
fields in an unnatural place, and StdRdOptions is split in two so that
the newly added fields can go at the end.
Patch by me, reviewed by Robert Haas, with additional input from Andres
Freund and Tom Lane.
2014-02-13 23:30:30 +01:00
|
|
|
},
|
2015-10-05 11:53:43 +02:00
|
|
|
-1, 10000, 2000000000
|
Separate multixact freezing parameters from xid's
Previously we were piggybacking on transaction ID parameters to freeze
multixacts; but since there isn't necessarily any relationship between
rates of Xid and multixact consumption, this turns out not to be a good
idea.
Therefore, we now have multixact-specific freezing parameters:
vacuum_multixact_freeze_min_age: when to remove multis as we come across
them in vacuum (default to 5 million, i.e. early in comparison to Xid's
default of 50 million)
vacuum_multixact_freeze_table_age: when to force whole-table scans
instead of scanning only the pages marked as not all visible in
visibility map (default to 150 million, same as for Xids). Whichever of
both which reaches the 150 million mark earlier will cause a whole-table
scan.
autovacuum_multixact_freeze_max_age: when for cause emergency,
uninterruptible whole-table scans (default to 400 million, double as
that for Xids). This means there shouldn't be more frequent emergency
vacuuming than previously, unless multixacts are being used very
rapidly.
Backpatch to 9.3 where multixacts were made to persist enough to require
freezing. To avoid an ABI break in 9.3, VacuumStmt has a couple of
fields in an unnatural place, and StdRdOptions is split in two so that
the newly added fields can go at the end.
Patch by me, reviewed by Robert Haas, with additional input from Andres
Freund and Tom Lane.
2014-02-13 23:30:30 +01:00
|
|
|
},
|
2009-02-09 21:57:59 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"autovacuum_freeze_table_age",
|
2013-12-24 02:32:29 +01:00
|
|
|
"Age at which VACUUM should perform a full table sweep to freeze row versions",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
|
|
|
ShareUpdateExclusiveLock
|
2014-08-28 22:10:47 +02:00
|
|
|
}, -1, 0, 2000000000
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
Separate multixact freezing parameters from xid's
Previously we were piggybacking on transaction ID parameters to freeze
multixacts; but since there isn't necessarily any relationship between
rates of Xid and multixact consumption, this turns out not to be a good
idea.
Therefore, we now have multixact-specific freezing parameters:
vacuum_multixact_freeze_min_age: when to remove multis as we come across
them in vacuum (default to 5 million, i.e. early in comparison to Xid's
default of 50 million)
vacuum_multixact_freeze_table_age: when to force whole-table scans
instead of scanning only the pages marked as not all visible in
visibility map (default to 150 million, same as for Xids). Whichever of
both which reaches the 150 million mark earlier will cause a whole-table
scan.
autovacuum_multixact_freeze_max_age: when for cause emergency,
uninterruptible whole-table scans (default to 400 million, double as
that for Xids). This means there shouldn't be more frequent emergency
vacuuming than previously, unless multixacts are being used very
rapidly.
Backpatch to 9.3 where multixacts were made to persist enough to require
freezing. To avoid an ABI break in 9.3, VacuumStmt has a couple of
fields in an unnatural place, and StdRdOptions is split in two so that
the newly added fields can go at the end.
Patch by me, reviewed by Robert Haas, with additional input from Andres
Freund and Tom Lane.
2014-02-13 23:30:30 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"autovacuum_multixact_freeze_table_age",
|
|
|
|
"Age of multixact at which VACUUM should perform a full table sweep to freeze row versions",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
|
|
|
ShareUpdateExclusiveLock
|
2014-08-28 22:10:47 +02:00
|
|
|
}, -1, 0, 2000000000
|
Separate multixact freezing parameters from xid's
Previously we were piggybacking on transaction ID parameters to freeze
multixacts; but since there isn't necessarily any relationship between
rates of Xid and multixact consumption, this turns out not to be a good
idea.
Therefore, we now have multixact-specific freezing parameters:
vacuum_multixact_freeze_min_age: when to remove multis as we come across
them in vacuum (default to 5 million, i.e. early in comparison to Xid's
default of 50 million)
vacuum_multixact_freeze_table_age: when to force whole-table scans
instead of scanning only the pages marked as not all visible in
visibility map (default to 150 million, same as for Xids). Whichever of
both which reaches the 150 million mark earlier will cause a whole-table
scan.
autovacuum_multixact_freeze_max_age: when for cause emergency,
uninterruptible whole-table scans (default to 400 million, double as
that for Xids). This means there shouldn't be more frequent emergency
vacuuming than previously, unless multixacts are being used very
rapidly.
Backpatch to 9.3 where multixacts were made to persist enough to require
freezing. To avoid an ABI break in 9.3, VacuumStmt has a couple of
fields in an unnatural place, and StdRdOptions is split in two so that
the newly added fields can go at the end.
Patch by me, reviewed by Robert Haas, with additional input from Andres
Freund and Tom Lane.
2014-02-13 23:30:30 +01:00
|
|
|
},
|
2015-04-03 16:55:50 +02:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"log_autovacuum_min_duration",
|
|
|
|
"Sets the minimum execution time above which autovacuum actions will be logged",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
|
|
|
ShareUpdateExclusiveLock
|
2015-04-03 16:55:50 +02:00
|
|
|
},
|
|
|
|
-1, -1, INT_MAX
|
|
|
|
},
|
2017-11-19 23:50:10 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"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
|
|
|
|
},
|
BRIN: Block Range Indexes
BRIN is a new index access method intended to accelerate scans of very
large tables, without the maintenance overhead of btrees or other
traditional indexes. They work by maintaining "summary" data about
block ranges. Bitmap index scans work by reading each summary tuple and
comparing them with the query quals; all pages in the range are returned
in a lossy TID bitmap if the quals are consistent with the values in the
summary tuple, otherwise not. Normal index scans are not supported
because these indexes do not store TIDs.
As new tuples are added into the index, the summary information is
updated (if the block range in which the tuple is added is already
summarized) or not; in the latter case, a subsequent pass of VACUUM or
the brin_summarize_new_values() function will create the summary
information.
For data types with natural 1-D sort orders, the summary info consists
of the maximum and the minimum values of each indexed column within each
page range. This type of operator class we call "Minmax", and we
supply a bunch of them for most data types with B-tree opclasses.
Since the BRIN code is generalized, other approaches are possible for
things such as arrays, geometric types, ranges, etc; even for things
such as enum types we could do something different than minmax with
better results. In this commit I only include minmax.
Catalog version bumped due to new builtin catalog entries.
There's more that could be done here, but this is a good step forwards.
Loosely based on ideas from Simon Riggs; code mostly by Álvaro Herrera,
with contribution by Heikki Linnakangas.
Patch reviewed by: Amit Kapila, Heikki Linnakangas, Robert Haas.
Testing help from Jeff Janes, Erik Rijkers, Emanuel Calvo.
PS:
The research leading to these results has received funding from the
European Union's Seventh Framework Programme (FP7/2007-2013) under
grant agreement n° 318633.
2014-11-07 20:38:14 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"pages_per_range",
|
|
|
|
"Number of pages that each page range covers in a BRIN index",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_BRIN,
|
|
|
|
AccessExclusiveLock
|
BRIN: Block Range Indexes
BRIN is a new index access method intended to accelerate scans of very
large tables, without the maintenance overhead of btrees or other
traditional indexes. They work by maintaining "summary" data about
block ranges. Bitmap index scans work by reading each summary tuple and
comparing them with the query quals; all pages in the range are returned
in a lossy TID bitmap if the quals are consistent with the values in the
summary tuple, otherwise not. Normal index scans are not supported
because these indexes do not store TIDs.
As new tuples are added into the index, the summary information is
updated (if the block range in which the tuple is added is already
summarized) or not; in the latter case, a subsequent pass of VACUUM or
the brin_summarize_new_values() function will create the summary
information.
For data types with natural 1-D sort orders, the summary info consists
of the maximum and the minimum values of each indexed column within each
page range. This type of operator class we call "Minmax", and we
supply a bunch of them for most data types with B-tree opclasses.
Since the BRIN code is generalized, other approaches are possible for
things such as arrays, geometric types, ranges, etc; even for things
such as enum types we could do something different than minmax with
better results. In this commit I only include minmax.
Catalog version bumped due to new builtin catalog entries.
There's more that could be done here, but this is a good step forwards.
Loosely based on ideas from Simon Riggs; code mostly by Álvaro Herrera,
with contribution by Heikki Linnakangas.
Patch reviewed by: Amit Kapila, Heikki Linnakangas, Robert Haas.
Testing help from Jeff Janes, Erik Rijkers, Emanuel Calvo.
PS:
The research leading to these results has received funding from the
European Union's Seventh Framework Programme (FP7/2007-2013) under
grant agreement n° 318633.
2014-11-07 20:38:14 +01:00
|
|
|
}, 128, 1, 131072
|
|
|
|
},
|
2014-11-11 13:08:21 +01:00
|
|
|
{
|
|
|
|
{
|
2014-11-13 04:14:48 +01:00
|
|
|
"gin_pending_list_limit",
|
2014-11-11 13:08:21 +01:00
|
|
|
"Maximum size of the pending list for this GIN index, in kilobytes.",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_GIN,
|
|
|
|
AccessExclusiveLock
|
2014-11-11 13:08:21 +01:00
|
|
|
},
|
|
|
|
-1, 64, MAX_KILOBYTES
|
|
|
|
},
|
2015-09-08 17:51:42 +02:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"effective_io_concurrency",
|
|
|
|
"Number of simultaneous requests that can be handled efficiently by the disk subsystem.",
|
|
|
|
RELOPT_KIND_TABLESPACE,
|
2017-03-06 11:34:31 +01:00
|
|
|
ShareUpdateExclusiveLock
|
2015-09-08 17:51:42 +02:00
|
|
|
},
|
|
|
|
#ifdef USE_PREFETCH
|
|
|
|
-1, 0, MAX_IO_CONCURRENCY
|
|
|
|
#else
|
|
|
|
0, 0, 0
|
2020-03-16 00:31:34 +01:00
|
|
|
#endif
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"maintenance_io_concurrency",
|
|
|
|
"Number of simultaneous requests that can be handled efficiently by the disk subsystem for maintenance work.",
|
|
|
|
RELOPT_KIND_TABLESPACE,
|
|
|
|
ShareUpdateExclusiveLock
|
|
|
|
},
|
|
|
|
#ifdef USE_PREFETCH
|
|
|
|
-1, 0, MAX_IO_CONCURRENCY
|
|
|
|
#else
|
|
|
|
0, 0, 0
|
2015-09-08 17:51:42 +02:00
|
|
|
#endif
|
|
|
|
},
|
2016-04-08 17:14:56 +02:00
|
|
|
{
|
|
|
|
{
|
2016-06-09 15:08:27 +02:00
|
|
|
"parallel_workers",
|
2016-04-08 17:14:56 +02:00
|
|
|
"Number of parallel processes that can be used per executor node for this relation.",
|
|
|
|
RELOPT_KIND_HEAP,
|
2017-03-06 11:34:31 +01:00
|
|
|
ShareUpdateExclusiveLock
|
2016-04-08 17:14:56 +02:00
|
|
|
},
|
2016-05-06 20:43:34 +02:00
|
|
|
-1, 0, 1024
|
2016-04-08 17:14:56 +02:00
|
|
|
},
|
Separate multixact freezing parameters from xid's
Previously we were piggybacking on transaction ID parameters to freeze
multixacts; but since there isn't necessarily any relationship between
rates of Xid and multixact consumption, this turns out not to be a good
idea.
Therefore, we now have multixact-specific freezing parameters:
vacuum_multixact_freeze_min_age: when to remove multis as we come across
them in vacuum (default to 5 million, i.e. early in comparison to Xid's
default of 50 million)
vacuum_multixact_freeze_table_age: when to force whole-table scans
instead of scanning only the pages marked as not all visible in
visibility map (default to 150 million, same as for Xids). Whichever of
both which reaches the 150 million mark earlier will cause a whole-table
scan.
autovacuum_multixact_freeze_max_age: when for cause emergency,
uninterruptible whole-table scans (default to 400 million, double as
that for Xids). This means there shouldn't be more frequent emergency
vacuuming than previously, unless multixacts are being used very
rapidly.
Backpatch to 9.3 where multixacts were made to persist enough to require
freezing. To avoid an ABI break in 9.3, VacuumStmt has a couple of
fields in an unnatural place, and StdRdOptions is split in two so that
the newly added fields can go at the end.
Patch by me, reviewed by Robert Haas, with additional input from Andres
Freund and Tom Lane.
2014-02-13 23:30:30 +01:00
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
/* list terminator */
|
|
|
|
{{NULL}}
|
|
|
|
};
|
|
|
|
|
|
|
|
static relopt_real realRelOpts[] =
|
|
|
|
{
|
2019-03-26 18:32:30 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"autovacuum_vacuum_cost_delay",
|
|
|
|
"Vacuum cost delay in milliseconds, for autovacuum",
|
|
|
|
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
|
|
|
ShareUpdateExclusiveLock
|
|
|
|
},
|
|
|
|
-1, 0.0, 100.0
|
|
|
|
},
|
2009-02-09 21:57:59 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"autovacuum_vacuum_scale_factor",
|
|
|
|
"Number of tuple updates or deletes prior to vacuum as a fraction of reltuples",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
|
|
|
ShareUpdateExclusiveLock
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
2009-08-27 19:18:44 +02:00
|
|
|
-1, 0.0, 100.0
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
Trigger autovacuum based on number of INSERTs
Traditionally autovacuum has only ever invoked a worker based on the
estimated number of dead tuples in a table and for anti-wraparound
purposes. For the latter, with certain classes of tables such as
insert-only tables, anti-wraparound vacuums could be the first vacuum that
the table ever receives. This could often lead to autovacuum workers being
busy for extended periods of time due to having to potentially freeze
every page in the table. This could be particularly bad for very large
tables. New clusters, or recently pg_restored clusters could suffer even
more as many large tables may have the same relfrozenxid, which could
result in large numbers of tables requiring an anti-wraparound vacuum all
at once.
Here we aim to reduce the work required by anti-wraparound and aggressive
vacuums in general, by triggering autovacuum when the table has received
enough INSERTs. This is controlled by adding two new GUCs and reloptions;
autovacuum_vacuum_insert_threshold and
autovacuum_vacuum_insert_scale_factor. These work exactly the same as the
existing scale factor and threshold controls, only base themselves off the
number of inserts since the last vacuum, rather than the number of dead
tuples. New controls were added rather than reusing the existing
controls, to allow these new vacuums to be tuned independently and perhaps
even completely disabled altogether, which can be done by setting
autovacuum_vacuum_insert_threshold to -1.
We make no attempt to skip index cleanup operations on these vacuums as
they may trigger for an insert-mostly table which continually doesn't have
enough dead tuples to trigger an autovacuum for the purpose of removing
those dead tuples. If we were to skip cleaning the indexes in this case,
then it is possible for the index(es) to become bloated over time.
There are additional benefits to triggering autovacuums based on inserts,
as tables which never contain enough dead tuples to trigger an autovacuum
are now more likely to receive a vacuum, which can mark more of the table
as "allvisible" and encourage the query planner to make use of Index Only
Scans.
Currently, we still obey vacuum_freeze_min_age when triggering these new
autovacuums based on INSERTs. For large insert-only tables, it may be
beneficial to lower the table's autovacuum_freeze_min_age so that tuples
are eligible to be frozen sooner. Here we've opted not to zero that for
these types of vacuums, since the table may just be insert-mostly and we
may otherwise freeze tuples that are still destined to be updated or
removed in the near future.
There was some debate to what exactly the new scale factor and threshold
should default to. For now, these are set to 0.2 and 1000, respectively.
There may be some motivation to adjust these before the release.
Author: Laurenz Albe, Darafei Praliaskouski
Reviewed-by: Alvaro Herrera, Masahiko Sawada, Chris Travers, Andres Freund, Justin Pryzby
Discussion: https://postgr.es/m/CAC8Q8t%2Bj36G_bLF%3D%2B0iMo6jGNWnLnWb1tujXuJr-%2Bx8ZCCTqoQ%40mail.gmail.com
2020-03-28 07:20:12 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"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
|
|
|
|
},
|
2009-02-09 21:57:59 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"autovacuum_analyze_scale_factor",
|
|
|
|
"Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples",
|
2021-08-16 23:27:52 +02:00
|
|
|
RELOPT_KIND_HEAP,
|
2015-08-14 15:19:28 +02:00
|
|
|
ShareUpdateExclusiveLock
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
2009-08-27 19:18:44 +02:00
|
|
|
-1, 0.0, 100.0
|
2009-02-09 21:57:59 +01:00
|
|
|
},
|
2010-01-05 22:54:00 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"seq_page_cost",
|
|
|
|
"Sets the planner's estimate of the cost of a sequentially fetched disk page.",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_TABLESPACE,
|
2017-03-06 11:34:31 +01:00
|
|
|
ShareUpdateExclusiveLock
|
2010-01-05 22:54:00 +01:00
|
|
|
},
|
|
|
|
-1, 0.0, DBL_MAX
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"random_page_cost",
|
|
|
|
"Sets the planner's estimate of the cost of a nonsequentially fetched disk page.",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_TABLESPACE,
|
2017-03-06 11:34:31 +01:00
|
|
|
ShareUpdateExclusiveLock
|
2010-01-05 22:54:00 +01:00
|
|
|
},
|
|
|
|
-1, 0.0, DBL_MAX
|
|
|
|
},
|
2010-01-22 17:40:19 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"n_distinct",
|
|
|
|
"Sets the planner's estimate of the number of distinct values appearing in a column (excluding child relations).",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_ATTRIBUTE,
|
2017-03-06 11:34:31 +01:00
|
|
|
ShareUpdateExclusiveLock
|
2010-01-22 17:40:19 +01:00
|
|
|
},
|
|
|
|
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).",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_ATTRIBUTE,
|
2017-03-06 11:34:31 +01:00
|
|
|
ShareUpdateExclusiveLock
|
2010-01-22 17:40:19 +01:00
|
|
|
},
|
|
|
|
0, -1.0, DBL_MAX
|
|
|
|
},
|
2021-03-11 21:42:46 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"vacuum_cleanup_index_scale_factor",
|
|
|
|
"Deprecated B-Tree parameter.",
|
|
|
|
RELOPT_KIND_BTREE,
|
|
|
|
ShareUpdateExclusiveLock
|
|
|
|
},
|
|
|
|
-1, 0.0, 1e10
|
|
|
|
},
|
2009-01-05 18:14:28 +01:00
|
|
|
/* list terminator */
|
|
|
|
{{NULL}}
|
|
|
|
};
|
|
|
|
|
2021-06-19 05:04:07 +02:00
|
|
|
/* values from StdRdOptIndexCleanup */
|
2022-05-12 18:19:04 +02:00
|
|
|
static relopt_enum_elt_def StdRdOptIndexCleanupValues[] =
|
2021-06-19 05:04:07 +02:00
|
|
|
{
|
|
|
|
{"auto", STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO},
|
|
|
|
{"on", STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON},
|
|
|
|
{"off", STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF},
|
|
|
|
{"true", STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON},
|
|
|
|
{"false", STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF},
|
|
|
|
{"yes", STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON},
|
|
|
|
{"no", STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF},
|
|
|
|
{"1", STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON},
|
|
|
|
{"0", STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF},
|
|
|
|
{(const char *) NULL} /* list terminator */
|
|
|
|
};
|
|
|
|
|
2019-09-25 20:56:52 +02:00
|
|
|
/* values from GistOptBufferingMode */
|
2022-05-12 18:19:04 +02:00
|
|
|
static relopt_enum_elt_def gistBufferingOptValues[] =
|
2019-09-25 20:56:52 +02:00
|
|
|
{
|
|
|
|
{"auto", GIST_OPTION_BUFFERING_AUTO},
|
|
|
|
{"on", GIST_OPTION_BUFFERING_ON},
|
|
|
|
{"off", GIST_OPTION_BUFFERING_OFF},
|
|
|
|
{(const char *) NULL} /* list terminator */
|
|
|
|
};
|
|
|
|
|
|
|
|
/* values from ViewOptCheckOption */
|
2022-05-12 18:19:04 +02:00
|
|
|
static relopt_enum_elt_def viewCheckOptValues[] =
|
2019-09-25 20:56:52 +02:00
|
|
|
{
|
|
|
|
/* no value for NOT_SET */
|
|
|
|
{"local", VIEW_OPTION_CHECK_OPTION_LOCAL},
|
|
|
|
{"cascaded", VIEW_OPTION_CHECK_OPTION_CASCADED},
|
|
|
|
{(const char *) NULL} /* list terminator */
|
|
|
|
};
|
|
|
|
|
|
|
|
static relopt_enum enumRelOpts[] =
|
2009-01-05 18:14:28 +01:00
|
|
|
{
|
2021-06-19 05:04:07 +02:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"vacuum_index_cleanup",
|
|
|
|
"Controls index vacuuming and index cleanup",
|
|
|
|
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
|
|
|
ShareUpdateExclusiveLock
|
|
|
|
},
|
|
|
|
StdRdOptIndexCleanupValues,
|
|
|
|
STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO,
|
|
|
|
gettext_noop("Valid values are \"on\", \"off\", and \"auto\".")
|
|
|
|
},
|
2011-09-08 16:51:23 +02:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"buffering",
|
|
|
|
"Enables buffering build for this GiST index",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_GIST,
|
|
|
|
AccessExclusiveLock
|
2011-09-08 16:51:23 +02:00
|
|
|
},
|
2019-09-25 20:56:52 +02:00
|
|
|
gistBufferingOptValues,
|
|
|
|
GIST_OPTION_BUFFERING_AUTO,
|
|
|
|
gettext_noop("Valid values are \"on\", \"off\", and \"auto\".")
|
2011-09-08 16:51:23 +02:00
|
|
|
},
|
2013-07-18 23:10:16 +02:00
|
|
|
{
|
|
|
|
{
|
|
|
|
"check_option",
|
|
|
|
"View has WITH CHECK OPTION defined (local or cascaded).",
|
2015-08-14 15:19:28 +02:00
|
|
|
RELOPT_KIND_VIEW,
|
|
|
|
AccessExclusiveLock
|
2013-07-18 23:10:16 +02:00
|
|
|
},
|
2019-09-25 20:56:52 +02:00
|
|
|
viewCheckOptValues,
|
|
|
|
VIEW_OPTION_CHECK_OPTION_NOT_SET,
|
|
|
|
gettext_noop("Valid values are \"local\" and \"cascaded\".")
|
2013-07-18 23:10:16 +02:00
|
|
|
},
|
2009-01-05 18:14:28 +01:00
|
|
|
/* list terminator */
|
|
|
|
{{NULL}}
|
|
|
|
};
|
|
|
|
|
2019-09-25 20:56:52 +02:00
|
|
|
static relopt_string stringRelOpts[] =
|
|
|
|
{
|
|
|
|
/* list terminator */
|
|
|
|
{{NULL}}
|
|
|
|
};
|
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
static relopt_gen **relOpts = NULL;
|
2009-05-25 00:22:44 +02:00
|
|
|
static bits32 last_assigned_kind = RELOPT_KIND_LAST_DEFAULT;
|
2009-01-05 18:14:28 +01:00
|
|
|
|
|
|
|
static int num_custom_options = 0;
|
|
|
|
static relopt_gen **custom_options = NULL;
|
|
|
|
static bool need_initialization = true;
|
|
|
|
|
|
|
|
static void initialize_reloptions(void);
|
|
|
|
static void parse_one_reloption(relopt_value *option, char *text_str,
|
|
|
|
int text_len, bool validate);
|
|
|
|
|
2019-11-14 05:59:59 +01:00
|
|
|
/*
|
|
|
|
* Get the length of a string reloption (either default or the user-defined
|
|
|
|
* value). This is used for allocation purposes when building a set of
|
|
|
|
* relation options.
|
|
|
|
*/
|
|
|
|
#define GET_STRING_RELOPTION_LEN(option) \
|
|
|
|
((option).isset ? strlen((option).values.string_val) : \
|
|
|
|
((relopt_string *) (option).gen)->default_len)
|
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
/*
|
|
|
|
* initialize_reloptions
|
|
|
|
* initialization routine, must be called before parsing
|
|
|
|
*
|
|
|
|
* Initialize the relOpts array and fill each variable's type and name length.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
initialize_reloptions(void)
|
|
|
|
{
|
|
|
|
int i;
|
2010-03-11 22:47:19 +01:00
|
|
|
int j;
|
2009-01-05 18:14:28 +01:00
|
|
|
|
2010-03-11 22:47:19 +01:00
|
|
|
j = 0;
|
2009-01-05 18:14:28 +01:00
|
|
|
for (i = 0; boolRelOpts[i].gen.name; i++)
|
2015-08-14 15:19:28 +02:00
|
|
|
{
|
|
|
|
Assert(DoLockModesConflict(boolRelOpts[i].gen.lockmode,
|
|
|
|
boolRelOpts[i].gen.lockmode));
|
2009-01-05 18:14:28 +01:00
|
|
|
j++;
|
2015-08-14 15:19:28 +02:00
|
|
|
}
|
2009-01-05 18:14:28 +01:00
|
|
|
for (i = 0; intRelOpts[i].gen.name; i++)
|
2015-08-14 15:19:28 +02:00
|
|
|
{
|
|
|
|
Assert(DoLockModesConflict(intRelOpts[i].gen.lockmode,
|
|
|
|
intRelOpts[i].gen.lockmode));
|
2009-01-05 18:14:28 +01:00
|
|
|
j++;
|
2015-08-14 15:19:28 +02:00
|
|
|
}
|
2009-01-05 18:14:28 +01:00
|
|
|
for (i = 0; realRelOpts[i].gen.name; i++)
|
2015-08-14 15:19:28 +02:00
|
|
|
{
|
|
|
|
Assert(DoLockModesConflict(realRelOpts[i].gen.lockmode,
|
|
|
|
realRelOpts[i].gen.lockmode));
|
2009-01-05 18:14:28 +01:00
|
|
|
j++;
|
2015-08-14 15:19:28 +02:00
|
|
|
}
|
2019-09-25 20:56:52 +02:00
|
|
|
for (i = 0; enumRelOpts[i].gen.name; i++)
|
|
|
|
{
|
|
|
|
Assert(DoLockModesConflict(enumRelOpts[i].gen.lockmode,
|
|
|
|
enumRelOpts[i].gen.lockmode));
|
|
|
|
j++;
|
|
|
|
}
|
2009-01-05 18:14:28 +01:00
|
|
|
for (i = 0; stringRelOpts[i].gen.name; i++)
|
2015-08-14 15:19:28 +02:00
|
|
|
{
|
|
|
|
Assert(DoLockModesConflict(stringRelOpts[i].gen.lockmode,
|
|
|
|
stringRelOpts[i].gen.lockmode));
|
2009-01-05 18:14:28 +01:00
|
|
|
j++;
|
2015-08-14 15:19:28 +02:00
|
|
|
}
|
2009-01-05 18:14:28 +01:00
|
|
|
j += num_custom_options;
|
|
|
|
|
|
|
|
if (relOpts)
|
|
|
|
pfree(relOpts);
|
|
|
|
relOpts = MemoryContextAlloc(TopMemoryContext,
|
|
|
|
(j + 1) * sizeof(relopt_gen *));
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
for (i = 0; boolRelOpts[i].gen.name; i++)
|
|
|
|
{
|
|
|
|
relOpts[j] = &boolRelOpts[i].gen;
|
|
|
|
relOpts[j]->type = RELOPT_TYPE_BOOL;
|
|
|
|
relOpts[j]->namelen = strlen(relOpts[j]->name);
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; intRelOpts[i].gen.name; i++)
|
|
|
|
{
|
|
|
|
relOpts[j] = &intRelOpts[i].gen;
|
|
|
|
relOpts[j]->type = RELOPT_TYPE_INT;
|
|
|
|
relOpts[j]->namelen = strlen(relOpts[j]->name);
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; realRelOpts[i].gen.name; i++)
|
|
|
|
{
|
|
|
|
relOpts[j] = &realRelOpts[i].gen;
|
|
|
|
relOpts[j]->type = RELOPT_TYPE_REAL;
|
|
|
|
relOpts[j]->namelen = strlen(relOpts[j]->name);
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
2019-09-25 20:56:52 +02:00
|
|
|
for (i = 0; enumRelOpts[i].gen.name; i++)
|
|
|
|
{
|
|
|
|
relOpts[j] = &enumRelOpts[i].gen;
|
|
|
|
relOpts[j]->type = RELOPT_TYPE_ENUM;
|
|
|
|
relOpts[j]->namelen = strlen(relOpts[j]->name);
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
for (i = 0; stringRelOpts[i].gen.name; i++)
|
|
|
|
{
|
|
|
|
relOpts[j] = &stringRelOpts[i].gen;
|
|
|
|
relOpts[j]->type = RELOPT_TYPE_STRING;
|
|
|
|
relOpts[j]->namelen = strlen(relOpts[j]->name);
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < num_custom_options; i++)
|
|
|
|
{
|
|
|
|
relOpts[j] = custom_options[i];
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add a list terminator */
|
|
|
|
relOpts[j] = NULL;
|
2010-03-11 22:47:19 +01:00
|
|
|
|
|
|
|
/* flag the work is complete */
|
|
|
|
need_initialization = false;
|
2009-01-05 18:14:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* add_reloption_kind
|
|
|
|
* Create a new relopt_kind value, to be used in custom reloptions by
|
|
|
|
* user-defined AMs.
|
|
|
|
*/
|
2009-04-04 02:45:02 +02:00
|
|
|
relopt_kind
|
2009-01-05 18:14:28 +01:00
|
|
|
add_reloption_kind(void)
|
|
|
|
{
|
2009-05-25 00:22:44 +02:00
|
|
|
/* don't hand out the last bit so that the enum's behavior is portable */
|
2009-01-05 18:14:28 +01:00
|
|
|
if (last_assigned_kind >= RELOPT_KIND_MAX)
|
|
|
|
ereport(ERROR,
|
2009-04-04 02:45:02 +02:00
|
|
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
|
|
|
errmsg("user-defined relation parameter types limit exceeded")));
|
|
|
|
last_assigned_kind <<= 1;
|
2009-05-25 00:22:44 +02:00
|
|
|
return (relopt_kind) last_assigned_kind;
|
2009-01-05 18:14:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* add_reloption
|
|
|
|
* Add an already-created custom reloption to the list, and recompute the
|
|
|
|
* main parser table.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
add_reloption(relopt_gen *newoption)
|
|
|
|
{
|
|
|
|
static int max_custom_options = 0;
|
|
|
|
|
|
|
|
if (num_custom_options >= max_custom_options)
|
|
|
|
{
|
|
|
|
MemoryContext oldcxt;
|
|
|
|
|
|
|
|
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
|
|
|
|
|
|
|
|
if (max_custom_options == 0)
|
|
|
|
{
|
|
|
|
max_custom_options = 8;
|
|
|
|
custom_options = palloc(max_custom_options * sizeof(relopt_gen *));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
max_custom_options *= 2;
|
|
|
|
custom_options = repalloc(custom_options,
|
|
|
|
max_custom_options * sizeof(relopt_gen *));
|
|
|
|
}
|
|
|
|
MemoryContextSwitchTo(oldcxt);
|
|
|
|
}
|
|
|
|
custom_options[num_custom_options++] = newoption;
|
|
|
|
|
|
|
|
need_initialization = true;
|
|
|
|
}
|
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
/*
|
|
|
|
* init_local_reloptions
|
|
|
|
* Initialize local reloptions that will parsed into bytea structure of
|
|
|
|
* 'relopt_struct_size'.
|
|
|
|
*/
|
|
|
|
void
|
2022-09-20 04:18:36 +02:00
|
|
|
init_local_reloptions(local_relopts *relopts, Size relopt_struct_size)
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
{
|
2022-09-20 04:18:36 +02:00
|
|
|
relopts->options = NIL;
|
|
|
|
relopts->validators = NIL;
|
|
|
|
relopts->relopt_struct_size = relopt_struct_size;
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* register_reloptions_validator
|
|
|
|
* Register custom validation callback that will be called at the end of
|
|
|
|
* build_local_reloptions().
|
|
|
|
*/
|
|
|
|
void
|
2022-09-20 04:18:36 +02:00
|
|
|
register_reloptions_validator(local_relopts *relopts, relopts_validator validator)
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
{
|
2022-09-20 04:18:36 +02:00
|
|
|
relopts->validators = lappend(relopts->validators, validator);
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* add_local_reloption
|
|
|
|
* Add an already-created custom reloption to the local list.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
add_local_reloption(local_relopts *relopts, relopt_gen *newoption, int offset)
|
|
|
|
{
|
|
|
|
local_relopt *opt = palloc(sizeof(*opt));
|
|
|
|
|
|
|
|
Assert(offset < relopts->relopt_struct_size);
|
|
|
|
|
|
|
|
opt->option = newoption;
|
|
|
|
opt->offset = offset;
|
|
|
|
|
|
|
|
relopts->options = lappend(relopts->options, opt);
|
|
|
|
}
|
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
/*
|
|
|
|
* allocate_reloption
|
|
|
|
* Allocate a new reloption and initialize the type-agnostic fields
|
|
|
|
* (for types other than string)
|
|
|
|
*/
|
|
|
|
static relopt_gen *
|
2019-09-25 03:13:52 +02:00
|
|
|
allocate_reloption(bits32 kinds, int type, const char *name, const char *desc,
|
|
|
|
LOCKMODE lockmode)
|
2009-01-05 18:14:28 +01:00
|
|
|
{
|
|
|
|
MemoryContext oldcxt;
|
|
|
|
size_t size;
|
|
|
|
relopt_gen *newoption;
|
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
if (kinds != RELOPT_KIND_LOCAL)
|
|
|
|
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
|
|
|
|
else
|
|
|
|
oldcxt = NULL;
|
2009-01-05 18:14:28 +01:00
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case RELOPT_TYPE_BOOL:
|
|
|
|
size = sizeof(relopt_bool);
|
|
|
|
break;
|
|
|
|
case RELOPT_TYPE_INT:
|
|
|
|
size = sizeof(relopt_int);
|
|
|
|
break;
|
|
|
|
case RELOPT_TYPE_REAL:
|
|
|
|
size = sizeof(relopt_real);
|
|
|
|
break;
|
2019-09-25 20:56:52 +02:00
|
|
|
case RELOPT_TYPE_ENUM:
|
|
|
|
size = sizeof(relopt_enum);
|
|
|
|
break;
|
2011-08-09 14:25:44 +02:00
|
|
|
case RELOPT_TYPE_STRING:
|
|
|
|
size = sizeof(relopt_string);
|
|
|
|
break;
|
2009-01-05 18:14:28 +01:00
|
|
|
default:
|
2015-08-03 05:49:19 +02:00
|
|
|
elog(ERROR, "unsupported reloption type %d", type);
|
2009-01-05 18:14:28 +01:00
|
|
|
return NULL; /* keep compiler quiet */
|
|
|
|
}
|
|
|
|
|
|
|
|
newoption = palloc(size);
|
|
|
|
|
|
|
|
newoption->name = pstrdup(name);
|
|
|
|
if (desc)
|
|
|
|
newoption->desc = pstrdup(desc);
|
|
|
|
else
|
|
|
|
newoption->desc = NULL;
|
2009-04-04 02:45:02 +02:00
|
|
|
newoption->kinds = kinds;
|
2009-01-05 18:14:28 +01:00
|
|
|
newoption->namelen = strlen(name);
|
|
|
|
newoption->type = type;
|
2019-09-25 03:13:52 +02:00
|
|
|
newoption->lockmode = lockmode;
|
2019-09-25 03:07:23 +02:00
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
if (oldcxt != NULL)
|
|
|
|
MemoryContextSwitchTo(oldcxt);
|
2009-01-05 18:14:28 +01:00
|
|
|
|
|
|
|
return newoption;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
* init_bool_reloption
|
|
|
|
* Allocate and initialize a new boolean reloption
|
2009-01-05 18:14:28 +01:00
|
|
|
*/
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
static relopt_bool *
|
|
|
|
init_bool_reloption(bits32 kinds, const char *name, const char *desc,
|
|
|
|
bool default_val, LOCKMODE lockmode)
|
2009-01-05 18:14:28 +01:00
|
|
|
{
|
|
|
|
relopt_bool *newoption;
|
|
|
|
|
2009-04-04 02:45:02 +02:00
|
|
|
newoption = (relopt_bool *) allocate_reloption(kinds, RELOPT_TYPE_BOOL,
|
2019-09-25 03:13:52 +02:00
|
|
|
name, desc, lockmode);
|
2009-01-05 18:14:28 +01:00
|
|
|
newoption->default_val = default_val;
|
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
return newoption;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* add_bool_reloption
|
|
|
|
* Add a new boolean reloption
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
add_bool_reloption(bits32 kinds, const char *name, const char *desc,
|
|
|
|
bool default_val, LOCKMODE lockmode)
|
|
|
|
{
|
|
|
|
relopt_bool *newoption = init_bool_reloption(kinds, name, desc,
|
|
|
|
default_val, lockmode);
|
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
add_reloption((relopt_gen *) newoption);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
* add_local_bool_reloption
|
|
|
|
* Add a new boolean local reloption
|
|
|
|
*
|
|
|
|
* 'offset' is offset of bool-typed field.
|
2009-01-05 18:14:28 +01:00
|
|
|
*/
|
|
|
|
void
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
add_local_bool_reloption(local_relopts *relopts, const char *name,
|
|
|
|
const char *desc, bool default_val, int offset)
|
|
|
|
{
|
|
|
|
relopt_bool *newoption = init_bool_reloption(RELOPT_KIND_LOCAL,
|
|
|
|
name, desc,
|
|
|
|
default_val, 0);
|
|
|
|
|
|
|
|
add_local_reloption(relopts, (relopt_gen *) newoption, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* init_real_reloption
|
|
|
|
* Allocate and initialize a new integer reloption
|
|
|
|
*/
|
|
|
|
static relopt_int *
|
|
|
|
init_int_reloption(bits32 kinds, const char *name, const char *desc,
|
|
|
|
int default_val, int min_val, int max_val,
|
|
|
|
LOCKMODE lockmode)
|
2009-01-05 18:14:28 +01:00
|
|
|
{
|
|
|
|
relopt_int *newoption;
|
|
|
|
|
2009-04-04 02:45:02 +02:00
|
|
|
newoption = (relopt_int *) allocate_reloption(kinds, RELOPT_TYPE_INT,
|
2019-09-25 03:13:52 +02:00
|
|
|
name, desc, lockmode);
|
2009-01-05 18:14:28 +01:00
|
|
|
newoption->default_val = default_val;
|
|
|
|
newoption->min = min_val;
|
|
|
|
newoption->max = max_val;
|
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
return newoption;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* add_int_reloption
|
|
|
|
* Add a new integer reloption
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
add_int_reloption(bits32 kinds, const char *name, const char *desc, int default_val,
|
|
|
|
int min_val, int max_val, LOCKMODE lockmode)
|
|
|
|
{
|
|
|
|
relopt_int *newoption = init_int_reloption(kinds, name, desc,
|
|
|
|
default_val, min_val,
|
|
|
|
max_val, lockmode);
|
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
add_reloption((relopt_gen *) newoption);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
* add_local_int_reloption
|
|
|
|
* Add a new local integer reloption
|
|
|
|
*
|
|
|
|
* 'offset' is offset of int-typed field.
|
2009-01-05 18:14:28 +01:00
|
|
|
*/
|
|
|
|
void
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
add_local_int_reloption(local_relopts *relopts, const char *name,
|
|
|
|
const char *desc, int default_val, int min_val,
|
|
|
|
int max_val, int offset)
|
|
|
|
{
|
|
|
|
relopt_int *newoption = init_int_reloption(RELOPT_KIND_LOCAL,
|
|
|
|
name, desc, default_val,
|
|
|
|
min_val, max_val, 0);
|
|
|
|
|
|
|
|
add_local_reloption(relopts, (relopt_gen *) newoption, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* init_real_reloption
|
|
|
|
* Allocate and initialize a new real reloption
|
|
|
|
*/
|
|
|
|
static relopt_real *
|
|
|
|
init_real_reloption(bits32 kinds, const char *name, const char *desc,
|
|
|
|
double default_val, double min_val, double max_val,
|
|
|
|
LOCKMODE lockmode)
|
2009-01-05 18:14:28 +01:00
|
|
|
{
|
|
|
|
relopt_real *newoption;
|
|
|
|
|
2009-04-04 02:45:02 +02:00
|
|
|
newoption = (relopt_real *) allocate_reloption(kinds, RELOPT_TYPE_REAL,
|
2019-09-25 03:13:52 +02:00
|
|
|
name, desc, lockmode);
|
2009-01-05 18:14:28 +01:00
|
|
|
newoption->default_val = default_val;
|
|
|
|
newoption->min = min_val;
|
|
|
|
newoption->max = max_val;
|
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
return newoption;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* add_real_reloption
|
|
|
|
* Add a new float reloption
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
add_real_reloption(bits32 kinds, const char *name, const char *desc,
|
|
|
|
double default_val, double min_val, double max_val,
|
|
|
|
LOCKMODE lockmode)
|
|
|
|
{
|
|
|
|
relopt_real *newoption = init_real_reloption(kinds, name, desc,
|
|
|
|
default_val, min_val,
|
|
|
|
max_val, lockmode);
|
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
add_reloption((relopt_gen *) newoption);
|
|
|
|
}
|
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
/*
|
|
|
|
* add_local_real_reloption
|
|
|
|
* Add a new local float reloption
|
|
|
|
*
|
|
|
|
* 'offset' is offset of double-typed field.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
add_local_real_reloption(local_relopts *relopts, const char *name,
|
|
|
|
const char *desc, double default_val,
|
|
|
|
double min_val, double max_val, int offset)
|
|
|
|
{
|
|
|
|
relopt_real *newoption = init_real_reloption(RELOPT_KIND_LOCAL,
|
|
|
|
name, desc,
|
|
|
|
default_val, min_val,
|
|
|
|
max_val, 0);
|
|
|
|
|
|
|
|
add_local_reloption(relopts, (relopt_gen *) newoption, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* init_enum_reloption
|
|
|
|
* Allocate and initialize a new enum reloption
|
|
|
|
*/
|
|
|
|
static relopt_enum *
|
|
|
|
init_enum_reloption(bits32 kinds, const char *name, const char *desc,
|
|
|
|
relopt_enum_elt_def *members, int default_val,
|
|
|
|
const char *detailmsg, LOCKMODE lockmode)
|
|
|
|
{
|
|
|
|
relopt_enum *newoption;
|
|
|
|
|
|
|
|
newoption = (relopt_enum *) allocate_reloption(kinds, RELOPT_TYPE_ENUM,
|
|
|
|
name, desc, lockmode);
|
|
|
|
newoption->members = members;
|
|
|
|
newoption->default_val = default_val;
|
|
|
|
newoption->detailmsg = detailmsg;
|
|
|
|
|
|
|
|
return newoption;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-25 20:56:52 +02:00
|
|
|
/*
|
|
|
|
* add_enum_reloption
|
|
|
|
* Add a new enum reloption
|
|
|
|
*
|
|
|
|
* The members array must have a terminating NULL entry.
|
|
|
|
*
|
|
|
|
* The detailmsg is shown when unsupported values are passed, and has this
|
|
|
|
* form: "Valid values are \"foo\", \"bar\", and \"bar\"."
|
|
|
|
*
|
|
|
|
* The members array and detailmsg are not copied -- caller must ensure that
|
|
|
|
* they are valid throughout the life of the process.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
add_enum_reloption(bits32 kinds, const char *name, const char *desc,
|
|
|
|
relopt_enum_elt_def *members, int default_val,
|
|
|
|
const char *detailmsg, LOCKMODE lockmode)
|
|
|
|
{
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
relopt_enum *newoption = init_enum_reloption(kinds, name, desc,
|
|
|
|
members, default_val,
|
|
|
|
detailmsg, lockmode);
|
2019-09-25 20:56:52 +02:00
|
|
|
|
|
|
|
add_reloption((relopt_gen *) newoption);
|
|
|
|
}
|
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
/*
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
* add_local_enum_reloption
|
|
|
|
* Add a new local enum reloption
|
2009-01-08 20:34:41 +01:00
|
|
|
*
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
* 'offset' is offset of int-typed field.
|
2009-01-05 18:14:28 +01:00
|
|
|
*/
|
|
|
|
void
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
add_local_enum_reloption(local_relopts *relopts, const char *name,
|
|
|
|
const char *desc, relopt_enum_elt_def *members,
|
|
|
|
int default_val, const char *detailmsg, int offset)
|
|
|
|
{
|
|
|
|
relopt_enum *newoption = init_enum_reloption(RELOPT_KIND_LOCAL,
|
|
|
|
name, desc,
|
|
|
|
members, default_val,
|
|
|
|
detailmsg, 0);
|
|
|
|
|
|
|
|
add_local_reloption(relopts, (relopt_gen *) newoption, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* init_string_reloption
|
|
|
|
* Allocate and initialize a new string reloption
|
|
|
|
*/
|
|
|
|
static relopt_string *
|
|
|
|
init_string_reloption(bits32 kinds, const char *name, const char *desc,
|
|
|
|
const char *default_val,
|
|
|
|
validate_string_relopt validator,
|
|
|
|
fill_string_relopt filler,
|
|
|
|
LOCKMODE lockmode)
|
2009-01-05 18:14:28 +01:00
|
|
|
{
|
|
|
|
relopt_string *newoption;
|
|
|
|
|
2011-08-09 14:25:44 +02:00
|
|
|
/* make sure the validator/default combination is sane */
|
|
|
|
if (validator)
|
|
|
|
(validator) (default_val);
|
2009-01-05 18:14:28 +01:00
|
|
|
|
2011-08-09 14:25:44 +02:00
|
|
|
newoption = (relopt_string *) allocate_reloption(kinds, RELOPT_TYPE_STRING,
|
2019-09-25 03:13:52 +02:00
|
|
|
name, desc, lockmode);
|
2009-01-08 20:34:41 +01:00
|
|
|
newoption->validate_cb = validator;
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
newoption->fill_cb = filler;
|
2009-01-05 18:14:28 +01:00
|
|
|
if (default_val)
|
|
|
|
{
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
if (kinds == RELOPT_KIND_LOCAL)
|
|
|
|
newoption->default_val = strdup(default_val);
|
|
|
|
else
|
|
|
|
newoption->default_val = MemoryContextStrdup(TopMemoryContext, default_val);
|
2011-08-09 14:25:44 +02:00
|
|
|
newoption->default_len = strlen(default_val);
|
2009-01-05 18:14:28 +01:00
|
|
|
newoption->default_isnull = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-08-09 14:25:44 +02:00
|
|
|
newoption->default_val = "";
|
2009-01-05 18:14:28 +01:00
|
|
|
newoption->default_len = 0;
|
|
|
|
newoption->default_isnull = true;
|
|
|
|
}
|
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
return newoption;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* add_string_reloption
|
|
|
|
* Add a new string reloption
|
|
|
|
*
|
|
|
|
* "validator" is an optional function pointer that can be used to test the
|
|
|
|
* validity of the values. It must elog(ERROR) when the argument string is
|
|
|
|
* not acceptable for the variable. Note that the default value must pass
|
|
|
|
* the validation.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
add_string_reloption(bits32 kinds, const char *name, const char *desc,
|
|
|
|
const char *default_val, validate_string_relopt validator,
|
|
|
|
LOCKMODE lockmode)
|
|
|
|
{
|
|
|
|
relopt_string *newoption = init_string_reloption(kinds, name, desc,
|
|
|
|
default_val,
|
|
|
|
validator, NULL,
|
|
|
|
lockmode);
|
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
add_reloption((relopt_gen *) newoption);
|
|
|
|
}
|
2006-07-04 00:45:41 +02:00
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
/*
|
|
|
|
* add_local_string_reloption
|
|
|
|
* Add a new local string reloption
|
|
|
|
*
|
|
|
|
* 'offset' is offset of int-typed field that will store offset of string value
|
|
|
|
* in the resulting bytea structure.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
add_local_string_reloption(local_relopts *relopts, const char *name,
|
|
|
|
const char *desc, const char *default_val,
|
|
|
|
validate_string_relopt validator,
|
|
|
|
fill_string_relopt filler, int offset)
|
|
|
|
{
|
|
|
|
relopt_string *newoption = init_string_reloption(RELOPT_KIND_LOCAL,
|
|
|
|
name, desc,
|
|
|
|
default_val,
|
|
|
|
validator, filler,
|
|
|
|
0);
|
|
|
|
|
|
|
|
add_local_reloption(relopts, (relopt_gen *) newoption, offset);
|
|
|
|
}
|
|
|
|
|
2006-07-04 00:45:41 +02:00
|
|
|
/*
|
2009-04-04 23:12:31 +02:00
|
|
|
* Transform a relation options list (list of DefElem) into the text array
|
2009-02-02 20:31:40 +01:00
|
|
|
* 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.
|
2006-07-04 00:45:41 +02:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
Remove WITH OIDS support, change oid catalog column visibility.
Previously tables declared WITH OIDS, including a significant fraction
of the catalog tables, stored the oid column not as a normal column,
but as part of the tuple header.
This special column was not shown by default, which was somewhat odd,
as it's often (consider e.g. pg_class.oid) one of the more important
parts of a row. Neither pg_dump nor COPY included the contents of the
oid column by default.
The fact that the oid column was not an ordinary column necessitated a
significant amount of special case code to support oid columns. That
already was painful for the existing, but upcoming work aiming to make
table storage pluggable, would have required expanding and duplicating
that "specialness" significantly.
WITH OIDS has been deprecated since 2005 (commit ff02d0a05280e0).
Remove it.
Removing includes:
- CREATE TABLE and ALTER TABLE syntax for declaring the table to be
WITH OIDS has been removed (WITH (oids[ = true]) will error out)
- pg_dump does not support dumping tables declared WITH OIDS and will
issue a warning when dumping one (and ignore the oid column).
- restoring an pg_dump archive with pg_restore will warn when
restoring a table with oid contents (and ignore the oid column)
- COPY will refuse to load binary dump that includes oids.
- pg_upgrade will error out when encountering tables declared WITH
OIDS, they have to be altered to remove the oid column first.
- Functionality to access the oid of the last inserted row (like
plpgsql's RESULT_OID, spi's SPI_lastoid, ...) has been removed.
The syntax for declaring a table WITHOUT OIDS (or WITH (oids = false)
for CREATE TABLE) is still supported. While that requires a bit of
support code, it seems unnecessary to break applications / dumps that
do not use oids, and are explicit about not using them.
The biggest user of WITH OID columns was postgres' catalog. This
commit changes all 'magic' oid columns to be columns that are normally
declared and stored. To reduce unnecessary query breakage all the
newly added columns are still named 'oid', even if a table's column
naming scheme would indicate 'reloid' or such. This obviously
requires adapting a lot code, mostly replacing oid access via
HeapTupleGetOid() with access to the underlying Form_pg_*->oid column.
The bootstrap process now assigns oids for all oid columns in
genbki.pl that do not have an explicit value (starting at the largest
oid previously used), only oids assigned later by oids will be above
FirstBootstrapObjectId. As the oid column now is a normal column the
special bootstrap syntax for oids has been removed.
Oids are not automatically assigned during insertion anymore, all
backend code explicitly assigns oids with GetNewOidWithIndex(). For
the rare case that insertions into the catalog via SQL are called for
the new pg_nextoid() function can be used (which only works on catalog
tables).
The fact that oid columns on system tables are now normal columns
means that they will be included in the set of columns expanded
by * (i.e. SELECT * FROM pg_class will now include the table's oid,
previously it did not). It'd not technically be hard to hide oid
column by default, but that'd mean confusing behavior would either
have to be carried forward forever, or it'd cause breakage down the
line.
While it's not unlikely that further adjustments are needed, the
scope/invasiveness of the patch makes it worthwhile to get merge this
now. It's painful to maintain externally, too complicated to commit
after the code code freeze, and a dependency of a number of other
patches.
Catversion bump, for obvious reasons.
Author: Andres Freund, with contributions by John Naylor
Discussion: https://postgr.es/m/20180930034810.ywp2c7awz7opzcfr@alap3.anarazel.de
2018-11-21 00:36:57 +01:00
|
|
|
* If acceptOidsOff is true, then we allow oids = false, but throw error when
|
|
|
|
* on. This is solely needed for backwards compatibility.
|
2006-07-04 00:45:41 +02:00
|
|
|
*
|
|
|
|
* Note that this is not responsible for determining whether the options
|
2009-02-02 20:31:40 +01:00
|
|
|
* are valid, but it does check that namespaces for all the options given are
|
2012-04-25 20:28:58 +02:00
|
|
|
* listed in validnsps. The NULL namespace is always valid and need not be
|
|
|
|
* explicitly listed. Passing a NULL pointer means that only the NULL
|
2009-02-02 20:31:40 +01:00
|
|
|
* namespace is valid.
|
2006-07-04 00:45:41 +02:00
|
|
|
*
|
|
|
|
* 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
|
2017-10-31 15:34:31 +01:00
|
|
|
transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
|
Remove WITH OIDS support, change oid catalog column visibility.
Previously tables declared WITH OIDS, including a significant fraction
of the catalog tables, stored the oid column not as a normal column,
but as part of the tuple header.
This special column was not shown by default, which was somewhat odd,
as it's often (consider e.g. pg_class.oid) one of the more important
parts of a row. Neither pg_dump nor COPY included the contents of the
oid column by default.
The fact that the oid column was not an ordinary column necessitated a
significant amount of special case code to support oid columns. That
already was painful for the existing, but upcoming work aiming to make
table storage pluggable, would have required expanding and duplicating
that "specialness" significantly.
WITH OIDS has been deprecated since 2005 (commit ff02d0a05280e0).
Remove it.
Removing includes:
- CREATE TABLE and ALTER TABLE syntax for declaring the table to be
WITH OIDS has been removed (WITH (oids[ = true]) will error out)
- pg_dump does not support dumping tables declared WITH OIDS and will
issue a warning when dumping one (and ignore the oid column).
- restoring an pg_dump archive with pg_restore will warn when
restoring a table with oid contents (and ignore the oid column)
- COPY will refuse to load binary dump that includes oids.
- pg_upgrade will error out when encountering tables declared WITH
OIDS, they have to be altered to remove the oid column first.
- Functionality to access the oid of the last inserted row (like
plpgsql's RESULT_OID, spi's SPI_lastoid, ...) has been removed.
The syntax for declaring a table WITHOUT OIDS (or WITH (oids = false)
for CREATE TABLE) is still supported. While that requires a bit of
support code, it seems unnecessary to break applications / dumps that
do not use oids, and are explicit about not using them.
The biggest user of WITH OID columns was postgres' catalog. This
commit changes all 'magic' oid columns to be columns that are normally
declared and stored. To reduce unnecessary query breakage all the
newly added columns are still named 'oid', even if a table's column
naming scheme would indicate 'reloid' or such. This obviously
requires adapting a lot code, mostly replacing oid access via
HeapTupleGetOid() with access to the underlying Form_pg_*->oid column.
The bootstrap process now assigns oids for all oid columns in
genbki.pl that do not have an explicit value (starting at the largest
oid previously used), only oids assigned later by oids will be above
FirstBootstrapObjectId. As the oid column now is a normal column the
special bootstrap syntax for oids has been removed.
Oids are not automatically assigned during insertion anymore, all
backend code explicitly assigns oids with GetNewOidWithIndex(). For
the rare case that insertions into the catalog via SQL are called for
the new pg_nextoid() function can be used (which only works on catalog
tables).
The fact that oid columns on system tables are now normal columns
means that they will be included in the set of columns expanded
by * (i.e. SELECT * FROM pg_class will now include the table's oid,
previously it did not). It'd not technically be hard to hide oid
column by default, but that'd mean confusing behavior would either
have to be carried forward forever, or it'd cause breakage down the
line.
While it's not unlikely that further adjustments are needed, the
scope/invasiveness of the patch makes it worthwhile to get merge this
now. It's painful to maintain externally, too complicated to commit
after the code code freeze, and a dependency of a number of other
patches.
Catversion bump, for obvious reasons.
Author: Andres Freund, with contributions by John Naylor
Discussion: https://postgr.es/m/20180930034810.ywp2c7awz7opzcfr@alap3.anarazel.de
2018-11-21 00:36:57 +01:00
|
|
|
char *validnsps[], bool acceptOidsOff, bool isReset)
|
2006-07-04 00:45:41 +02:00
|
|
|
{
|
|
|
|
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 */
|
2008-04-17 23:37:28 +02:00
|
|
|
if (PointerIsValid(DatumGetPointer(oldOptions)))
|
2006-07-04 00:45:41 +02:00
|
|
|
{
|
|
|
|
ArrayType *array = DatumGetArrayTypeP(oldOptions);
|
|
|
|
Datum *oldoptions;
|
|
|
|
int noldoptions;
|
|
|
|
int i;
|
|
|
|
|
2022-07-01 10:51:45 +02:00
|
|
|
deconstruct_array_builtin(array, TEXTOID, &oldoptions, NULL, &noldoptions);
|
2006-07-04 00:45:41 +02:00
|
|
|
|
|
|
|
for (i = 0; i < noldoptions; i++)
|
|
|
|
{
|
2017-03-13 00:35:31 +01:00
|
|
|
char *text_str = VARDATA(oldoptions[i]);
|
|
|
|
int text_len = VARSIZE(oldoptions[i]) - VARHDRSZ;
|
2006-07-04 00:45:41 +02:00
|
|
|
|
|
|
|
/* Search for a match in defList */
|
|
|
|
foreach(cell, defList)
|
|
|
|
{
|
2009-04-04 23:12:31 +02:00
|
|
|
DefElem *def = (DefElem *) lfirst(cell);
|
2009-02-02 20:31:40 +01:00
|
|
|
int kw_len;
|
2006-07-04 00:45:41 +02:00
|
|
|
|
2009-02-02 20:31:40 +01:00
|
|
|
/* ignore if not in the same namespace */
|
|
|
|
if (namspace == NULL)
|
|
|
|
{
|
2009-04-04 23:12:31 +02:00
|
|
|
if (def->defnamespace != NULL)
|
2009-02-02 20:31:40 +01:00
|
|
|
continue;
|
|
|
|
}
|
2009-04-04 23:12:31 +02:00
|
|
|
else if (def->defnamespace == NULL)
|
2009-02-02 20:31:40 +01:00
|
|
|
continue;
|
Avoid unnecessary use of pg_strcasecmp for already-downcased identifiers.
We have a lot of code in which option names, which from the user's
viewpoint are logically keywords, are passed through the grammar as plain
identifiers, and then matched to string literals during command execution.
This approach avoids making words into lexer keywords unnecessarily. Some
places matched these strings using plain strcmp, some using pg_strcasecmp.
But the latter should be unnecessary since identifiers would have been
downcased on their way through the parser. Aside from any efficiency
concerns (probably not a big factor), the lack of consistency in this area
creates a hazard of subtle bugs due to different places coming to different
conclusions about whether two option names are the same or different.
Hence, standardize on using strcmp() to match any option names that are
expected to have been fed through the parser.
This does create a user-visible behavioral change, which is that while
formerly all of these would work:
alter table foo set (fillfactor = 50);
alter table foo set (FillFactor = 50);
alter table foo set ("fillfactor" = 50);
alter table foo set ("FillFactor" = 50);
now the last case will fail because that double-quoted identifier is
different from the others. However, none of our documentation says that
you can use a quoted identifier in such contexts at all, and we should
discourage doing so since it would break if we ever decide to parse such
constructs as true lexer keywords rather than poor man's substitutes.
So this shouldn't create a significant compatibility issue for users.
Daniel Gustafsson, reviewed by Michael Paquier, small changes by me
Discussion: https://postgr.es/m/29405B24-564E-476B-98C0-677A29805B84@yesql.se
2018-01-27 00:25:02 +01:00
|
|
|
else if (strcmp(def->defnamespace, namspace) != 0)
|
2009-02-02 20:31:40 +01:00
|
|
|
continue;
|
|
|
|
|
2009-04-04 23:12:31 +02:00
|
|
|
kw_len = strlen(def->defname);
|
2006-07-04 00:45:41 +02:00
|
|
|
if (text_len > kw_len && text_str[kw_len] == '=' &&
|
Avoid unnecessary use of pg_strcasecmp for already-downcased identifiers.
We have a lot of code in which option names, which from the user's
viewpoint are logically keywords, are passed through the grammar as plain
identifiers, and then matched to string literals during command execution.
This approach avoids making words into lexer keywords unnecessarily. Some
places matched these strings using plain strcmp, some using pg_strcasecmp.
But the latter should be unnecessary since identifiers would have been
downcased on their way through the parser. Aside from any efficiency
concerns (probably not a big factor), the lack of consistency in this area
creates a hazard of subtle bugs due to different places coming to different
conclusions about whether two option names are the same or different.
Hence, standardize on using strcmp() to match any option names that are
expected to have been fed through the parser.
This does create a user-visible behavioral change, which is that while
formerly all of these would work:
alter table foo set (fillfactor = 50);
alter table foo set (FillFactor = 50);
alter table foo set ("fillfactor" = 50);
alter table foo set ("FillFactor" = 50);
now the last case will fail because that double-quoted identifier is
different from the others. However, none of our documentation says that
you can use a quoted identifier in such contexts at all, and we should
discourage doing so since it would break if we ever decide to parse such
constructs as true lexer keywords rather than poor man's substitutes.
So this shouldn't create a significant compatibility issue for users.
Daniel Gustafsson, reviewed by Michael Paquier, small changes by me
Discussion: https://postgr.es/m/29405B24-564E-476B-98C0-677A29805B84@yesql.se
2018-01-27 00:25:02 +01:00
|
|
|
strncmp(text_str, def->defname, kw_len) == 0)
|
2006-07-04 00:45:41 +02:00
|
|
|
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)
|
|
|
|
{
|
2009-04-04 23:12:31 +02:00
|
|
|
DefElem *def = (DefElem *) lfirst(cell);
|
2006-07-04 00:45:41 +02:00
|
|
|
|
|
|
|
if (isReset)
|
|
|
|
{
|
|
|
|
if (def->arg != NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("RESET must not include values for parameters")));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
text *t;
|
|
|
|
const char *value;
|
|
|
|
Size len;
|
|
|
|
|
2009-02-02 20:31:40 +01:00
|
|
|
/*
|
|
|
|
* Error out if the namespace is not valid. A NULL namespace is
|
|
|
|
* always valid.
|
|
|
|
*/
|
2009-04-04 23:12:31 +02:00
|
|
|
if (def->defnamespace != NULL)
|
2009-02-02 20:31:40 +01:00
|
|
|
{
|
|
|
|
bool valid = false;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (validnsps)
|
|
|
|
{
|
|
|
|
for (i = 0; validnsps[i]; i++)
|
|
|
|
{
|
Avoid unnecessary use of pg_strcasecmp for already-downcased identifiers.
We have a lot of code in which option names, which from the user's
viewpoint are logically keywords, are passed through the grammar as plain
identifiers, and then matched to string literals during command execution.
This approach avoids making words into lexer keywords unnecessarily. Some
places matched these strings using plain strcmp, some using pg_strcasecmp.
But the latter should be unnecessary since identifiers would have been
downcased on their way through the parser. Aside from any efficiency
concerns (probably not a big factor), the lack of consistency in this area
creates a hazard of subtle bugs due to different places coming to different
conclusions about whether two option names are the same or different.
Hence, standardize on using strcmp() to match any option names that are
expected to have been fed through the parser.
This does create a user-visible behavioral change, which is that while
formerly all of these would work:
alter table foo set (fillfactor = 50);
alter table foo set (FillFactor = 50);
alter table foo set ("fillfactor" = 50);
alter table foo set ("FillFactor" = 50);
now the last case will fail because that double-quoted identifier is
different from the others. However, none of our documentation says that
you can use a quoted identifier in such contexts at all, and we should
discourage doing so since it would break if we ever decide to parse such
constructs as true lexer keywords rather than poor man's substitutes.
So this shouldn't create a significant compatibility issue for users.
Daniel Gustafsson, reviewed by Michael Paquier, small changes by me
Discussion: https://postgr.es/m/29405B24-564E-476B-98C0-677A29805B84@yesql.se
2018-01-27 00:25:02 +01:00
|
|
|
if (strcmp(def->defnamespace, validnsps[i]) == 0)
|
2009-02-02 20:31:40 +01:00
|
|
|
{
|
|
|
|
valid = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!valid)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("unrecognized parameter namespace \"%s\"",
|
2009-04-04 23:12:31 +02:00
|
|
|
def->defnamespace)));
|
2009-02-02 20:31:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ignore if not in the same namespace */
|
|
|
|
if (namspace == NULL)
|
|
|
|
{
|
2009-04-04 23:12:31 +02:00
|
|
|
if (def->defnamespace != NULL)
|
2009-02-02 20:31:40 +01:00
|
|
|
continue;
|
|
|
|
}
|
2009-04-04 23:12:31 +02:00
|
|
|
else if (def->defnamespace == NULL)
|
2009-02-02 20:31:40 +01:00
|
|
|
continue;
|
Avoid unnecessary use of pg_strcasecmp for already-downcased identifiers.
We have a lot of code in which option names, which from the user's
viewpoint are logically keywords, are passed through the grammar as plain
identifiers, and then matched to string literals during command execution.
This approach avoids making words into lexer keywords unnecessarily. Some
places matched these strings using plain strcmp, some using pg_strcasecmp.
But the latter should be unnecessary since identifiers would have been
downcased on their way through the parser. Aside from any efficiency
concerns (probably not a big factor), the lack of consistency in this area
creates a hazard of subtle bugs due to different places coming to different
conclusions about whether two option names are the same or different.
Hence, standardize on using strcmp() to match any option names that are
expected to have been fed through the parser.
This does create a user-visible behavioral change, which is that while
formerly all of these would work:
alter table foo set (fillfactor = 50);
alter table foo set (FillFactor = 50);
alter table foo set ("fillfactor" = 50);
alter table foo set ("FillFactor" = 50);
now the last case will fail because that double-quoted identifier is
different from the others. However, none of our documentation says that
you can use a quoted identifier in such contexts at all, and we should
discourage doing so since it would break if we ever decide to parse such
constructs as true lexer keywords rather than poor man's substitutes.
So this shouldn't create a significant compatibility issue for users.
Daniel Gustafsson, reviewed by Michael Paquier, small changes by me
Discussion: https://postgr.es/m/29405B24-564E-476B-98C0-677A29805B84@yesql.se
2018-01-27 00:25:02 +01:00
|
|
|
else if (strcmp(def->defnamespace, namspace) != 0)
|
2006-07-04 00:45:41 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/*
|
2009-04-04 23:12:31 +02:00
|
|
|
* Flatten the DefElem into a text string like "name=arg". If we
|
2009-02-02 20:31:40 +01:00
|
|
|
* have just "name", assume "name=true" is meant. Note: the
|
|
|
|
* namespace is not output.
|
2006-07-04 00:45:41 +02:00
|
|
|
*/
|
|
|
|
if (def->arg != NULL)
|
2009-04-04 23:12:31 +02:00
|
|
|
value = defGetString(def);
|
2006-07-04 00:45:41 +02:00
|
|
|
else
|
|
|
|
value = "true";
|
Remove WITH OIDS support, change oid catalog column visibility.
Previously tables declared WITH OIDS, including a significant fraction
of the catalog tables, stored the oid column not as a normal column,
but as part of the tuple header.
This special column was not shown by default, which was somewhat odd,
as it's often (consider e.g. pg_class.oid) one of the more important
parts of a row. Neither pg_dump nor COPY included the contents of the
oid column by default.
The fact that the oid column was not an ordinary column necessitated a
significant amount of special case code to support oid columns. That
already was painful for the existing, but upcoming work aiming to make
table storage pluggable, would have required expanding and duplicating
that "specialness" significantly.
WITH OIDS has been deprecated since 2005 (commit ff02d0a05280e0).
Remove it.
Removing includes:
- CREATE TABLE and ALTER TABLE syntax for declaring the table to be
WITH OIDS has been removed (WITH (oids[ = true]) will error out)
- pg_dump does not support dumping tables declared WITH OIDS and will
issue a warning when dumping one (and ignore the oid column).
- restoring an pg_dump archive with pg_restore will warn when
restoring a table with oid contents (and ignore the oid column)
- COPY will refuse to load binary dump that includes oids.
- pg_upgrade will error out when encountering tables declared WITH
OIDS, they have to be altered to remove the oid column first.
- Functionality to access the oid of the last inserted row (like
plpgsql's RESULT_OID, spi's SPI_lastoid, ...) has been removed.
The syntax for declaring a table WITHOUT OIDS (or WITH (oids = false)
for CREATE TABLE) is still supported. While that requires a bit of
support code, it seems unnecessary to break applications / dumps that
do not use oids, and are explicit about not using them.
The biggest user of WITH OID columns was postgres' catalog. This
commit changes all 'magic' oid columns to be columns that are normally
declared and stored. To reduce unnecessary query breakage all the
newly added columns are still named 'oid', even if a table's column
naming scheme would indicate 'reloid' or such. This obviously
requires adapting a lot code, mostly replacing oid access via
HeapTupleGetOid() with access to the underlying Form_pg_*->oid column.
The bootstrap process now assigns oids for all oid columns in
genbki.pl that do not have an explicit value (starting at the largest
oid previously used), only oids assigned later by oids will be above
FirstBootstrapObjectId. As the oid column now is a normal column the
special bootstrap syntax for oids has been removed.
Oids are not automatically assigned during insertion anymore, all
backend code explicitly assigns oids with GetNewOidWithIndex(). For
the rare case that insertions into the catalog via SQL are called for
the new pg_nextoid() function can be used (which only works on catalog
tables).
The fact that oid columns on system tables are now normal columns
means that they will be included in the set of columns expanded
by * (i.e. SELECT * FROM pg_class will now include the table's oid,
previously it did not). It'd not technically be hard to hide oid
column by default, but that'd mean confusing behavior would either
have to be carried forward forever, or it'd cause breakage down the
line.
While it's not unlikely that further adjustments are needed, the
scope/invasiveness of the patch makes it worthwhile to get merge this
now. It's painful to maintain externally, too complicated to commit
after the code code freeze, and a dependency of a number of other
patches.
Catversion bump, for obvious reasons.
Author: Andres Freund, with contributions by John Naylor
Discussion: https://postgr.es/m/20180930034810.ywp2c7awz7opzcfr@alap3.anarazel.de
2018-11-21 00:36:57 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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(def->defname, "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;
|
|
|
|
}
|
|
|
|
|
2009-04-04 23:12:31 +02:00
|
|
|
len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
|
2006-07-04 00:45:41 +02:00
|
|
|
/* +1 leaves room for sprintf's trailing null */
|
|
|
|
t = (text *) palloc(len + 1);
|
2007-02-28 00:48:10 +01:00
|
|
|
SET_VARSIZE(t, len);
|
2009-04-04 23:12:31 +02:00
|
|
|
sprintf(VARDATA(t), "%s=%s", def->defname, value);
|
2006-07-04 00:45:41 +02:00
|
|
|
|
|
|
|
astate = accumArrayResult(astate, PointerGetDatum(t),
|
|
|
|
false, TEXTOID,
|
|
|
|
CurrentMemoryContext);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (astate)
|
|
|
|
result = makeArrayResult(astate, CurrentMemoryContext);
|
|
|
|
else
|
|
|
|
result = (Datum) 0;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-02 00:44:44 +01:00
|
|
|
/*
|
|
|
|
* 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 */
|
2008-04-17 23:37:28 +02:00
|
|
|
if (!PointerIsValid(DatumGetPointer(options)))
|
2007-12-02 00:44:44 +01:00
|
|
|
return result;
|
|
|
|
|
|
|
|
array = DatumGetArrayTypeP(options);
|
|
|
|
|
2022-07-01 10:51:45 +02:00
|
|
|
deconstruct_array_builtin(array, TEXTOID, &optiondatums, NULL, &noptions);
|
2007-12-02 00:44:44 +01:00
|
|
|
|
|
|
|
for (i = 0; i < noptions; i++)
|
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
char *p;
|
|
|
|
Node *val = NULL;
|
|
|
|
|
2008-03-25 23:42:46 +01:00
|
|
|
s = TextDatumGetCString(optiondatums[i]);
|
2007-12-02 00:44:44 +01:00
|
|
|
p = strchr(s, '=');
|
|
|
|
if (p)
|
|
|
|
{
|
|
|
|
*p++ = '\0';
|
2022-09-13 11:59:31 +02:00
|
|
|
val = (Node *) makeString(p);
|
2007-12-02 00:44:44 +01:00
|
|
|
}
|
2022-09-13 11:59:31 +02:00
|
|
|
result = lappend(result, makeDefElem(s, val, -1));
|
2007-12-02 00:44:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2009-01-26 20:41:06 +01:00
|
|
|
/*
|
|
|
|
* Extract and parse reloptions from a pg_class tuple.
|
|
|
|
*
|
|
|
|
* This is a low-level routine, expected to be used by relcache code and
|
|
|
|
* callers that do not have a table's relcache entry (e.g. autovacuum). For
|
|
|
|
* other uses, consider grabbing the rd_options pointer from the relcache entry
|
|
|
|
* instead.
|
|
|
|
*
|
Restructure index access method API to hide most of it at the C level.
This patch reduces pg_am to just two columns, a name and a handler
function. All the data formerly obtained from pg_am is now provided
in a C struct returned by the handler function. This is similar to
the designs we've adopted for FDWs and tablesample methods. There
are multiple advantages. For one, the index AM's support functions
are now simple C functions, making them faster to call and much less
error-prone, since the C compiler can now check function signatures.
For another, this will make it far more practical to define index access
methods in installable extensions.
A disadvantage is that SQL-level code can no longer see attributes
of index AMs; in particular, some of the crosschecks in the opr_sanity
regression test are no longer possible from SQL. We've addressed that
by adding a facility for the index AM to perform such checks instead.
(Much more could be done in that line, but for now we're content if the
amvalidate functions more or less replace what opr_sanity used to do.)
We might also want to expose some sort of reporting functionality, but
this patch doesn't do that.
Alexander Korotkov, reviewed by Petr Jelínek, and rather heavily
editorialized on by me.
2016-01-18 01:36:59 +01:00
|
|
|
* tupdesc is pg_class' tuple descriptor. amoptions is a pointer to the index
|
|
|
|
* AM's options parser function in the case of a tuple corresponding to an
|
|
|
|
* index, or NULL otherwise.
|
2009-01-26 20:41:06 +01:00
|
|
|
*/
|
|
|
|
bytea *
|
Restructure index access method API to hide most of it at the C level.
This patch reduces pg_am to just two columns, a name and a handler
function. All the data formerly obtained from pg_am is now provided
in a C struct returned by the handler function. This is similar to
the designs we've adopted for FDWs and tablesample methods. There
are multiple advantages. For one, the index AM's support functions
are now simple C functions, making them faster to call and much less
error-prone, since the C compiler can now check function signatures.
For another, this will make it far more practical to define index access
methods in installable extensions.
A disadvantage is that SQL-level code can no longer see attributes
of index AMs; in particular, some of the crosschecks in the opr_sanity
regression test are no longer possible from SQL. We've addressed that
by adding a facility for the index AM to perform such checks instead.
(Much more could be done in that line, but for now we're content if the
amvalidate functions more or less replace what opr_sanity used to do.)
We might also want to expose some sort of reporting functionality, but
this patch doesn't do that.
Alexander Korotkov, reviewed by Petr Jelínek, and rather heavily
editorialized on by me.
2016-01-18 01:36:59 +01:00
|
|
|
extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
|
|
|
|
amoptions_function amoptions)
|
2009-01-26 20:41:06 +01:00
|
|
|
{
|
|
|
|
bytea *options;
|
|
|
|
bool isnull;
|
|
|
|
Datum datum;
|
|
|
|
Form_pg_class classForm;
|
|
|
|
|
|
|
|
datum = fastgetattr(tuple,
|
|
|
|
Anum_pg_class_reloptions,
|
|
|
|
tupdesc,
|
|
|
|
&isnull);
|
|
|
|
if (isnull)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
classForm = (Form_pg_class) GETSTRUCT(tuple);
|
|
|
|
|
|
|
|
/* Parse into appropriate format; don't error out here */
|
|
|
|
switch (classForm->relkind)
|
|
|
|
{
|
|
|
|
case RELKIND_RELATION:
|
|
|
|
case RELKIND_TOASTVALUE:
|
2013-03-04 01:23:31 +01:00
|
|
|
case RELKIND_MATVIEW:
|
2009-01-26 20:41:06 +01:00
|
|
|
options = heap_reloptions(classForm->relkind, datum, false);
|
|
|
|
break;
|
2019-11-14 04:34:28 +01:00
|
|
|
case RELKIND_PARTITIONED_TABLE:
|
|
|
|
options = partitioned_table_reloptions(datum, false);
|
|
|
|
break;
|
2014-07-14 23:24:40 +02:00
|
|
|
case RELKIND_VIEW:
|
|
|
|
options = view_reloptions(datum, false);
|
|
|
|
break;
|
2009-01-26 20:41:06 +01:00
|
|
|
case RELKIND_INDEX:
|
Local partitioned indexes
When CREATE INDEX is run on a partitioned table, create catalog entries
for an index on the partitioned table (which is just a placeholder since
the table proper has no data of its own), and recurse to create actual
indexes on the existing partitions; create them in future partitions
also.
As a convenience gadget, if the new index definition matches some
existing index in partitions, these are picked up and used instead of
creating new ones. Whichever way these indexes come about, they become
attached to the index on the parent table and are dropped alongside it,
and cannot be dropped on isolation unless they are detached first.
To support pg_dump'ing these indexes, add commands
CREATE INDEX ON ONLY <table>
(which creates the index on the parent partitioned table, without
recursing) and
ALTER INDEX ATTACH PARTITION
(which is used after the indexes have been created individually on each
partition, to attach them to the parent index). These reconstruct prior
database state exactly.
Reviewed-by: (in alphabetical order) Peter Eisentraut, Robert Haas, Amit
Langote, Jesper Pedersen, Simon Riggs, David Rowley
Discussion: https://postgr.es/m/20171113170646.gzweigyrgg6pwsg4@alvherre.pgsql
2018-01-19 15:49:22 +01:00
|
|
|
case RELKIND_PARTITIONED_INDEX:
|
2009-01-26 20:41:06 +01:00
|
|
|
options = index_reloptions(amoptions, datum, false);
|
|
|
|
break;
|
2011-01-02 05:48:11 +01:00
|
|
|
case RELKIND_FOREIGN_TABLE:
|
|
|
|
options = NULL;
|
|
|
|
break;
|
2009-01-26 20:41:06 +01:00
|
|
|
default:
|
|
|
|
Assert(false); /* can't get here */
|
|
|
|
options = NULL; /* keep compiler quiet */
|
|
|
|
break;
|
|
|
|
}
|
2009-03-23 17:36:27 +01:00
|
|
|
|
2009-01-26 20:41:06 +01:00
|
|
|
return options;
|
|
|
|
}
|
2007-12-02 00:44:44 +01:00
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
static void
|
|
|
|
parseRelOptionsInternal(Datum options, bool validate,
|
|
|
|
relopt_value *reloptions, int numoptions)
|
|
|
|
{
|
|
|
|
ArrayType *array = DatumGetArrayTypeP(options);
|
|
|
|
Datum *optiondatums;
|
|
|
|
int noptions;
|
|
|
|
int i;
|
|
|
|
|
2022-07-01 10:51:45 +02:00
|
|
|
deconstruct_array_builtin(array, TEXTOID, &optiondatums, NULL, &noptions);
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
|
|
|
|
for (i = 0; i < noptions; i++)
|
|
|
|
{
|
|
|
|
char *text_str = VARDATA(optiondatums[i]);
|
|
|
|
int text_len = VARSIZE(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);
|
|
|
|
}
|
|
|
|
|
2006-07-04 00:45:41 +02:00
|
|
|
/*
|
|
|
|
* Interpret reloptions that are given in text-array format.
|
|
|
|
*
|
2009-01-05 18:14:28 +01:00
|
|
|
* options is a reloption text array as constructed by transformRelOptions.
|
|
|
|
* kind specifies the family of options to be processed.
|
|
|
|
*
|
|
|
|
* The return value is a relopt_value * array on which the options actually
|
|
|
|
* set in the options array are marked with isset=true. The length of this
|
|
|
|
* array is returned in *numrelopts. Options not set are also present in the
|
|
|
|
* array; this is so that the caller can easily locate the default values.
|
2006-07-04 00:45:41 +02:00
|
|
|
*
|
2009-01-05 18:14:28 +01:00
|
|
|
* If there are no options of the given kind, numrelopts is set to 0 and NULL
|
2017-03-31 22:28:30 +02:00
|
|
|
* is returned (unless options are illegally supplied despite none being
|
|
|
|
* defined, in which case an error occurs).
|
2009-01-05 18:14:28 +01:00
|
|
|
*
|
|
|
|
* Note: values of type int, bool and real are allocated as part of the
|
|
|
|
* returned array. Values of type string are allocated separately and must
|
|
|
|
* be freed by the caller.
|
2006-07-04 00:45:41 +02:00
|
|
|
*/
|
2019-11-14 05:59:59 +01:00
|
|
|
static relopt_value *
|
2009-01-05 18:14:28 +01:00
|
|
|
parseRelOptions(Datum options, bool validate, relopt_kind kind,
|
|
|
|
int *numrelopts)
|
2006-07-04 00:45:41 +02:00
|
|
|
{
|
2017-03-31 22:28:30 +02:00
|
|
|
relopt_value *reloptions = NULL;
|
2009-01-05 18:14:28 +01:00
|
|
|
int numoptions = 0;
|
2006-07-04 00:45:41 +02:00
|
|
|
int i;
|
2009-01-05 18:14:28 +01:00
|
|
|
int j;
|
2006-07-04 00:45:41 +02:00
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
if (need_initialization)
|
|
|
|
initialize_reloptions();
|
2006-07-04 00:45:41 +02:00
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
/* Build a list of expected options, based on kind */
|
2006-07-04 00:45:41 +02:00
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
for (i = 0; relOpts[i]; i++)
|
2009-04-04 02:45:02 +02:00
|
|
|
if (relOpts[i]->kinds & kind)
|
2009-01-05 18:14:28 +01:00
|
|
|
numoptions++;
|
2006-07-04 00:45:41 +02:00
|
|
|
|
2017-03-31 22:28:30 +02:00
|
|
|
if (numoptions > 0)
|
2009-01-05 18:14:28 +01:00
|
|
|
{
|
2017-03-31 22:28:30 +02:00
|
|
|
reloptions = palloc(numoptions * sizeof(relopt_value));
|
2006-07-04 00:45:41 +02:00
|
|
|
|
2017-03-31 22:28:30 +02:00
|
|
|
for (i = 0, j = 0; relOpts[i]; i++)
|
2009-01-05 18:14:28 +01:00
|
|
|
{
|
2017-03-31 22:28:30 +02:00
|
|
|
if (relOpts[i]->kinds & kind)
|
|
|
|
{
|
|
|
|
reloptions[j].gen = relOpts[i];
|
|
|
|
reloptions[j].isset = false;
|
|
|
|
j++;
|
|
|
|
}
|
2009-01-05 18:14:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Done if no options */
|
|
|
|
if (PointerIsValid(DatumGetPointer(options)))
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
parseRelOptionsInternal(options, validate, reloptions, numoptions);
|
2009-01-05 18:14:28 +01:00
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
*numrelopts = numoptions;
|
|
|
|
return reloptions;
|
|
|
|
}
|
2006-07-04 00:45:41 +02:00
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
/* Parse local unregistered options. */
|
|
|
|
static relopt_value *
|
|
|
|
parseLocalRelOptions(local_relopts *relopts, Datum options, bool validate)
|
|
|
|
{
|
|
|
|
int nopts = list_length(relopts->options);
|
|
|
|
relopt_value *values = palloc(sizeof(*values) * nopts);
|
|
|
|
ListCell *lc;
|
|
|
|
int i = 0;
|
2009-01-05 18:14:28 +01:00
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
foreach(lc, relopts->options)
|
|
|
|
{
|
|
|
|
local_relopt *opt = lfirst(lc);
|
2009-01-05 18:14:28 +01:00
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
values[i].gen = opt->option;
|
|
|
|
values[i].isset = false;
|
2014-08-13 17:35:51 +02:00
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
i++;
|
2006-07-04 00:45:41 +02:00
|
|
|
}
|
2009-01-05 18:14:28 +01:00
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
if (options != (Datum) 0)
|
|
|
|
parseRelOptionsInternal(options, validate, values, nopts);
|
|
|
|
|
|
|
|
return values;
|
2006-07-04 00:45:41 +02:00
|
|
|
}
|
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
/*
|
|
|
|
* Subroutine for parseRelOptions, to parse and validate a single option's
|
|
|
|
* value
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
parse_one_reloption(relopt_value *option, char *text_str, int text_len,
|
|
|
|
bool validate)
|
|
|
|
{
|
|
|
|
char *value;
|
|
|
|
int value_len;
|
2009-01-06 04:15:51 +01:00
|
|
|
bool parsed;
|
2009-01-05 18:14:28 +01:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
case RELOPT_TYPE_BOOL:
|
|
|
|
{
|
|
|
|
parsed = parse_bool(value, &option->values.bool_val);
|
|
|
|
if (validate && !parsed)
|
|
|
|
ereport(ERROR,
|
2015-08-03 05:49:19 +02:00
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("invalid value for boolean option \"%s\": %s",
|
2009-01-05 18:14:28 +01:00
|
|
|
option->gen->name, value)));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case RELOPT_TYPE_INT:
|
|
|
|
{
|
|
|
|
relopt_int *optint = (relopt_int *) option->gen;
|
|
|
|
|
2014-08-28 22:10:47 +02:00
|
|
|
parsed = parse_int(value, &option->values.int_val, 0, NULL);
|
2009-01-05 18:14:28 +01:00
|
|
|
if (validate && !parsed)
|
|
|
|
ereport(ERROR,
|
2015-08-03 05:49:19 +02:00
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("invalid value for integer option \"%s\": %s",
|
2014-08-28 22:10:47 +02:00
|
|
|
option->gen->name, value)));
|
2009-01-05 18:14:28 +01:00
|
|
|
if (validate && (option->values.int_val < optint->min ||
|
|
|
|
option->values.int_val > optint->max))
|
|
|
|
ereport(ERROR,
|
2015-08-03 05:49:19 +02:00
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("value %s out of bounds for option \"%s\"",
|
2009-01-05 18:14:28 +01:00
|
|
|
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;
|
|
|
|
|
2019-03-10 20:01:39 +01:00
|
|
|
parsed = parse_real(value, &option->values.real_val, 0, NULL);
|
2009-01-05 18:14:28 +01:00
|
|
|
if (validate && !parsed)
|
|
|
|
ereport(ERROR,
|
2015-08-03 05:49:19 +02:00
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("invalid value for floating point option \"%s\": %s",
|
2009-01-05 18:14:28 +01:00
|
|
|
option->gen->name, value)));
|
|
|
|
if (validate && (option->values.real_val < optreal->min ||
|
|
|
|
option->values.real_val > optreal->max))
|
|
|
|
ereport(ERROR,
|
2015-08-03 05:49:19 +02:00
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("value %s out of bounds for option \"%s\"",
|
2009-01-05 18:14:28 +01:00
|
|
|
value, option->gen->name),
|
|
|
|
errdetail("Valid values are between \"%f\" and \"%f\".",
|
|
|
|
optreal->min, optreal->max)));
|
|
|
|
}
|
|
|
|
break;
|
2019-09-25 20:56:52 +02:00
|
|
|
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;
|
2009-01-05 18:14:28 +01:00
|
|
|
case RELOPT_TYPE_STRING:
|
2009-01-08 20:34:41 +01:00
|
|
|
{
|
|
|
|
relopt_string *optstring = (relopt_string *) option->gen;
|
|
|
|
|
|
|
|
option->values.string_val = value;
|
|
|
|
nofree = true;
|
2009-01-12 22:02:15 +01:00
|
|
|
if (validate && optstring->validate_cb)
|
|
|
|
(optstring->validate_cb) (value);
|
2009-01-08 20:34:41 +01:00
|
|
|
parsed = true;
|
|
|
|
}
|
2009-01-05 18:14:28 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
elog(ERROR, "unsupported reloption type %d", option->gen->type);
|
2009-01-06 04:15:51 +01:00
|
|
|
parsed = true; /* quiet compiler */
|
2009-01-05 18:14:28 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parsed)
|
|
|
|
option->isset = true;
|
|
|
|
if (!nofree)
|
|
|
|
pfree(value);
|
|
|
|
}
|
2006-07-04 00:45:41 +02:00
|
|
|
|
2009-01-12 22:02:15 +01:00
|
|
|
/*
|
|
|
|
* 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).
|
|
|
|
*/
|
2019-11-14 05:59:59 +01:00
|
|
|
static void *
|
2009-01-12 22:02:15 +01:00
|
|
|
allocateReloptStruct(Size base, relopt_value *options, int numoptions)
|
|
|
|
{
|
|
|
|
Size size = base;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < numoptions; i++)
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
{
|
|
|
|
relopt_value *optval = &options[i];
|
|
|
|
|
|
|
|
if (optval->gen->type == RELOPT_TYPE_STRING)
|
|
|
|
{
|
|
|
|
relopt_string *optstr = (relopt_string *) optval->gen;
|
|
|
|
|
|
|
|
if (optstr->fill_cb)
|
|
|
|
{
|
|
|
|
const char *val = optval->isset ? optval->values.string_val :
|
2023-05-19 23:24:48 +02:00
|
|
|
optstr->default_isnull ? NULL : optstr->default_val;
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
|
|
|
|
size += optstr->fill_cb(val, NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
size += GET_STRING_RELOPTION_LEN(*optval) + 1;
|
|
|
|
}
|
|
|
|
}
|
2009-01-12 22:02:15 +01:00
|
|
|
|
|
|
|
return palloc0(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Given the result of parseRelOptions and a parsing table, fill in the
|
|
|
|
* struct (previously allocated with allocateReloptStruct) with the parsed
|
|
|
|
* values.
|
|
|
|
*
|
2009-03-23 17:36:27 +01:00
|
|
|
* 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.
|
2009-01-12 22:02:15 +01:00
|
|
|
*/
|
2019-11-14 05:59:59 +01:00
|
|
|
static void
|
2009-03-23 17:36:27 +01:00
|
|
|
fillRelOptions(void *rdopts, Size basesize,
|
|
|
|
relopt_value *options, int numoptions,
|
|
|
|
bool validate,
|
|
|
|
const relopt_parse_elt *elems, int numelems)
|
2009-01-12 22:02:15 +01:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int offset = basesize;
|
|
|
|
|
|
|
|
for (i = 0; i < numoptions; i++)
|
|
|
|
{
|
|
|
|
int j;
|
|
|
|
bool found = false;
|
|
|
|
|
|
|
|
for (j = 0; j < numelems; j++)
|
|
|
|
{
|
Avoid unnecessary use of pg_strcasecmp for already-downcased identifiers.
We have a lot of code in which option names, which from the user's
viewpoint are logically keywords, are passed through the grammar as plain
identifiers, and then matched to string literals during command execution.
This approach avoids making words into lexer keywords unnecessarily. Some
places matched these strings using plain strcmp, some using pg_strcasecmp.
But the latter should be unnecessary since identifiers would have been
downcased on their way through the parser. Aside from any efficiency
concerns (probably not a big factor), the lack of consistency in this area
creates a hazard of subtle bugs due to different places coming to different
conclusions about whether two option names are the same or different.
Hence, standardize on using strcmp() to match any option names that are
expected to have been fed through the parser.
This does create a user-visible behavioral change, which is that while
formerly all of these would work:
alter table foo set (fillfactor = 50);
alter table foo set (FillFactor = 50);
alter table foo set ("fillfactor" = 50);
alter table foo set ("FillFactor" = 50);
now the last case will fail because that double-quoted identifier is
different from the others. However, none of our documentation says that
you can use a quoted identifier in such contexts at all, and we should
discourage doing so since it would break if we ever decide to parse such
constructs as true lexer keywords rather than poor man's substitutes.
So this shouldn't create a significant compatibility issue for users.
Daniel Gustafsson, reviewed by Michael Paquier, small changes by me
Discussion: https://postgr.es/m/29405B24-564E-476B-98C0-677A29805B84@yesql.se
2018-01-27 00:25:02 +01:00
|
|
|
if (strcmp(options[i].gen->name, elems[j].optname) == 0)
|
2009-01-12 22:02:15 +01:00
|
|
|
{
|
|
|
|
relopt_string *optstring;
|
|
|
|
char *itempos = ((char *) rdopts) + elems[j].offset;
|
|
|
|
char *string_val;
|
|
|
|
|
|
|
|
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;
|
2019-09-25 20:56:52 +02:00
|
|
|
case RELOPT_TYPE_ENUM:
|
|
|
|
*(int *) itempos = options[i].isset ?
|
|
|
|
options[i].values.enum_val :
|
|
|
|
((relopt_enum *) options[i].gen)->default_val;
|
|
|
|
break;
|
2009-01-12 22:02:15 +01:00
|
|
|
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;
|
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
if (optstring->fill_cb)
|
|
|
|
{
|
|
|
|
Size size =
|
2023-05-19 23:24:48 +02:00
|
|
|
optstring->fill_cb(string_val,
|
|
|
|
(char *) rdopts + offset);
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
|
|
|
|
if (size)
|
|
|
|
{
|
|
|
|
*(int *) itempos = offset;
|
|
|
|
offset += size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*(int *) itempos = 0;
|
|
|
|
}
|
|
|
|
else if (string_val == NULL)
|
2009-01-12 22:02:15 +01:00
|
|
|
*(int *) itempos = 0;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
strcpy((char *) rdopts + offset, string_val);
|
|
|
|
*(int *) itempos = offset;
|
|
|
|
offset += strlen(string_val) + 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2015-08-03 05:49:19 +02:00
|
|
|
elog(ERROR, "unsupported reloption type %d",
|
2009-01-12 22:02:15 +01:00
|
|
|
options[i].gen->type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-01-15 18:07:10 +01:00
|
|
|
if (validate && !found)
|
2009-03-23 17:36:27 +01:00
|
|
|
elog(ERROR, "reloption \"%s\" not found in parse table",
|
2009-01-12 22:02:15 +01:00
|
|
|
options[i].gen->name);
|
|
|
|
}
|
|
|
|
SET_VARSIZE(rdopts, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-07-04 00:45:41 +02:00
|
|
|
/*
|
2016-04-08 17:14:56 +02:00
|
|
|
* Option parser for anything that uses StdRdOptions.
|
2006-07-04 00:45:41 +02:00
|
|
|
*/
|
|
|
|
bytea *
|
2009-01-05 18:14:28 +01:00
|
|
|
default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
|
2006-07-04 00:45:41 +02:00
|
|
|
{
|
2009-03-23 17:36:27 +01:00
|
|
|
static const relopt_parse_elt tab[] = {
|
2009-02-09 21:57:59 +01:00
|
|
|
{"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)},
|
Trigger autovacuum based on number of INSERTs
Traditionally autovacuum has only ever invoked a worker based on the
estimated number of dead tuples in a table and for anti-wraparound
purposes. For the latter, with certain classes of tables such as
insert-only tables, anti-wraparound vacuums could be the first vacuum that
the table ever receives. This could often lead to autovacuum workers being
busy for extended periods of time due to having to potentially freeze
every page in the table. This could be particularly bad for very large
tables. New clusters, or recently pg_restored clusters could suffer even
more as many large tables may have the same relfrozenxid, which could
result in large numbers of tables requiring an anti-wraparound vacuum all
at once.
Here we aim to reduce the work required by anti-wraparound and aggressive
vacuums in general, by triggering autovacuum when the table has received
enough INSERTs. This is controlled by adding two new GUCs and reloptions;
autovacuum_vacuum_insert_threshold and
autovacuum_vacuum_insert_scale_factor. These work exactly the same as the
existing scale factor and threshold controls, only base themselves off the
number of inserts since the last vacuum, rather than the number of dead
tuples. New controls were added rather than reusing the existing
controls, to allow these new vacuums to be tuned independently and perhaps
even completely disabled altogether, which can be done by setting
autovacuum_vacuum_insert_threshold to -1.
We make no attempt to skip index cleanup operations on these vacuums as
they may trigger for an insert-mostly table which continually doesn't have
enough dead tuples to trigger an autovacuum for the purpose of removing
those dead tuples. If we were to skip cleaning the indexes in this case,
then it is possible for the index(es) to become bloated over time.
There are additional benefits to triggering autovacuums based on inserts,
as tables which never contain enough dead tuples to trigger an autovacuum
are now more likely to receive a vacuum, which can mark more of the table
as "allvisible" and encourage the query planner to make use of Index Only
Scans.
Currently, we still obey vacuum_freeze_min_age when triggering these new
autovacuums based on INSERTs. For large insert-only tables, it may be
beneficial to lower the table's autovacuum_freeze_min_age so that tuples
are eligible to be frozen sooner. Here we've opted not to zero that for
these types of vacuums, since the table may just be insert-mostly and we
may otherwise freeze tuples that are still destined to be updated or
removed in the near future.
There was some debate to what exactly the new scale factor and threshold
should default to. For now, these are set to 0.2 and 1000, respectively.
There may be some motivation to adjust these before the release.
Author: Laurenz Albe, Darafei Praliaskouski
Reviewed-by: Alvaro Herrera, Masahiko Sawada, Chris Travers, Andres Freund, Justin Pryzby
Discussion: https://postgr.es/m/CAC8Q8t%2Bj36G_bLF%3D%2B0iMo6jGNWnLnWb1tujXuJr-%2Bx8ZCCTqoQ%40mail.gmail.com
2020-03-28 07:20:12 +01:00
|
|
|
{"autovacuum_vacuum_insert_threshold", RELOPT_TYPE_INT,
|
|
|
|
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_ins_threshold)},
|
2009-02-09 21:57:59 +01:00
|
|
|
{"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)},
|
Separate multixact freezing parameters from xid's
Previously we were piggybacking on transaction ID parameters to freeze
multixacts; but since there isn't necessarily any relationship between
rates of Xid and multixact consumption, this turns out not to be a good
idea.
Therefore, we now have multixact-specific freezing parameters:
vacuum_multixact_freeze_min_age: when to remove multis as we come across
them in vacuum (default to 5 million, i.e. early in comparison to Xid's
default of 50 million)
vacuum_multixact_freeze_table_age: when to force whole-table scans
instead of scanning only the pages marked as not all visible in
visibility map (default to 150 million, same as for Xids). Whichever of
both which reaches the 150 million mark earlier will cause a whole-table
scan.
autovacuum_multixact_freeze_max_age: when for cause emergency,
uninterruptible whole-table scans (default to 400 million, double as
that for Xids). This means there shouldn't be more frequent emergency
vacuuming than previously, unless multixacts are being used very
rapidly.
Backpatch to 9.3 where multixacts were made to persist enough to require
freezing. To avoid an ABI break in 9.3, VacuumStmt has a couple of
fields in an unnatural place, and StdRdOptions is split in two so that
the newly added fields can go at the end.
Patch by me, reviewed by Robert Haas, with additional input from Andres
Freund and Tom Lane.
2014-02-13 23:30:30 +01:00
|
|
|
{"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)},
|
2015-04-03 16:55:50 +02:00
|
|
|
{"log_autovacuum_min_duration", RELOPT_TYPE_INT,
|
|
|
|
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, log_min_duration)},
|
2017-11-19 23:50:10 +01:00
|
|
|
{"toast_tuple_target", RELOPT_TYPE_INT,
|
|
|
|
offsetof(StdRdOptions, toast_tuple_target)},
|
2019-03-10 20:01:39 +01:00
|
|
|
{"autovacuum_vacuum_cost_delay", RELOPT_TYPE_REAL,
|
|
|
|
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_delay)},
|
2009-02-09 21:57:59 +01:00
|
|
|
{"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL,
|
|
|
|
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_scale_factor)},
|
Trigger autovacuum based on number of INSERTs
Traditionally autovacuum has only ever invoked a worker based on the
estimated number of dead tuples in a table and for anti-wraparound
purposes. For the latter, with certain classes of tables such as
insert-only tables, anti-wraparound vacuums could be the first vacuum that
the table ever receives. This could often lead to autovacuum workers being
busy for extended periods of time due to having to potentially freeze
every page in the table. This could be particularly bad for very large
tables. New clusters, or recently pg_restored clusters could suffer even
more as many large tables may have the same relfrozenxid, which could
result in large numbers of tables requiring an anti-wraparound vacuum all
at once.
Here we aim to reduce the work required by anti-wraparound and aggressive
vacuums in general, by triggering autovacuum when the table has received
enough INSERTs. This is controlled by adding two new GUCs and reloptions;
autovacuum_vacuum_insert_threshold and
autovacuum_vacuum_insert_scale_factor. These work exactly the same as the
existing scale factor and threshold controls, only base themselves off the
number of inserts since the last vacuum, rather than the number of dead
tuples. New controls were added rather than reusing the existing
controls, to allow these new vacuums to be tuned independently and perhaps
even completely disabled altogether, which can be done by setting
autovacuum_vacuum_insert_threshold to -1.
We make no attempt to skip index cleanup operations on these vacuums as
they may trigger for an insert-mostly table which continually doesn't have
enough dead tuples to trigger an autovacuum for the purpose of removing
those dead tuples. If we were to skip cleaning the indexes in this case,
then it is possible for the index(es) to become bloated over time.
There are additional benefits to triggering autovacuums based on inserts,
as tables which never contain enough dead tuples to trigger an autovacuum
are now more likely to receive a vacuum, which can mark more of the table
as "allvisible" and encourage the query planner to make use of Index Only
Scans.
Currently, we still obey vacuum_freeze_min_age when triggering these new
autovacuums based on INSERTs. For large insert-only tables, it may be
beneficial to lower the table's autovacuum_freeze_min_age so that tuples
are eligible to be frozen sooner. Here we've opted not to zero that for
these types of vacuums, since the table may just be insert-mostly and we
may otherwise freeze tuples that are still destined to be updated or
removed in the near future.
There was some debate to what exactly the new scale factor and threshold
should default to. For now, these are set to 0.2 and 1000, respectively.
There may be some motivation to adjust these before the release.
Author: Laurenz Albe, Darafei Praliaskouski
Reviewed-by: Alvaro Herrera, Masahiko Sawada, Chris Travers, Andres Freund, Justin Pryzby
Discussion: https://postgr.es/m/CAC8Q8t%2Bj36G_bLF%3D%2B0iMo6jGNWnLnWb1tujXuJr-%2Bx8ZCCTqoQ%40mail.gmail.com
2020-03-28 07:20:12 +01:00
|
|
|
{"autovacuum_vacuum_insert_scale_factor", RELOPT_TYPE_REAL,
|
|
|
|
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_ins_scale_factor)},
|
2009-02-09 21:57:59 +01:00
|
|
|
{"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,
|
2011-12-22 22:15:57 +01:00
|
|
|
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_scale_factor)},
|
2013-12-11 01:17:34 +01:00
|
|
|
{"user_catalog_table", RELOPT_TYPE_BOOL,
|
2016-04-08 17:14:56 +02:00
|
|
|
offsetof(StdRdOptions, user_catalog_table)},
|
2016-06-09 15:08:27 +02:00
|
|
|
{"parallel_workers", RELOPT_TYPE_INT,
|
Skip full index scan during cleanup of B-tree indexes when possible
Vacuum of index consists from two stages: multiple (zero of more) ambulkdelete
calls and one amvacuumcleanup call. When workload on particular table
is append-only, then autovacuum isn't intended to touch this table. However,
user may run vacuum manually in order to fill visibility map and get benefits
of index-only scans. Then ambulkdelete wouldn't be called for indexes
of such table (because no heap tuples were deleted), only amvacuumcleanup would
be called In this case, amvacuumcleanup would perform full index scan for
two objectives: put recyclable pages into free space map and update index
statistics.
This patch allows btvacuumclanup to skip full index scan when two conditions
are satisfied: no pages are going to be put into free space map and index
statistics isn't stalled. In order to check first condition, we store
oldest btpo_xact in the meta-page. When it's precedes RecentGlobalXmin, then
there are some recyclable pages. In order to check second condition we store
number of heap tuples observed during previous full index scan by cleanup.
If fraction of newly inserted tuples is less than
vacuum_cleanup_index_scale_factor, then statistics isn't considered to be
stalled. vacuum_cleanup_index_scale_factor can be defined as both reloption and GUC (default).
This patch bumps B-tree meta-page version. Upgrade of meta-page is performed
"on the fly": during VACUUM meta-page is rewritten with new version. No special
handling in pg_upgrade is required.
Author: Masahiko Sawada, Alexander Korotkov
Review by: Peter Geoghegan, Kyotaro Horiguchi, Alexander Korotkov, Yura Sokolov
Discussion: https://www.postgresql.org/message-id/flat/CAD21AoAX+d2oD_nrd9O2YkpzHaFr=uQeGr9s1rKC3O4ENc568g@mail.gmail.com
2018-04-04 18:29:00 +02:00
|
|
|
offsetof(StdRdOptions, parallel_workers)},
|
2021-08-04 06:53:41 +02:00
|
|
|
{"vacuum_index_cleanup", RELOPT_TYPE_ENUM,
|
2019-04-08 09:43:57 +02:00
|
|
|
offsetof(StdRdOptions, vacuum_index_cleanup)},
|
|
|
|
{"vacuum_truncate", RELOPT_TYPE_BOOL,
|
2021-03-24 06:40:12 +01:00
|
|
|
offsetof(StdRdOptions, vacuum_truncate)}
|
2009-01-12 22:02:15 +01:00
|
|
|
};
|
2006-07-04 00:45:41 +02:00
|
|
|
|
2019-11-05 01:17:05 +01:00
|
|
|
return (bytea *) build_reloptions(reloptions, validate, kind,
|
|
|
|
sizeof(StdRdOptions),
|
|
|
|
tab, lengthof(tab));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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 */
|
2009-01-05 18:14:28 +01:00
|
|
|
options = parseRelOptions(reloptions, validate, kind, &numoptions);
|
2019-11-05 01:17:05 +01:00
|
|
|
Assert(numoptions <= num_relopt_elems);
|
2006-07-04 00:45:41 +02:00
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
/* if none set, we're done */
|
|
|
|
if (numoptions == 0)
|
2019-11-05 01:17:05 +01:00
|
|
|
{
|
|
|
|
Assert(options == NULL);
|
2006-07-04 00:45:41 +02:00
|
|
|
return NULL;
|
2019-11-05 01:17:05 +01:00
|
|
|
}
|
2006-07-04 00:45:41 +02:00
|
|
|
|
2019-11-05 01:17:05 +01:00
|
|
|
/* 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);
|
2006-07-04 00:45:41 +02:00
|
|
|
|
2009-01-05 18:14:28 +01:00
|
|
|
pfree(options);
|
2006-07-04 00:45:41 +02:00
|
|
|
|
2019-11-05 01:17:05 +01:00
|
|
|
return rdopts;
|
2006-07-04 00:45:41 +02:00
|
|
|
}
|
|
|
|
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
/*
|
|
|
|
* Parse local options, allocate a bytea struct that's of the specified
|
|
|
|
* 'base_size' plus any extra space that's needed for string variables,
|
|
|
|
* fill its option's fields located at the given offsets and return it.
|
|
|
|
*/
|
|
|
|
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;
|
|
|
|
|
|
|
|
foreach(lc, relopts->options)
|
|
|
|
{
|
|
|
|
local_relopt *opt = lfirst(lc);
|
|
|
|
|
|
|
|
elems[i].optname = opt->option->name;
|
|
|
|
elems[i].opttype = opt->option->type;
|
|
|
|
elems[i].offset = opt->offset;
|
|
|
|
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
vals = parseLocalRelOptions(relopts, options, validate);
|
|
|
|
opts = allocateReloptStruct(relopts->relopt_struct_size, vals, noptions);
|
|
|
|
fillRelOptions(opts, relopts->relopt_struct_size, vals, noptions, validate,
|
|
|
|
elems, noptions);
|
|
|
|
|
2023-04-23 12:55:49 +02:00
|
|
|
if (validate)
|
|
|
|
foreach(lc, relopts->validators)
|
|
|
|
((relopts_validator) lfirst(lc)) (opts, vals, noptions);
|
Implement operator class parameters
PostgreSQL provides set of template index access methods, where opclasses have
much freedom in the semantics of indexing. These index AMs are GiST, GIN,
SP-GiST and BRIN. There opclasses define representation of keys, operations on
them and supported search strategies. So, it's natural that opclasses may be
faced some tradeoffs, which require user-side decision. This commit implements
opclass parameters allowing users to set some values, which tell opclass how to
index the particular dataset.
This commit doesn't introduce new storage in system catalog. Instead it uses
pg_attribute.attoptions, which is used for table column storage options but
unused for index attributes.
In order to evade changing signature of each opclass support function, we
implement unified way to pass options to opclass support functions. Options
are set to fn_expr as the constant bytea expression. It's possible due to the
fact that opclass support functions are executed outside of expressions, so
fn_expr is unused for them.
This commit comes with some examples of opclass options usage. We parametrize
signature length in GiST. That applies to multiple opclasses: tsvector_ops,
gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and
gist_hstore_ops. Also we parametrize maximum number of integer ranges for
gist__int_ops. However, the main future usage of this feature is expected
to be json, where users would be able to specify which way to index particular
json parts.
Catversion is bumped.
Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru
Author: Nikita Glukhov, revised by me
Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
2020-03-30 18:17:11 +02:00
|
|
|
|
|
|
|
if (elems)
|
|
|
|
pfree(elems);
|
|
|
|
|
|
|
|
return opts;
|
|
|
|
}
|
|
|
|
|
2019-11-14 04:34:28 +01:00
|
|
|
/*
|
|
|
|
* Option parser for partitioned tables
|
|
|
|
*/
|
|
|
|
bytea *
|
|
|
|
partitioned_table_reloptions(Datum reloptions, bool validate)
|
|
|
|
{
|
2022-11-09 18:28:34 +01:00
|
|
|
if (validate && reloptions)
|
|
|
|
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."));
|
|
|
|
return NULL;
|
2019-11-14 04:34:28 +01:00
|
|
|
}
|
|
|
|
|
2014-07-14 23:24:40 +02:00
|
|
|
/*
|
|
|
|
* Option parser for views
|
|
|
|
*/
|
|
|
|
bytea *
|
|
|
|
view_reloptions(Datum reloptions, bool validate)
|
|
|
|
{
|
|
|
|
static const relopt_parse_elt tab[] = {
|
|
|
|
{"security_barrier", RELOPT_TYPE_BOOL,
|
|
|
|
offsetof(ViewOptions, security_barrier)},
|
2022-03-22 11:28:10 +01:00
|
|
|
{"security_invoker", RELOPT_TYPE_BOOL,
|
|
|
|
offsetof(ViewOptions, security_invoker)},
|
2019-09-25 20:56:52 +02:00
|
|
|
{"check_option", RELOPT_TYPE_ENUM,
|
|
|
|
offsetof(ViewOptions, check_option)}
|
2014-07-14 23:24:40 +02:00
|
|
|
};
|
|
|
|
|
2019-11-05 01:17:05 +01:00
|
|
|
return (bytea *) build_reloptions(reloptions, validate,
|
|
|
|
RELOPT_KIND_VIEW,
|
|
|
|
sizeof(ViewOptions),
|
|
|
|
tab, lengthof(tab));
|
2014-07-14 23:24:40 +02:00
|
|
|
}
|
|
|
|
|
2006-07-04 00:45:41 +02:00
|
|
|
/*
|
2011-12-22 22:15:57 +01:00
|
|
|
* Parse options for heaps, views and toast tables.
|
2006-07-04 00:45:41 +02:00
|
|
|
*/
|
|
|
|
bytea *
|
|
|
|
heap_reloptions(char relkind, Datum reloptions, bool validate)
|
|
|
|
{
|
2010-06-07 04:59:02 +02:00
|
|
|
StdRdOptions *rdopts;
|
|
|
|
|
2009-04-04 02:45:02 +02:00
|
|
|
switch (relkind)
|
|
|
|
{
|
|
|
|
case RELKIND_TOASTVALUE:
|
2010-06-07 04:59:02 +02:00
|
|
|
rdopts = (StdRdOptions *)
|
|
|
|
default_reloptions(reloptions, validate, RELOPT_KIND_TOAST);
|
|
|
|
if (rdopts != NULL)
|
|
|
|
{
|
|
|
|
/* adjust default-only parameters for TOAST relations */
|
|
|
|
rdopts->fillfactor = 100;
|
|
|
|
rdopts->autovacuum.analyze_threshold = -1;
|
|
|
|
rdopts->autovacuum.analyze_scale_factor = -1;
|
|
|
|
}
|
|
|
|
return (bytea *) rdopts;
|
2009-04-04 02:45:02 +02:00
|
|
|
case RELKIND_RELATION:
|
2013-03-04 01:23:31 +01:00
|
|
|
case RELKIND_MATVIEW:
|
2009-04-04 02:45:02 +02:00
|
|
|
return default_reloptions(reloptions, validate, RELOPT_KIND_HEAP);
|
|
|
|
default:
|
2011-01-02 05:48:11 +01:00
|
|
|
/* other relkinds are not supported */
|
2009-04-04 02:45:02 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
2006-07-04 00:45:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse options for indexes.
|
|
|
|
*
|
Restructure index access method API to hide most of it at the C level.
This patch reduces pg_am to just two columns, a name and a handler
function. All the data formerly obtained from pg_am is now provided
in a C struct returned by the handler function. This is similar to
the designs we've adopted for FDWs and tablesample methods. There
are multiple advantages. For one, the index AM's support functions
are now simple C functions, making them faster to call and much less
error-prone, since the C compiler can now check function signatures.
For another, this will make it far more practical to define index access
methods in installable extensions.
A disadvantage is that SQL-level code can no longer see attributes
of index AMs; in particular, some of the crosschecks in the opr_sanity
regression test are no longer possible from SQL. We've addressed that
by adding a facility for the index AM to perform such checks instead.
(Much more could be done in that line, but for now we're content if the
amvalidate functions more or less replace what opr_sanity used to do.)
We might also want to expose some sort of reporting functionality, but
this patch doesn't do that.
Alexander Korotkov, reviewed by Petr Jelínek, and rather heavily
editorialized on by me.
2016-01-18 01:36:59 +01:00
|
|
|
* amoptions index AM's option parser function
|
2006-07-04 00:45:41 +02:00
|
|
|
* reloptions options as text[] datum
|
|
|
|
* validate error flag
|
|
|
|
*/
|
|
|
|
bytea *
|
Restructure index access method API to hide most of it at the C level.
This patch reduces pg_am to just two columns, a name and a handler
function. All the data formerly obtained from pg_am is now provided
in a C struct returned by the handler function. This is similar to
the designs we've adopted for FDWs and tablesample methods. There
are multiple advantages. For one, the index AM's support functions
are now simple C functions, making them faster to call and much less
error-prone, since the C compiler can now check function signatures.
For another, this will make it far more practical to define index access
methods in installable extensions.
A disadvantage is that SQL-level code can no longer see attributes
of index AMs; in particular, some of the crosschecks in the opr_sanity
regression test are no longer possible from SQL. We've addressed that
by adding a facility for the index AM to perform such checks instead.
(Much more could be done in that line, but for now we're content if the
amvalidate functions more or less replace what opr_sanity used to do.)
We might also want to expose some sort of reporting functionality, but
this patch doesn't do that.
Alexander Korotkov, reviewed by Petr Jelínek, and rather heavily
editorialized on by me.
2016-01-18 01:36:59 +01:00
|
|
|
index_reloptions(amoptions_function amoptions, Datum reloptions, bool validate)
|
2006-07-04 00:45:41 +02:00
|
|
|
{
|
Restructure index access method API to hide most of it at the C level.
This patch reduces pg_am to just two columns, a name and a handler
function. All the data formerly obtained from pg_am is now provided
in a C struct returned by the handler function. This is similar to
the designs we've adopted for FDWs and tablesample methods. There
are multiple advantages. For one, the index AM's support functions
are now simple C functions, making them faster to call and much less
error-prone, since the C compiler can now check function signatures.
For another, this will make it far more practical to define index access
methods in installable extensions.
A disadvantage is that SQL-level code can no longer see attributes
of index AMs; in particular, some of the crosschecks in the opr_sanity
regression test are no longer possible from SQL. We've addressed that
by adding a facility for the index AM to perform such checks instead.
(Much more could be done in that line, but for now we're content if the
amvalidate functions more or less replace what opr_sanity used to do.)
We might also want to expose some sort of reporting functionality, but
this patch doesn't do that.
Alexander Korotkov, reviewed by Petr Jelínek, and rather heavily
editorialized on by me.
2016-01-18 01:36:59 +01:00
|
|
|
Assert(amoptions != NULL);
|
2006-07-04 00:45:41 +02:00
|
|
|
|
|
|
|
/* Assume function is strict */
|
2008-04-17 23:37:28 +02:00
|
|
|
if (!PointerIsValid(DatumGetPointer(reloptions)))
|
2006-07-04 00:45:41 +02:00
|
|
|
return NULL;
|
|
|
|
|
Restructure index access method API to hide most of it at the C level.
This patch reduces pg_am to just two columns, a name and a handler
function. All the data formerly obtained from pg_am is now provided
in a C struct returned by the handler function. This is similar to
the designs we've adopted for FDWs and tablesample methods. There
are multiple advantages. For one, the index AM's support functions
are now simple C functions, making them faster to call and much less
error-prone, since the C compiler can now check function signatures.
For another, this will make it far more practical to define index access
methods in installable extensions.
A disadvantage is that SQL-level code can no longer see attributes
of index AMs; in particular, some of the crosschecks in the opr_sanity
regression test are no longer possible from SQL. We've addressed that
by adding a facility for the index AM to perform such checks instead.
(Much more could be done in that line, but for now we're content if the
amvalidate functions more or less replace what opr_sanity used to do.)
We might also want to expose some sort of reporting functionality, but
this patch doesn't do that.
Alexander Korotkov, reviewed by Petr Jelínek, and rather heavily
editorialized on by me.
2016-01-18 01:36:59 +01:00
|
|
|
return amoptions(reloptions, validate);
|
2006-07-04 00:45:41 +02:00
|
|
|
}
|
2010-01-05 22:54:00 +01:00
|
|
|
|
2010-01-22 17:40:19 +01:00
|
|
|
/*
|
|
|
|
* Option parser for attribute reloptions
|
|
|
|
*/
|
|
|
|
bytea *
|
|
|
|
attribute_reloptions(Datum reloptions, bool validate)
|
|
|
|
{
|
|
|
|
static const relopt_parse_elt tab[] = {
|
|
|
|
{"n_distinct", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct)},
|
|
|
|
{"n_distinct_inherited", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct_inherited)}
|
|
|
|
};
|
|
|
|
|
2019-11-05 01:17:05 +01:00
|
|
|
return (bytea *) build_reloptions(reloptions, validate,
|
|
|
|
RELOPT_KIND_ATTRIBUTE,
|
|
|
|
sizeof(AttributeOpts),
|
|
|
|
tab, lengthof(tab));
|
2010-01-22 17:40:19 +01:00
|
|
|
}
|
|
|
|
|
2010-01-05 22:54:00 +01:00
|
|
|
/*
|
|
|
|
* Option parser for tablespace reloptions
|
|
|
|
*/
|
|
|
|
bytea *
|
|
|
|
tablespace_reloptions(Datum reloptions, bool validate)
|
|
|
|
{
|
|
|
|
static const relopt_parse_elt tab[] = {
|
|
|
|
{"random_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, random_page_cost)},
|
2015-09-08 17:51:42 +02:00
|
|
|
{"seq_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, seq_page_cost)},
|
2020-03-16 00:31:34 +01:00
|
|
|
{"effective_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, effective_io_concurrency)},
|
|
|
|
{"maintenance_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, maintenance_io_concurrency)}
|
2010-01-05 22:54:00 +01:00
|
|
|
};
|
|
|
|
|
2019-11-05 01:17:05 +01:00
|
|
|
return (bytea *) build_reloptions(reloptions, validate,
|
|
|
|
RELOPT_KIND_TABLESPACE,
|
|
|
|
sizeof(TableSpaceOpts),
|
|
|
|
tab, lengthof(tab));
|
2010-01-05 22:54:00 +01:00
|
|
|
}
|
2015-08-14 15:19:28 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Determine the required LOCKMODE from an option list.
|
|
|
|
*
|
|
|
|
* Called from AlterTableGetLockLevel(), see that function
|
|
|
|
* for a longer explanation of how this works.
|
|
|
|
*/
|
|
|
|
LOCKMODE
|
|
|
|
AlterTableGetRelOptionsLockLevel(List *defList)
|
|
|
|
{
|
|
|
|
LOCKMODE lockmode = NoLock;
|
|
|
|
ListCell *cell;
|
|
|
|
|
|
|
|
if (defList == NIL)
|
|
|
|
return AccessExclusiveLock;
|
|
|
|
|
|
|
|
if (need_initialization)
|
|
|
|
initialize_reloptions();
|
|
|
|
|
|
|
|
foreach(cell, defList)
|
|
|
|
{
|
|
|
|
DefElem *def = (DefElem *) lfirst(cell);
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; relOpts[i]; i++)
|
|
|
|
{
|
Avoid unnecessary use of pg_strcasecmp for already-downcased identifiers.
We have a lot of code in which option names, which from the user's
viewpoint are logically keywords, are passed through the grammar as plain
identifiers, and then matched to string literals during command execution.
This approach avoids making words into lexer keywords unnecessarily. Some
places matched these strings using plain strcmp, some using pg_strcasecmp.
But the latter should be unnecessary since identifiers would have been
downcased on their way through the parser. Aside from any efficiency
concerns (probably not a big factor), the lack of consistency in this area
creates a hazard of subtle bugs due to different places coming to different
conclusions about whether two option names are the same or different.
Hence, standardize on using strcmp() to match any option names that are
expected to have been fed through the parser.
This does create a user-visible behavioral change, which is that while
formerly all of these would work:
alter table foo set (fillfactor = 50);
alter table foo set (FillFactor = 50);
alter table foo set ("fillfactor" = 50);
alter table foo set ("FillFactor" = 50);
now the last case will fail because that double-quoted identifier is
different from the others. However, none of our documentation says that
you can use a quoted identifier in such contexts at all, and we should
discourage doing so since it would break if we ever decide to parse such
constructs as true lexer keywords rather than poor man's substitutes.
So this shouldn't create a significant compatibility issue for users.
Daniel Gustafsson, reviewed by Michael Paquier, small changes by me
Discussion: https://postgr.es/m/29405B24-564E-476B-98C0-677A29805B84@yesql.se
2018-01-27 00:25:02 +01:00
|
|
|
if (strncmp(relOpts[i]->name,
|
|
|
|
def->defname,
|
|
|
|
relOpts[i]->namelen + 1) == 0)
|
2015-08-14 15:19:28 +02:00
|
|
|
{
|
|
|
|
if (lockmode < relOpts[i]->lockmode)
|
|
|
|
lockmode = relOpts[i]->lockmode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return lockmode;
|
|
|
|
}
|