2011-02-08 22:08:41 +01:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* extension.c
|
|
|
|
* Commands to manipulate extensions
|
|
|
|
*
|
|
|
|
* Extensions in PostgreSQL allow management of collections of SQL objects.
|
|
|
|
*
|
|
|
|
* All we need internally to manage an extension is an OID so that the
|
|
|
|
* dependent objects can be associated with it. An extension is created by
|
|
|
|
* populating the pg_extension catalog from a "control" file.
|
|
|
|
* The extension control file is parsed with the same parser we use for
|
2018-11-25 16:31:16 +01:00
|
|
|
* postgresql.conf. An extension also has an installation script file,
|
|
|
|
* containing SQL commands to create the extension's objects.
|
2011-02-08 22:08:41 +01:00
|
|
|
*
|
2024-01-04 02:49:05 +01:00
|
|
|
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
|
2011-02-08 22:08:41 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
|
|
|
* src/backend/commands/extension.c
|
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
#include <dirent.h>
|
2011-02-14 22:07:00 +01:00
|
|
|
#include <limits.h>
|
2015-06-28 20:35:46 +02:00
|
|
|
#include <sys/file.h>
|
|
|
|
#include <sys/stat.h>
|
2011-02-08 22:08:41 +01:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2019-12-27 00:09:00 +01:00
|
|
|
#include "access/genam.h"
|
2012-08-30 22:15:44 +02:00
|
|
|
#include "access/htup_details.h"
|
2019-01-21 19:18:20 +01:00
|
|
|
#include "access/relation.h"
|
|
|
|
#include "access/table.h"
|
2011-02-08 22:08:41 +01:00
|
|
|
#include "access/xact.h"
|
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
|
|
|
#include "catalog/catalog.h"
|
2011-02-08 22:08:41 +01:00
|
|
|
#include "catalog/dependency.h"
|
|
|
|
#include "catalog/indexing.h"
|
|
|
|
#include "catalog/namespace.h"
|
2011-03-24 23:44:49 +01:00
|
|
|
#include "catalog/objectaccess.h"
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
#include "catalog/pg_authid.h"
|
2011-10-12 21:45:03 +02:00
|
|
|
#include "catalog/pg_collation.h"
|
2022-11-13 08:11:17 +01:00
|
|
|
#include "catalog/pg_database.h"
|
2011-02-08 22:08:41 +01:00
|
|
|
#include "catalog/pg_depend.h"
|
|
|
|
#include "catalog/pg_extension.h"
|
|
|
|
#include "catalog/pg_namespace.h"
|
|
|
|
#include "catalog/pg_type.h"
|
|
|
|
#include "commands/alter.h"
|
|
|
|
#include "commands/comment.h"
|
2015-10-03 18:19:37 +02:00
|
|
|
#include "commands/defrem.h"
|
2011-02-08 22:08:41 +01:00
|
|
|
#include "commands/extension.h"
|
2011-08-24 03:49:07 +02:00
|
|
|
#include "commands/schemacmds.h"
|
2011-02-08 22:08:41 +01:00
|
|
|
#include "funcapi.h"
|
|
|
|
#include "mb/pg_wchar.h"
|
|
|
|
#include "miscadmin.h"
|
2012-08-29 00:02:07 +02:00
|
|
|
#include "storage/fd.h"
|
2011-02-08 22:08:41 +01:00
|
|
|
#include "tcop/utility.h"
|
2017-01-30 05:05:07 +01:00
|
|
|
#include "utils/acl.h"
|
2011-02-08 22:08:41 +01:00
|
|
|
#include "utils/builtins.h"
|
2022-11-24 23:40:12 +01:00
|
|
|
#include "utils/conffiles.h"
|
2011-02-08 22:08:41 +01:00
|
|
|
#include "utils/fmgroids.h"
|
|
|
|
#include "utils/lsyscache.h"
|
2015-06-28 20:35:46 +02:00
|
|
|
#include "utils/memutils.h"
|
2011-02-23 18:18:09 +01:00
|
|
|
#include "utils/rel.h"
|
2011-02-08 22:08:41 +01:00
|
|
|
#include "utils/snapmgr.h"
|
2017-01-21 02:29:53 +01:00
|
|
|
#include "utils/varlena.h"
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
/* Globally visible state variables */
|
2011-02-08 22:08:41 +01:00
|
|
|
bool creating_extension = false;
|
|
|
|
Oid CurrentExtensionObject = InvalidOid;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Internal data structure to hold the results of parsing a control file
|
|
|
|
*/
|
|
|
|
typedef struct ExtensionControlFile
|
|
|
|
{
|
|
|
|
char *name; /* name of the extension */
|
2011-02-12 03:25:20 +01:00
|
|
|
char *directory; /* directory for script files */
|
|
|
|
char *default_version; /* default install target version, if any */
|
2011-02-13 19:38:05 +01:00
|
|
|
char *module_pathname; /* string to substitute for
|
|
|
|
* MODULE_PATHNAME */
|
2011-02-08 22:08:41 +01:00
|
|
|
char *comment; /* comment, if any */
|
|
|
|
char *schema; /* target schema (allowed if !relocatable) */
|
|
|
|
bool relocatable; /* is ALTER EXTENSION SET SCHEMA supported? */
|
2011-03-04 22:08:24 +01:00
|
|
|
bool superuser; /* must be superuser to install? */
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
bool trusted; /* allow becoming superuser on the fly? */
|
2011-02-08 22:08:41 +01:00
|
|
|
int encoding; /* encoding of the script file, or -1 */
|
|
|
|
List *requires; /* names of prerequisite extensions */
|
2023-03-20 23:37:11 +01:00
|
|
|
List *no_relocate; /* names of prerequisite extensions that
|
|
|
|
* should not be relocated */
|
2011-02-08 22:08:41 +01:00
|
|
|
} ExtensionControlFile;
|
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
/*
|
|
|
|
* Internal data structure for update path information
|
|
|
|
*/
|
|
|
|
typedef struct ExtensionVersionInfo
|
|
|
|
{
|
|
|
|
char *name; /* name of the starting version */
|
|
|
|
List *reachable; /* List of ExtensionVersionInfo's */
|
2011-02-14 22:07:00 +01:00
|
|
|
bool installable; /* does this version have an install script? */
|
2011-02-12 03:25:20 +01:00
|
|
|
/* working state for Dijkstra's algorithm: */
|
|
|
|
bool distance_known; /* is distance from start known yet? */
|
|
|
|
int distance; /* current worst-case distance estimate */
|
|
|
|
struct ExtensionVersionInfo *previous; /* current best predecessor */
|
|
|
|
} ExtensionVersionInfo;
|
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
/* Local functions */
|
2011-02-14 22:07:00 +01:00
|
|
|
static List *find_update_path(List *evi_list,
|
|
|
|
ExtensionVersionInfo *evi_start,
|
|
|
|
ExtensionVersionInfo *evi_target,
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
bool reject_indirect,
|
2011-02-14 22:07:00 +01:00
|
|
|
bool reinitialize);
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
static Oid get_required_extension(char *reqExtensionName,
|
|
|
|
char *extensionName,
|
|
|
|
char *origSchemaName,
|
|
|
|
bool cascade,
|
|
|
|
List *parents,
|
|
|
|
bool is_create);
|
2011-02-14 22:07:00 +01:00
|
|
|
static void get_available_versions_for_extension(ExtensionControlFile *pcontrol,
|
|
|
|
Tuplestorestate *tupstore,
|
|
|
|
TupleDesc tupdesc);
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
static Datum convert_requires_to_datum(List *requires);
|
2011-02-12 22:40:41 +01:00
|
|
|
static void ApplyExtensionUpdates(Oid extensionOid,
|
|
|
|
ExtensionControlFile *pcontrol,
|
|
|
|
const char *initialVersion,
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
List *updateVersions,
|
|
|
|
char *origSchemaName,
|
|
|
|
bool cascade,
|
|
|
|
bool is_create);
|
Explicitly list dependent types as extension members in pg_depend.
Auto-generated array types, multirange types, and relation rowtypes
are treated as dependent objects: they can't be dropped separately
from the base object, nor can they have their own ownership or
permissions. We previously felt that, for objects that are in an
extension, only the base object needs to be listed as an extension
member in pg_depend. While that's sufficient to prevent inappropriate
drops, it results in undesirable answers if someone asks whether a
dependent type belongs to the extension. It looks like the dependent
type is just some random separately-created object that happens to
depend on the base object. Notably, this results in postgres_fdw
concluding that expressions involving an array type are not shippable
to the remote server, even when the defining extension has been
whitelisted.
To fix, cause GenerateTypeDependencies to make extension dependencies
for dependent types as well as their base objects, and adjust
ExecAlterExtensionContentsStmt so that object addition and removal
operations recurse to dependent types. The latter change means that
pg_upgrade of a type-defining extension will end with the dependent
type(s) now also listed as extension members, even if they were
not that way in the source database. Normally we want pg_upgrade
to precisely reproduce the source extension's state, but it seems
desirable to make an exception here.
This is arguably a bug fix, but we can't back-patch it since it
causes changes in the expected contents of pg_depend. (Because
it does, I've bumped catversion, even though there's no change
in the immediate post-initdb catalog contents.)
Tom Lane and David Geier
Discussion: https://postgr.es/m/4a847c55-489f-4e8d-a664-fc6b1cbe306f@gmail.com
2024-03-04 20:49:31 +01:00
|
|
|
static void ExecAlterExtensionContentsRecurse(AlterExtensionContentsStmt *stmt,
|
|
|
|
ObjectAddress extension,
|
|
|
|
ObjectAddress object);
|
2015-06-28 20:35:46 +02:00
|
|
|
static char *read_whole_file(const char *filename, int *length);
|
2011-02-12 22:40:41 +01:00
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* get_extension_oid - given an extension name, look up the OID
|
|
|
|
*
|
|
|
|
* If missing_ok is false, throw an error if extension name not found. If
|
|
|
|
* true, just return InvalidOid.
|
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
get_extension_oid(const char *extname, bool missing_ok)
|
|
|
|
{
|
|
|
|
Oid result;
|
|
|
|
Relation rel;
|
|
|
|
SysScanDesc scandesc;
|
|
|
|
HeapTuple tuple;
|
|
|
|
ScanKeyData entry[1];
|
|
|
|
|
2019-01-21 19:32:19 +01:00
|
|
|
rel = table_open(ExtensionRelationId, AccessShareLock);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
ScanKeyInit(&entry[0],
|
|
|
|
Anum_pg_extension_extname,
|
|
|
|
BTEqualStrategyNumber, F_NAMEEQ,
|
|
|
|
CStringGetDatum(extname));
|
|
|
|
|
|
|
|
scandesc = systable_beginscan(rel, ExtensionNameIndexId, true,
|
Use an MVCC snapshot, rather than SnapshotNow, for catalog scans.
SnapshotNow scans have the undesirable property that, in the face of
concurrent updates, the scan can fail to see either the old or the new
versions of the row. In many cases, we work around this by requiring
DDL operations to hold AccessExclusiveLock on the object being
modified; in some cases, the existing locking is inadequate and random
failures occur as a result. This commit doesn't change anything
related to locking, but will hopefully pave the way to allowing lock
strength reductions in the future.
The major issue has held us back from making this change in the past
is that taking an MVCC snapshot is significantly more expensive than
using a static special snapshot such as SnapshotNow. However, testing
of various worst-case scenarios reveals that this problem is not
severe except under fairly extreme workloads. To mitigate those
problems, we avoid retaking the MVCC snapshot for each new scan;
instead, we take a new snapshot only when invalidation messages have
been processed. The catcache machinery already requires that
invalidation messages be sent before releasing the related heavyweight
lock; else other backends might rely on locally-cached data rather
than scanning the catalog at all. Thus, making snapshot reuse
dependent on the same guarantees shouldn't break anything that wasn't
already subtly broken.
Patch by me. Review by Michael Paquier and Andres Freund.
2013-07-02 15:47:01 +02:00
|
|
|
NULL, 1, entry);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
tuple = systable_getnext(scandesc);
|
|
|
|
|
|
|
|
/* We assume that there can be at most one matching tuple */
|
|
|
|
if (HeapTupleIsValid(tuple))
|
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
|
|
|
result = ((Form_pg_extension) GETSTRUCT(tuple))->oid;
|
2011-02-08 22:08:41 +01:00
|
|
|
else
|
|
|
|
result = InvalidOid;
|
|
|
|
|
|
|
|
systable_endscan(scandesc);
|
|
|
|
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(rel, AccessShareLock);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
if (!OidIsValid(result) && !missing_ok)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("extension \"%s\" does not exist",
|
|
|
|
extname)));
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* get_extension_name - given an extension OID, look up the name
|
|
|
|
*
|
|
|
|
* Returns a palloc'd string, or NULL if no such extension.
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
get_extension_name(Oid ext_oid)
|
|
|
|
{
|
|
|
|
char *result;
|
|
|
|
Relation rel;
|
|
|
|
SysScanDesc scandesc;
|
|
|
|
HeapTuple tuple;
|
|
|
|
ScanKeyData entry[1];
|
|
|
|
|
2019-01-21 19:32:19 +01:00
|
|
|
rel = table_open(ExtensionRelationId, AccessShareLock);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
ScanKeyInit(&entry[0],
|
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
|
|
|
Anum_pg_extension_oid,
|
2011-02-08 22:08:41 +01:00
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(ext_oid));
|
|
|
|
|
|
|
|
scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
|
Use an MVCC snapshot, rather than SnapshotNow, for catalog scans.
SnapshotNow scans have the undesirable property that, in the face of
concurrent updates, the scan can fail to see either the old or the new
versions of the row. In many cases, we work around this by requiring
DDL operations to hold AccessExclusiveLock on the object being
modified; in some cases, the existing locking is inadequate and random
failures occur as a result. This commit doesn't change anything
related to locking, but will hopefully pave the way to allowing lock
strength reductions in the future.
The major issue has held us back from making this change in the past
is that taking an MVCC snapshot is significantly more expensive than
using a static special snapshot such as SnapshotNow. However, testing
of various worst-case scenarios reveals that this problem is not
severe except under fairly extreme workloads. To mitigate those
problems, we avoid retaking the MVCC snapshot for each new scan;
instead, we take a new snapshot only when invalidation messages have
been processed. The catcache machinery already requires that
invalidation messages be sent before releasing the related heavyweight
lock; else other backends might rely on locally-cached data rather
than scanning the catalog at all. Thus, making snapshot reuse
dependent on the same guarantees shouldn't break anything that wasn't
already subtly broken.
Patch by me. Review by Michael Paquier and Andres Freund.
2013-07-02 15:47:01 +02:00
|
|
|
NULL, 1, entry);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
tuple = systable_getnext(scandesc);
|
|
|
|
|
|
|
|
/* We assume that there can be at most one matching tuple */
|
|
|
|
if (HeapTupleIsValid(tuple))
|
|
|
|
result = pstrdup(NameStr(((Form_pg_extension) GETSTRUCT(tuple))->extname));
|
|
|
|
else
|
|
|
|
result = NULL;
|
|
|
|
|
|
|
|
systable_endscan(scandesc);
|
|
|
|
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(rel, AccessShareLock);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* get_extension_schema - given an extension OID, fetch its extnamespace
|
|
|
|
*
|
|
|
|
* Returns InvalidOid if no such extension.
|
|
|
|
*/
|
2023-03-07 06:18:20 +01:00
|
|
|
Oid
|
2011-02-08 22:08:41 +01:00
|
|
|
get_extension_schema(Oid ext_oid)
|
|
|
|
{
|
|
|
|
Oid result;
|
|
|
|
Relation rel;
|
|
|
|
SysScanDesc scandesc;
|
|
|
|
HeapTuple tuple;
|
|
|
|
ScanKeyData entry[1];
|
|
|
|
|
2019-01-21 19:32:19 +01:00
|
|
|
rel = table_open(ExtensionRelationId, AccessShareLock);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
ScanKeyInit(&entry[0],
|
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
|
|
|
Anum_pg_extension_oid,
|
2011-02-08 22:08:41 +01:00
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(ext_oid));
|
|
|
|
|
|
|
|
scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
|
Use an MVCC snapshot, rather than SnapshotNow, for catalog scans.
SnapshotNow scans have the undesirable property that, in the face of
concurrent updates, the scan can fail to see either the old or the new
versions of the row. In many cases, we work around this by requiring
DDL operations to hold AccessExclusiveLock on the object being
modified; in some cases, the existing locking is inadequate and random
failures occur as a result. This commit doesn't change anything
related to locking, but will hopefully pave the way to allowing lock
strength reductions in the future.
The major issue has held us back from making this change in the past
is that taking an MVCC snapshot is significantly more expensive than
using a static special snapshot such as SnapshotNow. However, testing
of various worst-case scenarios reveals that this problem is not
severe except under fairly extreme workloads. To mitigate those
problems, we avoid retaking the MVCC snapshot for each new scan;
instead, we take a new snapshot only when invalidation messages have
been processed. The catcache machinery already requires that
invalidation messages be sent before releasing the related heavyweight
lock; else other backends might rely on locally-cached data rather
than scanning the catalog at all. Thus, making snapshot reuse
dependent on the same guarantees shouldn't break anything that wasn't
already subtly broken.
Patch by me. Review by Michael Paquier and Andres Freund.
2013-07-02 15:47:01 +02:00
|
|
|
NULL, 1, entry);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
tuple = systable_getnext(scandesc);
|
|
|
|
|
|
|
|
/* We assume that there can be at most one matching tuple */
|
|
|
|
if (HeapTupleIsValid(tuple))
|
|
|
|
result = ((Form_pg_extension) GETSTRUCT(tuple))->extnamespace;
|
|
|
|
else
|
|
|
|
result = InvalidOid;
|
|
|
|
|
|
|
|
systable_endscan(scandesc);
|
|
|
|
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(rel, AccessShareLock);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
/*
|
|
|
|
* Utility functions to check validity of extension and version names
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
check_valid_extension_name(const char *extensionname)
|
|
|
|
{
|
2011-02-13 19:03:41 +01:00
|
|
|
int namelen = strlen(extensionname);
|
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
/*
|
2011-02-13 19:03:41 +01:00
|
|
|
* Disallow empty names (the parser rejects empty identifiers anyway, but
|
|
|
|
* let's check).
|
|
|
|
*/
|
|
|
|
if (namelen == 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("invalid extension name: \"%s\"", extensionname),
|
|
|
|
errdetail("Extension names must not be empty.")));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No double dashes, since that would make script filenames ambiguous.
|
|
|
|
*/
|
|
|
|
if (strstr(extensionname, "--"))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("invalid extension name: \"%s\"", extensionname),
|
|
|
|
errdetail("Extension names must not contain \"--\".")));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No leading or trailing dash either. (We could probably allow this, but
|
|
|
|
* it would require much care in filename parsing and would make filenames
|
|
|
|
* visually if not formally ambiguous. Since there's no real-world use
|
|
|
|
* case, let's just forbid it.)
|
|
|
|
*/
|
|
|
|
if (extensionname[0] == '-' || extensionname[namelen - 1] == '-')
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("invalid extension name: \"%s\"", extensionname),
|
|
|
|
errdetail("Extension names must not begin or end with \"-\".")));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No directory separators either (this is sufficient to prevent ".."
|
|
|
|
* style attacks).
|
2011-02-12 03:25:20 +01:00
|
|
|
*/
|
|
|
|
if (first_dir_separator(extensionname) != NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("invalid extension name: \"%s\"", extensionname),
|
|
|
|
errdetail("Extension names must not contain directory separator characters.")));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
check_valid_version_name(const char *versionname)
|
|
|
|
{
|
2011-02-13 19:03:41 +01:00
|
|
|
int namelen = strlen(versionname);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Disallow empty names (we could possibly allow this, but there seems
|
|
|
|
* little point).
|
|
|
|
*/
|
|
|
|
if (namelen == 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("invalid extension version name: \"%s\"", versionname),
|
|
|
|
errdetail("Version names must not be empty.")));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No double dashes, since that would make script filenames ambiguous.
|
|
|
|
*/
|
|
|
|
if (strstr(versionname, "--"))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("invalid extension version name: \"%s\"", versionname),
|
|
|
|
errdetail("Version names must not contain \"--\".")));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No leading or trailing dash either.
|
|
|
|
*/
|
|
|
|
if (versionname[0] == '-' || versionname[namelen - 1] == '-')
|
2011-02-12 03:25:20 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("invalid extension version name: \"%s\"", versionname),
|
2011-02-13 19:03:41 +01:00
|
|
|
errdetail("Version names must not begin or end with \"-\".")));
|
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
/*
|
2011-02-13 19:03:41 +01:00
|
|
|
* No directory separators either (this is sufficient to prevent ".."
|
|
|
|
* style attacks).
|
2011-02-12 03:25:20 +01:00
|
|
|
*/
|
|
|
|
if (first_dir_separator(versionname) != NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("invalid extension version name: \"%s\"", versionname),
|
|
|
|
errdetail("Version names must not contain directory separator characters.")));
|
|
|
|
}
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
/*
|
|
|
|
* Utility functions to handle extension-related path names
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
is_extension_control_filename(const char *filename)
|
|
|
|
{
|
|
|
|
const char *extension = strrchr(filename, '.');
|
|
|
|
|
|
|
|
return (extension != NULL) && (strcmp(extension, ".control") == 0);
|
|
|
|
}
|
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
static bool
|
|
|
|
is_extension_script_filename(const char *filename)
|
|
|
|
{
|
|
|
|
const char *extension = strrchr(filename, '.');
|
|
|
|
|
|
|
|
return (extension != NULL) && (strcmp(extension, ".sql") == 0);
|
|
|
|
}
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
static char *
|
|
|
|
get_extension_control_directory(void)
|
|
|
|
{
|
|
|
|
char sharepath[MAXPGPATH];
|
|
|
|
char *result;
|
|
|
|
|
|
|
|
get_share_path(my_exec_path, sharepath);
|
|
|
|
result = (char *) palloc(MAXPGPATH);
|
2011-02-12 04:53:43 +01:00
|
|
|
snprintf(result, MAXPGPATH, "%s/extension", sharepath);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
get_extension_control_filename(const char *extname)
|
|
|
|
{
|
|
|
|
char sharepath[MAXPGPATH];
|
|
|
|
char *result;
|
|
|
|
|
|
|
|
get_share_path(my_exec_path, sharepath);
|
|
|
|
result = (char *) palloc(MAXPGPATH);
|
2011-02-12 04:53:43 +01:00
|
|
|
snprintf(result, MAXPGPATH, "%s/extension/%s.control",
|
2011-02-12 03:25:20 +01:00
|
|
|
sharepath, extname);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
2011-02-12 03:25:20 +01:00
|
|
|
get_extension_script_directory(ExtensionControlFile *control)
|
2011-02-08 22:08:41 +01:00
|
|
|
{
|
|
|
|
char sharepath[MAXPGPATH];
|
|
|
|
char *result;
|
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
/*
|
|
|
|
* The directory parameter can be omitted, absolute, or relative to the
|
2011-02-12 04:53:43 +01:00
|
|
|
* installation's share directory.
|
2011-02-12 03:25:20 +01:00
|
|
|
*/
|
|
|
|
if (!control->directory)
|
|
|
|
return get_extension_control_directory();
|
|
|
|
|
|
|
|
if (is_absolute_path(control->directory))
|
|
|
|
return pstrdup(control->directory);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
get_share_path(my_exec_path, sharepath);
|
|
|
|
result = (char *) palloc(MAXPGPATH);
|
2011-02-12 04:53:43 +01:00
|
|
|
snprintf(result, MAXPGPATH, "%s/%s", sharepath, control->directory);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
get_extension_aux_control_filename(ExtensionControlFile *control,
|
|
|
|
const char *version)
|
|
|
|
{
|
|
|
|
char *result;
|
|
|
|
char *scriptdir;
|
|
|
|
|
|
|
|
scriptdir = get_extension_script_directory(control);
|
|
|
|
|
|
|
|
result = (char *) palloc(MAXPGPATH);
|
2011-02-13 19:03:41 +01:00
|
|
|
snprintf(result, MAXPGPATH, "%s/%s--%s.control",
|
|
|
|
scriptdir, control->name, version);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
|
|
|
pfree(scriptdir);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
get_extension_script_filename(ExtensionControlFile *control,
|
|
|
|
const char *from_version, const char *version)
|
|
|
|
{
|
|
|
|
char *result;
|
|
|
|
char *scriptdir;
|
|
|
|
|
|
|
|
scriptdir = get_extension_script_directory(control);
|
|
|
|
|
|
|
|
result = (char *) palloc(MAXPGPATH);
|
|
|
|
if (from_version)
|
2011-02-13 19:03:41 +01:00
|
|
|
snprintf(result, MAXPGPATH, "%s/%s--%s--%s.sql",
|
|
|
|
scriptdir, control->name, from_version, version);
|
2011-02-12 03:25:20 +01:00
|
|
|
else
|
2011-02-13 19:03:41 +01:00
|
|
|
snprintf(result, MAXPGPATH, "%s/%s--%s.sql",
|
|
|
|
scriptdir, control->name, version);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
|
|
|
pfree(scriptdir);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2011-02-12 03:25:20 +01:00
|
|
|
* Parse contents of primary or auxiliary control file, and fill in
|
|
|
|
* fields of *control. We parse primary file if version == NULL,
|
|
|
|
* else the optional auxiliary file for that version.
|
2011-02-08 22:08:41 +01:00
|
|
|
*
|
2011-02-12 03:25:20 +01:00
|
|
|
* Control files are supposed to be very short, half a dozen lines,
|
|
|
|
* so we don't worry about memory allocation risks here. Also we don't
|
|
|
|
* worry about what encoding it's in; all values are expected to be ASCII.
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
2011-02-12 03:25:20 +01:00
|
|
|
static void
|
|
|
|
parse_extension_control_file(ExtensionControlFile *control,
|
|
|
|
const char *version)
|
2011-02-08 22:08:41 +01:00
|
|
|
{
|
2011-02-12 03:25:20 +01:00
|
|
|
char *filename;
|
2011-02-08 22:08:41 +01:00
|
|
|
FILE *file;
|
|
|
|
ConfigVariable *item,
|
|
|
|
*head = NULL,
|
|
|
|
*tail = NULL;
|
|
|
|
|
|
|
|
/*
|
2011-02-12 03:25:20 +01:00
|
|
|
* Locate the file to read. Auxiliary files are optional.
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
2011-02-12 03:25:20 +01:00
|
|
|
if (version)
|
|
|
|
filename = get_extension_aux_control_filename(control, version);
|
|
|
|
else
|
|
|
|
filename = get_extension_control_filename(control->name);
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
if ((file = AllocateFile(filename, "r")) == NULL)
|
2011-02-12 03:25:20 +01:00
|
|
|
{
|
2022-01-11 20:22:00 +01:00
|
|
|
if (errno == ENOENT)
|
2011-02-12 03:25:20 +01:00
|
|
|
{
|
2022-01-11 20:22:00 +01:00
|
|
|
/* no complaint for missing auxiliary file */
|
|
|
|
if (version)
|
|
|
|
{
|
|
|
|
pfree(filename);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* missing control file indicates extension is not installed */
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("extension \"%s\" is not available", control->name),
|
|
|
|
errdetail("Could not open extension control file \"%s\": %m.",
|
|
|
|
filename),
|
|
|
|
errhint("The extension must first be installed on the system where PostgreSQL is running.")));
|
2011-02-12 03:25:20 +01:00
|
|
|
}
|
2011-02-08 22:08:41 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode_for_file_access(),
|
|
|
|
errmsg("could not open extension control file \"%s\": %m",
|
|
|
|
filename)));
|
2011-02-12 03:25:20 +01:00
|
|
|
}
|
2011-02-08 22:08:41 +01:00
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
/*
|
Restructure error handling in reading of postgresql.conf.
This patch has two distinct purposes: to report multiple problems in
postgresql.conf rather than always bailing out after the first one,
and to change the policy for whether changes are applied when there are
unrelated errors in postgresql.conf.
Formerly the policy was to apply no changes if any errors could be
detected, but that had a significant consistency problem, because in some
cases specific values might be seen as valid by some processes but invalid
by others. This meant that the latter processes would fail to adopt
changes in other parameters even though the former processes had done so.
The new policy is that during SIGHUP, the file is rejected as a whole
if there are any errors in the "name = value" syntax, or if any lines
attempt to set nonexistent built-in parameters, or if any lines attempt
to set custom parameters whose prefix is not listed in (the new value of)
custom_variable_classes. These tests should always give the same results
in all processes, and provide what seems a reasonably robust defense
against loading values from badly corrupted config files. If these tests
pass, all processes will apply all settings that they individually see as
good, ignoring (but logging) any they don't.
In addition, the postmaster does not abandon reading a configuration file
after the first syntax error, but continues to read the file and report
syntax errors (up to a maximum of 100 syntax errors per file).
The postmaster will still refuse to start up if the configuration file
contains any errors at startup time, but these changes allow multiple
errors to be detected and reported before quitting.
Alexey Klyukin, reviewed by Andy Colson and av (Alexander ?)
with some additional hacking by Tom Lane
2011-10-02 22:50:04 +02:00
|
|
|
* Parse the file content, using GUC's file parsing code. We need not
|
|
|
|
* check the return value since any errors will be thrown at ERROR level.
|
2011-02-12 03:25:20 +01:00
|
|
|
*/
|
2022-11-24 23:40:12 +01:00
|
|
|
(void) ParseConfigFp(file, filename, CONF_FILE_START_DEPTH, ERROR,
|
|
|
|
&head, &tail);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
FreeFile(file);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert the ConfigVariable list into ExtensionControlFile entries.
|
|
|
|
*/
|
|
|
|
for (item = head; item != NULL; item = item->next)
|
|
|
|
{
|
2011-02-12 03:25:20 +01:00
|
|
|
if (strcmp(item->name, "directory") == 0)
|
2011-02-08 22:08:41 +01:00
|
|
|
{
|
2011-02-12 03:25:20 +01:00
|
|
|
if (version)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
2011-02-13 19:03:41 +01:00
|
|
|
errmsg("parameter \"%s\" cannot be set in a secondary extension control file",
|
2011-02-12 03:25:20 +01:00
|
|
|
item->name)));
|
|
|
|
|
|
|
|
control->directory = pstrdup(item->value);
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
2011-02-12 03:25:20 +01:00
|
|
|
else if (strcmp(item->name, "default_version") == 0)
|
2011-02-08 22:08:41 +01:00
|
|
|
{
|
2011-02-12 03:25:20 +01:00
|
|
|
if (version)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
2011-02-13 19:03:41 +01:00
|
|
|
errmsg("parameter \"%s\" cannot be set in a secondary extension control file",
|
2011-02-12 03:25:20 +01:00
|
|
|
item->name)));
|
|
|
|
|
|
|
|
control->default_version = pstrdup(item->value);
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
2011-02-13 19:38:05 +01:00
|
|
|
else if (strcmp(item->name, "module_pathname") == 0)
|
|
|
|
{
|
|
|
|
control->module_pathname = pstrdup(item->value);
|
|
|
|
}
|
2011-02-08 22:08:41 +01:00
|
|
|
else if (strcmp(item->name, "comment") == 0)
|
|
|
|
{
|
|
|
|
control->comment = pstrdup(item->value);
|
|
|
|
}
|
|
|
|
else if (strcmp(item->name, "schema") == 0)
|
|
|
|
{
|
|
|
|
control->schema = pstrdup(item->value);
|
|
|
|
}
|
|
|
|
else if (strcmp(item->name, "relocatable") == 0)
|
|
|
|
{
|
|
|
|
if (!parse_bool(item->value, &control->relocatable))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("parameter \"%s\" requires a Boolean value",
|
|
|
|
item->name)));
|
|
|
|
}
|
2011-03-04 22:08:24 +01:00
|
|
|
else if (strcmp(item->name, "superuser") == 0)
|
|
|
|
{
|
|
|
|
if (!parse_bool(item->value, &control->superuser))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("parameter \"%s\" requires a Boolean value",
|
|
|
|
item->name)));
|
|
|
|
}
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
else if (strcmp(item->name, "trusted") == 0)
|
|
|
|
{
|
|
|
|
if (!parse_bool(item->value, &control->trusted))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("parameter \"%s\" requires a Boolean value",
|
|
|
|
item->name)));
|
|
|
|
}
|
2011-02-08 22:08:41 +01:00
|
|
|
else if (strcmp(item->name, "encoding") == 0)
|
|
|
|
{
|
|
|
|
control->encoding = pg_valid_server_encoding(item->value);
|
|
|
|
if (control->encoding < 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("\"%s\" is not a valid encoding name",
|
|
|
|
item->value)));
|
|
|
|
}
|
|
|
|
else if (strcmp(item->name, "requires") == 0)
|
|
|
|
{
|
|
|
|
/* Need a modifiable copy of string */
|
|
|
|
char *rawnames = pstrdup(item->value);
|
|
|
|
|
|
|
|
/* Parse string into list of identifiers */
|
|
|
|
if (!SplitIdentifierString(rawnames, ',', &control->requires))
|
|
|
|
{
|
|
|
|
/* syntax error in name list */
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("parameter \"%s\" must be a list of extension names",
|
|
|
|
item->name)));
|
|
|
|
}
|
|
|
|
}
|
2023-03-20 23:37:11 +01:00
|
|
|
else if (strcmp(item->name, "no_relocate") == 0)
|
|
|
|
{
|
|
|
|
/* Need a modifiable copy of string */
|
|
|
|
char *rawnames = pstrdup(item->value);
|
|
|
|
|
|
|
|
/* Parse string into list of identifiers */
|
|
|
|
if (!SplitIdentifierString(rawnames, ',', &control->no_relocate))
|
|
|
|
{
|
|
|
|
/* syntax error in name list */
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("parameter \"%s\" must be a list of extension names",
|
|
|
|
item->name)));
|
|
|
|
}
|
|
|
|
}
|
2011-02-08 22:08:41 +01:00
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("unrecognized parameter \"%s\" in file \"%s\"",
|
|
|
|
item->name, filename)));
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeConfigVariables(head);
|
|
|
|
|
|
|
|
if (control->relocatable && control->schema != NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("parameter \"schema\" cannot be specified when \"relocatable\" is true")));
|
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
pfree(filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read the primary control file for the specified extension.
|
|
|
|
*/
|
|
|
|
static ExtensionControlFile *
|
|
|
|
read_extension_control_file(const char *extname)
|
|
|
|
{
|
|
|
|
ExtensionControlFile *control;
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
/*
|
2011-02-12 03:25:20 +01:00
|
|
|
* Set up default values. Pointer fields are initially null.
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
2011-02-12 03:25:20 +01:00
|
|
|
control = (ExtensionControlFile *) palloc0(sizeof(ExtensionControlFile));
|
|
|
|
control->name = pstrdup(extname);
|
|
|
|
control->relocatable = false;
|
2011-03-04 22:08:24 +01:00
|
|
|
control->superuser = true;
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
control->trusted = false;
|
2011-02-12 03:25:20 +01:00
|
|
|
control->encoding = -1;
|
2011-02-08 22:08:41 +01:00
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
/*
|
|
|
|
* Parse the primary control file.
|
|
|
|
*/
|
|
|
|
parse_extension_control_file(control, NULL);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
return control;
|
|
|
|
}
|
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
/*
|
|
|
|
* Read the auxiliary control file for the specified extension and version.
|
|
|
|
*
|
|
|
|
* Returns a new modified ExtensionControlFile struct; the original struct
|
|
|
|
* (reflecting just the primary control file) is not modified.
|
|
|
|
*/
|
|
|
|
static ExtensionControlFile *
|
|
|
|
read_extension_aux_control_file(const ExtensionControlFile *pcontrol,
|
|
|
|
const char *version)
|
|
|
|
{
|
|
|
|
ExtensionControlFile *acontrol;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Flat-copy the struct. Pointer fields share values with original.
|
|
|
|
*/
|
|
|
|
acontrol = (ExtensionControlFile *) palloc(sizeof(ExtensionControlFile));
|
|
|
|
memcpy(acontrol, pcontrol, sizeof(ExtensionControlFile));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse the auxiliary control file, overwriting struct fields
|
|
|
|
*/
|
|
|
|
parse_extension_control_file(acontrol, version);
|
|
|
|
|
|
|
|
return acontrol;
|
|
|
|
}
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
/*
|
2011-06-21 23:33:20 +02:00
|
|
|
* Read an SQL script file into a string, and convert to database encoding
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
read_extension_script_file(const ExtensionControlFile *control,
|
|
|
|
const char *filename)
|
|
|
|
{
|
|
|
|
int src_encoding;
|
|
|
|
char *src_str;
|
|
|
|
char *dest_str;
|
|
|
|
int len;
|
|
|
|
|
2015-06-28 20:35:46 +02:00
|
|
|
src_str = read_whole_file(filename, &len);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
/* use database encoding if not given */
|
|
|
|
if (control->encoding < 0)
|
2014-02-23 22:59:05 +01:00
|
|
|
src_encoding = GetDatabaseEncoding();
|
2011-02-08 22:08:41 +01:00
|
|
|
else
|
|
|
|
src_encoding = control->encoding;
|
|
|
|
|
|
|
|
/* make sure that source string is valid in the expected encoding */
|
2021-01-28 13:40:07 +01:00
|
|
|
(void) pg_verify_mbstr(src_encoding, src_str, len, false);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
2015-06-28 20:35:46 +02:00
|
|
|
/*
|
|
|
|
* Convert the encoding to the database encoding. read_whole_file
|
|
|
|
* null-terminated the string, so if no conversion happens the string is
|
|
|
|
* valid as is.
|
|
|
|
*/
|
2014-02-23 22:59:05 +01:00
|
|
|
dest_str = pg_any_to_server(src_str, len, src_encoding);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
return dest_str;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Execute given SQL string.
|
|
|
|
*
|
|
|
|
* Note: it's tempting to just use SPI to execute the string, but that does
|
|
|
|
* not work very well. The really serious problem is that SPI will parse,
|
|
|
|
* analyze, and plan the whole string before executing any of it; of course
|
|
|
|
* this fails if there are any plannable statements referring to objects
|
|
|
|
* created earlier in the script. A lesser annoyance is that SPI insists
|
|
|
|
* on printing the whole string as errcontext in case of any error, and that
|
|
|
|
* could be very long.
|
|
|
|
*/
|
|
|
|
static void
|
2018-09-13 09:56:57 +02:00
|
|
|
execute_sql_string(const char *sql)
|
2011-02-08 22:08:41 +01:00
|
|
|
{
|
|
|
|
List *raw_parsetree_list;
|
|
|
|
DestReceiver *dest;
|
|
|
|
ListCell *lc1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse the SQL string into a list of raw parse trees.
|
|
|
|
*/
|
|
|
|
raw_parsetree_list = pg_parse_query(sql);
|
|
|
|
|
|
|
|
/* All output from SELECTs goes to the bit bucket */
|
|
|
|
dest = CreateDestReceiver(DestNone);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do parse analysis, rule rewrite, planning, and execution for each raw
|
|
|
|
* parsetree. We must fully execute each query before beginning parse
|
|
|
|
* analysis on the next one, since there may be interdependencies.
|
|
|
|
*/
|
|
|
|
foreach(lc1, raw_parsetree_list)
|
|
|
|
{
|
Improve castNode notation by introducing list-extraction-specific variants.
This extends the castNode() notation introduced by commit 5bcab1114 to
provide, in one step, extraction of a list cell's pointer and coercion to
a concrete node type. For example, "lfirst_node(Foo, lc)" is the same
as "castNode(Foo, lfirst(lc))". Almost half of the uses of castNode
that have appeared so far include a list extraction call, so this is
pretty widely useful, and it saves a few more keystrokes compared to the
old way.
As with the previous patch, back-patch the addition of these macros to
pg_list.h, so that the notation will be available when back-patching.
Patch by me, after an idea of Andrew Gierth's.
Discussion: https://postgr.es/m/14197.1491841216@sss.pgh.pa.us
2017-04-10 19:51:29 +02:00
|
|
|
RawStmt *parsetree = lfirst_node(RawStmt, lc1);
|
Reduce memory consumption for multi-statement query strings.
Previously, exec_simple_query always ran parse analysis, rewrite, and
planning in MessageContext, allowing all the data generated thereby
to persist until the end of processing of the whole query string.
That's fine for single-command strings, but if a client sends many
commands in a single simple-Query message, this strategy could result
in annoying memory bloat, as complained of by Andreas Seltenreich.
To fix, create a child context to do this work in, and reclaim it
after each command. But we only do so for parsetrees that are not
last in their query string. That avoids adding any memory management
overhead for the typical case of a single-command string. Memory
allocated for the last parsetree would be freed immediately after
finishing the command string anyway.
Similarly, adjust extension.c's execute_sql_string() to reclaim memory
after each command. In that usage, multi-command strings are the norm,
so it's a bit surprising that no one has yet complained of bloat ---
especially since the bloat extended to whatever data ProcessUtility
execution might leak.
Amit Langote, reviewed by Julien Rouhaud
Discussion: https://postgr.es/m/87ftp6l2qr.fsf@credativ.de
2019-07-10 20:32:28 +02:00
|
|
|
MemoryContext per_parsetree_context,
|
|
|
|
oldcontext;
|
2011-02-08 22:08:41 +01:00
|
|
|
List *stmt_list;
|
|
|
|
ListCell *lc2;
|
|
|
|
|
Reduce memory consumption for multi-statement query strings.
Previously, exec_simple_query always ran parse analysis, rewrite, and
planning in MessageContext, allowing all the data generated thereby
to persist until the end of processing of the whole query string.
That's fine for single-command strings, but if a client sends many
commands in a single simple-Query message, this strategy could result
in annoying memory bloat, as complained of by Andreas Seltenreich.
To fix, create a child context to do this work in, and reclaim it
after each command. But we only do so for parsetrees that are not
last in their query string. That avoids adding any memory management
overhead for the typical case of a single-command string. Memory
allocated for the last parsetree would be freed immediately after
finishing the command string anyway.
Similarly, adjust extension.c's execute_sql_string() to reclaim memory
after each command. In that usage, multi-command strings are the norm,
so it's a bit surprising that no one has yet complained of bloat ---
especially since the bloat extended to whatever data ProcessUtility
execution might leak.
Amit Langote, reviewed by Julien Rouhaud
Discussion: https://postgr.es/m/87ftp6l2qr.fsf@credativ.de
2019-07-10 20:32:28 +02:00
|
|
|
/*
|
|
|
|
* We do the work for each parsetree in a short-lived context, to
|
|
|
|
* limit the memory used when there are many commands in the string.
|
|
|
|
*/
|
|
|
|
per_parsetree_context =
|
|
|
|
AllocSetContextCreate(CurrentMemoryContext,
|
|
|
|
"execute_sql_string per-statement context",
|
|
|
|
ALLOCSET_DEFAULT_SIZES);
|
|
|
|
oldcontext = MemoryContextSwitchTo(per_parsetree_context);
|
|
|
|
|
2017-05-03 00:05:53 +02:00
|
|
|
/* Be sure parser can see any DDL done so far */
|
|
|
|
CommandCounterIncrement();
|
|
|
|
|
2022-03-04 14:49:37 +01:00
|
|
|
stmt_list = pg_analyze_and_rewrite_fixedparams(parsetree,
|
2011-02-08 22:08:41 +01:00
|
|
|
sql,
|
|
|
|
NULL,
|
2017-04-01 06:17:18 +02:00
|
|
|
0,
|
|
|
|
NULL);
|
2020-03-30 06:51:05 +02:00
|
|
|
stmt_list = pg_plan_queries(stmt_list, sql, CURSOR_OPT_PARALLEL_OK, NULL);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
foreach(lc2, stmt_list)
|
|
|
|
{
|
Improve castNode notation by introducing list-extraction-specific variants.
This extends the castNode() notation introduced by commit 5bcab1114 to
provide, in one step, extraction of a list cell's pointer and coercion to
a concrete node type. For example, "lfirst_node(Foo, lc)" is the same
as "castNode(Foo, lfirst(lc))". Almost half of the uses of castNode
that have appeared so far include a list extraction call, so this is
pretty widely useful, and it saves a few more keystrokes compared to the
old way.
As with the previous patch, back-patch the addition of these macros to
pg_list.h, so that the notation will be available when back-patching.
Patch by me, after an idea of Andrew Gierth's.
Discussion: https://postgr.es/m/14197.1491841216@sss.pgh.pa.us
2017-04-10 19:51:29 +02:00
|
|
|
PlannedStmt *stmt = lfirst_node(PlannedStmt, lc2);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
CommandCounterIncrement();
|
|
|
|
|
|
|
|
PushActiveSnapshot(GetTransactionSnapshot());
|
|
|
|
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
if (stmt->utilityStmt == NULL)
|
2011-02-08 22:08:41 +01:00
|
|
|
{
|
|
|
|
QueryDesc *qdesc;
|
|
|
|
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
qdesc = CreateQueryDesc(stmt,
|
2011-02-08 22:08:41 +01:00
|
|
|
sql,
|
|
|
|
GetActiveSnapshot(), NULL,
|
2017-04-01 06:17:18 +02:00
|
|
|
dest, NULL, NULL, 0);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
ExecutorStart(qdesc, 0);
|
2017-03-23 18:05:48 +01:00
|
|
|
ExecutorRun(qdesc, ForwardScanDirection, 0, true);
|
2011-02-27 19:43:29 +01:00
|
|
|
ExecutorFinish(qdesc);
|
2011-02-08 22:08:41 +01:00
|
|
|
ExecutorEnd(qdesc);
|
|
|
|
|
|
|
|
FreeQueryDesc(qdesc);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
if (IsA(stmt->utilityStmt, TransactionStmt))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("transaction control statements are not allowed within an extension script")));
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
ProcessUtility(stmt,
|
|
|
|
sql,
|
Centralize the logic for protective copying of utility statements.
In the "simple Query" code path, it's fine for parse analysis or
execution of a utility statement to scribble on the statement's node
tree, since that'll just be thrown away afterwards. However it's
not fine if the node tree is in the plan cache, as then it'd be
corrupted for subsequent executions. Up to now we've dealt with
that by having individual utility-statement functions apply
copyObject() if they were going to modify the tree. But that's
prone to errors of omission. Bug #17053 from Charles Samborski
shows that CREATE/ALTER DOMAIN didn't get this memo, and can
crash if executed repeatedly from plan cache.
In the back branches, we'll just apply a narrow band-aid for that,
but in HEAD it seems prudent to have a more principled fix that
will close off the possibility of other similar bugs in future.
Hence, let's hoist the responsibility for doing copyObject up into
ProcessUtility from its children, thus ensuring that it happens for
all utility statement types.
Also, modify ProcessUtility's API so that its callers can tell it
whether a copy step is necessary. It turns out that in all cases,
the immediate caller knows whether the node tree is transient, so
this doesn't involve a huge amount of code thrashing. In this way,
while we lose a little bit in the execute-from-cache code path due
to sometimes copying node trees that wouldn't be mutated anyway,
we gain something in the simple-Query code path by not copying
throwaway node trees. Statements that are complex enough to be
expensive to copy are almost certainly ones that would have to be
copied anyway, so the loss in the cache code path shouldn't be much.
(Note that this whole problem applies only to utility statements.
Optimizable statements don't have the issue because we long ago made
the executor treat Plan trees as read-only. Perhaps someday we will
make utility statement execution act likewise, but I'm not holding
my breath.)
Discussion: https://postgr.es/m/931771.1623893989@sss.pgh.pa.us
Discussion: https://postgr.es/m/17053-3ca3f501bbc212b4@postgresql.org
2021-06-18 17:22:58 +02:00
|
|
|
false,
|
2013-04-28 06:18:45 +02:00
|
|
|
PROCESS_UTILITY_QUERY,
|
2011-02-08 22:08:41 +01:00
|
|
|
NULL,
|
2017-04-01 06:17:18 +02:00
|
|
|
NULL,
|
2011-02-08 22:08:41 +01:00
|
|
|
dest,
|
2013-04-28 06:18:45 +02:00
|
|
|
NULL);
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
PopActiveSnapshot();
|
|
|
|
}
|
Reduce memory consumption for multi-statement query strings.
Previously, exec_simple_query always ran parse analysis, rewrite, and
planning in MessageContext, allowing all the data generated thereby
to persist until the end of processing of the whole query string.
That's fine for single-command strings, but if a client sends many
commands in a single simple-Query message, this strategy could result
in annoying memory bloat, as complained of by Andreas Seltenreich.
To fix, create a child context to do this work in, and reclaim it
after each command. But we only do so for parsetrees that are not
last in their query string. That avoids adding any memory management
overhead for the typical case of a single-command string. Memory
allocated for the last parsetree would be freed immediately after
finishing the command string anyway.
Similarly, adjust extension.c's execute_sql_string() to reclaim memory
after each command. In that usage, multi-command strings are the norm,
so it's a bit surprising that no one has yet complained of bloat ---
especially since the bloat extended to whatever data ProcessUtility
execution might leak.
Amit Langote, reviewed by Julien Rouhaud
Discussion: https://postgr.es/m/87ftp6l2qr.fsf@credativ.de
2019-07-10 20:32:28 +02:00
|
|
|
|
|
|
|
/* Clean up per-parsetree context. */
|
|
|
|
MemoryContextSwitchTo(oldcontext);
|
|
|
|
MemoryContextDelete(per_parsetree_context);
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Be sure to advance the command counter after the last script command */
|
|
|
|
CommandCounterIncrement();
|
|
|
|
}
|
|
|
|
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
/*
|
|
|
|
* Policy function: is the given extension trusted for installation by a
|
|
|
|
* non-superuser?
|
|
|
|
*
|
|
|
|
* (Update the errhint logic below if you change this.)
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
extension_is_trusted(ExtensionControlFile *control)
|
|
|
|
{
|
|
|
|
AclResult aclresult;
|
|
|
|
|
|
|
|
/* Never trust unless extension's control file says it's okay */
|
|
|
|
if (!control->trusted)
|
|
|
|
return false;
|
|
|
|
/* Allow if user has CREATE privilege on current database */
|
2022-11-13 08:11:17 +01:00
|
|
|
aclresult = object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(), ACL_CREATE);
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
if (aclresult == ACLCHECK_OK)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
/*
|
2011-02-12 03:25:20 +01:00
|
|
|
* Execute the appropriate script file for installing or updating the extension
|
|
|
|
*
|
|
|
|
* If from_version isn't NULL, it's an update
|
2023-03-20 23:37:11 +01:00
|
|
|
*
|
|
|
|
* Note: requiredSchemas must be one-for-one with the control->requires list
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
|
2011-02-12 03:25:20 +01:00
|
|
|
const char *from_version,
|
|
|
|
const char *version,
|
2011-02-08 22:08:41 +01:00
|
|
|
List *requiredSchemas,
|
|
|
|
const char *schemaName, Oid schemaOid)
|
|
|
|
{
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
bool switch_to_superuser = false;
|
2011-02-12 03:25:20 +01:00
|
|
|
char *filename;
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
Oid save_userid = 0;
|
|
|
|
int save_sec_context = 0;
|
Improve and simplify CREATE EXTENSION's management of GUC variables.
CREATE EXTENSION needs to transiently set search_path, as well as
client_min_messages and log_min_messages. We were doing this by the
expedient of saving the current string value of each variable, doing a
SET LOCAL, and then doing another SET LOCAL with the previous value at
the end of the command. This is a bit expensive though, and it also fails
badly if there is anything funny about the existing search_path value,
as seen in a recent report from Roger Niederland. Fortunately, there's a
much better way, which is to piggyback on the GUC infrastructure previously
developed for functions with SET options. We just open a new GUC nesting
level, do our assignments with GUC_ACTION_SAVE, and then close the nesting
level when done. This automatically restores the prior settings without a
re-parsing pass, so (in principle anyway) there can't be an error. And
guc.c still takes care of cleanup in event of an error abort.
The CREATE EXTENSION code for this was modeled on some much older code in
ri_triggers.c, which I also changed to use the better method, even though
there wasn't really much risk of failure there. Also improve the comments
in guc.c to reflect this additional usage.
2011-10-06 02:44:16 +02:00
|
|
|
int save_nestlevel;
|
2011-02-08 22:08:41 +01:00
|
|
|
StringInfoData pathbuf;
|
|
|
|
ListCell *lc;
|
2023-03-20 23:37:11 +01:00
|
|
|
ListCell *lc2;
|
2011-02-08 22:08:41 +01:00
|
|
|
|
2011-03-04 22:08:24 +01:00
|
|
|
/*
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
* Enforce superuser-ness if appropriate. We postpone these checks until
|
|
|
|
* here so that the control flags are correctly associated with the right
|
|
|
|
* script(s) if they happen to be set in secondary control files.
|
2011-03-04 22:08:24 +01:00
|
|
|
*/
|
|
|
|
if (control->superuser && !superuser())
|
|
|
|
{
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
if (extension_is_trusted(control))
|
|
|
|
switch_to_superuser = true;
|
|
|
|
else if (from_version == NULL)
|
2011-03-04 22:08:24 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
|
|
|
errmsg("permission denied to create extension \"%s\"",
|
|
|
|
control->name),
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
control->trusted
|
|
|
|
? errhint("Must have CREATE privilege on current database to create this extension.")
|
|
|
|
: errhint("Must be superuser to create this extension.")));
|
2011-03-04 22:08:24 +01:00
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
|
|
|
errmsg("permission denied to update extension \"%s\"",
|
|
|
|
control->name),
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
control->trusted
|
|
|
|
? errhint("Must have CREATE privilege on current database to update this extension.")
|
|
|
|
: errhint("Must be superuser to update this extension.")));
|
2011-03-04 22:08:24 +01:00
|
|
|
}
|
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
filename = get_extension_script_filename(control, from_version, version);
|
|
|
|
|
2022-07-02 20:20:45 +02:00
|
|
|
if (from_version == NULL)
|
|
|
|
elog(DEBUG1, "executing extension script for \"%s\" version '%s'", control->name, version);
|
|
|
|
else
|
|
|
|
elog(DEBUG1, "executing extension script for \"%s\" update from version '%s' to '%s'", control->name, from_version, version);
|
|
|
|
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
/*
|
|
|
|
* If installing a trusted extension on behalf of a non-superuser, become
|
|
|
|
* the bootstrap superuser. (This switch will be cleaned up automatically
|
|
|
|
* if the transaction aborts, as will the GUC changes below.)
|
|
|
|
*/
|
|
|
|
if (switch_to_superuser)
|
|
|
|
{
|
|
|
|
GetUserIdAndSecContext(&save_userid, &save_sec_context);
|
|
|
|
SetUserIdAndSecContext(BOOTSTRAP_SUPERUSERID,
|
|
|
|
save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
|
|
|
|
}
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
/*
|
|
|
|
* Force client_min_messages and log_min_messages to be at least WARNING,
|
|
|
|
* so that we won't spam the user with useless NOTICE messages from common
|
|
|
|
* script actions like creating shell types.
|
|
|
|
*
|
Improve and simplify CREATE EXTENSION's management of GUC variables.
CREATE EXTENSION needs to transiently set search_path, as well as
client_min_messages and log_min_messages. We were doing this by the
expedient of saving the current string value of each variable, doing a
SET LOCAL, and then doing another SET LOCAL with the previous value at
the end of the command. This is a bit expensive though, and it also fails
badly if there is anything funny about the existing search_path value,
as seen in a recent report from Roger Niederland. Fortunately, there's a
much better way, which is to piggyback on the GUC infrastructure previously
developed for functions with SET options. We just open a new GUC nesting
level, do our assignments with GUC_ACTION_SAVE, and then close the nesting
level when done. This automatically restores the prior settings without a
re-parsing pass, so (in principle anyway) there can't be an error. And
guc.c still takes care of cleanup in event of an error abort.
The CREATE EXTENSION code for this was modeled on some much older code in
ri_triggers.c, which I also changed to use the better method, even though
there wasn't really much risk of failure there. Also improve the comments
in guc.c to reflect this additional usage.
2011-10-06 02:44:16 +02:00
|
|
|
* We use the equivalent of a function SET option to allow the setting to
|
|
|
|
* persist for exactly the duration of the script execution. guc.c also
|
|
|
|
* takes care of undoing the setting on error.
|
2022-07-19 23:21:55 +02:00
|
|
|
*
|
|
|
|
* log_min_messages can't be set by ordinary users, so for that one we
|
|
|
|
* pretend to be superuser.
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
Improve and simplify CREATE EXTENSION's management of GUC variables.
CREATE EXTENSION needs to transiently set search_path, as well as
client_min_messages and log_min_messages. We were doing this by the
expedient of saving the current string value of each variable, doing a
SET LOCAL, and then doing another SET LOCAL with the previous value at
the end of the command. This is a bit expensive though, and it also fails
badly if there is anything funny about the existing search_path value,
as seen in a recent report from Roger Niederland. Fortunately, there's a
much better way, which is to piggyback on the GUC infrastructure previously
developed for functions with SET options. We just open a new GUC nesting
level, do our assignments with GUC_ACTION_SAVE, and then close the nesting
level when done. This automatically restores the prior settings without a
re-parsing pass, so (in principle anyway) there can't be an error. And
guc.c still takes care of cleanup in event of an error abort.
The CREATE EXTENSION code for this was modeled on some much older code in
ri_triggers.c, which I also changed to use the better method, even though
there wasn't really much risk of failure there. Also improve the comments
in guc.c to reflect this additional usage.
2011-10-06 02:44:16 +02:00
|
|
|
save_nestlevel = NewGUCNestLevel();
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
if (client_min_messages < WARNING)
|
|
|
|
(void) set_config_option("client_min_messages", "warning",
|
|
|
|
PGC_USERSET, PGC_S_SESSION,
|
2014-11-24 22:13:11 +01:00
|
|
|
GUC_ACTION_SAVE, true, 0, false);
|
2011-02-08 22:08:41 +01:00
|
|
|
if (log_min_messages < WARNING)
|
2022-07-19 23:21:55 +02:00
|
|
|
(void) set_config_option_ext("log_min_messages", "warning",
|
|
|
|
PGC_SUSET, PGC_S_SESSION,
|
|
|
|
BOOTSTRAP_SUPERUSERID,
|
|
|
|
GUC_ACTION_SAVE, true, 0, false);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
/*
|
Make contrib modules' installation scripts more secure.
Hostile objects located within the installation-time search_path could
capture references in an extension's installation or upgrade script.
If the extension is being installed with superuser privileges, this
opens the door to privilege escalation. While such hazards have existed
all along, their urgency increases with the v13 "trusted extensions"
feature, because that lets a non-superuser control the installation path
for a superuser-privileged script. Therefore, make a number of changes
to make such situations more secure:
* Tweak the construction of the installation-time search_path to ensure
that references to objects in pg_catalog can't be subverted; and
explicitly add pg_temp to the end of the path to prevent attacks using
temporary objects.
* Disable check_function_bodies within installation/upgrade scripts,
so that any security gaps in SQL-language or PL-language function bodies
cannot create a risk of unwanted installation-time code execution.
* Adjust lookup of type input/receive functions and join estimator
functions to complain if there are multiple candidate functions. This
prevents capture of references to functions whose signature is not the
first one checked; and it's arguably more user-friendly anyway.
* Modify various contrib upgrade scripts to ensure that catalog
modification queries are executed with secure search paths. (These
are in-place modifications with no extension version changes, since
it is the update process itself that is at issue, not the end result.)
Extensions that depend on other extensions cannot be made fully secure
by these methods alone; therefore, revert the "trusted" marking that
commit eb67623c9 applied to earthdistance and hstore_plperl, pending
some better solution to that set of issues.
Also add documentation around these issues, to help extension authors
write secure installation scripts.
Patch by me, following an observation by Andres Freund; thanks
to Noah Misch for review.
Security: CVE-2020-14350
2020-08-10 16:44:42 +02:00
|
|
|
* Similarly disable check_function_bodies, to ensure that SQL functions
|
|
|
|
* won't be parsed during creation.
|
|
|
|
*/
|
|
|
|
if (check_function_bodies)
|
|
|
|
(void) set_config_option("check_function_bodies", "off",
|
|
|
|
PGC_USERSET, PGC_S_SESSION,
|
|
|
|
GUC_ACTION_SAVE, true, 0, false);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up the search path to have the target schema first, making it be
|
|
|
|
* the default creation target namespace. Then add the schemas of any
|
|
|
|
* prerequisite extensions, unless they are in pg_catalog which would be
|
|
|
|
* searched anyway. (Listing pg_catalog explicitly in a non-first
|
|
|
|
* position would be bad for security.) Finally add pg_temp to ensure
|
|
|
|
* that temp objects can't take precedence over others.
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
|
|
|
initStringInfo(&pathbuf);
|
|
|
|
appendStringInfoString(&pathbuf, quote_identifier(schemaName));
|
|
|
|
foreach(lc, requiredSchemas)
|
|
|
|
{
|
|
|
|
Oid reqschema = lfirst_oid(lc);
|
|
|
|
char *reqname = get_namespace_name(reqschema);
|
|
|
|
|
Make contrib modules' installation scripts more secure.
Hostile objects located within the installation-time search_path could
capture references in an extension's installation or upgrade script.
If the extension is being installed with superuser privileges, this
opens the door to privilege escalation. While such hazards have existed
all along, their urgency increases with the v13 "trusted extensions"
feature, because that lets a non-superuser control the installation path
for a superuser-privileged script. Therefore, make a number of changes
to make such situations more secure:
* Tweak the construction of the installation-time search_path to ensure
that references to objects in pg_catalog can't be subverted; and
explicitly add pg_temp to the end of the path to prevent attacks using
temporary objects.
* Disable check_function_bodies within installation/upgrade scripts,
so that any security gaps in SQL-language or PL-language function bodies
cannot create a risk of unwanted installation-time code execution.
* Adjust lookup of type input/receive functions and join estimator
functions to complain if there are multiple candidate functions. This
prevents capture of references to functions whose signature is not the
first one checked; and it's arguably more user-friendly anyway.
* Modify various contrib upgrade scripts to ensure that catalog
modification queries are executed with secure search paths. (These
are in-place modifications with no extension version changes, since
it is the update process itself that is at issue, not the end result.)
Extensions that depend on other extensions cannot be made fully secure
by these methods alone; therefore, revert the "trusted" marking that
commit eb67623c9 applied to earthdistance and hstore_plperl, pending
some better solution to that set of issues.
Also add documentation around these issues, to help extension authors
write secure installation scripts.
Patch by me, following an observation by Andres Freund; thanks
to Noah Misch for review.
Security: CVE-2020-14350
2020-08-10 16:44:42 +02:00
|
|
|
if (reqname && strcmp(reqname, "pg_catalog") != 0)
|
2011-02-08 22:08:41 +01:00
|
|
|
appendStringInfo(&pathbuf, ", %s", quote_identifier(reqname));
|
|
|
|
}
|
Make contrib modules' installation scripts more secure.
Hostile objects located within the installation-time search_path could
capture references in an extension's installation or upgrade script.
If the extension is being installed with superuser privileges, this
opens the door to privilege escalation. While such hazards have existed
all along, their urgency increases with the v13 "trusted extensions"
feature, because that lets a non-superuser control the installation path
for a superuser-privileged script. Therefore, make a number of changes
to make such situations more secure:
* Tweak the construction of the installation-time search_path to ensure
that references to objects in pg_catalog can't be subverted; and
explicitly add pg_temp to the end of the path to prevent attacks using
temporary objects.
* Disable check_function_bodies within installation/upgrade scripts,
so that any security gaps in SQL-language or PL-language function bodies
cannot create a risk of unwanted installation-time code execution.
* Adjust lookup of type input/receive functions and join estimator
functions to complain if there are multiple candidate functions. This
prevents capture of references to functions whose signature is not the
first one checked; and it's arguably more user-friendly anyway.
* Modify various contrib upgrade scripts to ensure that catalog
modification queries are executed with secure search paths. (These
are in-place modifications with no extension version changes, since
it is the update process itself that is at issue, not the end result.)
Extensions that depend on other extensions cannot be made fully secure
by these methods alone; therefore, revert the "trusted" marking that
commit eb67623c9 applied to earthdistance and hstore_plperl, pending
some better solution to that set of issues.
Also add documentation around these issues, to help extension authors
write secure installation scripts.
Patch by me, following an observation by Andres Freund; thanks
to Noah Misch for review.
Security: CVE-2020-14350
2020-08-10 16:44:42 +02:00
|
|
|
appendStringInfoString(&pathbuf, ", pg_temp");
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
(void) set_config_option("search_path", pathbuf.data,
|
|
|
|
PGC_USERSET, PGC_S_SESSION,
|
2014-11-24 22:13:11 +01:00
|
|
|
GUC_ACTION_SAVE, true, 0, false);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set creating_extension and related variables so that
|
|
|
|
* recordDependencyOnCurrentExtension and other functions do the right
|
|
|
|
* things. On failure, ensure we reset these variables.
|
|
|
|
*/
|
|
|
|
creating_extension = true;
|
|
|
|
CurrentExtensionObject = extensionOid;
|
|
|
|
PG_TRY();
|
|
|
|
{
|
2011-10-12 21:45:03 +02:00
|
|
|
char *c_sql = read_extension_script_file(control, filename);
|
|
|
|
Datum t_sql;
|
|
|
|
|
Reject substituting extension schemas or owners matching ["$'\].
Substituting such values in extension scripts facilitated SQL injection
when @extowner@, @extschema@, or @extschema:...@ appeared inside a
quoting construct (dollar quoting, '', or ""). No bundled extension was
vulnerable. Vulnerable uses do appear in a documentation example and in
non-bundled extensions. Hence, the attack prerequisite was an
administrator having installed files of a vulnerable, trusted,
non-bundled extension. Subject to that prerequisite, this enabled an
attacker having database-level CREATE privilege to execute arbitrary
code as the bootstrap superuser. By blocking this attack in the core
server, there's no need to modify individual extensions. Back-patch to
v11 (all supported versions).
Reported by Micah Gate, Valerie Woolard, Tim Carey-Smith, and Christoph
Berg.
Security: CVE-2023-39417
2023-08-07 15:05:56 +02:00
|
|
|
/*
|
|
|
|
* We filter each substitution through quote_identifier(). When the
|
|
|
|
* arg contains one of the following characters, no one collection of
|
|
|
|
* quoting can work inside $$dollar-quoted string literals$$,
|
|
|
|
* 'single-quoted string literals', and outside of any literal. To
|
|
|
|
* avoid a security snare for extension authors, error on substitution
|
|
|
|
* for arguments containing these.
|
|
|
|
*/
|
|
|
|
const char *quoting_relevant_chars = "\"$'\\";
|
|
|
|
|
2011-10-12 21:45:03 +02:00
|
|
|
/* We use various functions that want to operate on text datums */
|
|
|
|
t_sql = CStringGetTextDatum(c_sql);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reduce any lines beginning with "\echo" to empty. This allows
|
|
|
|
* scripts to contain messages telling people not to run them via
|
|
|
|
* psql, which has been found to be necessary due to old habits.
|
|
|
|
*/
|
|
|
|
t_sql = DirectFunctionCall4Coll(textregexreplace,
|
|
|
|
C_COLLATION_OID,
|
|
|
|
t_sql,
|
|
|
|
CStringGetTextDatum("^\\\\echo.*$"),
|
|
|
|
CStringGetTextDatum(""),
|
|
|
|
CStringGetTextDatum("ng"));
|
2011-02-08 22:08:41 +01:00
|
|
|
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
/*
|
|
|
|
* If the script uses @extowner@, substitute the calling username.
|
|
|
|
*/
|
|
|
|
if (strstr(c_sql, "@extowner@"))
|
|
|
|
{
|
|
|
|
Oid uid = switch_to_superuser ? save_userid : GetUserId();
|
|
|
|
const char *userName = GetUserNameFromId(uid, false);
|
|
|
|
const char *qUserName = quote_identifier(userName);
|
|
|
|
|
|
|
|
t_sql = DirectFunctionCall3Coll(replace_text,
|
|
|
|
C_COLLATION_OID,
|
|
|
|
t_sql,
|
|
|
|
CStringGetTextDatum("@extowner@"),
|
|
|
|
CStringGetTextDatum(qUserName));
|
Reject substituting extension schemas or owners matching ["$'\].
Substituting such values in extension scripts facilitated SQL injection
when @extowner@, @extschema@, or @extschema:...@ appeared inside a
quoting construct (dollar quoting, '', or ""). No bundled extension was
vulnerable. Vulnerable uses do appear in a documentation example and in
non-bundled extensions. Hence, the attack prerequisite was an
administrator having installed files of a vulnerable, trusted,
non-bundled extension. Subject to that prerequisite, this enabled an
attacker having database-level CREATE privilege to execute arbitrary
code as the bootstrap superuser. By blocking this attack in the core
server, there's no need to modify individual extensions. Back-patch to
v11 (all supported versions).
Reported by Micah Gate, Valerie Woolard, Tim Carey-Smith, and Christoph
Berg.
Security: CVE-2023-39417
2023-08-07 15:05:56 +02:00
|
|
|
if (strpbrk(userName, quoting_relevant_chars))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
|
|
errmsg("invalid character in extension owner: must not contain any of \"%s\"",
|
|
|
|
quoting_relevant_chars)));
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
}
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
/*
|
|
|
|
* If it's not relocatable, substitute the target schema name for
|
2012-02-23 01:44:52 +01:00
|
|
|
* occurrences of @extschema@.
|
2011-02-08 22:08:41 +01:00
|
|
|
*
|
2011-10-12 21:45:03 +02:00
|
|
|
* For a relocatable extension, we needn't do this. There cannot be
|
|
|
|
* any need for @extschema@, else it wouldn't be relocatable.
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
|
|
|
if (!control->relocatable)
|
|
|
|
{
|
Reject substituting extension schemas or owners matching ["$'\].
Substituting such values in extension scripts facilitated SQL injection
when @extowner@, @extschema@, or @extschema:...@ appeared inside a
quoting construct (dollar quoting, '', or ""). No bundled extension was
vulnerable. Vulnerable uses do appear in a documentation example and in
non-bundled extensions. Hence, the attack prerequisite was an
administrator having installed files of a vulnerable, trusted,
non-bundled extension. Subject to that prerequisite, this enabled an
attacker having database-level CREATE privilege to execute arbitrary
code as the bootstrap superuser. By blocking this attack in the core
server, there's no need to modify individual extensions. Back-patch to
v11 (all supported versions).
Reported by Micah Gate, Valerie Woolard, Tim Carey-Smith, and Christoph
Berg.
Security: CVE-2023-39417
2023-08-07 15:05:56 +02:00
|
|
|
Datum old = t_sql;
|
2011-02-08 22:08:41 +01:00
|
|
|
const char *qSchemaName = quote_identifier(schemaName);
|
|
|
|
|
2019-03-22 12:09:32 +01:00
|
|
|
t_sql = DirectFunctionCall3Coll(replace_text,
|
|
|
|
C_COLLATION_OID,
|
2011-10-12 21:45:03 +02:00
|
|
|
t_sql,
|
|
|
|
CStringGetTextDatum("@extschema@"),
|
|
|
|
CStringGetTextDatum(qSchemaName));
|
Reject substituting extension schemas or owners matching ["$'\].
Substituting such values in extension scripts facilitated SQL injection
when @extowner@, @extschema@, or @extschema:...@ appeared inside a
quoting construct (dollar quoting, '', or ""). No bundled extension was
vulnerable. Vulnerable uses do appear in a documentation example and in
non-bundled extensions. Hence, the attack prerequisite was an
administrator having installed files of a vulnerable, trusted,
non-bundled extension. Subject to that prerequisite, this enabled an
attacker having database-level CREATE privilege to execute arbitrary
code as the bootstrap superuser. By blocking this attack in the core
server, there's no need to modify individual extensions. Back-patch to
v11 (all supported versions).
Reported by Micah Gate, Valerie Woolard, Tim Carey-Smith, and Christoph
Berg.
Security: CVE-2023-39417
2023-08-07 15:05:56 +02:00
|
|
|
if (t_sql != old && strpbrk(schemaName, quoting_relevant_chars))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
|
|
errmsg("invalid character in extension \"%s\" schema: must not contain any of \"%s\"",
|
|
|
|
control->name, quoting_relevant_chars)));
|
2011-02-13 19:38:05 +01:00
|
|
|
}
|
2011-02-08 22:08:41 +01:00
|
|
|
|
2023-03-20 23:37:11 +01:00
|
|
|
/*
|
|
|
|
* Likewise, substitute required extensions' schema names for
|
|
|
|
* occurrences of @extschema:extension_name@.
|
|
|
|
*/
|
|
|
|
Assert(list_length(control->requires) == list_length(requiredSchemas));
|
|
|
|
forboth(lc, control->requires, lc2, requiredSchemas)
|
|
|
|
{
|
Reject substituting extension schemas or owners matching ["$'\].
Substituting such values in extension scripts facilitated SQL injection
when @extowner@, @extschema@, or @extschema:...@ appeared inside a
quoting construct (dollar quoting, '', or ""). No bundled extension was
vulnerable. Vulnerable uses do appear in a documentation example and in
non-bundled extensions. Hence, the attack prerequisite was an
administrator having installed files of a vulnerable, trusted,
non-bundled extension. Subject to that prerequisite, this enabled an
attacker having database-level CREATE privilege to execute arbitrary
code as the bootstrap superuser. By blocking this attack in the core
server, there's no need to modify individual extensions. Back-patch to
v11 (all supported versions).
Reported by Micah Gate, Valerie Woolard, Tim Carey-Smith, and Christoph
Berg.
Security: CVE-2023-39417
2023-08-07 15:05:56 +02:00
|
|
|
Datum old = t_sql;
|
2023-03-20 23:37:11 +01:00
|
|
|
char *reqextname = (char *) lfirst(lc);
|
|
|
|
Oid reqschema = lfirst_oid(lc2);
|
|
|
|
char *schemaName = get_namespace_name(reqschema);
|
|
|
|
const char *qSchemaName = quote_identifier(schemaName);
|
|
|
|
char *repltoken;
|
|
|
|
|
|
|
|
repltoken = psprintf("@extschema:%s@", reqextname);
|
|
|
|
t_sql = DirectFunctionCall3Coll(replace_text,
|
|
|
|
C_COLLATION_OID,
|
|
|
|
t_sql,
|
|
|
|
CStringGetTextDatum(repltoken),
|
|
|
|
CStringGetTextDatum(qSchemaName));
|
Reject substituting extension schemas or owners matching ["$'\].
Substituting such values in extension scripts facilitated SQL injection
when @extowner@, @extschema@, or @extschema:...@ appeared inside a
quoting construct (dollar quoting, '', or ""). No bundled extension was
vulnerable. Vulnerable uses do appear in a documentation example and in
non-bundled extensions. Hence, the attack prerequisite was an
administrator having installed files of a vulnerable, trusted,
non-bundled extension. Subject to that prerequisite, this enabled an
attacker having database-level CREATE privilege to execute arbitrary
code as the bootstrap superuser. By blocking this attack in the core
server, there's no need to modify individual extensions. Back-patch to
v11 (all supported versions).
Reported by Micah Gate, Valerie Woolard, Tim Carey-Smith, and Christoph
Berg.
Security: CVE-2023-39417
2023-08-07 15:05:56 +02:00
|
|
|
if (t_sql != old && strpbrk(schemaName, quoting_relevant_chars))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
|
|
errmsg("invalid character in extension \"%s\" schema: must not contain any of \"%s\"",
|
|
|
|
reqextname, quoting_relevant_chars)));
|
2023-03-20 23:37:11 +01:00
|
|
|
}
|
|
|
|
|
2011-02-13 19:38:05 +01:00
|
|
|
/*
|
|
|
|
* If module_pathname was set in the control file, substitute its
|
|
|
|
* value for occurrences of MODULE_PATHNAME.
|
|
|
|
*/
|
|
|
|
if (control->module_pathname)
|
|
|
|
{
|
2019-03-22 12:09:32 +01:00
|
|
|
t_sql = DirectFunctionCall3Coll(replace_text,
|
|
|
|
C_COLLATION_OID,
|
2011-10-12 21:45:03 +02:00
|
|
|
t_sql,
|
|
|
|
CStringGetTextDatum("MODULE_PATHNAME"),
|
|
|
|
CStringGetTextDatum(control->module_pathname));
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
|
|
|
|
2011-10-12 21:45:03 +02:00
|
|
|
/* And now back to C string */
|
|
|
|
c_sql = text_to_cstring(DatumGetTextPP(t_sql));
|
|
|
|
|
2018-09-13 09:56:57 +02:00
|
|
|
execute_sql_string(c_sql);
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
2019-11-01 11:09:52 +01:00
|
|
|
PG_FINALLY();
|
2011-02-08 22:08:41 +01:00
|
|
|
{
|
|
|
|
creating_extension = false;
|
|
|
|
CurrentExtensionObject = InvalidOid;
|
|
|
|
}
|
|
|
|
PG_END_TRY();
|
|
|
|
|
|
|
|
/*
|
Improve and simplify CREATE EXTENSION's management of GUC variables.
CREATE EXTENSION needs to transiently set search_path, as well as
client_min_messages and log_min_messages. We were doing this by the
expedient of saving the current string value of each variable, doing a
SET LOCAL, and then doing another SET LOCAL with the previous value at
the end of the command. This is a bit expensive though, and it also fails
badly if there is anything funny about the existing search_path value,
as seen in a recent report from Roger Niederland. Fortunately, there's a
much better way, which is to piggyback on the GUC infrastructure previously
developed for functions with SET options. We just open a new GUC nesting
level, do our assignments with GUC_ACTION_SAVE, and then close the nesting
level when done. This automatically restores the prior settings without a
re-parsing pass, so (in principle anyway) there can't be an error. And
guc.c still takes care of cleanup in event of an error abort.
The CREATE EXTENSION code for this was modeled on some much older code in
ri_triggers.c, which I also changed to use the better method, even though
there wasn't really much risk of failure there. Also improve the comments
in guc.c to reflect this additional usage.
2011-10-06 02:44:16 +02:00
|
|
|
* Restore the GUC variables we set above.
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
Improve and simplify CREATE EXTENSION's management of GUC variables.
CREATE EXTENSION needs to transiently set search_path, as well as
client_min_messages and log_min_messages. We were doing this by the
expedient of saving the current string value of each variable, doing a
SET LOCAL, and then doing another SET LOCAL with the previous value at
the end of the command. This is a bit expensive though, and it also fails
badly if there is anything funny about the existing search_path value,
as seen in a recent report from Roger Niederland. Fortunately, there's a
much better way, which is to piggyback on the GUC infrastructure previously
developed for functions with SET options. We just open a new GUC nesting
level, do our assignments with GUC_ACTION_SAVE, and then close the nesting
level when done. This automatically restores the prior settings without a
re-parsing pass, so (in principle anyway) there can't be an error. And
guc.c still takes care of cleanup in event of an error abort.
The CREATE EXTENSION code for this was modeled on some much older code in
ri_triggers.c, which I also changed to use the better method, even though
there wasn't really much risk of failure there. Also improve the comments
in guc.c to reflect this additional usage.
2011-10-06 02:44:16 +02:00
|
|
|
AtEOXact_GUC(true, save_nestlevel);
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Restore authentication state if needed.
|
|
|
|
*/
|
|
|
|
if (switch_to_superuser)
|
|
|
|
SetUserIdAndSecContext(save_userid, save_sec_context);
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
/*
|
|
|
|
* Find or create an ExtensionVersionInfo for the specified version name
|
|
|
|
*
|
|
|
|
* Currently, we just use a List of the ExtensionVersionInfo's. Searching
|
|
|
|
* for them therefore uses about O(N^2) time when there are N versions of
|
|
|
|
* the extension. We could change the data structure to a hash table if
|
|
|
|
* this ever becomes a bottleneck.
|
|
|
|
*/
|
|
|
|
static ExtensionVersionInfo *
|
|
|
|
get_ext_ver_info(const char *versionname, List **evi_list)
|
|
|
|
{
|
|
|
|
ExtensionVersionInfo *evi;
|
|
|
|
ListCell *lc;
|
|
|
|
|
|
|
|
foreach(lc, *evi_list)
|
|
|
|
{
|
|
|
|
evi = (ExtensionVersionInfo *) lfirst(lc);
|
|
|
|
if (strcmp(evi->name, versionname) == 0)
|
|
|
|
return evi;
|
|
|
|
}
|
|
|
|
|
|
|
|
evi = (ExtensionVersionInfo *) palloc(sizeof(ExtensionVersionInfo));
|
|
|
|
evi->name = pstrdup(versionname);
|
|
|
|
evi->reachable = NIL;
|
2011-02-14 22:07:00 +01:00
|
|
|
evi->installable = false;
|
2011-02-12 03:25:20 +01:00
|
|
|
/* initialize for later application of Dijkstra's algorithm */
|
|
|
|
evi->distance_known = false;
|
|
|
|
evi->distance = INT_MAX;
|
|
|
|
evi->previous = NULL;
|
|
|
|
|
|
|
|
*evi_list = lappend(*evi_list, evi);
|
|
|
|
|
|
|
|
return evi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Locate the nearest unprocessed ExtensionVersionInfo
|
|
|
|
*
|
|
|
|
* This part of the algorithm is also about O(N^2). A priority queue would
|
|
|
|
* make it much faster, but for now there's no need.
|
|
|
|
*/
|
|
|
|
static ExtensionVersionInfo *
|
|
|
|
get_nearest_unprocessed_vertex(List *evi_list)
|
|
|
|
{
|
|
|
|
ExtensionVersionInfo *evi = NULL;
|
|
|
|
ListCell *lc;
|
|
|
|
|
|
|
|
foreach(lc, evi_list)
|
|
|
|
{
|
|
|
|
ExtensionVersionInfo *evi2 = (ExtensionVersionInfo *) lfirst(lc);
|
|
|
|
|
|
|
|
/* only vertices whose distance is still uncertain are candidates */
|
|
|
|
if (evi2->distance_known)
|
|
|
|
continue;
|
|
|
|
/* remember the closest such vertex */
|
|
|
|
if (evi == NULL ||
|
|
|
|
evi->distance > evi2->distance)
|
|
|
|
evi = evi2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return evi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Obtain information about the set of update scripts available for the
|
|
|
|
* specified extension. The result is a List of ExtensionVersionInfo
|
|
|
|
* structs, each with a subsidiary list of the ExtensionVersionInfos for
|
|
|
|
* the versions that can be reached in one step from that version.
|
|
|
|
*/
|
|
|
|
static List *
|
|
|
|
get_ext_ver_list(ExtensionControlFile *control)
|
|
|
|
{
|
|
|
|
List *evi_list = NIL;
|
|
|
|
int extnamelen = strlen(control->name);
|
|
|
|
char *location;
|
|
|
|
DIR *dir;
|
|
|
|
struct dirent *de;
|
|
|
|
|
|
|
|
location = get_extension_script_directory(control);
|
|
|
|
dir = AllocateDir(location);
|
|
|
|
while ((de = ReadDir(dir, location)) != NULL)
|
|
|
|
{
|
|
|
|
char *vername;
|
|
|
|
char *vername2;
|
|
|
|
ExtensionVersionInfo *evi;
|
|
|
|
ExtensionVersionInfo *evi2;
|
|
|
|
|
|
|
|
/* must be a .sql file ... */
|
|
|
|
if (!is_extension_script_filename(de->d_name))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* ... matching extension name followed by separator */
|
|
|
|
if (strncmp(de->d_name, control->name, extnamelen) != 0 ||
|
2011-02-13 19:03:41 +01:00
|
|
|
de->d_name[extnamelen] != '-' ||
|
|
|
|
de->d_name[extnamelen + 1] != '-')
|
2011-02-12 03:25:20 +01:00
|
|
|
continue;
|
|
|
|
|
2011-02-14 22:07:00 +01:00
|
|
|
/* extract version name(s) from 'extname--something.sql' filename */
|
2011-02-13 19:03:41 +01:00
|
|
|
vername = pstrdup(de->d_name + extnamelen + 2);
|
2011-02-12 03:25:20 +01:00
|
|
|
*strrchr(vername, '.') = '\0';
|
2011-02-13 19:03:41 +01:00
|
|
|
vername2 = strstr(vername, "--");
|
2011-02-12 03:25:20 +01:00
|
|
|
if (!vername2)
|
2011-02-14 22:07:00 +01:00
|
|
|
{
|
|
|
|
/* It's an install, not update, script; record its version name */
|
|
|
|
evi = get_ext_ver_info(vername, &evi_list);
|
|
|
|
evi->installable = true;
|
|
|
|
continue;
|
|
|
|
}
|
2011-02-13 19:03:41 +01:00
|
|
|
*vername2 = '\0'; /* terminate first version */
|
|
|
|
vername2 += 2; /* and point to second */
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-14 22:07:00 +01:00
|
|
|
/* if there's a third --, it's bogus, ignore it */
|
|
|
|
if (strstr(vername2, "--"))
|
|
|
|
continue;
|
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
/* Create ExtensionVersionInfos and link them together */
|
|
|
|
evi = get_ext_ver_info(vername, &evi_list);
|
|
|
|
evi2 = get_ext_ver_info(vername2, &evi_list);
|
|
|
|
evi->reachable = lappend(evi->reachable, evi2);
|
|
|
|
}
|
|
|
|
FreeDir(dir);
|
|
|
|
|
|
|
|
return evi_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Given an initial and final version name, identify the sequence of update
|
|
|
|
* scripts that have to be applied to perform that update.
|
|
|
|
*
|
2011-02-12 22:40:41 +01:00
|
|
|
* Result is a List of names of versions to transition through (the initial
|
|
|
|
* version is *not* included).
|
2011-02-12 03:25:20 +01:00
|
|
|
*/
|
|
|
|
static List *
|
|
|
|
identify_update_path(ExtensionControlFile *control,
|
|
|
|
const char *oldVersion, const char *newVersion)
|
|
|
|
{
|
|
|
|
List *result;
|
|
|
|
List *evi_list;
|
|
|
|
ExtensionVersionInfo *evi_start;
|
|
|
|
ExtensionVersionInfo *evi_target;
|
|
|
|
|
|
|
|
/* Extract the version update graph from the script directory */
|
|
|
|
evi_list = get_ext_ver_list(control);
|
|
|
|
|
|
|
|
/* Initialize start and end vertices */
|
|
|
|
evi_start = get_ext_ver_info(oldVersion, &evi_list);
|
|
|
|
evi_target = get_ext_ver_info(newVersion, &evi_list);
|
|
|
|
|
2011-02-14 22:07:00 +01:00
|
|
|
/* Find shortest path */
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
result = find_update_path(evi_list, evi_start, evi_target, false, false);
|
2011-02-14 22:07:00 +01:00
|
|
|
|
|
|
|
if (result == NIL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("extension \"%s\" has no update path from version \"%s\" to version \"%s\"",
|
|
|
|
control->name, oldVersion, newVersion)));
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Apply Dijkstra's algorithm to find the shortest path from evi_start to
|
|
|
|
* evi_target.
|
|
|
|
*
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
* If reject_indirect is true, ignore paths that go through installable
|
|
|
|
* versions. This saves work when the caller will consider starting from
|
|
|
|
* all installable versions anyway.
|
|
|
|
*
|
2011-02-14 22:07:00 +01:00
|
|
|
* If reinitialize is false, assume the ExtensionVersionInfo list has not
|
|
|
|
* been used for this before, and the initialization done by get_ext_ver_info
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
* is still good. Otherwise, reinitialize all transient fields used here.
|
2011-02-14 22:07:00 +01:00
|
|
|
*
|
|
|
|
* Result is a List of names of versions to transition through (the initial
|
|
|
|
* version is *not* included). Returns NIL if no such path.
|
|
|
|
*/
|
|
|
|
static List *
|
|
|
|
find_update_path(List *evi_list,
|
|
|
|
ExtensionVersionInfo *evi_start,
|
|
|
|
ExtensionVersionInfo *evi_target,
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
bool reject_indirect,
|
2011-02-14 22:07:00 +01:00
|
|
|
bool reinitialize)
|
|
|
|
{
|
|
|
|
List *result;
|
|
|
|
ExtensionVersionInfo *evi;
|
|
|
|
ListCell *lc;
|
|
|
|
|
|
|
|
/* Caller error if start == target */
|
|
|
|
Assert(evi_start != evi_target);
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
/* Caller error if reject_indirect and target is installable */
|
|
|
|
Assert(!(reject_indirect && evi_target->installable));
|
2011-02-14 22:07:00 +01:00
|
|
|
|
|
|
|
if (reinitialize)
|
|
|
|
{
|
|
|
|
foreach(lc, evi_list)
|
|
|
|
{
|
|
|
|
evi = (ExtensionVersionInfo *) lfirst(lc);
|
|
|
|
evi->distance_known = false;
|
|
|
|
evi->distance = INT_MAX;
|
|
|
|
evi->previous = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
evi_start->distance = 0;
|
|
|
|
|
|
|
|
while ((evi = get_nearest_unprocessed_vertex(evi_list)) != NULL)
|
|
|
|
{
|
|
|
|
if (evi->distance == INT_MAX)
|
|
|
|
break; /* all remaining vertices are unreachable */
|
|
|
|
evi->distance_known = true;
|
|
|
|
if (evi == evi_target)
|
|
|
|
break; /* found shortest path to target */
|
|
|
|
foreach(lc, evi->reachable)
|
|
|
|
{
|
|
|
|
ExtensionVersionInfo *evi2 = (ExtensionVersionInfo *) lfirst(lc);
|
|
|
|
int newdist;
|
|
|
|
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
/* if reject_indirect, treat installable versions as unreachable */
|
|
|
|
if (reject_indirect && evi2->installable)
|
|
|
|
continue;
|
2011-02-12 03:25:20 +01:00
|
|
|
newdist = evi->distance + 1;
|
|
|
|
if (newdist < evi2->distance)
|
|
|
|
{
|
|
|
|
evi2->distance = newdist;
|
|
|
|
evi2->previous = evi;
|
|
|
|
}
|
2011-02-13 19:03:41 +01:00
|
|
|
else if (newdist == evi2->distance &&
|
|
|
|
evi2->previous != NULL &&
|
|
|
|
strcmp(evi->name, evi2->previous->name) < 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Break ties in favor of the version name that comes first
|
|
|
|
* according to strcmp(). This behavior is undocumented and
|
|
|
|
* users shouldn't rely on it. We do it just to ensure that
|
|
|
|
* if there is a tie, the update path that is chosen does not
|
|
|
|
* depend on random factors like the order in which directory
|
|
|
|
* entries get visited.
|
|
|
|
*/
|
|
|
|
evi2->previous = evi;
|
|
|
|
}
|
2011-02-12 03:25:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-14 22:07:00 +01:00
|
|
|
/* Return NIL if target is not reachable from start */
|
2011-02-12 03:25:20 +01:00
|
|
|
if (!evi_target->distance_known)
|
2011-02-14 22:07:00 +01:00
|
|
|
return NIL;
|
2011-02-12 03:25:20 +01:00
|
|
|
|
|
|
|
/* Build and return list of version names representing the update path */
|
|
|
|
result = NIL;
|
|
|
|
for (evi = evi_target; evi != evi_start; evi = evi->previous)
|
|
|
|
result = lcons(evi->name, result);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
/*
|
|
|
|
* Given a target version that is not directly installable, find the
|
|
|
|
* best installation sequence starting from a directly-installable version.
|
|
|
|
*
|
|
|
|
* evi_list: previously-collected version update graph
|
|
|
|
* evi_target: member of that list that we want to reach
|
|
|
|
*
|
|
|
|
* Returns the best starting-point version, or NULL if there is none.
|
|
|
|
* On success, *best_path is set to the path from the start point.
|
|
|
|
*
|
|
|
|
* If there's more than one possible start point, prefer shorter update paths,
|
|
|
|
* and break any ties arbitrarily on the basis of strcmp'ing the starting
|
|
|
|
* versions' names.
|
|
|
|
*/
|
|
|
|
static ExtensionVersionInfo *
|
|
|
|
find_install_path(List *evi_list, ExtensionVersionInfo *evi_target,
|
|
|
|
List **best_path)
|
|
|
|
{
|
|
|
|
ExtensionVersionInfo *evi_start = NULL;
|
|
|
|
ListCell *lc;
|
|
|
|
|
|
|
|
*best_path = NIL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We don't expect to be called for an installable target, but if we are,
|
|
|
|
* the answer is easy: just start from there, with an empty update path.
|
|
|
|
*/
|
|
|
|
if (evi_target->installable)
|
|
|
|
return evi_target;
|
|
|
|
|
|
|
|
/* Consider all installable versions as start points */
|
|
|
|
foreach(lc, evi_list)
|
|
|
|
{
|
|
|
|
ExtensionVersionInfo *evi1 = (ExtensionVersionInfo *) lfirst(lc);
|
|
|
|
List *path;
|
|
|
|
|
|
|
|
if (!evi1->installable)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find shortest path from evi1 to evi_target; but no need to consider
|
|
|
|
* paths going through other installable versions.
|
|
|
|
*/
|
|
|
|
path = find_update_path(evi_list, evi1, evi_target, true, true);
|
|
|
|
if (path == NIL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Remember best path */
|
|
|
|
if (evi_start == NULL ||
|
|
|
|
list_length(path) < list_length(*best_path) ||
|
|
|
|
(list_length(path) == list_length(*best_path) &&
|
|
|
|
strcmp(evi_start->name, evi1->name) < 0))
|
|
|
|
{
|
|
|
|
evi_start = evi1;
|
|
|
|
*best_path = path;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return evi_start;
|
|
|
|
}
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
/*
|
2015-10-03 18:19:37 +02:00
|
|
|
* CREATE EXTENSION worker
|
|
|
|
*
|
2016-09-06 00:53:25 +02:00
|
|
|
* When CASCADE is specified, CreateExtensionInternal() recurses if required
|
|
|
|
* extensions need to be installed. To sanely handle cyclic dependencies,
|
|
|
|
* the "parents" list contains a list of names of extensions already being
|
|
|
|
* installed, allowing us to error out if we recurse to one of those.
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
2015-10-03 18:19:37 +02:00
|
|
|
static ObjectAddress
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
CreateExtensionInternal(char *extensionName,
|
|
|
|
char *schemaName,
|
2017-10-31 15:34:31 +01:00
|
|
|
const char *versionName,
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
bool cascade,
|
|
|
|
List *parents,
|
|
|
|
bool is_create)
|
2011-02-08 22:08:41 +01:00
|
|
|
{
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
char *origSchemaName = schemaName;
|
2015-10-03 18:19:37 +02:00
|
|
|
Oid schemaOid = InvalidOid;
|
2011-02-08 22:08:41 +01:00
|
|
|
Oid extowner = GetUserId();
|
2011-02-12 22:40:41 +01:00
|
|
|
ExtensionControlFile *pcontrol;
|
2011-02-08 22:08:41 +01:00
|
|
|
ExtensionControlFile *control;
|
2020-02-19 22:59:14 +01:00
|
|
|
char *filename;
|
|
|
|
struct stat fst;
|
2011-02-12 22:40:41 +01:00
|
|
|
List *updateVersions;
|
2011-02-08 22:08:41 +01:00
|
|
|
List *requiredExtensions;
|
|
|
|
List *requiredSchemas;
|
|
|
|
Oid extensionOid;
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddress address;
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
ListCell *lc;
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
/*
|
2011-02-12 03:25:20 +01:00
|
|
|
* Read the primary control file. Note we assume that it does not contain
|
|
|
|
* any non-ASCII data, so there is no need to worry about encoding at this
|
|
|
|
* point.
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
pcontrol = read_extension_control_file(extensionName);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
/*
|
|
|
|
* Determine the version to install
|
|
|
|
*/
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
if (versionName == NULL)
|
2011-02-12 03:25:20 +01:00
|
|
|
{
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
if (pcontrol->default_version)
|
|
|
|
versionName = pcontrol->default_version;
|
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("version to install must be specified")));
|
2011-02-12 03:25:20 +01:00
|
|
|
}
|
|
|
|
check_valid_version_name(versionName);
|
|
|
|
|
|
|
|
/*
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
* Figure out which script(s) we need to run to install the desired
|
|
|
|
* version of the extension. If we do not have a script that directly
|
|
|
|
* does what is needed, we try to find a sequence of update scripts that
|
|
|
|
* will get us there.
|
2011-02-12 03:25:20 +01:00
|
|
|
*/
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
filename = get_extension_script_filename(pcontrol, NULL, versionName);
|
|
|
|
if (stat(filename, &fst) == 0)
|
|
|
|
{
|
|
|
|
/* Easy, no extra scripts */
|
|
|
|
updateVersions = NIL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Look for best way to install this version */
|
|
|
|
List *evi_list;
|
|
|
|
ExtensionVersionInfo *evi_start;
|
|
|
|
ExtensionVersionInfo *evi_target;
|
|
|
|
|
|
|
|
/* Extract the version update graph from the script directory */
|
|
|
|
evi_list = get_ext_ver_list(pcontrol);
|
|
|
|
|
|
|
|
/* Identify the target version */
|
|
|
|
evi_target = get_ext_ver_info(versionName, &evi_list);
|
|
|
|
|
|
|
|
/* Identify best path to reach target */
|
|
|
|
evi_start = find_install_path(evi_list, evi_target,
|
|
|
|
&updateVersions);
|
|
|
|
|
|
|
|
/* Fail if no path ... */
|
|
|
|
if (evi_start == NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("extension \"%s\" has no installation script nor update path for version \"%s\"",
|
|
|
|
pcontrol->name, versionName)));
|
|
|
|
|
|
|
|
/* Otherwise, install best starting point and then upgrade */
|
|
|
|
versionName = evi_start->name;
|
|
|
|
}
|
2011-02-12 22:40:41 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Fetch control parameters for installation target version
|
|
|
|
*/
|
|
|
|
control = read_extension_aux_control_file(pcontrol, versionName);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
/*
|
|
|
|
* Determine the target schema to install the extension into
|
|
|
|
*/
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
if (schemaName)
|
2011-02-08 22:08:41 +01:00
|
|
|
{
|
2015-10-03 18:19:37 +02:00
|
|
|
/* If the user is giving us the schema name, it must exist already. */
|
2011-02-08 22:08:41 +01:00
|
|
|
schemaOid = get_namespace_oid(schemaName, false);
|
|
|
|
}
|
2015-10-03 18:19:37 +02:00
|
|
|
|
|
|
|
if (control->schema != NULL)
|
2011-02-08 22:08:41 +01:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* The extension is not relocatable and the author gave us a schema
|
2015-10-03 18:19:37 +02:00
|
|
|
* for it.
|
|
|
|
*
|
|
|
|
* Unless CASCADE parameter was given, it's an error to give a schema
|
|
|
|
* different from control->schema if control->schema is specified.
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
2015-10-03 18:19:37 +02:00
|
|
|
if (schemaName && strcmp(control->schema, schemaName) != 0 &&
|
|
|
|
!cascade)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("extension \"%s\" must be installed in schema \"%s\"",
|
|
|
|
control->name,
|
|
|
|
control->schema)));
|
|
|
|
|
|
|
|
/* Always use the schema from control file for current extension. */
|
2011-02-08 22:08:41 +01:00
|
|
|
schemaName = control->schema;
|
2015-10-03 18:19:37 +02:00
|
|
|
|
|
|
|
/* Find or create the schema in case it does not exist. */
|
2011-02-08 22:08:41 +01:00
|
|
|
schemaOid = get_namespace_oid(schemaName, true);
|
|
|
|
|
2015-10-03 18:19:37 +02:00
|
|
|
if (!OidIsValid(schemaOid))
|
2011-02-08 22:08:41 +01:00
|
|
|
{
|
2011-08-24 03:49:07 +02:00
|
|
|
CreateSchemaStmt *csstmt = makeNode(CreateSchemaStmt);
|
|
|
|
|
|
|
|
csstmt->schemaname = schemaName;
|
Allow CURRENT/SESSION_USER to be used in certain commands
Commands such as ALTER USER, ALTER GROUP, ALTER ROLE, GRANT, and the
various ALTER OBJECT / OWNER TO, as well as ad-hoc clauses related to
roles such as the AUTHORIZATION clause of CREATE SCHEMA, the FOR clause
of CREATE USER MAPPING, and the FOR ROLE clause of ALTER DEFAULT
PRIVILEGES can now take the keywords CURRENT_USER and SESSION_USER as
user specifiers in place of an explicit user name.
This commit also fixes some quite ugly handling of special standards-
mandated syntax in CREATE USER MAPPING, which in particular would fail
to work in presence of a role named "current_user".
The special role specifiers PUBLIC and NONE also have more consistent
handling now.
Also take the opportunity to add location tracking to user specifiers.
Authors: Kyotaro Horiguchi. Heavily reworked by Álvaro Herrera.
Reviewed by: Rushabh Lathia, Adam Brightwell, Marti Raudsepp.
2015-03-09 19:41:54 +01:00
|
|
|
csstmt->authrole = NULL; /* will be created by current user */
|
2011-08-24 03:49:07 +02:00
|
|
|
csstmt->schemaElts = NIL;
|
2012-10-04 01:47:11 +02:00
|
|
|
csstmt->if_not_exists = false;
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
CreateSchemaCommand(csstmt, "(generated CREATE SCHEMA command)",
|
|
|
|
-1, -1);
|
2011-08-24 03:49:07 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* CreateSchemaCommand includes CommandCounterIncrement, so new
|
2015-10-03 18:19:37 +02:00
|
|
|
* schema is now visible.
|
2011-08-24 03:49:07 +02:00
|
|
|
*/
|
|
|
|
schemaOid = get_namespace_oid(schemaName, false);
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
|
|
|
}
|
2015-10-03 18:19:37 +02:00
|
|
|
else if (!OidIsValid(schemaOid))
|
2011-02-08 22:08:41 +01:00
|
|
|
{
|
|
|
|
/*
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
* Neither user nor author of the extension specified schema; use the
|
2015-10-03 18:19:37 +02:00
|
|
|
* current default creation namespace, which is the first explicit
|
|
|
|
* entry in the search_path.
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
|
|
|
List *search_path = fetch_search_path(false);
|
|
|
|
|
2013-06-04 23:22:29 +02:00
|
|
|
if (search_path == NIL) /* nothing valid in search_path? */
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_SCHEMA),
|
|
|
|
errmsg("no schema has been selected to create in")));
|
2011-02-08 22:08:41 +01:00
|
|
|
schemaOid = linitial_oid(search_path);
|
|
|
|
schemaName = get_namespace_name(schemaOid);
|
|
|
|
if (schemaName == NULL) /* recently-deleted namespace? */
|
2013-06-04 23:22:29 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_SCHEMA),
|
|
|
|
errmsg("no schema has been selected to create in")));
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
list_free(search_path);
|
|
|
|
}
|
|
|
|
|
Restrict the use of temporary namespace in two-phase transactions
Attempting to use a temporary table within a two-phase transaction is
forbidden for ages. However, there have been uncovered grounds for
a couple of other object types and commands which work on temporary
objects with two-phase commit. In short, trying to create, lock or drop
an object on a temporary schema should not be authorized within a
two-phase transaction, as it would cause its state to create
dependencies with other sessions, causing all sorts of side effects with
the existing session or other sessions spawned later on trying to use
the same temporary schema name.
Regression tests are added to cover all the grounds found, the original
report mentioned function creation, but monitoring closer there are many
other patterns with LOCK, DROP or CREATE EXTENSION which are involved.
One of the symptoms resulting in combining both is that the session
which used the temporary schema is not able to shut down completely,
waiting for being able to drop the temporary schema, something that it
cannot complete because of the two-phase transaction involved with
temporary objects. In this case the client is able to disconnect but
the session remains alive on the backend-side, potentially blocking
connection backend slots from being used. Other problems reported could
also involve server crashes.
This is back-patched down to v10, which is where 9b013dc has introduced
MyXactFlags, something that this patch relies on.
Reported-by: Alexey Bashtanov
Author: Michael Paquier
Reviewed-by: Masahiko Sawada
Discussion: https://postgr.es/m/5d910e2e-0db8-ec06-dd5f-baec420513c3@imap.cc
Backpatch-through: 10
2019-01-18 01:21:44 +01:00
|
|
|
/*
|
|
|
|
* Make note if a temporary namespace has been accessed in this
|
|
|
|
* transaction.
|
|
|
|
*/
|
|
|
|
if (isTempNamespace(schemaOid))
|
|
|
|
MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
/*
|
2011-03-05 03:51:14 +01:00
|
|
|
* We don't check creation rights on the target namespace here. If the
|
|
|
|
* extension script actually creates any objects there, it will fail if
|
|
|
|
* the user doesn't have such permissions. But there are cases such as
|
|
|
|
* procedural languages where it's convenient to set schema = pg_catalog
|
|
|
|
* yet we don't want to restrict the command to users with ACL_CREATE for
|
|
|
|
* pg_catalog.
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2016-09-06 00:53:25 +02:00
|
|
|
* Look up the prerequisite extensions, install them if necessary, and
|
|
|
|
* build lists of their OIDs and the OIDs of their target schemas.
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
|
|
|
requiredExtensions = NIL;
|
|
|
|
requiredSchemas = NIL;
|
|
|
|
foreach(lc, control->requires)
|
|
|
|
{
|
|
|
|
char *curreq = (char *) lfirst(lc);
|
|
|
|
Oid reqext;
|
|
|
|
Oid reqschema;
|
|
|
|
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
reqext = get_required_extension(curreq,
|
|
|
|
extensionName,
|
|
|
|
origSchemaName,
|
|
|
|
cascade,
|
|
|
|
parents,
|
|
|
|
is_create);
|
2011-02-08 22:08:41 +01:00
|
|
|
reqschema = get_extension_schema(reqext);
|
|
|
|
requiredExtensions = lappend_oid(requiredExtensions, reqext);
|
|
|
|
requiredSchemas = lappend_oid(requiredSchemas, reqschema);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-02-10 01:17:33 +01:00
|
|
|
* Insert new tuple into pg_extension, and create dependency entries.
|
|
|
|
*/
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
address = InsertExtensionTuple(control->name, extowner,
|
|
|
|
schemaOid, control->relocatable,
|
|
|
|
versionName,
|
|
|
|
PointerGetDatum(NULL),
|
|
|
|
PointerGetDatum(NULL),
|
|
|
|
requiredExtensions);
|
|
|
|
extensionOid = address.objectId;
|
2011-02-10 01:17:33 +01:00
|
|
|
|
|
|
|
/*
|
2011-02-13 19:03:41 +01:00
|
|
|
* Apply any control-file comment on extension
|
2011-02-10 01:17:33 +01:00
|
|
|
*/
|
|
|
|
if (control->comment != NULL)
|
|
|
|
CreateComments(extensionOid, ExtensionRelationId, 0, control->comment);
|
|
|
|
|
|
|
|
/*
|
2011-02-12 22:40:41 +01:00
|
|
|
* Execute the installation script file
|
2011-02-10 01:17:33 +01:00
|
|
|
*/
|
2011-02-12 22:40:41 +01:00
|
|
|
execute_extension_script(extensionOid, control,
|
2020-02-19 22:59:14 +01:00
|
|
|
NULL, versionName,
|
2011-02-12 22:40:41 +01:00
|
|
|
requiredSchemas,
|
|
|
|
schemaName, schemaOid);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
/*
|
|
|
|
* If additional update scripts have to be executed, apply the updates as
|
|
|
|
* though a series of ALTER EXTENSION UPDATE commands were given
|
|
|
|
*/
|
|
|
|
ApplyExtensionUpdates(extensionOid, pcontrol,
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
versionName, updateVersions,
|
|
|
|
origSchemaName, cascade, is_create);
|
2012-12-24 00:25:03 +01:00
|
|
|
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
return address;
|
2011-02-10 01:17:33 +01:00
|
|
|
}
|
|
|
|
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
/*
|
|
|
|
* Get the OID of an extension listed in "requires", possibly creating it.
|
|
|
|
*/
|
|
|
|
static Oid
|
|
|
|
get_required_extension(char *reqExtensionName,
|
|
|
|
char *extensionName,
|
|
|
|
char *origSchemaName,
|
|
|
|
bool cascade,
|
|
|
|
List *parents,
|
|
|
|
bool is_create)
|
|
|
|
{
|
|
|
|
Oid reqExtensionOid;
|
|
|
|
|
|
|
|
reqExtensionOid = get_extension_oid(reqExtensionName, true);
|
|
|
|
if (!OidIsValid(reqExtensionOid))
|
|
|
|
{
|
|
|
|
if (cascade)
|
|
|
|
{
|
|
|
|
/* Must install it. */
|
|
|
|
ObjectAddress addr;
|
|
|
|
List *cascade_parents;
|
|
|
|
ListCell *lc;
|
|
|
|
|
|
|
|
/* Check extension name validity before trying to cascade. */
|
|
|
|
check_valid_extension_name(reqExtensionName);
|
|
|
|
|
|
|
|
/* Check for cyclic dependency between extensions. */
|
|
|
|
foreach(lc, parents)
|
|
|
|
{
|
|
|
|
char *pname = (char *) lfirst(lc);
|
|
|
|
|
|
|
|
if (strcmp(pname, reqExtensionName) == 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_RECURSION),
|
|
|
|
errmsg("cyclic dependency detected between extensions \"%s\" and \"%s\"",
|
|
|
|
reqExtensionName, extensionName)));
|
|
|
|
}
|
|
|
|
|
|
|
|
ereport(NOTICE,
|
|
|
|
(errmsg("installing required extension \"%s\"",
|
|
|
|
reqExtensionName)));
|
|
|
|
|
|
|
|
/* Add current extension to list of parents to pass down. */
|
|
|
|
cascade_parents = lappend(list_copy(parents), extensionName);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create the required extension. We propagate the SCHEMA option
|
|
|
|
* if any, and CASCADE, but no other options.
|
|
|
|
*/
|
|
|
|
addr = CreateExtensionInternal(reqExtensionName,
|
|
|
|
origSchemaName,
|
|
|
|
NULL,
|
|
|
|
cascade,
|
|
|
|
cascade_parents,
|
|
|
|
is_create);
|
|
|
|
|
|
|
|
/* Get its newly-assigned OID. */
|
|
|
|
reqExtensionOid = addr.objectId;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("required extension \"%s\" is not installed",
|
|
|
|
reqExtensionName),
|
|
|
|
is_create ?
|
|
|
|
errhint("Use CREATE EXTENSION ... CASCADE to install required extensions too.") : 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
return reqExtensionOid;
|
|
|
|
}
|
|
|
|
|
2015-10-03 18:19:37 +02:00
|
|
|
/*
|
|
|
|
* CREATE EXTENSION
|
|
|
|
*/
|
|
|
|
ObjectAddress
|
2016-09-06 18:00:00 +02:00
|
|
|
CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
|
2015-10-03 18:19:37 +02:00
|
|
|
{
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
DefElem *d_schema = NULL;
|
|
|
|
DefElem *d_new_version = NULL;
|
|
|
|
DefElem *d_cascade = NULL;
|
|
|
|
char *schemaName = NULL;
|
|
|
|
char *versionName = NULL;
|
|
|
|
bool cascade = false;
|
|
|
|
ListCell *lc;
|
|
|
|
|
2015-10-03 18:19:37 +02:00
|
|
|
/* Check extension name validity before any filesystem access */
|
|
|
|
check_valid_extension_name(stmt->extname);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for duplicate extension name. The unique index on
|
|
|
|
* pg_extension.extname would catch this anyway, and serves as a backstop
|
|
|
|
* in case of race conditions; but this is a friendlier error message, and
|
|
|
|
* besides we need a check to support IF NOT EXISTS.
|
|
|
|
*/
|
|
|
|
if (get_extension_oid(stmt->extname, true) != InvalidOid)
|
|
|
|
{
|
|
|
|
if (stmt->if_not_exists)
|
|
|
|
{
|
|
|
|
ereport(NOTICE,
|
|
|
|
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
|
|
|
errmsg("extension \"%s\" already exists, skipping",
|
|
|
|
stmt->extname)));
|
|
|
|
return InvalidObjectAddress;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
|
|
|
errmsg("extension \"%s\" already exists",
|
|
|
|
stmt->extname)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We use global variables to track the extension being created, so we can
|
|
|
|
* create only one extension at the same time.
|
|
|
|
*/
|
|
|
|
if (creating_extension)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("nested CREATE EXTENSION is not supported")));
|
|
|
|
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
/* Deconstruct the statement option list */
|
|
|
|
foreach(lc, stmt->options)
|
|
|
|
{
|
|
|
|
DefElem *defel = (DefElem *) lfirst(lc);
|
|
|
|
|
|
|
|
if (strcmp(defel->defname, "schema") == 0)
|
|
|
|
{
|
|
|
|
if (d_schema)
|
Improve reporting of "conflicting or redundant options" errors.
When reporting "conflicting or redundant options" errors, try to
ensure that errposition() is used, to help the user identify the
offending option.
Formerly, errposition() was invoked in less than 60% of cases. This
patch raises that to over 90%, but there remain a few places where the
ParseState is not readily available. Using errdetail() might improve
the error in such cases, but that is left as a task for the future.
Additionally, since this error is thrown from over 100 places in the
codebase, introduce a dedicated function to throw it, reducing code
duplication.
Extracted from a slightly larger patch by Vignesh C. Reviewed by
Bharath Rupireddy, Alvaro Herrera, Dilip Kumar, Hou Zhijie, Peter
Smith, Daniel Gustafsson, Julien Rouhaud and me.
Discussion: https://postgr.es/m/CALDaNm33FFSS5tVyvmkoK2cCMuDVxcui=gFrjti9ROfynqSAGA@mail.gmail.com
2021-07-15 09:49:45 +02:00
|
|
|
errorConflictingDefElem(defel, pstate);
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
d_schema = defel;
|
|
|
|
schemaName = defGetString(d_schema);
|
|
|
|
}
|
|
|
|
else if (strcmp(defel->defname, "new_version") == 0)
|
|
|
|
{
|
|
|
|
if (d_new_version)
|
Improve reporting of "conflicting or redundant options" errors.
When reporting "conflicting or redundant options" errors, try to
ensure that errposition() is used, to help the user identify the
offending option.
Formerly, errposition() was invoked in less than 60% of cases. This
patch raises that to over 90%, but there remain a few places where the
ParseState is not readily available. Using errdetail() might improve
the error in such cases, but that is left as a task for the future.
Additionally, since this error is thrown from over 100 places in the
codebase, introduce a dedicated function to throw it, reducing code
duplication.
Extracted from a slightly larger patch by Vignesh C. Reviewed by
Bharath Rupireddy, Alvaro Herrera, Dilip Kumar, Hou Zhijie, Peter
Smith, Daniel Gustafsson, Julien Rouhaud and me.
Discussion: https://postgr.es/m/CALDaNm33FFSS5tVyvmkoK2cCMuDVxcui=gFrjti9ROfynqSAGA@mail.gmail.com
2021-07-15 09:49:45 +02:00
|
|
|
errorConflictingDefElem(defel, pstate);
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
d_new_version = defel;
|
|
|
|
versionName = defGetString(d_new_version);
|
|
|
|
}
|
|
|
|
else if (strcmp(defel->defname, "cascade") == 0)
|
|
|
|
{
|
|
|
|
if (d_cascade)
|
Improve reporting of "conflicting or redundant options" errors.
When reporting "conflicting or redundant options" errors, try to
ensure that errposition() is used, to help the user identify the
offending option.
Formerly, errposition() was invoked in less than 60% of cases. This
patch raises that to over 90%, but there remain a few places where the
ParseState is not readily available. Using errdetail() might improve
the error in such cases, but that is left as a task for the future.
Additionally, since this error is thrown from over 100 places in the
codebase, introduce a dedicated function to throw it, reducing code
duplication.
Extracted from a slightly larger patch by Vignesh C. Reviewed by
Bharath Rupireddy, Alvaro Herrera, Dilip Kumar, Hou Zhijie, Peter
Smith, Daniel Gustafsson, Julien Rouhaud and me.
Discussion: https://postgr.es/m/CALDaNm33FFSS5tVyvmkoK2cCMuDVxcui=gFrjti9ROfynqSAGA@mail.gmail.com
2021-07-15 09:49:45 +02:00
|
|
|
errorConflictingDefElem(defel, pstate);
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
d_cascade = defel;
|
|
|
|
cascade = defGetBoolean(d_cascade);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
elog(ERROR, "unrecognized option: %s", defel->defname);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Call CreateExtensionInternal to do the real work. */
|
|
|
|
return CreateExtensionInternal(stmt->extname,
|
|
|
|
schemaName,
|
|
|
|
versionName,
|
|
|
|
cascade,
|
|
|
|
NIL,
|
|
|
|
true);
|
2015-10-03 18:19:37 +02:00
|
|
|
}
|
|
|
|
|
2011-02-10 01:17:33 +01:00
|
|
|
/*
|
|
|
|
* InsertExtensionTuple
|
|
|
|
*
|
|
|
|
* Insert the new pg_extension row, and create extension's dependency entries.
|
|
|
|
* Return the OID assigned to the new row.
|
|
|
|
*
|
|
|
|
* This is exported for the benefit of pg_upgrade, which has to create a
|
|
|
|
* pg_extension entry (and the extension-level dependencies) without
|
|
|
|
* actually running the extension's script.
|
|
|
|
*
|
|
|
|
* extConfig and extCondition should be arrays or PointerGetDatum(NULL).
|
|
|
|
* We declare them as plain Datum to avoid needing array.h in extension.h.
|
|
|
|
*/
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddress
|
2011-02-10 01:17:33 +01:00
|
|
|
InsertExtensionTuple(const char *extName, Oid extOwner,
|
|
|
|
Oid schemaOid, bool relocatable, const char *extVersion,
|
|
|
|
Datum extConfig, Datum extCondition,
|
|
|
|
List *requiredExtensions)
|
|
|
|
{
|
|
|
|
Oid extensionOid;
|
|
|
|
Relation rel;
|
|
|
|
Datum values[Natts_pg_extension];
|
|
|
|
bool nulls[Natts_pg_extension];
|
|
|
|
HeapTuple tuple;
|
|
|
|
ObjectAddress myself;
|
|
|
|
ObjectAddress nsp;
|
2020-07-01 04:12:33 +02:00
|
|
|
ObjectAddresses *refobjs;
|
2011-02-10 01:17:33 +01:00
|
|
|
ListCell *lc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Build and insert the pg_extension tuple
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
2019-01-21 19:32:19 +01:00
|
|
|
rel = table_open(ExtensionRelationId, RowExclusiveLock);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
memset(values, 0, sizeof(values));
|
|
|
|
memset(nulls, 0, sizeof(nulls));
|
|
|
|
|
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
|
|
|
extensionOid = GetNewOidWithIndex(rel, ExtensionOidIndexId,
|
|
|
|
Anum_pg_extension_oid);
|
|
|
|
values[Anum_pg_extension_oid - 1] = ObjectIdGetDatum(extensionOid);
|
2011-02-08 22:08:41 +01:00
|
|
|
values[Anum_pg_extension_extname - 1] =
|
2011-02-10 01:17:33 +01:00
|
|
|
DirectFunctionCall1(namein, CStringGetDatum(extName));
|
|
|
|
values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extOwner);
|
2011-02-08 22:08:41 +01:00
|
|
|
values[Anum_pg_extension_extnamespace - 1] = ObjectIdGetDatum(schemaOid);
|
2011-02-10 01:17:33 +01:00
|
|
|
values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(relocatable);
|
2011-02-12 03:25:20 +01:00
|
|
|
values[Anum_pg_extension_extversion - 1] = CStringGetTextDatum(extVersion);
|
2011-02-10 01:17:33 +01:00
|
|
|
|
|
|
|
if (extConfig == PointerGetDatum(NULL))
|
|
|
|
nulls[Anum_pg_extension_extconfig - 1] = true;
|
|
|
|
else
|
|
|
|
values[Anum_pg_extension_extconfig - 1] = extConfig;
|
2011-02-08 22:08:41 +01:00
|
|
|
|
2011-02-10 01:17:33 +01:00
|
|
|
if (extCondition == PointerGetDatum(NULL))
|
|
|
|
nulls[Anum_pg_extension_extcondition - 1] = true;
|
|
|
|
else
|
|
|
|
values[Anum_pg_extension_extcondition - 1] = extCondition;
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
tuple = heap_form_tuple(rel->rd_att, values, nulls);
|
|
|
|
|
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
|
|
|
CatalogTupleInsert(rel, tuple);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
heap_freetuple(tuple);
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(rel, RowExclusiveLock);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Record dependencies on owner, schema, and prerequisite extensions
|
|
|
|
*/
|
2011-02-10 01:17:33 +01:00
|
|
|
recordDependencyOnOwner(ExtensionRelationId, extensionOid, extOwner);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
2020-07-01 04:12:33 +02:00
|
|
|
refobjs = new_object_addresses();
|
2011-02-08 22:08:41 +01:00
|
|
|
|
2020-07-01 04:12:33 +02:00
|
|
|
ObjectAddressSet(myself, ExtensionRelationId, extensionOid);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
2020-07-01 04:12:33 +02:00
|
|
|
ObjectAddressSet(nsp, NamespaceRelationId, schemaOid);
|
|
|
|
add_exact_object_address(&nsp, refobjs);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
foreach(lc, requiredExtensions)
|
|
|
|
{
|
|
|
|
Oid reqext = lfirst_oid(lc);
|
|
|
|
ObjectAddress otherext;
|
|
|
|
|
2020-07-01 04:12:33 +02:00
|
|
|
ObjectAddressSet(otherext, ExtensionRelationId, reqext);
|
|
|
|
add_exact_object_address(&otherext, refobjs);
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
2020-07-01 04:12:33 +02:00
|
|
|
|
|
|
|
/* Record all of them (this includes duplicate elimination) */
|
|
|
|
record_object_address_dependencies(&myself, refobjs, DEPENDENCY_NORMAL);
|
|
|
|
free_object_addresses(refobjs);
|
|
|
|
|
2011-03-24 23:44:49 +01:00
|
|
|
/* Post creation hook for new extension */
|
2013-03-07 02:52:06 +01:00
|
|
|
InvokeObjectPostCreateHook(ExtensionRelationId, extensionOid, 0);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
return myself;
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Guts of extension deletion.
|
|
|
|
*
|
|
|
|
* All we need do here is remove the pg_extension tuple itself. Everything
|
|
|
|
* else is taken care of by the dependency infrastructure.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
RemoveExtensionById(Oid extId)
|
|
|
|
{
|
|
|
|
Relation rel;
|
|
|
|
SysScanDesc scandesc;
|
|
|
|
HeapTuple tuple;
|
|
|
|
ScanKeyData entry[1];
|
|
|
|
|
2011-11-29 01:12:17 +01:00
|
|
|
/*
|
|
|
|
* Disallow deletion of any extension that's currently open for insertion;
|
|
|
|
* else subsequent executions of recordDependencyOnCurrentExtension()
|
|
|
|
* could create dangling pg_depend records that refer to a no-longer-valid
|
|
|
|
* pg_extension OID. This is needed not so much because we think people
|
|
|
|
* might write "DROP EXTENSION foo" in foo's own script files, as because
|
|
|
|
* errors in dependency management in extension script files could give
|
|
|
|
* rise to cases where an extension is dropped as a result of recursing
|
|
|
|
* from some contained object. Because of that, we must test for the case
|
|
|
|
* here, not at some higher level of the DROP EXTENSION command.
|
|
|
|
*/
|
|
|
|
if (extId == CurrentExtensionObject)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
|
|
|
errmsg("cannot drop extension \"%s\" because it is being modified",
|
|
|
|
get_extension_name(extId))));
|
|
|
|
|
2019-01-21 19:32:19 +01:00
|
|
|
rel = table_open(ExtensionRelationId, RowExclusiveLock);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
ScanKeyInit(&entry[0],
|
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
|
|
|
Anum_pg_extension_oid,
|
2011-02-08 22:08:41 +01:00
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(extId));
|
|
|
|
scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
|
Use an MVCC snapshot, rather than SnapshotNow, for catalog scans.
SnapshotNow scans have the undesirable property that, in the face of
concurrent updates, the scan can fail to see either the old or the new
versions of the row. In many cases, we work around this by requiring
DDL operations to hold AccessExclusiveLock on the object being
modified; in some cases, the existing locking is inadequate and random
failures occur as a result. This commit doesn't change anything
related to locking, but will hopefully pave the way to allowing lock
strength reductions in the future.
The major issue has held us back from making this change in the past
is that taking an MVCC snapshot is significantly more expensive than
using a static special snapshot such as SnapshotNow. However, testing
of various worst-case scenarios reveals that this problem is not
severe except under fairly extreme workloads. To mitigate those
problems, we avoid retaking the MVCC snapshot for each new scan;
instead, we take a new snapshot only when invalidation messages have
been processed. The catcache machinery already requires that
invalidation messages be sent before releasing the related heavyweight
lock; else other backends might rely on locally-cached data rather
than scanning the catalog at all. Thus, making snapshot reuse
dependent on the same guarantees shouldn't break anything that wasn't
already subtly broken.
Patch by me. Review by Michael Paquier and Andres Freund.
2013-07-02 15:47:01 +02:00
|
|
|
NULL, 1, entry);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
tuple = systable_getnext(scandesc);
|
|
|
|
|
|
|
|
/* We assume that there can be at most one matching tuple */
|
|
|
|
if (HeapTupleIsValid(tuple))
|
2017-02-01 22:13:30 +01:00
|
|
|
CatalogTupleDelete(rel, &tuple->t_self);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
systable_endscan(scandesc);
|
|
|
|
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(rel, RowExclusiveLock);
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-02-14 22:07:00 +01:00
|
|
|
* This function lists the available extensions (one row per primary control
|
|
|
|
* file in the control directory). We parse each control file and report the
|
|
|
|
* interesting fields.
|
2011-02-08 22:08:41 +01:00
|
|
|
*
|
|
|
|
* The system view pg_available_extensions provides a user interface to this
|
|
|
|
* SRF, adding information about whether the extensions are installed in the
|
|
|
|
* current DB.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
pg_available_extensions(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
|
|
|
|
char *location;
|
|
|
|
DIR *dir;
|
|
|
|
struct dirent *de;
|
|
|
|
|
2011-02-14 22:07:00 +01:00
|
|
|
/* Build tuplestore to hold the result rows */
|
2022-10-18 03:22:35 +02:00
|
|
|
InitMaterializedSRF(fcinfo, 0);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
location = get_extension_control_directory();
|
|
|
|
dir = AllocateDir(location);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the control directory doesn't exist, we want to silently return an
|
|
|
|
* empty set. Any other error will be reported by ReadDir.
|
|
|
|
*/
|
|
|
|
if (dir == NULL && errno == ENOENT)
|
|
|
|
{
|
|
|
|
/* do nothing */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while ((de = ReadDir(dir, location)) != NULL)
|
|
|
|
{
|
|
|
|
ExtensionControlFile *control;
|
|
|
|
char *extname;
|
2011-02-14 22:07:00 +01:00
|
|
|
Datum values[3];
|
|
|
|
bool nulls[3];
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
if (!is_extension_control_filename(de->d_name))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* extract extension name from 'name.control' filename */
|
|
|
|
extname = pstrdup(de->d_name);
|
|
|
|
*strrchr(extname, '.') = '\0';
|
|
|
|
|
2011-02-13 19:03:41 +01:00
|
|
|
/* ignore it if it's an auxiliary control file */
|
|
|
|
if (strstr(extname, "--"))
|
|
|
|
continue;
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
control = read_extension_control_file(extname);
|
|
|
|
|
|
|
|
memset(values, 0, sizeof(values));
|
|
|
|
memset(nulls, 0, sizeof(nulls));
|
|
|
|
|
|
|
|
/* name */
|
|
|
|
values[0] = DirectFunctionCall1(namein,
|
|
|
|
CStringGetDatum(control->name));
|
2011-02-12 03:25:20 +01:00
|
|
|
/* default_version */
|
|
|
|
if (control->default_version == NULL)
|
2011-02-08 22:08:41 +01:00
|
|
|
nulls[1] = true;
|
|
|
|
else
|
2011-02-12 03:25:20 +01:00
|
|
|
values[1] = CStringGetTextDatum(control->default_version);
|
2011-02-08 22:08:41 +01:00
|
|
|
/* comment */
|
|
|
|
if (control->comment == NULL)
|
2011-02-14 22:07:00 +01:00
|
|
|
nulls[2] = true;
|
2011-02-08 22:08:41 +01:00
|
|
|
else
|
2011-02-14 22:07:00 +01:00
|
|
|
values[2] = CStringGetTextDatum(control->comment);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
Create routine able to set single-call SRFs for Materialize mode
Set-returning functions that use the Materialize mode, creating a
tuplestore to include all the tuples returned in a set rather than doing
so in multiple calls, use roughly the same set of steps to prepare
ReturnSetInfo for this job:
- Check if ReturnSetInfo supports returning a tuplestore and if the
materialize mode is enabled.
- Create a tuplestore for all the tuples part of the returned set in the
per-query memory context, stored in ReturnSetInfo->setResult.
- Build a tuple descriptor mostly from get_call_result_type(), then
stored in ReturnSetInfo->setDesc. Note that there are some cases where
the SRF's tuple descriptor has to be the one specified by the function
caller.
This refactoring is done so as there are (well, should be) no behavior
changes in any of the in-core functions refactored, and the centralized
function that checks and sets up the function's ReturnSetInfo can be
controlled with a set of bits32 options. Two of them prove to be
necessary now:
- SRF_SINGLE_USE_EXPECTED to use expectedDesc as tuple descriptor, as
expected by the function's caller.
- SRF_SINGLE_BLESS to validate the tuple descriptor for the SRF.
The same initialization pattern is simplified in 28 places per my
count as of src/backend/, shaving up to ~900 lines of code. These
mostly come from the removal of the per-query initializations and the
sanity checks now grouped in a single location. There are more
locations that could be simplified in contrib/, that are left for a
follow-up cleanup.
fcc2817, 07daca5 and d61a361 have prepared the areas of the code related
to this change, to ease this refactoring.
Author: Melanie Plageman, Michael Paquier
Reviewed-by: Álvaro Herrera, Justin Pryzby
Discussion: https://postgr.es/m/CAAKRu_azyd1Z3W_r7Ou4sorTjRCs+PxeHw1CWJeXKofkE6TuZg@mail.gmail.com
2022-03-07 02:26:29 +01:00
|
|
|
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
|
|
|
|
values, nulls);
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
FreeDir(dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (Datum) 0;
|
|
|
|
}
|
|
|
|
|
2011-02-14 22:07:00 +01:00
|
|
|
/*
|
|
|
|
* This function lists the available extension versions (one row per
|
|
|
|
* extension installation script). For each version, we parse the related
|
|
|
|
* control file(s) and report the interesting fields.
|
|
|
|
*
|
|
|
|
* The system view pg_available_extension_versions provides a user interface
|
|
|
|
* to this SRF, adding information about which versions are installed in the
|
|
|
|
* current DB.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
pg_available_extension_versions(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
|
|
|
|
char *location;
|
|
|
|
DIR *dir;
|
|
|
|
struct dirent *de;
|
|
|
|
|
|
|
|
/* Build tuplestore to hold the result rows */
|
2022-10-18 03:22:35 +02:00
|
|
|
InitMaterializedSRF(fcinfo, 0);
|
2011-02-14 22:07:00 +01:00
|
|
|
|
|
|
|
location = get_extension_control_directory();
|
|
|
|
dir = AllocateDir(location);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the control directory doesn't exist, we want to silently return an
|
|
|
|
* empty set. Any other error will be reported by ReadDir.
|
|
|
|
*/
|
|
|
|
if (dir == NULL && errno == ENOENT)
|
|
|
|
{
|
|
|
|
/* do nothing */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while ((de = ReadDir(dir, location)) != NULL)
|
|
|
|
{
|
|
|
|
ExtensionControlFile *control;
|
|
|
|
char *extname;
|
|
|
|
|
|
|
|
if (!is_extension_control_filename(de->d_name))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* extract extension name from 'name.control' filename */
|
|
|
|
extname = pstrdup(de->d_name);
|
|
|
|
*strrchr(extname, '.') = '\0';
|
|
|
|
|
|
|
|
/* ignore it if it's an auxiliary control file */
|
|
|
|
if (strstr(extname, "--"))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* read the control file */
|
|
|
|
control = read_extension_control_file(extname);
|
|
|
|
|
|
|
|
/* scan extension's script directory for install scripts */
|
Create routine able to set single-call SRFs for Materialize mode
Set-returning functions that use the Materialize mode, creating a
tuplestore to include all the tuples returned in a set rather than doing
so in multiple calls, use roughly the same set of steps to prepare
ReturnSetInfo for this job:
- Check if ReturnSetInfo supports returning a tuplestore and if the
materialize mode is enabled.
- Create a tuplestore for all the tuples part of the returned set in the
per-query memory context, stored in ReturnSetInfo->setResult.
- Build a tuple descriptor mostly from get_call_result_type(), then
stored in ReturnSetInfo->setDesc. Note that there are some cases where
the SRF's tuple descriptor has to be the one specified by the function
caller.
This refactoring is done so as there are (well, should be) no behavior
changes in any of the in-core functions refactored, and the centralized
function that checks and sets up the function's ReturnSetInfo can be
controlled with a set of bits32 options. Two of them prove to be
necessary now:
- SRF_SINGLE_USE_EXPECTED to use expectedDesc as tuple descriptor, as
expected by the function's caller.
- SRF_SINGLE_BLESS to validate the tuple descriptor for the SRF.
The same initialization pattern is simplified in 28 places per my
count as of src/backend/, shaving up to ~900 lines of code. These
mostly come from the removal of the per-query initializations and the
sanity checks now grouped in a single location. There are more
locations that could be simplified in contrib/, that are left for a
follow-up cleanup.
fcc2817, 07daca5 and d61a361 have prepared the areas of the code related
to this change, to ease this refactoring.
Author: Melanie Plageman, Michael Paquier
Reviewed-by: Álvaro Herrera, Justin Pryzby
Discussion: https://postgr.es/m/CAAKRu_azyd1Z3W_r7Ou4sorTjRCs+PxeHw1CWJeXKofkE6TuZg@mail.gmail.com
2022-03-07 02:26:29 +01:00
|
|
|
get_available_versions_for_extension(control, rsinfo->setResult,
|
|
|
|
rsinfo->setDesc);
|
2011-02-14 22:07:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
FreeDir(dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (Datum) 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Inner loop for pg_available_extension_versions:
|
|
|
|
* read versions of one extension, add rows to tupstore
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
get_available_versions_for_extension(ExtensionControlFile *pcontrol,
|
|
|
|
Tuplestorestate *tupstore,
|
|
|
|
TupleDesc tupdesc)
|
|
|
|
{
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
List *evi_list;
|
|
|
|
ListCell *lc;
|
2011-02-14 22:07:00 +01:00
|
|
|
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
/* Extract the version update graph from the script directory */
|
|
|
|
evi_list = get_ext_ver_list(pcontrol);
|
|
|
|
|
|
|
|
/* For each installable version ... */
|
|
|
|
foreach(lc, evi_list)
|
2011-02-14 22:07:00 +01:00
|
|
|
{
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
ExtensionVersionInfo *evi = (ExtensionVersionInfo *) lfirst(lc);
|
2011-02-14 22:07:00 +01:00
|
|
|
ExtensionControlFile *control;
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
Datum values[8];
|
|
|
|
bool nulls[8];
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
ListCell *lc2;
|
2011-02-14 22:07:00 +01:00
|
|
|
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
if (!evi->installable)
|
2011-02-14 22:07:00 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Fetch parameters for specific version (pcontrol is not changed)
|
|
|
|
*/
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
control = read_extension_aux_control_file(pcontrol, evi->name);
|
2011-02-14 22:07:00 +01:00
|
|
|
|
|
|
|
memset(values, 0, sizeof(values));
|
|
|
|
memset(nulls, 0, sizeof(nulls));
|
|
|
|
|
|
|
|
/* name */
|
|
|
|
values[0] = DirectFunctionCall1(namein,
|
|
|
|
CStringGetDatum(control->name));
|
|
|
|
/* version */
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
values[1] = CStringGetTextDatum(evi->name);
|
2011-03-04 22:08:24 +01:00
|
|
|
/* superuser */
|
|
|
|
values[2] = BoolGetDatum(control->superuser);
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
/* trusted */
|
|
|
|
values[3] = BoolGetDatum(control->trusted);
|
2011-02-14 22:07:00 +01:00
|
|
|
/* relocatable */
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
values[4] = BoolGetDatum(control->relocatable);
|
2011-02-14 22:07:00 +01:00
|
|
|
/* schema */
|
|
|
|
if (control->schema == NULL)
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
nulls[5] = true;
|
2011-02-14 22:07:00 +01:00
|
|
|
else
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
values[5] = DirectFunctionCall1(namein,
|
2011-02-14 22:07:00 +01:00
|
|
|
CStringGetDatum(control->schema));
|
|
|
|
/* requires */
|
|
|
|
if (control->requires == NIL)
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
nulls[6] = true;
|
2011-02-14 22:07:00 +01:00
|
|
|
else
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
values[6] = convert_requires_to_datum(control->requires);
|
2011-02-14 22:07:00 +01:00
|
|
|
/* comment */
|
|
|
|
if (control->comment == NULL)
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
nulls[7] = true;
|
2011-02-14 22:07:00 +01:00
|
|
|
else
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
values[7] = CStringGetTextDatum(control->comment);
|
2011-02-14 22:07:00 +01:00
|
|
|
|
|
|
|
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Find all non-directly-installable versions that would be installed
|
|
|
|
* starting from this version, and report them, inheriting the
|
|
|
|
* parameters that aren't changed in updates from this version.
|
|
|
|
*/
|
|
|
|
foreach(lc2, evi_list)
|
|
|
|
{
|
|
|
|
ExtensionVersionInfo *evi2 = (ExtensionVersionInfo *) lfirst(lc2);
|
|
|
|
List *best_path;
|
|
|
|
|
|
|
|
if (evi2->installable)
|
|
|
|
continue;
|
|
|
|
if (find_install_path(evi_list, evi2, &best_path) == evi)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Fetch parameters for this version (pcontrol is not changed)
|
|
|
|
*/
|
|
|
|
control = read_extension_aux_control_file(pcontrol, evi2->name);
|
|
|
|
|
|
|
|
/* name stays the same */
|
|
|
|
/* version */
|
|
|
|
values[1] = CStringGetTextDatum(evi2->name);
|
|
|
|
/* superuser */
|
|
|
|
values[2] = BoolGetDatum(control->superuser);
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
/* trusted */
|
|
|
|
values[3] = BoolGetDatum(control->trusted);
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
/* relocatable */
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
values[4] = BoolGetDatum(control->relocatable);
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
/* schema stays the same */
|
|
|
|
/* requires */
|
|
|
|
if (control->requires == NIL)
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
nulls[6] = true;
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
else
|
|
|
|
{
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
values[6] = convert_requires_to_datum(control->requires);
|
|
|
|
nulls[6] = false;
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
}
|
|
|
|
/* comment stays the same */
|
|
|
|
|
|
|
|
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
|
|
|
|
}
|
|
|
|
}
|
2011-02-14 22:07:00 +01:00
|
|
|
}
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
}
|
2011-02-14 22:07:00 +01:00
|
|
|
|
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension
that's marked that way in its control file can be installed by a
non-superuser who has the CREATE privilege on the current database,
even if the extension contains objects that normally would have to be
created by a superuser. The objects within the extension will (by
default) be owned by the bootstrap superuser, but the extension itself
will be owned by the calling user. This allows replicating the old
behavior around trusted procedural languages, without all the
special-case logic in CREATE LANGUAGE. We have, however, chosen to
loosen the rules slightly: formerly, only a database owner could take
advantage of the special case that allowed installation of a trusted
language, but now anyone who has CREATE privilege can do so.
Having done that, we can delete the pg_pltemplate catalog, moving the
knowledge it contained into the extension script files for the various
PLs. This ends up being no change at all for the in-core PLs, but it is
a large step forward for external PLs: they can now have the same ease
of installation as core PLs do. The old "trusted PL" behavior was only
available to PLs that had entries in pg_pltemplate, but now any
extension can be marked trusted if appropriate.
This also removes one of the stumbling blocks for our Python 2 -> 3
migration, since the association of "plpythonu" with Python 2 is no
longer hard-wired into pg_pltemplate's initial contents. Exactly where
we go from here on that front remains to be settled, but one problem
is fixed.
Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others.
Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
2020-01-30 00:42:43 +01:00
|
|
|
/*
|
|
|
|
* Test whether the given extension exists (not whether it's installed)
|
|
|
|
*
|
|
|
|
* This checks for the existence of a matching control file in the extension
|
|
|
|
* directory. That's not a bulletproof check, since the file might be
|
|
|
|
* invalid, but this is only used for hints so it doesn't have to be 100%
|
|
|
|
* right.
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
extension_file_exists(const char *extensionName)
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
char *location;
|
|
|
|
DIR *dir;
|
|
|
|
struct dirent *de;
|
|
|
|
|
|
|
|
location = get_extension_control_directory();
|
|
|
|
dir = AllocateDir(location);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the control directory doesn't exist, we want to silently return
|
|
|
|
* false. Any other error will be reported by ReadDir.
|
|
|
|
*/
|
|
|
|
if (dir == NULL && errno == ENOENT)
|
|
|
|
{
|
|
|
|
/* do nothing */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while ((de = ReadDir(dir, location)) != NULL)
|
|
|
|
{
|
|
|
|
char *extname;
|
|
|
|
|
|
|
|
if (!is_extension_control_filename(de->d_name))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* extract extension name from 'name.control' filename */
|
|
|
|
extname = pstrdup(de->d_name);
|
|
|
|
*strrchr(extname, '.') = '\0';
|
|
|
|
|
|
|
|
/* ignore it if it's an auxiliary control file */
|
|
|
|
if (strstr(extname, "--"))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* done if it matches request */
|
|
|
|
if (strcmp(extname, extensionName) == 0)
|
|
|
|
{
|
|
|
|
result = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeDir(dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
/*
|
|
|
|
* Convert a list of extension names to a name[] Datum
|
|
|
|
*/
|
|
|
|
static Datum
|
|
|
|
convert_requires_to_datum(List *requires)
|
|
|
|
{
|
|
|
|
Datum *datums;
|
|
|
|
int ndatums;
|
|
|
|
ArrayType *a;
|
|
|
|
ListCell *lc;
|
|
|
|
|
|
|
|
ndatums = list_length(requires);
|
|
|
|
datums = (Datum *) palloc(ndatums * sizeof(Datum));
|
|
|
|
ndatums = 0;
|
|
|
|
foreach(lc, requires)
|
|
|
|
{
|
|
|
|
char *curreq = (char *) lfirst(lc);
|
|
|
|
|
|
|
|
datums[ndatums++] =
|
|
|
|
DirectFunctionCall1(namein, CStringGetDatum(curreq));
|
|
|
|
}
|
2022-07-01 10:51:45 +02:00
|
|
|
a = construct_array_builtin(datums, ndatums, NAMEOID);
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
return PointerGetDatum(a);
|
2011-02-14 22:07:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function reports the version update paths that exist for the
|
|
|
|
* specified extension.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
pg_extension_update_paths(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Name extname = PG_GETARG_NAME(0);
|
|
|
|
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
|
|
|
|
List *evi_list;
|
|
|
|
ExtensionControlFile *control;
|
|
|
|
ListCell *lc1;
|
|
|
|
|
|
|
|
/* Check extension name validity before any filesystem access */
|
|
|
|
check_valid_extension_name(NameStr(*extname));
|
|
|
|
|
|
|
|
/* Build tuplestore to hold the result rows */
|
2022-10-18 03:22:35 +02:00
|
|
|
InitMaterializedSRF(fcinfo, 0);
|
2011-02-14 22:07:00 +01:00
|
|
|
|
|
|
|
/* Read the extension's control file */
|
|
|
|
control = read_extension_control_file(NameStr(*extname));
|
|
|
|
|
|
|
|
/* Extract the version update graph from the script directory */
|
|
|
|
evi_list = get_ext_ver_list(control);
|
|
|
|
|
|
|
|
/* Iterate over all pairs of versions */
|
|
|
|
foreach(lc1, evi_list)
|
|
|
|
{
|
|
|
|
ExtensionVersionInfo *evi1 = (ExtensionVersionInfo *) lfirst(lc1);
|
|
|
|
ListCell *lc2;
|
|
|
|
|
|
|
|
foreach(lc2, evi_list)
|
|
|
|
{
|
|
|
|
ExtensionVersionInfo *evi2 = (ExtensionVersionInfo *) lfirst(lc2);
|
|
|
|
List *path;
|
|
|
|
Datum values[3];
|
|
|
|
bool nulls[3];
|
|
|
|
|
|
|
|
if (evi1 == evi2)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Find shortest path from evi1 to evi2 */
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
path = find_update_path(evi_list, evi1, evi2, false, true);
|
2011-02-14 22:07:00 +01:00
|
|
|
|
|
|
|
/* Emit result row */
|
|
|
|
memset(values, 0, sizeof(values));
|
|
|
|
memset(nulls, 0, sizeof(nulls));
|
|
|
|
|
|
|
|
/* source */
|
|
|
|
values[0] = CStringGetTextDatum(evi1->name);
|
|
|
|
/* target */
|
|
|
|
values[1] = CStringGetTextDatum(evi2->name);
|
|
|
|
/* path */
|
|
|
|
if (path == NIL)
|
|
|
|
nulls[2] = true;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
StringInfoData pathbuf;
|
|
|
|
ListCell *lcv;
|
|
|
|
|
|
|
|
initStringInfo(&pathbuf);
|
|
|
|
/* The path doesn't include start vertex, but show it */
|
|
|
|
appendStringInfoString(&pathbuf, evi1->name);
|
|
|
|
foreach(lcv, path)
|
|
|
|
{
|
|
|
|
char *versionName = (char *) lfirst(lcv);
|
|
|
|
|
|
|
|
appendStringInfoString(&pathbuf, "--");
|
|
|
|
appendStringInfoString(&pathbuf, versionName);
|
|
|
|
}
|
|
|
|
values[2] = CStringGetTextDatum(pathbuf.data);
|
|
|
|
pfree(pathbuf.data);
|
|
|
|
}
|
|
|
|
|
Create routine able to set single-call SRFs for Materialize mode
Set-returning functions that use the Materialize mode, creating a
tuplestore to include all the tuples returned in a set rather than doing
so in multiple calls, use roughly the same set of steps to prepare
ReturnSetInfo for this job:
- Check if ReturnSetInfo supports returning a tuplestore and if the
materialize mode is enabled.
- Create a tuplestore for all the tuples part of the returned set in the
per-query memory context, stored in ReturnSetInfo->setResult.
- Build a tuple descriptor mostly from get_call_result_type(), then
stored in ReturnSetInfo->setDesc. Note that there are some cases where
the SRF's tuple descriptor has to be the one specified by the function
caller.
This refactoring is done so as there are (well, should be) no behavior
changes in any of the in-core functions refactored, and the centralized
function that checks and sets up the function's ReturnSetInfo can be
controlled with a set of bits32 options. Two of them prove to be
necessary now:
- SRF_SINGLE_USE_EXPECTED to use expectedDesc as tuple descriptor, as
expected by the function's caller.
- SRF_SINGLE_BLESS to validate the tuple descriptor for the SRF.
The same initialization pattern is simplified in 28 places per my
count as of src/backend/, shaving up to ~900 lines of code. These
mostly come from the removal of the per-query initializations and the
sanity checks now grouped in a single location. There are more
locations that could be simplified in contrib/, that are left for a
follow-up cleanup.
fcc2817, 07daca5 and d61a361 have prepared the areas of the code related
to this change, to ease this refactoring.
Author: Melanie Plageman, Michael Paquier
Reviewed-by: Álvaro Herrera, Justin Pryzby
Discussion: https://postgr.es/m/CAAKRu_azyd1Z3W_r7Ou4sorTjRCs+PxeHw1CWJeXKofkE6TuZg@mail.gmail.com
2022-03-07 02:26:29 +01:00
|
|
|
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
|
|
|
|
values, nulls);
|
2011-02-14 22:07:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (Datum) 0;
|
|
|
|
}
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
/*
|
|
|
|
* pg_extension_config_dump
|
|
|
|
*
|
|
|
|
* Record information about a configuration table that belongs to an
|
|
|
|
* extension being created, but whose contents should be dumped in whole
|
|
|
|
* or in part during pg_dump.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
pg_extension_config_dump(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid tableoid = PG_GETARG_OID(0);
|
2017-03-13 00:35:34 +01:00
|
|
|
text *wherecond = PG_GETARG_TEXT_PP(1);
|
2011-02-08 22:08:41 +01:00
|
|
|
char *tablename;
|
|
|
|
Relation extRel;
|
|
|
|
ScanKeyData key[1];
|
|
|
|
SysScanDesc extScan;
|
|
|
|
HeapTuple extTup;
|
|
|
|
Datum arrayDatum;
|
|
|
|
Datum elementDatum;
|
2012-12-20 22:30:59 +01:00
|
|
|
int arrayLength;
|
2011-02-08 22:08:41 +01:00
|
|
|
int arrayIndex;
|
|
|
|
bool isnull;
|
|
|
|
Datum repl_val[Natts_pg_extension];
|
|
|
|
bool repl_null[Natts_pg_extension];
|
|
|
|
bool repl_repl[Natts_pg_extension];
|
|
|
|
ArrayType *a;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We only allow this to be called from an extension's SQL script. We
|
|
|
|
* shouldn't need any permissions check beyond that.
|
|
|
|
*/
|
|
|
|
if (!creating_extension)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
2018-12-19 18:51:13 +01:00
|
|
|
errmsg("%s can only be called from an SQL script executed by CREATE EXTENSION",
|
|
|
|
"pg_extension_config_dump()")));
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check that the table exists and is a member of the extension being
|
2012-12-20 22:30:59 +01:00
|
|
|
* created. This ensures that we don't need to register an additional
|
|
|
|
* dependency to protect the extconfig entry.
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
|
|
|
tablename = get_rel_name(tableoid);
|
|
|
|
if (tablename == NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_TABLE),
|
|
|
|
errmsg("OID %u does not refer to a table", tableoid)));
|
|
|
|
if (getExtensionOfObject(RelationRelationId, tableoid) !=
|
|
|
|
CurrentExtensionObject)
|
|
|
|
ereport(ERROR,
|
2011-02-09 17:55:32 +01:00
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
2011-02-08 22:08:41 +01:00
|
|
|
errmsg("table \"%s\" is not a member of the extension being created",
|
|
|
|
tablename)));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add the table OID and WHERE condition to the extension's extconfig and
|
|
|
|
* extcondition arrays.
|
2012-12-20 22:30:59 +01:00
|
|
|
*
|
|
|
|
* If the table is already in extconfig, treat this as an update of the
|
|
|
|
* WHERE condition.
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Find the pg_extension tuple */
|
2019-01-21 19:32:19 +01:00
|
|
|
extRel = table_open(ExtensionRelationId, RowExclusiveLock);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
ScanKeyInit(&key[0],
|
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
|
|
|
Anum_pg_extension_oid,
|
2011-02-08 22:08:41 +01:00
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(CurrentExtensionObject));
|
|
|
|
|
|
|
|
extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
|
Use an MVCC snapshot, rather than SnapshotNow, for catalog scans.
SnapshotNow scans have the undesirable property that, in the face of
concurrent updates, the scan can fail to see either the old or the new
versions of the row. In many cases, we work around this by requiring
DDL operations to hold AccessExclusiveLock on the object being
modified; in some cases, the existing locking is inadequate and random
failures occur as a result. This commit doesn't change anything
related to locking, but will hopefully pave the way to allowing lock
strength reductions in the future.
The major issue has held us back from making this change in the past
is that taking an MVCC snapshot is significantly more expensive than
using a static special snapshot such as SnapshotNow. However, testing
of various worst-case scenarios reveals that this problem is not
severe except under fairly extreme workloads. To mitigate those
problems, we avoid retaking the MVCC snapshot for each new scan;
instead, we take a new snapshot only when invalidation messages have
been processed. The catcache machinery already requires that
invalidation messages be sent before releasing the related heavyweight
lock; else other backends might rely on locally-cached data rather
than scanning the catalog at all. Thus, making snapshot reuse
dependent on the same guarantees shouldn't break anything that wasn't
already subtly broken.
Patch by me. Review by Michael Paquier and Andres Freund.
2013-07-02 15:47:01 +02:00
|
|
|
NULL, 1, key);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
extTup = systable_getnext(extScan);
|
|
|
|
|
|
|
|
if (!HeapTupleIsValid(extTup)) /* should not happen */
|
2017-06-04 22:20:03 +02:00
|
|
|
elog(ERROR, "could not find tuple for extension %u",
|
2011-02-08 22:08:41 +01:00
|
|
|
CurrentExtensionObject);
|
|
|
|
|
|
|
|
memset(repl_val, 0, sizeof(repl_val));
|
|
|
|
memset(repl_null, false, sizeof(repl_null));
|
|
|
|
memset(repl_repl, false, sizeof(repl_repl));
|
|
|
|
|
|
|
|
/* Build or modify the extconfig value */
|
|
|
|
elementDatum = ObjectIdGetDatum(tableoid);
|
|
|
|
|
|
|
|
arrayDatum = heap_getattr(extTup, Anum_pg_extension_extconfig,
|
|
|
|
RelationGetDescr(extRel), &isnull);
|
|
|
|
if (isnull)
|
|
|
|
{
|
2012-12-20 22:30:59 +01:00
|
|
|
/* Previously empty extconfig, so build 1-element array */
|
|
|
|
arrayLength = 0;
|
|
|
|
arrayIndex = 1;
|
|
|
|
|
2022-07-01 10:51:45 +02:00
|
|
|
a = construct_array_builtin(&elementDatum, 1, OIDOID);
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-12-20 22:30:59 +01:00
|
|
|
/* Modify or extend existing extconfig array */
|
|
|
|
Oid *arrayData;
|
|
|
|
int i;
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
a = DatumGetArrayTypeP(arrayDatum);
|
|
|
|
|
2012-12-20 22:30:59 +01:00
|
|
|
arrayLength = ARR_DIMS(a)[0];
|
|
|
|
if (ARR_NDIM(a) != 1 ||
|
|
|
|
ARR_LBOUND(a)[0] != 1 ||
|
|
|
|
arrayLength < 0 ||
|
|
|
|
ARR_HASNULL(a) ||
|
|
|
|
ARR_ELEMTYPE(a) != OIDOID)
|
|
|
|
elog(ERROR, "extconfig is not a 1-D Oid array");
|
|
|
|
arrayData = (Oid *) ARR_DATA_PTR(a);
|
|
|
|
|
|
|
|
arrayIndex = arrayLength + 1; /* set up to add after end */
|
|
|
|
|
|
|
|
for (i = 0; i < arrayLength; i++)
|
|
|
|
{
|
|
|
|
if (arrayData[i] == tableoid)
|
|
|
|
{
|
|
|
|
arrayIndex = i + 1; /* replace this element instead */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
a = array_set(a, 1, &arrayIndex,
|
|
|
|
elementDatum,
|
|
|
|
false,
|
|
|
|
-1 /* varlena array */ ,
|
|
|
|
sizeof(Oid) /* OID's typlen */ ,
|
|
|
|
true /* OID's typbyval */ ,
|
2020-03-04 16:34:25 +01:00
|
|
|
TYPALIGN_INT /* OID's typalign */ );
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
|
|
|
repl_val[Anum_pg_extension_extconfig - 1] = PointerGetDatum(a);
|
|
|
|
repl_repl[Anum_pg_extension_extconfig - 1] = true;
|
|
|
|
|
|
|
|
/* Build or modify the extcondition value */
|
|
|
|
elementDatum = PointerGetDatum(wherecond);
|
|
|
|
|
|
|
|
arrayDatum = heap_getattr(extTup, Anum_pg_extension_extcondition,
|
|
|
|
RelationGetDescr(extRel), &isnull);
|
|
|
|
if (isnull)
|
|
|
|
{
|
2012-12-20 22:30:59 +01:00
|
|
|
if (arrayLength != 0)
|
|
|
|
elog(ERROR, "extconfig and extcondition arrays do not match");
|
|
|
|
|
2022-07-01 10:51:45 +02:00
|
|
|
a = construct_array_builtin(&elementDatum, 1, TEXTOID);
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
a = DatumGetArrayTypeP(arrayDatum);
|
|
|
|
|
2012-12-20 22:30:59 +01:00
|
|
|
if (ARR_NDIM(a) != 1 ||
|
|
|
|
ARR_LBOUND(a)[0] != 1 ||
|
|
|
|
ARR_HASNULL(a) ||
|
|
|
|
ARR_ELEMTYPE(a) != TEXTOID)
|
|
|
|
elog(ERROR, "extcondition is not a 1-D text array");
|
|
|
|
if (ARR_DIMS(a)[0] != arrayLength)
|
|
|
|
elog(ERROR, "extconfig and extcondition arrays do not match");
|
2011-02-08 22:08:41 +01:00
|
|
|
|
2012-12-20 22:30:59 +01:00
|
|
|
/* Add or replace at same index as in extconfig */
|
2011-02-08 22:08:41 +01:00
|
|
|
a = array_set(a, 1, &arrayIndex,
|
|
|
|
elementDatum,
|
|
|
|
false,
|
|
|
|
-1 /* varlena array */ ,
|
|
|
|
-1 /* TEXT's typlen */ ,
|
|
|
|
false /* TEXT's typbyval */ ,
|
2020-03-04 16:34:25 +01:00
|
|
|
TYPALIGN_INT /* TEXT's typalign */ );
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
|
|
|
repl_val[Anum_pg_extension_extcondition - 1] = PointerGetDatum(a);
|
|
|
|
repl_repl[Anum_pg_extension_extcondition - 1] = true;
|
|
|
|
|
|
|
|
extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel),
|
|
|
|
repl_val, repl_null, repl_repl);
|
|
|
|
|
2017-01-31 22:42:24 +01:00
|
|
|
CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
systable_endscan(extScan);
|
|
|
|
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(extRel, RowExclusiveLock);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
PG_RETURN_VOID();
|
|
|
|
}
|
|
|
|
|
2012-12-20 22:30:59 +01:00
|
|
|
/*
|
|
|
|
* extension_config_remove
|
|
|
|
*
|
|
|
|
* Remove the specified table OID from extension's extconfig, if present.
|
|
|
|
* This is not currently exposed as a function, but it could be;
|
|
|
|
* for now, we just invoke it from ALTER EXTENSION DROP.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
extension_config_remove(Oid extensionoid, Oid tableoid)
|
|
|
|
{
|
|
|
|
Relation extRel;
|
|
|
|
ScanKeyData key[1];
|
|
|
|
SysScanDesc extScan;
|
|
|
|
HeapTuple extTup;
|
|
|
|
Datum arrayDatum;
|
|
|
|
int arrayLength;
|
|
|
|
int arrayIndex;
|
|
|
|
bool isnull;
|
|
|
|
Datum repl_val[Natts_pg_extension];
|
|
|
|
bool repl_null[Natts_pg_extension];
|
|
|
|
bool repl_repl[Natts_pg_extension];
|
|
|
|
ArrayType *a;
|
|
|
|
|
|
|
|
/* Find the pg_extension tuple */
|
2019-01-21 19:32:19 +01:00
|
|
|
extRel = table_open(ExtensionRelationId, RowExclusiveLock);
|
2012-12-20 22:30:59 +01:00
|
|
|
|
|
|
|
ScanKeyInit(&key[0],
|
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
|
|
|
Anum_pg_extension_oid,
|
2012-12-20 22:30:59 +01:00
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(extensionoid));
|
|
|
|
|
|
|
|
extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
|
Use an MVCC snapshot, rather than SnapshotNow, for catalog scans.
SnapshotNow scans have the undesirable property that, in the face of
concurrent updates, the scan can fail to see either the old or the new
versions of the row. In many cases, we work around this by requiring
DDL operations to hold AccessExclusiveLock on the object being
modified; in some cases, the existing locking is inadequate and random
failures occur as a result. This commit doesn't change anything
related to locking, but will hopefully pave the way to allowing lock
strength reductions in the future.
The major issue has held us back from making this change in the past
is that taking an MVCC snapshot is significantly more expensive than
using a static special snapshot such as SnapshotNow. However, testing
of various worst-case scenarios reveals that this problem is not
severe except under fairly extreme workloads. To mitigate those
problems, we avoid retaking the MVCC snapshot for each new scan;
instead, we take a new snapshot only when invalidation messages have
been processed. The catcache machinery already requires that
invalidation messages be sent before releasing the related heavyweight
lock; else other backends might rely on locally-cached data rather
than scanning the catalog at all. Thus, making snapshot reuse
dependent on the same guarantees shouldn't break anything that wasn't
already subtly broken.
Patch by me. Review by Michael Paquier and Andres Freund.
2013-07-02 15:47:01 +02:00
|
|
|
NULL, 1, key);
|
2012-12-20 22:30:59 +01:00
|
|
|
|
|
|
|
extTup = systable_getnext(extScan);
|
|
|
|
|
|
|
|
if (!HeapTupleIsValid(extTup)) /* should not happen */
|
2017-06-04 22:20:03 +02:00
|
|
|
elog(ERROR, "could not find tuple for extension %u",
|
2012-12-20 22:30:59 +01:00
|
|
|
extensionoid);
|
|
|
|
|
|
|
|
/* Search extconfig for the tableoid */
|
|
|
|
arrayDatum = heap_getattr(extTup, Anum_pg_extension_extconfig,
|
|
|
|
RelationGetDescr(extRel), &isnull);
|
|
|
|
if (isnull)
|
|
|
|
{
|
|
|
|
/* nothing to do */
|
|
|
|
a = NULL;
|
|
|
|
arrayLength = 0;
|
|
|
|
arrayIndex = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Oid *arrayData;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
a = DatumGetArrayTypeP(arrayDatum);
|
|
|
|
|
|
|
|
arrayLength = ARR_DIMS(a)[0];
|
|
|
|
if (ARR_NDIM(a) != 1 ||
|
|
|
|
ARR_LBOUND(a)[0] != 1 ||
|
|
|
|
arrayLength < 0 ||
|
|
|
|
ARR_HASNULL(a) ||
|
|
|
|
ARR_ELEMTYPE(a) != OIDOID)
|
|
|
|
elog(ERROR, "extconfig is not a 1-D Oid array");
|
|
|
|
arrayData = (Oid *) ARR_DATA_PTR(a);
|
|
|
|
|
|
|
|
arrayIndex = -1; /* flag for no deletion needed */
|
|
|
|
|
|
|
|
for (i = 0; i < arrayLength; i++)
|
|
|
|
{
|
|
|
|
if (arrayData[i] == tableoid)
|
|
|
|
{
|
|
|
|
arrayIndex = i; /* index to remove */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If tableoid is not in extconfig, nothing to do */
|
|
|
|
if (arrayIndex < 0)
|
|
|
|
{
|
|
|
|
systable_endscan(extScan);
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(extRel, RowExclusiveLock);
|
2012-12-20 22:30:59 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Modify or delete the extconfig value */
|
|
|
|
memset(repl_val, 0, sizeof(repl_val));
|
|
|
|
memset(repl_null, false, sizeof(repl_null));
|
|
|
|
memset(repl_repl, false, sizeof(repl_repl));
|
|
|
|
|
|
|
|
if (arrayLength <= 1)
|
|
|
|
{
|
|
|
|
/* removing only element, just set array to null */
|
|
|
|
repl_null[Anum_pg_extension_extconfig - 1] = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* squeeze out the target element */
|
|
|
|
Datum *dvalues;
|
|
|
|
int nelems;
|
|
|
|
int i;
|
|
|
|
|
2018-11-12 17:50:28 +01:00
|
|
|
/* We already checked there are no nulls */
|
2022-07-01 10:51:45 +02:00
|
|
|
deconstruct_array_builtin(a, OIDOID, &dvalues, NULL, &nelems);
|
2012-12-20 22:30:59 +01:00
|
|
|
|
|
|
|
for (i = arrayIndex; i < arrayLength - 1; i++)
|
|
|
|
dvalues[i] = dvalues[i + 1];
|
|
|
|
|
2022-07-01 10:51:45 +02:00
|
|
|
a = construct_array_builtin(dvalues, arrayLength - 1, OIDOID);
|
2012-12-20 22:30:59 +01:00
|
|
|
|
|
|
|
repl_val[Anum_pg_extension_extconfig - 1] = PointerGetDatum(a);
|
|
|
|
}
|
|
|
|
repl_repl[Anum_pg_extension_extconfig - 1] = true;
|
|
|
|
|
|
|
|
/* Modify or delete the extcondition value */
|
|
|
|
arrayDatum = heap_getattr(extTup, Anum_pg_extension_extcondition,
|
|
|
|
RelationGetDescr(extRel), &isnull);
|
|
|
|
if (isnull)
|
|
|
|
{
|
|
|
|
elog(ERROR, "extconfig and extcondition arrays do not match");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
a = DatumGetArrayTypeP(arrayDatum);
|
|
|
|
|
|
|
|
if (ARR_NDIM(a) != 1 ||
|
|
|
|
ARR_LBOUND(a)[0] != 1 ||
|
|
|
|
ARR_HASNULL(a) ||
|
|
|
|
ARR_ELEMTYPE(a) != TEXTOID)
|
|
|
|
elog(ERROR, "extcondition is not a 1-D text array");
|
|
|
|
if (ARR_DIMS(a)[0] != arrayLength)
|
|
|
|
elog(ERROR, "extconfig and extcondition arrays do not match");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (arrayLength <= 1)
|
|
|
|
{
|
|
|
|
/* removing only element, just set array to null */
|
|
|
|
repl_null[Anum_pg_extension_extcondition - 1] = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* squeeze out the target element */
|
|
|
|
Datum *dvalues;
|
|
|
|
int nelems;
|
|
|
|
int i;
|
|
|
|
|
2018-11-12 17:50:28 +01:00
|
|
|
/* We already checked there are no nulls */
|
2022-07-01 10:51:45 +02:00
|
|
|
deconstruct_array_builtin(a, TEXTOID, &dvalues, NULL, &nelems);
|
2012-12-20 22:30:59 +01:00
|
|
|
|
|
|
|
for (i = arrayIndex; i < arrayLength - 1; i++)
|
|
|
|
dvalues[i] = dvalues[i + 1];
|
|
|
|
|
2022-07-01 10:51:45 +02:00
|
|
|
a = construct_array_builtin(dvalues, arrayLength - 1, TEXTOID);
|
2012-12-20 22:30:59 +01:00
|
|
|
|
|
|
|
repl_val[Anum_pg_extension_extcondition - 1] = PointerGetDatum(a);
|
|
|
|
}
|
|
|
|
repl_repl[Anum_pg_extension_extcondition - 1] = true;
|
|
|
|
|
|
|
|
extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel),
|
|
|
|
repl_val, repl_null, repl_repl);
|
|
|
|
|
2017-01-31 22:42:24 +01:00
|
|
|
CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
|
2012-12-20 22:30:59 +01:00
|
|
|
|
|
|
|
systable_endscan(extScan);
|
|
|
|
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(extRel, RowExclusiveLock);
|
2012-12-20 22:30:59 +01:00
|
|
|
}
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
/*
|
|
|
|
* Execute ALTER EXTENSION SET SCHEMA
|
|
|
|
*/
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddress
|
Remove objname/objargs split for referring to objects
In simpler times, it might have worked to refer to all kinds of objects
by a list of name components and an optional argument list. But this
doesn't work for all objects, which has resulted in a collection of
hacks to place various other nodes types into these fields, which have
to be unpacked at the other end. This makes it also weird to represent
lists of such things in the grammar, because they would have to be lists
of singleton lists, to make the unpacking work consistently. The other
problem is that keeping separate name and args fields makes it awkward
to deal with lists of functions.
Change that by dropping the objargs field and have objname, renamed to
object, be a generic Node, which can then be flexibly assigned and
managed using the normal Node mechanisms. In many cases it will still
be a List of names, in some cases it will be a string Value, for types
it will be the existing Typename, for functions it will now use the
existing ObjectWithArgs node type. Some of the more obscure object
types still use somewhat arbitrary nested lists.
Reviewed-by: Jim Nasby <Jim.Nasby@BlueTreble.com>
Reviewed-by: Michael Paquier <michael.paquier@gmail.com>
2016-11-12 18:00:00 +01:00
|
|
|
AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *oldschema)
|
2011-02-08 22:08:41 +01:00
|
|
|
{
|
|
|
|
Oid extensionOid;
|
|
|
|
Oid nspOid;
|
2023-07-10 02:40:07 +02:00
|
|
|
Oid oldNspOid;
|
2011-03-04 22:08:24 +01:00
|
|
|
AclResult aclresult;
|
2011-02-08 22:08:41 +01:00
|
|
|
Relation extRel;
|
|
|
|
ScanKeyData key[2];
|
|
|
|
SysScanDesc extScan;
|
|
|
|
HeapTuple extTup;
|
|
|
|
Form_pg_extension extForm;
|
|
|
|
Relation depRel;
|
|
|
|
SysScanDesc depScan;
|
|
|
|
HeapTuple depTup;
|
2012-10-31 14:52:55 +01:00
|
|
|
ObjectAddresses *objsMoved;
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddress extAddr;
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
extensionOid = get_extension_oid(extensionName, false);
|
|
|
|
|
|
|
|
nspOid = LookupCreationNamespace(newschema);
|
|
|
|
|
2011-03-04 22:08:24 +01:00
|
|
|
/*
|
|
|
|
* Permission check: must own extension. Note that we don't bother to
|
|
|
|
* check ownership of the individual member objects ...
|
|
|
|
*/
|
2022-11-13 08:11:17 +01:00
|
|
|
if (!object_ownercheck(ExtensionRelationId, extensionOid, GetUserId()))
|
2017-12-02 15:26:34 +01:00
|
|
|
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_EXTENSION,
|
2011-03-04 22:08:24 +01:00
|
|
|
extensionName);
|
|
|
|
|
|
|
|
/* Permission check: must have creation rights in target namespace */
|
2022-11-13 08:11:17 +01:00
|
|
|
aclresult = object_aclcheck(NamespaceRelationId, nspOid, GetUserId(), ACL_CREATE);
|
2011-03-04 22:08:24 +01:00
|
|
|
if (aclresult != ACLCHECK_OK)
|
2017-12-02 15:26:34 +01:00
|
|
|
aclcheck_error(aclresult, OBJECT_SCHEMA, newschema);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
2012-08-15 17:26:55 +02:00
|
|
|
/*
|
|
|
|
* If the schema is currently a member of the extension, disallow moving
|
|
|
|
* the extension into the schema. That would create a dependency loop.
|
|
|
|
*/
|
|
|
|
if (getExtensionOfObject(NamespaceRelationId, nspOid) == extensionOid)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
|
|
|
errmsg("cannot move extension \"%s\" into schema \"%s\" "
|
|
|
|
"because the extension contains the schema",
|
|
|
|
extensionName, newschema)));
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
/* Locate the pg_extension tuple */
|
2019-01-21 19:32:19 +01:00
|
|
|
extRel = table_open(ExtensionRelationId, RowExclusiveLock);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
ScanKeyInit(&key[0],
|
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
|
|
|
Anum_pg_extension_oid,
|
2011-02-08 22:08:41 +01:00
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(extensionOid));
|
|
|
|
|
|
|
|
extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
|
Use an MVCC snapshot, rather than SnapshotNow, for catalog scans.
SnapshotNow scans have the undesirable property that, in the face of
concurrent updates, the scan can fail to see either the old or the new
versions of the row. In many cases, we work around this by requiring
DDL operations to hold AccessExclusiveLock on the object being
modified; in some cases, the existing locking is inadequate and random
failures occur as a result. This commit doesn't change anything
related to locking, but will hopefully pave the way to allowing lock
strength reductions in the future.
The major issue has held us back from making this change in the past
is that taking an MVCC snapshot is significantly more expensive than
using a static special snapshot such as SnapshotNow. However, testing
of various worst-case scenarios reveals that this problem is not
severe except under fairly extreme workloads. To mitigate those
problems, we avoid retaking the MVCC snapshot for each new scan;
instead, we take a new snapshot only when invalidation messages have
been processed. The catcache machinery already requires that
invalidation messages be sent before releasing the related heavyweight
lock; else other backends might rely on locally-cached data rather
than scanning the catalog at all. Thus, making snapshot reuse
dependent on the same guarantees shouldn't break anything that wasn't
already subtly broken.
Patch by me. Review by Michael Paquier and Andres Freund.
2013-07-02 15:47:01 +02:00
|
|
|
NULL, 1, key);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
extTup = systable_getnext(extScan);
|
|
|
|
|
|
|
|
if (!HeapTupleIsValid(extTup)) /* should not happen */
|
2017-06-04 22:20:03 +02:00
|
|
|
elog(ERROR, "could not find tuple for extension %u",
|
|
|
|
extensionOid);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
/* Copy tuple so we can modify it below */
|
|
|
|
extTup = heap_copytuple(extTup);
|
|
|
|
extForm = (Form_pg_extension) GETSTRUCT(extTup);
|
|
|
|
|
|
|
|
systable_endscan(extScan);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the extension is already in the target schema, just silently do
|
|
|
|
* nothing.
|
|
|
|
*/
|
|
|
|
if (extForm->extnamespace == nspOid)
|
|
|
|
{
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(extRel, RowExclusiveLock);
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
return InvalidObjectAddress;
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check extension is supposed to be relocatable */
|
|
|
|
if (!extForm->extrelocatable)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("extension \"%s\" does not support SET SCHEMA",
|
|
|
|
NameStr(extForm->extname))));
|
|
|
|
|
2012-10-31 14:52:55 +01:00
|
|
|
objsMoved = new_object_addresses();
|
|
|
|
|
2023-07-10 02:40:07 +02:00
|
|
|
/* store the OID of the namespace to-be-changed */
|
|
|
|
oldNspOid = extForm->extnamespace;
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
/*
|
|
|
|
* Scan pg_depend to find objects that depend directly on the extension,
|
|
|
|
* and alter each one's schema.
|
|
|
|
*/
|
2019-01-21 19:32:19 +01:00
|
|
|
depRel = table_open(DependRelationId, AccessShareLock);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
ScanKeyInit(&key[0],
|
|
|
|
Anum_pg_depend_refclassid,
|
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(ExtensionRelationId));
|
|
|
|
ScanKeyInit(&key[1],
|
|
|
|
Anum_pg_depend_refobjid,
|
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(extensionOid));
|
|
|
|
|
|
|
|
depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
|
Use an MVCC snapshot, rather than SnapshotNow, for catalog scans.
SnapshotNow scans have the undesirable property that, in the face of
concurrent updates, the scan can fail to see either the old or the new
versions of the row. In many cases, we work around this by requiring
DDL operations to hold AccessExclusiveLock on the object being
modified; in some cases, the existing locking is inadequate and random
failures occur as a result. This commit doesn't change anything
related to locking, but will hopefully pave the way to allowing lock
strength reductions in the future.
The major issue has held us back from making this change in the past
is that taking an MVCC snapshot is significantly more expensive than
using a static special snapshot such as SnapshotNow. However, testing
of various worst-case scenarios reveals that this problem is not
severe except under fairly extreme workloads. To mitigate those
problems, we avoid retaking the MVCC snapshot for each new scan;
instead, we take a new snapshot only when invalidation messages have
been processed. The catcache machinery already requires that
invalidation messages be sent before releasing the related heavyweight
lock; else other backends might rely on locally-cached data rather
than scanning the catalog at all. Thus, making snapshot reuse
dependent on the same guarantees shouldn't break anything that wasn't
already subtly broken.
Patch by me. Review by Michael Paquier and Andres Freund.
2013-07-02 15:47:01 +02:00
|
|
|
NULL, 2, key);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
|
|
|
|
{
|
|
|
|
Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
|
|
|
|
ObjectAddress dep;
|
|
|
|
Oid dep_oldNspOid;
|
|
|
|
|
|
|
|
/*
|
2023-03-20 23:37:11 +01:00
|
|
|
* If a dependent extension has a no_relocate request for this
|
|
|
|
* extension, disallow SET SCHEMA. (XXX it's a bit ugly to do this in
|
|
|
|
* the same loop that's actually executing the renames: we may detect
|
|
|
|
* the error condition only after having expended a fair amount of
|
|
|
|
* work. However, the alternative is to do two scans of pg_depend,
|
|
|
|
* which seems like optimizing for failure cases. The rename work
|
|
|
|
* will all roll back cleanly enough if we do fail here.)
|
|
|
|
*/
|
|
|
|
if (pg_depend->deptype == DEPENDENCY_NORMAL &&
|
|
|
|
pg_depend->classid == ExtensionRelationId)
|
|
|
|
{
|
|
|
|
char *depextname = get_extension_name(pg_depend->objid);
|
|
|
|
ExtensionControlFile *dcontrol;
|
|
|
|
ListCell *lc;
|
|
|
|
|
|
|
|
dcontrol = read_extension_control_file(depextname);
|
|
|
|
foreach(lc, dcontrol->no_relocate)
|
|
|
|
{
|
|
|
|
char *nrextname = (char *) lfirst(lc);
|
|
|
|
|
|
|
|
if (strcmp(nrextname, NameStr(extForm->extname)) == 0)
|
|
|
|
{
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("cannot SET SCHEMA of extension \"%s\" because other extensions prevent it",
|
|
|
|
NameStr(extForm->extname)),
|
|
|
|
errdetail("Extension \"%s\" requests no relocation of extension \"%s\".",
|
|
|
|
depextname,
|
|
|
|
NameStr(extForm->extname))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Otherwise, ignore non-membership dependencies. (Currently, the
|
|
|
|
* only other case we could see here is a normal dependency from
|
|
|
|
* another extension.)
|
2011-02-08 22:08:41 +01:00
|
|
|
*/
|
|
|
|
if (pg_depend->deptype != DEPENDENCY_EXTENSION)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
dep.classId = pg_depend->classid;
|
|
|
|
dep.objectId = pg_depend->objid;
|
|
|
|
dep.objectSubId = pg_depend->objsubid;
|
|
|
|
|
|
|
|
if (dep.objectSubId != 0) /* should not happen */
|
|
|
|
elog(ERROR, "extension should not have a sub-object dependency");
|
|
|
|
|
2012-10-31 14:52:55 +01:00
|
|
|
/* Relocate the object */
|
2011-02-08 22:08:41 +01:00
|
|
|
dep_oldNspOid = AlterObjectNamespace_oid(dep.classId,
|
|
|
|
dep.objectId,
|
2012-10-31 14:52:55 +01:00
|
|
|
nspOid,
|
|
|
|
objsMoved);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If not all the objects had the same old namespace (ignoring any
|
|
|
|
* that are not in namespaces), complain.
|
|
|
|
*/
|
|
|
|
if (dep_oldNspOid != InvalidOid && dep_oldNspOid != oldNspOid)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("extension \"%s\" does not support SET SCHEMA",
|
|
|
|
NameStr(extForm->extname)),
|
|
|
|
errdetail("%s is not in the extension's schema \"%s\"",
|
2020-07-15 02:03:10 +02:00
|
|
|
getObjectDescription(&dep, false),
|
2011-02-08 22:08:41 +01:00
|
|
|
get_namespace_name(oldNspOid))));
|
|
|
|
}
|
|
|
|
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
/* report old schema, if caller wants it */
|
|
|
|
if (oldschema)
|
|
|
|
*oldschema = oldNspOid;
|
|
|
|
|
2011-02-08 22:08:41 +01:00
|
|
|
systable_endscan(depScan);
|
|
|
|
|
|
|
|
relation_close(depRel, AccessShareLock);
|
|
|
|
|
|
|
|
/* Now adjust pg_extension.extnamespace */
|
|
|
|
extForm->extnamespace = nspOid;
|
|
|
|
|
2017-01-31 22:42:24 +01:00
|
|
|
CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(extRel, RowExclusiveLock);
|
2011-02-08 22:08:41 +01:00
|
|
|
|
2023-07-10 06:08:10 +02:00
|
|
|
/* update dependency to point to the new schema */
|
|
|
|
if (changeDependencyFor(ExtensionRelationId, extensionOid,
|
|
|
|
NamespaceRelationId, oldNspOid, nspOid) != 1)
|
|
|
|
elog(ERROR, "could not change schema dependency for extension %s",
|
|
|
|
NameStr(extForm->extname));
|
2012-12-24 00:25:03 +01:00
|
|
|
|
2013-03-18 03:55:14 +01:00
|
|
|
InvokeObjectPostAlterHook(ExtensionRelationId, extensionOid, 0);
|
|
|
|
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddressSet(extAddr, ExtensionRelationId, extensionOid);
|
|
|
|
|
|
|
|
return extAddr;
|
2011-02-08 22:08:41 +01:00
|
|
|
}
|
2011-02-09 17:55:32 +01:00
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
/*
|
|
|
|
* Execute ALTER EXTENSION UPDATE
|
|
|
|
*/
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddress
|
2016-09-06 18:00:00 +02:00
|
|
|
ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
|
2011-02-12 03:25:20 +01:00
|
|
|
{
|
|
|
|
DefElem *d_new_version = NULL;
|
|
|
|
char *versionName;
|
|
|
|
char *oldVersionName;
|
|
|
|
ExtensionControlFile *control;
|
|
|
|
Oid extensionOid;
|
|
|
|
Relation extRel;
|
|
|
|
ScanKeyData key[1];
|
|
|
|
SysScanDesc extScan;
|
|
|
|
HeapTuple extTup;
|
|
|
|
List *updateVersions;
|
|
|
|
Datum datum;
|
|
|
|
bool isnull;
|
|
|
|
ListCell *lc;
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddress address;
|
2011-02-12 03:25:20 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We use global variables to track the extension being created, so we can
|
2011-02-12 22:40:41 +01:00
|
|
|
* create/update only one extension at the same time.
|
2011-02-12 03:25:20 +01:00
|
|
|
*/
|
|
|
|
if (creating_extension)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("nested ALTER EXTENSION is not supported")));
|
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
/*
|
|
|
|
* Look up the extension --- it must already exist in pg_extension
|
|
|
|
*/
|
2019-01-21 19:32:19 +01:00
|
|
|
extRel = table_open(ExtensionRelationId, AccessShareLock);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
|
|
|
ScanKeyInit(&key[0],
|
|
|
|
Anum_pg_extension_extname,
|
|
|
|
BTEqualStrategyNumber, F_NAMEEQ,
|
|
|
|
CStringGetDatum(stmt->extname));
|
|
|
|
|
|
|
|
extScan = systable_beginscan(extRel, ExtensionNameIndexId, true,
|
Use an MVCC snapshot, rather than SnapshotNow, for catalog scans.
SnapshotNow scans have the undesirable property that, in the face of
concurrent updates, the scan can fail to see either the old or the new
versions of the row. In many cases, we work around this by requiring
DDL operations to hold AccessExclusiveLock on the object being
modified; in some cases, the existing locking is inadequate and random
failures occur as a result. This commit doesn't change anything
related to locking, but will hopefully pave the way to allowing lock
strength reductions in the future.
The major issue has held us back from making this change in the past
is that taking an MVCC snapshot is significantly more expensive than
using a static special snapshot such as SnapshotNow. However, testing
of various worst-case scenarios reveals that this problem is not
severe except under fairly extreme workloads. To mitigate those
problems, we avoid retaking the MVCC snapshot for each new scan;
instead, we take a new snapshot only when invalidation messages have
been processed. The catcache machinery already requires that
invalidation messages be sent before releasing the related heavyweight
lock; else other backends might rely on locally-cached data rather
than scanning the catalog at all. Thus, making snapshot reuse
dependent on the same guarantees shouldn't break anything that wasn't
already subtly broken.
Patch by me. Review by Michael Paquier and Andres Freund.
2013-07-02 15:47:01 +02:00
|
|
|
NULL, 1, key);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
|
|
|
extTup = systable_getnext(extScan);
|
|
|
|
|
|
|
|
if (!HeapTupleIsValid(extTup))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("extension \"%s\" does not exist",
|
|
|
|
stmt->extname)));
|
|
|
|
|
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
|
|
|
extensionOid = ((Form_pg_extension) GETSTRUCT(extTup))->oid;
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
/*
|
|
|
|
* Determine the existing version we are updating from
|
|
|
|
*/
|
|
|
|
datum = heap_getattr(extTup, Anum_pg_extension_extversion,
|
|
|
|
RelationGetDescr(extRel), &isnull);
|
|
|
|
if (isnull)
|
|
|
|
elog(ERROR, "extversion is null");
|
|
|
|
oldVersionName = text_to_cstring(DatumGetTextPP(datum));
|
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
systable_endscan(extScan);
|
|
|
|
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(extRel, AccessShareLock);
|
2011-02-12 22:40:41 +01:00
|
|
|
|
2011-03-04 22:08:24 +01:00
|
|
|
/* Permission check: must own extension */
|
2022-11-13 08:11:17 +01:00
|
|
|
if (!object_ownercheck(ExtensionRelationId, extensionOid, GetUserId()))
|
2017-12-02 15:26:34 +01:00
|
|
|
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_EXTENSION,
|
2011-03-04 22:08:24 +01:00
|
|
|
stmt->extname);
|
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
/*
|
|
|
|
* Read the primary control file. Note we assume that it does not contain
|
|
|
|
* any non-ASCII data, so there is no need to worry about encoding at this
|
|
|
|
* point.
|
|
|
|
*/
|
|
|
|
control = read_extension_control_file(stmt->extname);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read the statement option list
|
|
|
|
*/
|
|
|
|
foreach(lc, stmt->options)
|
|
|
|
{
|
|
|
|
DefElem *defel = (DefElem *) lfirst(lc);
|
|
|
|
|
|
|
|
if (strcmp(defel->defname, "new_version") == 0)
|
|
|
|
{
|
|
|
|
if (d_new_version)
|
Improve reporting of "conflicting or redundant options" errors.
When reporting "conflicting or redundant options" errors, try to
ensure that errposition() is used, to help the user identify the
offending option.
Formerly, errposition() was invoked in less than 60% of cases. This
patch raises that to over 90%, but there remain a few places where the
ParseState is not readily available. Using errdetail() might improve
the error in such cases, but that is left as a task for the future.
Additionally, since this error is thrown from over 100 places in the
codebase, introduce a dedicated function to throw it, reducing code
duplication.
Extracted from a slightly larger patch by Vignesh C. Reviewed by
Bharath Rupireddy, Alvaro Herrera, Dilip Kumar, Hou Zhijie, Peter
Smith, Daniel Gustafsson, Julien Rouhaud and me.
Discussion: https://postgr.es/m/CALDaNm33FFSS5tVyvmkoK2cCMuDVxcui=gFrjti9ROfynqSAGA@mail.gmail.com
2021-07-15 09:49:45 +02:00
|
|
|
errorConflictingDefElem(defel, pstate);
|
2011-02-12 03:25:20 +01:00
|
|
|
d_new_version = defel;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
elog(ERROR, "unrecognized option: %s", defel->defname);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-02-12 22:40:41 +01:00
|
|
|
* Determine the version to update to
|
2011-02-12 03:25:20 +01:00
|
|
|
*/
|
|
|
|
if (d_new_version && d_new_version->arg)
|
|
|
|
versionName = strVal(d_new_version->arg);
|
|
|
|
else if (control->default_version)
|
|
|
|
versionName = control->default_version;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("version to install must be specified")));
|
|
|
|
versionName = NULL; /* keep compiler quiet */
|
|
|
|
}
|
|
|
|
check_valid_version_name(versionName);
|
|
|
|
|
2011-02-16 18:39:45 +01:00
|
|
|
/*
|
|
|
|
* If we're already at that version, just say so
|
|
|
|
*/
|
|
|
|
if (strcmp(oldVersionName, versionName) == 0)
|
|
|
|
{
|
|
|
|
ereport(NOTICE,
|
|
|
|
(errmsg("version \"%s\" of extension \"%s\" is already installed",
|
|
|
|
versionName, stmt->extname)));
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
return InvalidObjectAddress;
|
2011-02-16 18:39:45 +01:00
|
|
|
}
|
|
|
|
|
2011-02-12 03:25:20 +01:00
|
|
|
/*
|
2011-02-12 22:40:41 +01:00
|
|
|
* Identify the series of update script files we need to execute
|
2011-02-12 03:25:20 +01:00
|
|
|
*/
|
2011-02-12 22:40:41 +01:00
|
|
|
updateVersions = identify_update_path(control,
|
|
|
|
oldVersionName,
|
|
|
|
versionName);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
|
|
|
/*
|
2011-02-12 22:40:41 +01:00
|
|
|
* Update the pg_extension row and execute the update scripts, one at a
|
|
|
|
* time
|
2011-02-12 03:25:20 +01:00
|
|
|
*/
|
2011-02-12 22:40:41 +01:00
|
|
|
ApplyExtensionUpdates(extensionOid, control,
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
oldVersionName, updateVersions,
|
|
|
|
NULL, false, false);
|
2012-12-29 13:55:37 +01:00
|
|
|
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddressSet(address, ExtensionRelationId, extensionOid);
|
|
|
|
|
|
|
|
return address;
|
2011-02-12 22:40:41 +01:00
|
|
|
}
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
/*
|
|
|
|
* Apply a series of update scripts as though individual ALTER EXTENSION
|
|
|
|
* UPDATE commands had been given, including altering the pg_extension row
|
|
|
|
* and dependencies each time.
|
|
|
|
*
|
|
|
|
* This might be more work than necessary, but it ensures that old update
|
|
|
|
* scripts don't break if newer versions have different control parameters.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ApplyExtensionUpdates(Oid extensionOid,
|
|
|
|
ExtensionControlFile *pcontrol,
|
|
|
|
const char *initialVersion,
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
List *updateVersions,
|
|
|
|
char *origSchemaName,
|
|
|
|
bool cascade,
|
|
|
|
bool is_create)
|
2011-02-12 22:40:41 +01:00
|
|
|
{
|
|
|
|
const char *oldVersionName = initialVersion;
|
|
|
|
ListCell *lcv;
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
foreach(lcv, updateVersions)
|
2011-02-12 03:25:20 +01:00
|
|
|
{
|
2011-02-12 22:40:41 +01:00
|
|
|
char *versionName = (char *) lfirst(lcv);
|
|
|
|
ExtensionControlFile *control;
|
|
|
|
char *schemaName;
|
|
|
|
Oid schemaOid;
|
|
|
|
List *requiredExtensions;
|
|
|
|
List *requiredSchemas;
|
|
|
|
Relation extRel;
|
|
|
|
ScanKeyData key[1];
|
|
|
|
SysScanDesc extScan;
|
|
|
|
HeapTuple extTup;
|
|
|
|
Form_pg_extension extForm;
|
|
|
|
Datum values[Natts_pg_extension];
|
|
|
|
bool nulls[Natts_pg_extension];
|
|
|
|
bool repl[Natts_pg_extension];
|
|
|
|
ObjectAddress myself;
|
|
|
|
ListCell *lc;
|
2011-02-12 03:25:20 +01:00
|
|
|
|
|
|
|
/*
|
2011-02-12 22:40:41 +01:00
|
|
|
* Fetch parameters for specific version (pcontrol is not changed)
|
2011-02-12 03:25:20 +01:00
|
|
|
*/
|
2011-02-12 22:40:41 +01:00
|
|
|
control = read_extension_aux_control_file(pcontrol, versionName);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
/* Find the pg_extension tuple */
|
2019-01-21 19:32:19 +01:00
|
|
|
extRel = table_open(ExtensionRelationId, RowExclusiveLock);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
ScanKeyInit(&key[0],
|
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
|
|
|
Anum_pg_extension_oid,
|
2011-02-12 22:40:41 +01:00
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(extensionOid));
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
|
Use an MVCC snapshot, rather than SnapshotNow, for catalog scans.
SnapshotNow scans have the undesirable property that, in the face of
concurrent updates, the scan can fail to see either the old or the new
versions of the row. In many cases, we work around this by requiring
DDL operations to hold AccessExclusiveLock on the object being
modified; in some cases, the existing locking is inadequate and random
failures occur as a result. This commit doesn't change anything
related to locking, but will hopefully pave the way to allowing lock
strength reductions in the future.
The major issue has held us back from making this change in the past
is that taking an MVCC snapshot is significantly more expensive than
using a static special snapshot such as SnapshotNow. However, testing
of various worst-case scenarios reveals that this problem is not
severe except under fairly extreme workloads. To mitigate those
problems, we avoid retaking the MVCC snapshot for each new scan;
instead, we take a new snapshot only when invalidation messages have
been processed. The catcache machinery already requires that
invalidation messages be sent before releasing the related heavyweight
lock; else other backends might rely on locally-cached data rather
than scanning the catalog at all. Thus, making snapshot reuse
dependent on the same guarantees shouldn't break anything that wasn't
already subtly broken.
Patch by me. Review by Michael Paquier and Andres Freund.
2013-07-02 15:47:01 +02:00
|
|
|
NULL, 1, key);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
extTup = systable_getnext(extScan);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
if (!HeapTupleIsValid(extTup)) /* should not happen */
|
2017-06-04 22:20:03 +02:00
|
|
|
elog(ERROR, "could not find tuple for extension %u",
|
2011-02-12 22:40:41 +01:00
|
|
|
extensionOid);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
extForm = (Form_pg_extension) GETSTRUCT(extTup);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
/*
|
|
|
|
* Determine the target schema (set by original install)
|
|
|
|
*/
|
|
|
|
schemaOid = extForm->extnamespace;
|
|
|
|
schemaName = get_namespace_name(schemaOid);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
/*
|
|
|
|
* Modify extrelocatable and extversion in the pg_extension tuple
|
|
|
|
*/
|
|
|
|
memset(values, 0, sizeof(values));
|
|
|
|
memset(nulls, 0, sizeof(nulls));
|
|
|
|
memset(repl, 0, sizeof(repl));
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
values[Anum_pg_extension_extrelocatable - 1] =
|
|
|
|
BoolGetDatum(control->relocatable);
|
|
|
|
repl[Anum_pg_extension_extrelocatable - 1] = true;
|
|
|
|
values[Anum_pg_extension_extversion - 1] =
|
|
|
|
CStringGetTextDatum(versionName);
|
|
|
|
repl[Anum_pg_extension_extversion - 1] = true;
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel),
|
|
|
|
values, nulls, repl);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2017-01-31 22:42:24 +01:00
|
|
|
CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
systable_endscan(extScan);
|
|
|
|
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(extRel, RowExclusiveLock);
|
2011-02-12 03:25:20 +01:00
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
/*
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
* Look up the prerequisite extensions for this version, install them
|
|
|
|
* if necessary, and build lists of their OIDs and the OIDs of their
|
|
|
|
* target schemas.
|
2011-02-12 22:40:41 +01:00
|
|
|
*/
|
|
|
|
requiredExtensions = NIL;
|
|
|
|
requiredSchemas = NIL;
|
|
|
|
foreach(lc, control->requires)
|
|
|
|
{
|
|
|
|
char *curreq = (char *) lfirst(lc);
|
|
|
|
Oid reqext;
|
|
|
|
Oid reqschema;
|
|
|
|
|
Allow CREATE EXTENSION to follow extension update paths.
Previously, to update an extension you had to produce both a version-update
script and a new base installation script. It's become more and more
obvious that that's tedious, duplicative, and error-prone. This patch
attempts to improve matters by allowing the new base installation script
to be omitted. CREATE EXTENSION will install a requested version if it
can find a base script and a chain of update scripts that will get there.
As in the existing update logic, shorter chains are preferred if there's
more than one possibility, with an arbitrary tie-break rule for chains
of equal length.
Also adjust the pg_available_extension_versions view to show such versions
as installable.
While at it, refactor the code so that CASCADE processing works for
extensions requested during ApplyExtensionUpdates(). Without this,
addition of a new requirement in an updated extension would require
creating a new base script, even if there was no other reason to do that.
(It would be easy at this point to add a CASCADE option to ALTER EXTENSION
UPDATE, to allow the same thing to happen during a manually-commanded
version update, but I have not done that here.)
Tom Lane, reviewed by Andres Freund
Discussion: <20160905005919.jz2m2yh3und2dsuy@alap3.anarazel.de>
2016-09-11 20:15:07 +02:00
|
|
|
reqext = get_required_extension(curreq,
|
|
|
|
control->name,
|
|
|
|
origSchemaName,
|
|
|
|
cascade,
|
|
|
|
NIL,
|
|
|
|
is_create);
|
2011-02-12 22:40:41 +01:00
|
|
|
reqschema = get_extension_schema(reqext);
|
|
|
|
requiredExtensions = lappend_oid(requiredExtensions, reqext);
|
|
|
|
requiredSchemas = lappend_oid(requiredSchemas, reqschema);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove and recreate dependencies on prerequisite extensions
|
|
|
|
*/
|
|
|
|
deleteDependencyRecordsForClass(ExtensionRelationId, extensionOid,
|
|
|
|
ExtensionRelationId,
|
|
|
|
DEPENDENCY_NORMAL);
|
|
|
|
|
|
|
|
myself.classId = ExtensionRelationId;
|
|
|
|
myself.objectId = extensionOid;
|
|
|
|
myself.objectSubId = 0;
|
|
|
|
|
|
|
|
foreach(lc, requiredExtensions)
|
|
|
|
{
|
|
|
|
Oid reqext = lfirst_oid(lc);
|
|
|
|
ObjectAddress otherext;
|
|
|
|
|
|
|
|
otherext.classId = ExtensionRelationId;
|
|
|
|
otherext.objectId = reqext;
|
|
|
|
otherext.objectSubId = 0;
|
|
|
|
|
|
|
|
recordDependencyOn(&myself, &otherext, DEPENDENCY_NORMAL);
|
|
|
|
}
|
|
|
|
|
2013-03-18 03:55:14 +01:00
|
|
|
InvokeObjectPostAlterHook(ExtensionRelationId, extensionOid, 0);
|
|
|
|
|
2011-02-12 22:40:41 +01:00
|
|
|
/*
|
|
|
|
* Finally, execute the update script file
|
|
|
|
*/
|
2011-02-12 03:25:20 +01:00
|
|
|
execute_extension_script(extensionOid, control,
|
2011-02-12 22:40:41 +01:00
|
|
|
oldVersionName, versionName,
|
2011-02-12 03:25:20 +01:00
|
|
|
requiredSchemas,
|
|
|
|
schemaName, schemaOid);
|
2011-02-12 22:40:41 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Update prior-version name and loop around. Since
|
|
|
|
* execute_sql_string did a final CommandCounterIncrement, we can
|
|
|
|
* update the pg_extension row again.
|
|
|
|
*/
|
|
|
|
oldVersionName = versionName;
|
2011-02-12 03:25:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-09 17:55:32 +01:00
|
|
|
/*
|
2011-02-10 23:36:44 +01:00
|
|
|
* Execute ALTER EXTENSION ADD/DROP
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
*
|
|
|
|
* Return value is the address of the altered extension.
|
|
|
|
*
|
|
|
|
* objAddr is an output argument which, if not NULL, is set to the address of
|
|
|
|
* the added/dropped object.
|
2011-02-09 17:55:32 +01:00
|
|
|
*/
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddress
|
|
|
|
ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
|
|
|
|
ObjectAddress *objAddr)
|
2011-02-09 17:55:32 +01:00
|
|
|
{
|
|
|
|
ObjectAddress extension;
|
|
|
|
ObjectAddress object;
|
|
|
|
Relation relation;
|
|
|
|
|
2020-06-13 09:03:28 +02:00
|
|
|
switch (stmt->objtype)
|
|
|
|
{
|
|
|
|
case OBJECT_DATABASE:
|
|
|
|
case OBJECT_EXTENSION:
|
|
|
|
case OBJECT_INDEX:
|
|
|
|
case OBJECT_PUBLICATION:
|
|
|
|
case OBJECT_ROLE:
|
|
|
|
case OBJECT_STATISTIC_EXT:
|
|
|
|
case OBJECT_SUBSCRIPTION:
|
|
|
|
case OBJECT_TABLESPACE:
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
|
|
|
errmsg("cannot add an object of this type to an extension")));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* OK */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-07-11 18:54:24 +02:00
|
|
|
/*
|
|
|
|
* Find the extension and acquire a lock on it, to ensure it doesn't get
|
|
|
|
* dropped concurrently. A sharable lock seems sufficient: there's no
|
|
|
|
* reason not to allow other sorts of manipulations, such as add/drop of
|
|
|
|
* other objects, to occur concurrently. Concurrently adding/dropping the
|
|
|
|
* *same* object would be bad, but we prevent that by using a non-sharable
|
|
|
|
* lock on the individual object, below.
|
|
|
|
*/
|
|
|
|
extension = get_object_address(OBJECT_EXTENSION,
|
|
|
|
(Node *) makeString(stmt->extname),
|
|
|
|
&relation, AccessShareLock, false);
|
2011-02-09 17:55:32 +01:00
|
|
|
|
2011-03-04 22:08:24 +01:00
|
|
|
/* Permission check: must own extension */
|
2022-11-13 08:11:17 +01:00
|
|
|
if (!object_ownercheck(ExtensionRelationId, extension.objectId, GetUserId()))
|
2017-12-02 15:26:34 +01:00
|
|
|
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_EXTENSION,
|
2011-03-04 22:08:24 +01:00
|
|
|
stmt->extname);
|
|
|
|
|
2011-02-09 17:55:32 +01:00
|
|
|
/*
|
|
|
|
* Translate the parser representation that identifies the object into an
|
|
|
|
* ObjectAddress. get_object_address() will throw an error if the object
|
2011-02-10 23:36:44 +01:00
|
|
|
* does not exist, and will also acquire a lock on the object to guard
|
|
|
|
* against concurrent DROP and ALTER EXTENSION ADD/DROP operations.
|
2011-02-09 17:55:32 +01:00
|
|
|
*/
|
Remove objname/objargs split for referring to objects
In simpler times, it might have worked to refer to all kinds of objects
by a list of name components and an optional argument list. But this
doesn't work for all objects, which has resulted in a collection of
hacks to place various other nodes types into these fields, which have
to be unpacked at the other end. This makes it also weird to represent
lists of such things in the grammar, because they would have to be lists
of singleton lists, to make the unpacking work consistently. The other
problem is that keeping separate name and args fields makes it awkward
to deal with lists of functions.
Change that by dropping the objargs field and have objname, renamed to
object, be a generic Node, which can then be flexibly assigned and
managed using the normal Node mechanisms. In many cases it will still
be a List of names, in some cases it will be a string Value, for types
it will be the existing Typename, for functions it will now use the
existing ObjectWithArgs node type. Some of the more obscure object
types still use somewhat arbitrary nested lists.
Reviewed-by: Jim Nasby <Jim.Nasby@BlueTreble.com>
Reviewed-by: Michael Paquier <michael.paquier@gmail.com>
2016-11-12 18:00:00 +01:00
|
|
|
object = get_object_address(stmt->objtype, stmt->object,
|
2011-06-28 03:17:25 +02:00
|
|
|
&relation, ShareUpdateExclusiveLock, false);
|
2011-02-09 17:55:32 +01:00
|
|
|
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
Assert(object.objectSubId == 0);
|
|
|
|
if (objAddr)
|
|
|
|
*objAddr = object;
|
|
|
|
|
2011-03-04 22:08:24 +01:00
|
|
|
/* Permission check: must own target object, too */
|
|
|
|
check_object_ownership(GetUserId(), stmt->objtype, object,
|
Remove objname/objargs split for referring to objects
In simpler times, it might have worked to refer to all kinds of objects
by a list of name components and an optional argument list. But this
doesn't work for all objects, which has resulted in a collection of
hacks to place various other nodes types into these fields, which have
to be unpacked at the other end. This makes it also weird to represent
lists of such things in the grammar, because they would have to be lists
of singleton lists, to make the unpacking work consistently. The other
problem is that keeping separate name and args fields makes it awkward
to deal with lists of functions.
Change that by dropping the objargs field and have objname, renamed to
object, be a generic Node, which can then be flexibly assigned and
managed using the normal Node mechanisms. In many cases it will still
be a List of names, in some cases it will be a string Value, for types
it will be the existing Typename, for functions it will now use the
existing ObjectWithArgs node type. Some of the more obscure object
types still use somewhat arbitrary nested lists.
Reviewed-by: Jim Nasby <Jim.Nasby@BlueTreble.com>
Reviewed-by: Michael Paquier <michael.paquier@gmail.com>
2016-11-12 18:00:00 +01:00
|
|
|
stmt->object, relation);
|
2011-03-04 22:08:24 +01:00
|
|
|
|
Explicitly list dependent types as extension members in pg_depend.
Auto-generated array types, multirange types, and relation rowtypes
are treated as dependent objects: they can't be dropped separately
from the base object, nor can they have their own ownership or
permissions. We previously felt that, for objects that are in an
extension, only the base object needs to be listed as an extension
member in pg_depend. While that's sufficient to prevent inappropriate
drops, it results in undesirable answers if someone asks whether a
dependent type belongs to the extension. It looks like the dependent
type is just some random separately-created object that happens to
depend on the base object. Notably, this results in postgres_fdw
concluding that expressions involving an array type are not shippable
to the remote server, even when the defining extension has been
whitelisted.
To fix, cause GenerateTypeDependencies to make extension dependencies
for dependent types as well as their base objects, and adjust
ExecAlterExtensionContentsStmt so that object addition and removal
operations recurse to dependent types. The latter change means that
pg_upgrade of a type-defining extension will end with the dependent
type(s) now also listed as extension members, even if they were
not that way in the source database. Normally we want pg_upgrade
to precisely reproduce the source extension's state, but it seems
desirable to make an exception here.
This is arguably a bug fix, but we can't back-patch it since it
causes changes in the expected contents of pg_depend. (Because
it does, I've bumped catversion, even though there's no change
in the immediate post-initdb catalog contents.)
Tom Lane and David Geier
Discussion: https://postgr.es/m/4a847c55-489f-4e8d-a664-fc6b1cbe306f@gmail.com
2024-03-04 20:49:31 +01:00
|
|
|
/* Do the update, recursing to any dependent objects */
|
|
|
|
ExecAlterExtensionContentsRecurse(stmt, extension, object);
|
|
|
|
|
|
|
|
/* Finish up */
|
|
|
|
InvokeObjectPostAlterHook(ExtensionRelationId, extension.objectId, 0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If get_object_address() opened the relation for us, we close it to keep
|
|
|
|
* the reference count correct - but we retain any locks acquired by
|
|
|
|
* get_object_address() until commit time, to guard against concurrent
|
|
|
|
* activity.
|
|
|
|
*/
|
|
|
|
if (relation != NULL)
|
|
|
|
relation_close(relation, NoLock);
|
|
|
|
|
|
|
|
return extension;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ExecAlterExtensionContentsRecurse
|
|
|
|
* Subroutine for ExecAlterExtensionContentsStmt
|
|
|
|
*
|
|
|
|
* Do the bare alteration of object's membership in extension,
|
|
|
|
* without permission checks. Recurse to dependent objects, if any.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ExecAlterExtensionContentsRecurse(AlterExtensionContentsStmt *stmt,
|
|
|
|
ObjectAddress extension,
|
|
|
|
ObjectAddress object)
|
|
|
|
{
|
|
|
|
Oid oldExtension;
|
|
|
|
|
2011-02-09 17:55:32 +01:00
|
|
|
/*
|
2011-02-10 23:36:44 +01:00
|
|
|
* Check existing extension membership.
|
2011-02-09 17:55:32 +01:00
|
|
|
*/
|
2011-02-10 23:36:44 +01:00
|
|
|
oldExtension = getExtensionOfObject(object.classId, object.objectId);
|
2011-02-09 17:55:32 +01:00
|
|
|
|
2011-02-10 23:36:44 +01:00
|
|
|
if (stmt->action > 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* ADD, so complain if object is already attached to some extension.
|
|
|
|
*/
|
|
|
|
if (OidIsValid(oldExtension))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
|
|
|
errmsg("%s is already a member of extension \"%s\"",
|
2020-07-15 02:03:10 +02:00
|
|
|
getObjectDescription(&object, false),
|
2011-02-10 23:36:44 +01:00
|
|
|
get_extension_name(oldExtension))));
|
|
|
|
|
2012-08-15 17:26:55 +02:00
|
|
|
/*
|
|
|
|
* Prevent a schema from being added to an extension if the schema
|
|
|
|
* contains the extension. That would create a dependency loop.
|
|
|
|
*/
|
|
|
|
if (object.classId == NamespaceRelationId &&
|
|
|
|
object.objectId == get_extension_schema(extension.objectId))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
|
|
|
errmsg("cannot add schema \"%s\" to extension \"%s\" "
|
|
|
|
"because the schema contains the extension",
|
|
|
|
get_namespace_name(object.objectId),
|
|
|
|
stmt->extname)));
|
|
|
|
|
2011-02-10 23:36:44 +01:00
|
|
|
/*
|
|
|
|
* OK, add the dependency.
|
|
|
|
*/
|
|
|
|
recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
|
2017-01-30 05:05:07 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Also record the initial ACL on the object, if any.
|
|
|
|
*
|
|
|
|
* Note that this will handle the object's ACLs, as well as any ACLs
|
|
|
|
* on object subIds. (In other words, when the object is a table,
|
|
|
|
* this will record the table's ACL and the ACLs for the columns on
|
|
|
|
* the table, if any).
|
|
|
|
*/
|
|
|
|
recordExtObjInitPriv(object.objectId, object.classId);
|
2011-02-10 23:36:44 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* DROP, so complain if it's not a member.
|
|
|
|
*/
|
|
|
|
if (oldExtension != extension.objectId)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
|
|
|
errmsg("%s is not a member of extension \"%s\"",
|
2020-07-15 02:03:10 +02:00
|
|
|
getObjectDescription(&object, false),
|
2011-02-10 23:36:44 +01:00
|
|
|
stmt->extname)));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* OK, drop the dependency.
|
|
|
|
*/
|
|
|
|
if (deleteDependencyRecordsForClass(object.classId, object.objectId,
|
|
|
|
ExtensionRelationId,
|
|
|
|
DEPENDENCY_EXTENSION) != 1)
|
|
|
|
elog(ERROR, "unexpected number of extension dependency records");
|
2012-12-20 22:30:59 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If it's a relation, it might have an entry in the extension's
|
|
|
|
* extconfig array, which we must remove.
|
|
|
|
*/
|
|
|
|
if (object.classId == RelationRelationId)
|
|
|
|
extension_config_remove(extension.objectId, object.objectId);
|
2017-01-30 05:05:07 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove all the initial ACLs, if any.
|
|
|
|
*
|
|
|
|
* Note that this will remove the object's ACLs, as well as any ACLs
|
|
|
|
* on object subIds. (In other words, when the object is a table,
|
|
|
|
* this will remove the table's ACL and the ACLs for the columns on
|
|
|
|
* the table, if any).
|
|
|
|
*/
|
|
|
|
removeExtObjInitPriv(object.objectId, object.classId);
|
2011-02-10 23:36:44 +01:00
|
|
|
}
|
2011-02-09 17:55:32 +01:00
|
|
|
|
|
|
|
/*
|
Explicitly list dependent types as extension members in pg_depend.
Auto-generated array types, multirange types, and relation rowtypes
are treated as dependent objects: they can't be dropped separately
from the base object, nor can they have their own ownership or
permissions. We previously felt that, for objects that are in an
extension, only the base object needs to be listed as an extension
member in pg_depend. While that's sufficient to prevent inappropriate
drops, it results in undesirable answers if someone asks whether a
dependent type belongs to the extension. It looks like the dependent
type is just some random separately-created object that happens to
depend on the base object. Notably, this results in postgres_fdw
concluding that expressions involving an array type are not shippable
to the remote server, even when the defining extension has been
whitelisted.
To fix, cause GenerateTypeDependencies to make extension dependencies
for dependent types as well as their base objects, and adjust
ExecAlterExtensionContentsStmt so that object addition and removal
operations recurse to dependent types. The latter change means that
pg_upgrade of a type-defining extension will end with the dependent
type(s) now also listed as extension members, even if they were
not that way in the source database. Normally we want pg_upgrade
to precisely reproduce the source extension's state, but it seems
desirable to make an exception here.
This is arguably a bug fix, but we can't back-patch it since it
causes changes in the expected contents of pg_depend. (Because
it does, I've bumped catversion, even though there's no change
in the immediate post-initdb catalog contents.)
Tom Lane and David Geier
Discussion: https://postgr.es/m/4a847c55-489f-4e8d-a664-fc6b1cbe306f@gmail.com
2024-03-04 20:49:31 +01:00
|
|
|
* Recurse to any dependent objects; currently, this includes the array
|
|
|
|
* type of a base type, the multirange type associated with a range type,
|
|
|
|
* and the rowtype of a table.
|
2011-02-09 17:55:32 +01:00
|
|
|
*/
|
Explicitly list dependent types as extension members in pg_depend.
Auto-generated array types, multirange types, and relation rowtypes
are treated as dependent objects: they can't be dropped separately
from the base object, nor can they have their own ownership or
permissions. We previously felt that, for objects that are in an
extension, only the base object needs to be listed as an extension
member in pg_depend. While that's sufficient to prevent inappropriate
drops, it results in undesirable answers if someone asks whether a
dependent type belongs to the extension. It looks like the dependent
type is just some random separately-created object that happens to
depend on the base object. Notably, this results in postgres_fdw
concluding that expressions involving an array type are not shippable
to the remote server, even when the defining extension has been
whitelisted.
To fix, cause GenerateTypeDependencies to make extension dependencies
for dependent types as well as their base objects, and adjust
ExecAlterExtensionContentsStmt so that object addition and removal
operations recurse to dependent types. The latter change means that
pg_upgrade of a type-defining extension will end with the dependent
type(s) now also listed as extension members, even if they were
not that way in the source database. Normally we want pg_upgrade
to precisely reproduce the source extension's state, but it seems
desirable to make an exception here.
This is arguably a bug fix, but we can't back-patch it since it
causes changes in the expected contents of pg_depend. (Because
it does, I've bumped catversion, even though there's no change
in the immediate post-initdb catalog contents.)
Tom Lane and David Geier
Discussion: https://postgr.es/m/4a847c55-489f-4e8d-a664-fc6b1cbe306f@gmail.com
2024-03-04 20:49:31 +01:00
|
|
|
if (object.classId == TypeRelationId)
|
|
|
|
{
|
|
|
|
ObjectAddress depobject;
|
2012-12-29 13:55:37 +01:00
|
|
|
|
Explicitly list dependent types as extension members in pg_depend.
Auto-generated array types, multirange types, and relation rowtypes
are treated as dependent objects: they can't be dropped separately
from the base object, nor can they have their own ownership or
permissions. We previously felt that, for objects that are in an
extension, only the base object needs to be listed as an extension
member in pg_depend. While that's sufficient to prevent inappropriate
drops, it results in undesirable answers if someone asks whether a
dependent type belongs to the extension. It looks like the dependent
type is just some random separately-created object that happens to
depend on the base object. Notably, this results in postgres_fdw
concluding that expressions involving an array type are not shippable
to the remote server, even when the defining extension has been
whitelisted.
To fix, cause GenerateTypeDependencies to make extension dependencies
for dependent types as well as their base objects, and adjust
ExecAlterExtensionContentsStmt so that object addition and removal
operations recurse to dependent types. The latter change means that
pg_upgrade of a type-defining extension will end with the dependent
type(s) now also listed as extension members, even if they were
not that way in the source database. Normally we want pg_upgrade
to precisely reproduce the source extension's state, but it seems
desirable to make an exception here.
This is arguably a bug fix, but we can't back-patch it since it
causes changes in the expected contents of pg_depend. (Because
it does, I've bumped catversion, even though there's no change
in the immediate post-initdb catalog contents.)
Tom Lane and David Geier
Discussion: https://postgr.es/m/4a847c55-489f-4e8d-a664-fc6b1cbe306f@gmail.com
2024-03-04 20:49:31 +01:00
|
|
|
depobject.classId = TypeRelationId;
|
|
|
|
depobject.objectSubId = 0;
|
|
|
|
|
|
|
|
/* If it has an array type, update that too */
|
|
|
|
depobject.objectId = get_array_type(object.objectId);
|
|
|
|
if (OidIsValid(depobject.objectId))
|
|
|
|
ExecAlterExtensionContentsRecurse(stmt, extension, depobject);
|
|
|
|
|
|
|
|
/* If it is a range type, update the associated multirange too */
|
|
|
|
if (type_is_range(object.objectId))
|
|
|
|
{
|
|
|
|
depobject.objectId = get_range_multirange(object.objectId);
|
|
|
|
if (!OidIsValid(depobject.objectId))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("could not find multirange type for data type %s",
|
|
|
|
format_type_be(object.objectId))));
|
|
|
|
ExecAlterExtensionContentsRecurse(stmt, extension, depobject);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (object.classId == RelationRelationId)
|
|
|
|
{
|
|
|
|
ObjectAddress depobject;
|
|
|
|
|
|
|
|
depobject.classId = TypeRelationId;
|
|
|
|
depobject.objectSubId = 0;
|
|
|
|
|
|
|
|
/* It might not have a rowtype, but if it does, update that */
|
|
|
|
depobject.objectId = get_rel_type_id(object.objectId);
|
|
|
|
if (OidIsValid(depobject.objectId))
|
|
|
|
ExecAlterExtensionContentsRecurse(stmt, extension, depobject);
|
|
|
|
}
|
2011-02-09 17:55:32 +01:00
|
|
|
}
|
2015-06-28 20:35:46 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Read the whole of file into memory.
|
|
|
|
*
|
|
|
|
* The file contents are returned as a single palloc'd chunk. For convenience
|
|
|
|
* of the callers, an extra \0 byte is added to the end.
|
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
read_whole_file(const char *filename, int *length)
|
|
|
|
{
|
|
|
|
char *buf;
|
|
|
|
FILE *file;
|
|
|
|
size_t bytes_to_read;
|
|
|
|
struct stat fst;
|
|
|
|
|
|
|
|
if (stat(filename, &fst) < 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode_for_file_access(),
|
|
|
|
errmsg("could not stat file \"%s\": %m", filename)));
|
|
|
|
|
|
|
|
if (fst.st_size > (MaxAllocSize - 1))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
2015-11-17 03:16:42 +01:00
|
|
|
errmsg("file \"%s\" is too large", filename)));
|
2015-06-28 20:35:46 +02:00
|
|
|
bytes_to_read = (size_t) fst.st_size;
|
|
|
|
|
|
|
|
if ((file = AllocateFile(filename, PG_BINARY_R)) == NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode_for_file_access(),
|
|
|
|
errmsg("could not open file \"%s\" for reading: %m",
|
|
|
|
filename)));
|
|
|
|
|
|
|
|
buf = (char *) palloc(bytes_to_read + 1);
|
|
|
|
|
|
|
|
*length = fread(buf, 1, bytes_to_read, file);
|
|
|
|
|
|
|
|
if (ferror(file))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode_for_file_access(),
|
|
|
|
errmsg("could not read file \"%s\": %m", filename)));
|
|
|
|
|
|
|
|
FreeFile(file);
|
|
|
|
|
|
|
|
buf[*length] = '\0';
|
|
|
|
return buf;
|
|
|
|
}
|