1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* rewriteDefine.c
|
1996-07-09 08:22:35 +02:00
|
|
|
* routines for defining a rewrite rule
|
|
|
|
*
|
2020-01-01 18:21:45 +01:00
|
|
|
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/rewrite/rewriteDefine.c
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
1999-07-16 05:14:30 +02:00
|
|
|
#include "access/heapam.h"
|
2012-08-30 22:15:44 +02:00
|
|
|
#include "access/htup_details.h"
|
2013-03-04 01:05:47 +01:00
|
|
|
#include "access/multixact.h"
|
tableam: Add and use scan APIs.
Too allow table accesses to be not directly dependent on heap, several
new abstractions are needed. Specifically:
1) Heap scans need to be generalized into table scans. Do this by
introducing TableScanDesc, which will be the "base class" for
individual AMs. This contains the AM independent fields from
HeapScanDesc.
The previous heap_{beginscan,rescan,endscan} et al. have been
replaced with a table_ version.
There's no direct replacement for heap_getnext(), as that returned
a HeapTuple, which is undesirable for a other AMs. Instead there's
table_scan_getnextslot(). But note that heap_getnext() lives on,
it's still used widely to access catalog tables.
This is achieved by new scan_begin, scan_end, scan_rescan,
scan_getnextslot callbacks.
2) The portion of parallel scans that's shared between backends need
to be able to do so without the user doing per-AM work. To achieve
that new parallelscan_{estimate, initialize, reinitialize}
callbacks are introduced, which operate on a new
ParallelTableScanDesc, which again can be subclassed by AMs.
As it is likely that several AMs are going to be block oriented,
block oriented callbacks that can be shared between such AMs are
provided and used by heap. table_block_parallelscan_{estimate,
intiialize, reinitialize} as callbacks, and
table_block_parallelscan_{nextpage, init} for use in AMs. These
operate on a ParallelBlockTableScanDesc.
3) Index scans need to be able to access tables to return a tuple, and
there needs to be state across individual accesses to the heap to
store state like buffers. That's now handled by introducing a
sort-of-scan IndexFetchTable, which again is intended to be
subclassed by individual AMs (for heap IndexFetchHeap).
The relevant callbacks for an AM are index_fetch_{end, begin,
reset} to create the necessary state, and index_fetch_tuple to
retrieve an indexed tuple. Note that index_fetch_tuple
implementations need to be smarter than just blindly fetching the
tuples for AMs that have optimizations similar to heap's HOT - the
currently alive tuple in the update chain needs to be fetched if
appropriate.
Similar to table_scan_getnextslot(), it's undesirable to continue
to return HeapTuples. Thus index_fetch_heap (might want to rename
that later) now accepts a slot as an argument. Core code doesn't
have a lot of call sites performing index scans without going
through the systable_* API (in contrast to loads of heap_getnext
calls and working directly with HeapTuples).
Index scans now store the result of a search in
IndexScanDesc->xs_heaptid, rather than xs_ctup->t_self. As the
target is not generally a HeapTuple anymore that seems cleaner.
To be able to sensible adapt code to use the above, two further
callbacks have been introduced:
a) slot_callbacks returns a TupleTableSlotOps* suitable for creating
slots capable of holding a tuple of the AMs
type. table_slot_callbacks() and table_slot_create() are based
upon that, but have additional logic to deal with views, foreign
tables, etc.
While this change could have been done separately, nearly all the
call sites that needed to be adapted for the rest of this commit
also would have been needed to be adapted for
table_slot_callbacks(), making separation not worthwhile.
b) tuple_satisfies_snapshot checks whether the tuple in a slot is
currently visible according to a snapshot. That's required as a few
places now don't have a buffer + HeapTuple around, but a
slot (which in heap's case internally has that information).
Additionally a few infrastructure changes were needed:
I) SysScanDesc, as used by systable_{beginscan, getnext} et al. now
internally uses a slot to keep track of tuples. While
systable_getnext() still returns HeapTuples, and will so for the
foreseeable future, the index API (see 1) above) now only deals with
slots.
The remainder, and largest part, of this commit is then adjusting all
scans in postgres to use the new APIs.
Author: Andres Freund, Haribabu Kommi, Alvaro Herrera
Discussion:
https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de
https://postgr.es/m/20160812231527.GA690404@alvherre.pgsql
2019-03-11 20:46:41 +01:00
|
|
|
#include "access/tableam.h"
|
2013-03-04 01:05:47 +01:00
|
|
|
#include "access/transam.h"
|
|
|
|
#include "access/xact.h"
|
2009-05-14 00:32:55 +02:00
|
|
|
#include "catalog/catalog.h"
|
2002-07-12 20:43:19 +02:00
|
|
|
#include "catalog/dependency.h"
|
2012-10-24 19:39:37 +02:00
|
|
|
#include "catalog/heap.h"
|
2000-06-28 05:33:33 +02:00
|
|
|
#include "catalog/indexing.h"
|
2007-08-27 05:36:08 +02:00
|
|
|
#include "catalog/namespace.h"
|
2010-11-25 17:48:49 +01:00
|
|
|
#include "catalog/objectaccess.h"
|
Disallow converting an inheritance child table to a view.
Generally, members of inheritance trees must be plain tables (or,
in more recent versions, foreign tables). ALTER TABLE INHERIT
rejects creating an inheritance relationship that has a view at
either end. When DefineQueryRewrite attempts to convert a relation
to a view, it already had checks prohibiting doing so for partitioning
parents or children as well as traditional-inheritance parents ...
but it neglected to check that a traditional-inheritance child wasn't
being converted. Since the planner assumes that any inheritance
child is a table, this led to making plans that tried to do a physical
scan on a view, causing failures (or even crashes, in recent versions).
One could imagine trying to support such a case by expanding the view
normally, but since the rewriter runs before the planner does
inheritance expansion, it would take some very fundamental refactoring
to make that possible. There are probably a lot of other parts of the
system that don't cope well with such a situation, too. For now,
just forbid it.
Per bug #16856 from Yang Lin. Back-patch to all supported branches.
(In versions before v10, this includes back-patching the portion of
commit 501ed02cf that added has_superclass(). Perhaps the lack of
that infrastructure partially explains the missing check.)
Discussion: https://postgr.es/m/16856-0363e05c6e1612fd@postgresql.org
2021-02-06 21:17:01 +01:00
|
|
|
#include "catalog/pg_inherits.h"
|
2000-06-28 05:33:33 +02:00
|
|
|
#include "catalog/pg_rewrite.h"
|
2008-11-19 11:34:52 +01:00
|
|
|
#include "catalog/storage.h"
|
2015-07-29 01:24:01 +02:00
|
|
|
#include "commands/policy.h"
|
Disallow converting a table to a view within an outer SQL command.
We have long disallowed all forms of ALTER TABLE if the table is
already opened by some outer SQL command in the same session.
This has the same purpose as obtaining AccessExclusiveLock, but
since a session's own locks don't conflict the lock only blocks use
of the table by other sessions, not our own. Without this check,
the ALTER might confuse the outer SQL command since any previous
inspection of the table would potentially become invalid.
However, the RelisBecomingView code path in DefineQueryRewrite never
got that memo, and assumed that AccessExclusiveLock is sufficient
for performing something morally equivalent to a rather invasive
ALTER TABLE. Unsurprisingly, this can confuse an outer command
that is trying to do something with the table.
This was submitted as a security issue, but the security team
has been unable to identify any consequence worse than a null
pointer dereference (from trying to access rd_tableam methods
that the relation no longer has). Therefore, in accordance
with our usual policy, it's not security material and should
just be fixed as a routine bug.
Fix by disallowing the operation if the table is open locally,
exactly as ALTER TABLE does it.
Per an anonymous security researcher, via Bundesamt für Sicherheit
in der Informationstechnik.
Patch v12-v15 only. In v16 and later, we removed this code
altogether (cf. commit b23cd185f), so that there's no issue.
2024-04-30 21:22:55 +02:00
|
|
|
#include "commands/tablecmds.h"
|
2000-09-29 20:21:41 +02:00
|
|
|
#include "miscadmin.h"
|
2008-08-26 00:42:34 +02:00
|
|
|
#include "nodes/nodeFuncs.h"
|
2007-06-24 00:12:52 +02:00
|
|
|
#include "parser/parse_utilcmd.h"
|
1996-11-10 04:06:38 +01:00
|
|
|
#include "rewrite/rewriteDefine.h"
|
2000-12-05 20:15:10 +01:00
|
|
|
#include "rewrite/rewriteManip.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "rewrite/rewriteSupport.h"
|
2002-03-22 00:27:25 +01:00
|
|
|
#include "utils/acl.h"
|
2000-09-29 20:21:41 +02:00
|
|
|
#include "utils/builtins.h"
|
2008-03-26 22:10:39 +01:00
|
|
|
#include "utils/inval.h"
|
2003-07-25 02:01:09 +02:00
|
|
|
#include "utils/lsyscache.h"
|
2008-06-19 02:46:06 +02:00
|
|
|
#include "utils/rel.h"
|
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
|
|
|
#include "utils/snapmgr.h"
|
2001-08-12 23:35:19 +02:00
|
|
|
#include "utils/syscache.h"
|
2000-09-29 20:21:41 +02:00
|
|
|
|
|
|
|
|
2006-09-02 19:06:52 +02:00
|
|
|
static void checkRuleResultList(List *targetList, TupleDesc resultDesc,
|
2013-11-04 21:31:07 +01:00
|
|
|
bool isSelect, bool requireColumnNameMatch);
|
2005-06-28 07:09:14 +02:00
|
|
|
static bool setRuleCheckAsUser_walker(Node *node, Oid *context);
|
2006-09-05 23:08:36 +02:00
|
|
|
static void setRuleCheckAsUser_Query(Query *qry, Oid userid);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1999-10-21 03:46:24 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
|
|
|
* InsertRule -
|
2002-04-18 22:01:11 +02:00
|
|
|
* takes the arguments and inserts them as a row into the system
|
1996-07-09 08:22:35 +02:00
|
|
|
* relation "pg_rewrite"
|
|
|
|
*/
|
|
|
|
static Oid
|
2017-10-31 15:34:31 +01:00
|
|
|
InsertRule(const char *rulname,
|
1996-07-09 08:22:35 +02:00
|
|
|
int evtype,
|
2000-06-30 09:04:23 +02:00
|
|
|
Oid eventrel_oid,
|
1996-07-09 08:22:35 +02:00
|
|
|
bool evinstead,
|
2002-07-16 07:53:34 +02:00
|
|
|
Node *event_qual,
|
2002-09-02 04:13:02 +02:00
|
|
|
List *action,
|
|
|
|
bool replace)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2002-07-16 07:53:34 +02:00
|
|
|
char *evqual = nodeToString(event_qual);
|
|
|
|
char *actiontree = nodeToString((Node *) action);
|
2000-06-28 05:33:33 +02:00
|
|
|
Datum values[Natts_pg_rewrite];
|
2008-11-02 02:45:28 +01:00
|
|
|
bool nulls[Natts_pg_rewrite];
|
|
|
|
bool replaces[Natts_pg_rewrite];
|
2000-06-28 05:33:33 +02:00
|
|
|
NameData rname;
|
|
|
|
Relation pg_rewrite_desc;
|
2002-09-02 04:13:02 +02:00
|
|
|
HeapTuple tup,
|
|
|
|
oldtup;
|
2000-06-28 05:33:33 +02:00
|
|
|
Oid rewriteObjectId;
|
2002-07-12 20:43:19 +02:00
|
|
|
ObjectAddress myself,
|
|
|
|
referenced;
|
2002-09-02 04:13:02 +02:00
|
|
|
bool is_update = false;
|
1999-10-21 03:46:24 +02:00
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
/*
|
|
|
|
* Set up *nulls and *values arrays
|
|
|
|
*/
|
2008-11-02 02:45:28 +01:00
|
|
|
MemSet(nulls, false, sizeof(nulls));
|
2000-06-28 05:33:33 +02:00
|
|
|
|
|
|
|
namestrcpy(&rname, rulname);
|
2011-06-16 23:03:58 +02:00
|
|
|
values[Anum_pg_rewrite_rulename - 1] = NameGetDatum(&rname);
|
|
|
|
values[Anum_pg_rewrite_ev_class - 1] = ObjectIdGetDatum(eventrel_oid);
|
|
|
|
values[Anum_pg_rewrite_ev_type - 1] = CharGetDatum(evtype + '0');
|
|
|
|
values[Anum_pg_rewrite_ev_enabled - 1] = CharGetDatum(RULE_FIRES_ON_ORIGIN);
|
|
|
|
values[Anum_pg_rewrite_is_instead - 1] = BoolGetDatum(evinstead);
|
|
|
|
values[Anum_pg_rewrite_ev_qual - 1] = CStringGetTextDatum(evqual);
|
|
|
|
values[Anum_pg_rewrite_ev_action - 1] = CStringGetTextDatum(actiontree);
|
2000-06-28 05:33:33 +02:00
|
|
|
|
|
|
|
/*
|
2002-09-02 04:13:02 +02:00
|
|
|
* Ready to store new pg_rewrite tuple
|
2000-06-28 05:33:33 +02:00
|
|
|
*/
|
2019-01-21 19:32:19 +01:00
|
|
|
pg_rewrite_desc = table_open(RewriteRelationId, RowExclusiveLock);
|
2000-06-28 05:33:33 +02:00
|
|
|
|
2002-09-02 04:13:02 +02:00
|
|
|
/*
|
|
|
|
* Check to see if we are replacing an existing tuple
|
|
|
|
*/
|
2010-02-14 19:42:19 +01:00
|
|
|
oldtup = SearchSysCache2(RULERELNAME,
|
|
|
|
ObjectIdGetDatum(eventrel_oid),
|
|
|
|
PointerGetDatum(rulname));
|
2002-09-02 04:13:02 +02:00
|
|
|
|
|
|
|
if (HeapTupleIsValid(oldtup))
|
|
|
|
{
|
2009-01-27 13:40:15 +01:00
|
|
|
if (!replace)
|
2003-07-25 02:01:09 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
|
|
|
errmsg("rule \"%s\" for relation \"%s\" already exists",
|
|
|
|
rulname, get_rel_name(eventrel_oid))));
|
2002-09-02 04:13:02 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* When replacing, we don't need to replace every attribute
|
|
|
|
*/
|
2008-11-02 02:45:28 +01:00
|
|
|
MemSet(replaces, false, sizeof(replaces));
|
|
|
|
replaces[Anum_pg_rewrite_ev_type - 1] = true;
|
|
|
|
replaces[Anum_pg_rewrite_is_instead - 1] = true;
|
|
|
|
replaces[Anum_pg_rewrite_ev_qual - 1] = true;
|
|
|
|
replaces[Anum_pg_rewrite_ev_action - 1] = true;
|
|
|
|
|
|
|
|
tup = heap_modify_tuple(oldtup, RelationGetDescr(pg_rewrite_desc),
|
2002-09-02 04:13:02 +02:00
|
|
|
values, nulls, replaces);
|
|
|
|
|
2017-01-31 22:42:24 +01:00
|
|
|
CatalogTupleUpdate(pg_rewrite_desc, &tup->t_self, tup);
|
2000-06-28 05:33:33 +02:00
|
|
|
|
2002-09-02 04:13:02 +02:00
|
|
|
ReleaseSysCache(oldtup);
|
|
|
|
|
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
|
|
|
rewriteObjectId = ((Form_pg_rewrite) GETSTRUCT(tup))->oid;
|
2002-09-02 04:13:02 +02:00
|
|
|
is_update = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
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
|
|
|
rewriteObjectId = GetNewOidWithIndex(pg_rewrite_desc,
|
|
|
|
RewriteOidIndexId,
|
|
|
|
Anum_pg_rewrite_oid);
|
|
|
|
values[Anum_pg_rewrite_oid - 1] = ObjectIdGetDatum(rewriteObjectId);
|
|
|
|
|
2008-11-02 02:45:28 +01:00
|
|
|
tup = heap_form_tuple(pg_rewrite_desc->rd_att, values, nulls);
|
2000-06-28 05:33:33 +02:00
|
|
|
|
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(pg_rewrite_desc, tup);
|
2002-09-02 04:13:02 +02:00
|
|
|
}
|
2000-06-28 05:33:33 +02:00
|
|
|
|
1999-10-21 03:46:24 +02:00
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
heap_freetuple(tup);
|
1999-10-21 04:33:25 +02:00
|
|
|
|
2002-09-02 04:13:02 +02:00
|
|
|
/* If replacing, get rid of old dependencies and make new ones */
|
|
|
|
if (is_update)
|
2011-02-08 22:08:41 +01:00
|
|
|
deleteDependencyRecordsFor(RewriteRelationId, rewriteObjectId, false);
|
2002-09-02 04:13:02 +02:00
|
|
|
|
2002-07-12 20:43:19 +02:00
|
|
|
/*
|
|
|
|
* Install dependency on rule's relation to ensure it will go away on
|
|
|
|
* relation deletion. If the rule is ON SELECT, make the dependency
|
|
|
|
* implicit --- this prevents deleting a view's SELECT rule. Other kinds
|
|
|
|
* of rules can be AUTO.
|
|
|
|
*/
|
2005-04-14 03:38:22 +02:00
|
|
|
myself.classId = RewriteRelationId;
|
2002-07-12 20:43:19 +02:00
|
|
|
myself.objectId = rewriteObjectId;
|
|
|
|
myself.objectSubId = 0;
|
|
|
|
|
2005-04-14 03:38:22 +02:00
|
|
|
referenced.classId = RelationRelationId;
|
2002-07-12 20:43:19 +02:00
|
|
|
referenced.objectId = eventrel_oid;
|
|
|
|
referenced.objectSubId = 0;
|
|
|
|
|
|
|
|
recordDependencyOn(&myself, &referenced,
|
2002-09-02 04:13:02 +02:00
|
|
|
(evtype == CMD_SELECT) ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO);
|
2002-07-12 20:43:19 +02:00
|
|
|
|
2002-07-16 07:53:34 +02:00
|
|
|
/*
|
|
|
|
* Also install dependencies on objects referenced in action and qual.
|
|
|
|
*/
|
|
|
|
recordDependencyOnExpr(&myself, (Node *) action, NIL,
|
|
|
|
DEPENDENCY_NORMAL);
|
2002-09-02 04:13:02 +02:00
|
|
|
|
2002-07-16 07:53:34 +02:00
|
|
|
if (event_qual != NULL)
|
|
|
|
{
|
|
|
|
/* Find query containing OLD/NEW rtable entries */
|
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
|
|
|
Query *qry = linitial_node(Query, action);
|
2002-07-16 07:53:34 +02:00
|
|
|
|
|
|
|
qry = getInsertSelectQuery(qry, NULL);
|
|
|
|
recordDependencyOnExpr(&myself, event_qual, qry->rtable,
|
|
|
|
DEPENDENCY_NORMAL);
|
|
|
|
}
|
|
|
|
|
2010-11-25 17:48:49 +01:00
|
|
|
/* Post creation hook for new rule */
|
2013-03-07 02:52:06 +01:00
|
|
|
InvokeObjectPostCreateHook(RewriteRelationId, rewriteObjectId, 0);
|
2010-11-25 17:48:49 +01:00
|
|
|
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(pg_rewrite_desc, RowExclusiveLock);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
return rewriteObjectId;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2007-03-13 01:33:44 +01:00
|
|
|
/*
|
|
|
|
* DefineRule
|
|
|
|
* Execute a CREATE RULE command.
|
|
|
|
*/
|
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
|
2007-03-13 01:33:44 +01:00
|
|
|
DefineRule(RuleStmt *stmt, const char *queryString)
|
|
|
|
{
|
|
|
|
List *actions;
|
|
|
|
Node *whereClause;
|
2007-08-27 05:36:08 +02:00
|
|
|
Oid relId;
|
2007-03-13 01:33:44 +01:00
|
|
|
|
2011-07-09 04:19:30 +02:00
|
|
|
/* Parse analysis. */
|
2007-06-24 00:12:52 +02:00
|
|
|
transformRuleStmt(stmt, queryString, &actions, &whereClause);
|
2007-03-13 01:33:44 +01:00
|
|
|
|
2011-07-09 04:19:30 +02:00
|
|
|
/*
|
|
|
|
* Find and lock the relation. Lock level should match
|
|
|
|
* DefineQueryRewrite.
|
|
|
|
*/
|
Improve table locking behavior in the face of current DDL.
In the previous coding, callers were faced with an awkward choice:
look up the name, do permissions checks, and then lock the table; or
look up the name, lock the table, and then do permissions checks.
The first choice was wrong because the results of the name lookup
and permissions checks might be out-of-date by the time the table
lock was acquired, while the second allowed a user with no privileges
to interfere with access to a table by users who do have privileges
(e.g. if a malicious backend queues up for an AccessExclusiveLock on
a table on which AccessShareLock is already held, further attempts
to access the table will be blocked until the AccessExclusiveLock
is obtained and the malicious backend's transaction rolls back).
To fix, allow callers of RangeVarGetRelid() to pass a callback which
gets executed after performing the name lookup but before acquiring
the relation lock. If the name lookup is retried (because
invalidation messages are received), the callback will be re-executed
as well, so we get the best of both worlds. RangeVarGetRelid() is
renamed to RangeVarGetRelidExtended(); callers not wishing to supply
a callback can continue to invoke it as RangeVarGetRelid(), which is
now a macro. Since the only one caller that uses nowait = true now
passes a callback anyway, the RangeVarGetRelid() macro defaults nowait
as well. The callback can also be used for supplemental locking - for
example, REINDEX INDEX needs to acquire the table lock before the index
lock to reduce deadlock possibilities.
There's a lot more work to be done here to fix all the cases where this
can be a problem, but this commit provides the general infrastructure
and fixes the following specific cases: REINDEX INDEX, REINDEX TABLE,
LOCK TABLE, and and DROP TABLE/INDEX/SEQUENCE/VIEW/FOREIGN TABLE.
Per discussion with Noah Misch and Alvaro Herrera.
2011-11-30 16:12:27 +01:00
|
|
|
relId = RangeVarGetRelid(stmt->relation, AccessExclusiveLock, false);
|
2007-08-27 05:36:08 +02:00
|
|
|
|
|
|
|
/* ... and execute */
|
2012-12-29 13:55:37 +01:00
|
|
|
return DefineQueryRewrite(stmt->rulename,
|
|
|
|
relId,
|
|
|
|
whereClause,
|
|
|
|
stmt->event,
|
|
|
|
stmt->instead,
|
|
|
|
stmt->replace,
|
|
|
|
actions);
|
2007-03-13 01:33:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* DefineQueryRewrite
|
|
|
|
* Create a rule
|
|
|
|
*
|
|
|
|
* This is essentially the same as DefineRule() except that the rule's
|
|
|
|
* action and qual have already been passed through parse analysis.
|
|
|
|
*/
|
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
|
2017-10-31 15:34:31 +01:00
|
|
|
DefineQueryRewrite(const char *rulename,
|
2007-08-27 05:36:08 +02:00
|
|
|
Oid event_relid,
|
2007-03-13 01:33:44 +01:00
|
|
|
Node *event_qual,
|
|
|
|
CmdType event_type,
|
|
|
|
bool is_instead,
|
|
|
|
bool replace,
|
|
|
|
List *action)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-30 09:04:23 +02:00
|
|
|
Relation event_relation;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
1998-08-24 03:38:11 +02:00
|
|
|
Query *query;
|
2000-09-12 06:49:17 +02:00
|
|
|
bool RelisBecomingView = false;
|
2012-12-29 13:55:37 +01:00
|
|
|
Oid ruleId = InvalidOid;
|
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;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-06-30 09:04:23 +02:00
|
|
|
/*
|
|
|
|
* If we are installing an ON SELECT rule, we had better grab
|
|
|
|
* AccessExclusiveLock to ensure no SELECTs are currently running on the
|
2011-07-07 19:14:46 +02:00
|
|
|
* event relation. For other types of rules, it would be sufficient to
|
|
|
|
* grab ShareRowExclusiveLock to lock out insert/update/delete actions and
|
|
|
|
* to ensure that we lock out current CREATE RULE statements; but because
|
|
|
|
* of race conditions in access to catalog entries, we can't do that yet.
|
2011-07-09 04:19:30 +02:00
|
|
|
*
|
|
|
|
* Note that this lock level should match the one used in DefineRule.
|
2000-06-30 09:04:23 +02:00
|
|
|
*/
|
2019-01-21 19:32:19 +01:00
|
|
|
event_relation = table_open(event_relid, AccessExclusiveLock);
|
2000-06-30 09:04:23 +02:00
|
|
|
|
2009-05-14 00:32:55 +02:00
|
|
|
/*
|
|
|
|
* Verify relation is of a type that rules can sensibly be applied to.
|
2013-07-05 21:25:51 +02:00
|
|
|
* Internal callers can target materialized views, but transformRuleStmt()
|
|
|
|
* blocks them for users. Don't mention them in the error message.
|
2009-05-14 00:32:55 +02:00
|
|
|
*/
|
|
|
|
if (event_relation->rd_rel->relkind != RELKIND_RELATION &&
|
2013-03-04 01:23:31 +01:00
|
|
|
event_relation->rd_rel->relkind != RELKIND_MATVIEW &&
|
Implement table partitioning.
Table partitioning is like table inheritance and reuses much of the
existing infrastructure, but there are some important differences.
The parent is called a partitioned table and is always empty; it may
not have indexes or non-inherited constraints, since those make no
sense for a relation with no data of its own. The children are called
partitions and contain all of the actual data. Each partition has an
implicit partitioning constraint. Multiple inheritance is not
allowed, and partitioning and inheritance can't be mixed. Partitions
can't have extra columns and may not allow nulls unless the parent
does. Tuples inserted into the parent are automatically routed to the
correct partition, so tuple-routing ON INSERT triggers are not needed.
Tuple routing isn't yet supported for partitions which are foreign
tables, and it doesn't handle updates that cross partition boundaries.
Currently, tables can be range-partitioned or list-partitioned. List
partitioning is limited to a single column, but range partitioning can
involve multiple columns. A partitioning "column" can be an
expression.
Because table partitioning is less general than table inheritance, it
is hoped that it will be easier to reason about properties of
partitions, and therefore that this will serve as a better foundation
for a variety of possible optimizations, including query planner
optimizations. The tuple routing based which this patch does based on
the implicit partitioning constraints is an example of this, but it
seems likely that many other useful optimizations are also possible.
Amit Langote, reviewed and tested by Robert Haas, Ashutosh Bapat,
Amit Kapila, Rajkumar Raghuwanshi, Corey Huinker, Jaime Casanova,
Rushabh Lathia, Erik Rijkers, among others. Minor revisions by me.
2016-12-07 19:17:43 +01:00
|
|
|
event_relation->rd_rel->relkind != RELKIND_VIEW &&
|
|
|
|
event_relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
|
2009-05-14 00:32:55 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
|
|
errmsg("\"%s\" is not a table or view",
|
|
|
|
RelationGetRelationName(event_relation))));
|
|
|
|
|
|
|
|
if (!allowSystemTableMods && IsSystemRelation(event_relation))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
|
|
|
errmsg("permission denied: \"%s\" is a system catalog",
|
|
|
|
RelationGetRelationName(event_relation))));
|
|
|
|
|
2002-03-22 00:27:25 +01:00
|
|
|
/*
|
|
|
|
* Check user has permission to apply rules to this relation.
|
|
|
|
*/
|
2007-08-27 05:36:08 +02:00
|
|
|
if (!pg_class_ownercheck(event_relid, GetUserId()))
|
2017-12-02 15:26:34 +01:00
|
|
|
aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(event_relation->rd_rel->relkind),
|
2003-08-01 02:15:26 +02:00
|
|
|
RelationGetRelationName(event_relation));
|
2002-03-22 00:27:25 +01:00
|
|
|
|
1998-10-02 18:28:04 +02:00
|
|
|
/*
|
|
|
|
* No rule actions that modify OLD or NEW
|
|
|
|
*/
|
2000-06-30 09:04:23 +02:00
|
|
|
foreach(l, action)
|
1998-08-24 03:38:11 +02:00
|
|
|
{
|
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
|
|
|
query = lfirst_node(Query, l);
|
2000-12-05 20:15:10 +01:00
|
|
|
if (query->resultRelation == 0)
|
|
|
|
continue;
|
|
|
|
/* Don't be fooled by INSERT/SELECT */
|
|
|
|
if (query != getInsertSelectQuery(query, NULL))
|
|
|
|
continue;
|
2000-09-12 22:38:09 +02:00
|
|
|
if (query->resultRelation == PRS2_OLD_VARNO)
|
2003-07-25 02:01:09 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("rule actions on OLD are not implemented"),
|
|
|
|
errhint("Use views or triggers instead.")));
|
2000-09-12 22:38:09 +02:00
|
|
|
if (query->resultRelation == PRS2_NEW_VARNO)
|
2003-07-25 02:01:09 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("rule actions on NEW are not implemented"),
|
|
|
|
errhint("Use triggers instead.")));
|
1998-09-01 06:40:42 +02:00
|
|
|
}
|
1998-08-24 03:38:11 +02:00
|
|
|
|
|
|
|
if (event_type == CMD_SELECT)
|
|
|
|
{
|
1998-10-02 18:28:04 +02:00
|
|
|
/*
|
2006-09-02 19:06:52 +02:00
|
|
|
* Rules ON SELECT are restricted to view definitions
|
|
|
|
*
|
1998-10-02 18:28:04 +02:00
|
|
|
* So there cannot be INSTEAD NOTHING, ...
|
|
|
|
*/
|
2004-05-31 01:40:41 +02:00
|
|
|
if (list_length(action) == 0)
|
2003-07-25 02:01:09 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
2003-09-26 17:27:37 +02:00
|
|
|
errmsg("INSTEAD NOTHING rules on SELECT are not implemented"),
|
2003-07-25 02:01:09 +02:00
|
|
|
errhint("Use views instead.")));
|
1998-10-02 18:28:04 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ... there cannot be multiple actions, ...
|
|
|
|
*/
|
2004-05-31 01:40:41 +02:00
|
|
|
if (list_length(action) > 1)
|
2003-07-25 02:01:09 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
2003-09-29 02:05:25 +02:00
|
|
|
errmsg("multiple actions for rules on SELECT are not implemented")));
|
1999-05-25 18:15:34 +02:00
|
|
|
|
1998-10-02 18:28:04 +02:00
|
|
|
/*
|
|
|
|
* ... the one action must be a SELECT, ...
|
|
|
|
*/
|
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
|
|
|
query = linitial_node(Query, action);
|
2006-08-12 22:05:56 +02:00
|
|
|
if (!is_instead ||
|
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
|
|
|
query->commandType != CMD_SELECT)
|
2003-07-25 02:01:09 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
2003-09-26 17:27:37 +02:00
|
|
|
errmsg("rules on SELECT must have action INSTEAD SELECT")));
|
2000-09-29 20:21:41 +02:00
|
|
|
|
2011-02-26 00:56:23 +01:00
|
|
|
/*
|
|
|
|
* ... it cannot contain data-modifying WITH ...
|
|
|
|
*/
|
|
|
|
if (query->hasModifyingCTE)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("rules on SELECT must not contain data-modifying statements in WITH")));
|
|
|
|
|
2000-09-29 20:21:41 +02:00
|
|
|
/*
|
|
|
|
* ... there can be no rule qual, ...
|
|
|
|
*/
|
1998-10-02 18:28:04 +02:00
|
|
|
if (event_qual != NULL)
|
2003-07-25 02:01:09 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
2003-09-25 08:58:07 +02:00
|
|
|
errmsg("event qualifications are not implemented for rules on SELECT")));
|
1998-10-02 18:28:04 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ... the targetlist of the SELECT action must exactly match the
|
1998-10-07 00:14:21 +02:00
|
|
|
* event relation, ...
|
1998-10-02 18:28:04 +02:00
|
|
|
*/
|
2006-09-02 19:06:52 +02:00
|
|
|
checkRuleResultList(query->targetList,
|
|
|
|
RelationGetDescr(event_relation),
|
2013-11-04 21:31:07 +01:00
|
|
|
true,
|
|
|
|
event_relation->rd_rel->relkind !=
|
|
|
|
RELKIND_MATVIEW);
|
2000-09-29 20:21:41 +02:00
|
|
|
|
1998-10-02 18:28:04 +02:00
|
|
|
/*
|
1998-10-07 00:14:21 +02:00
|
|
|
* ... there must not be another ON SELECT rule already ...
|
1998-10-02 18:28:04 +02:00
|
|
|
*/
|
2002-09-02 04:13:02 +02:00
|
|
|
if (!replace && event_relation->rd_rules != NULL)
|
1998-10-02 18:28:04 +02:00
|
|
|
{
|
2006-09-02 19:06:52 +02:00
|
|
|
int i;
|
|
|
|
|
1998-10-02 18:28:04 +02:00
|
|
|
for (i = 0; i < event_relation->rd_rules->numLocks; i++)
|
|
|
|
{
|
|
|
|
RewriteRule *rule;
|
|
|
|
|
|
|
|
rule = event_relation->rd_rules->rules[i];
|
|
|
|
if (rule->event == CMD_SELECT)
|
2003-07-25 02:01:09 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
|
|
|
errmsg("\"%s\" is already a view",
|
|
|
|
RelationGetRelationName(event_relation))));
|
1998-10-02 18:28:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-10-07 00:14:21 +02:00
|
|
|
/*
|
2002-04-20 01:13:54 +02:00
|
|
|
* ... and finally the rule must be named _RETURN.
|
1998-10-07 00:14:21 +02:00
|
|
|
*/
|
2007-03-13 01:33:44 +01:00
|
|
|
if (strcmp(rulename, ViewSelectRuleName) != 0)
|
1998-10-07 00:14:21 +02:00
|
|
|
{
|
2002-04-20 01:13:54 +02:00
|
|
|
/*
|
|
|
|
* In versions before 7.3, the expected name was _RETviewname. For
|
|
|
|
* backwards compatibility with old pg_dump output, accept that
|
|
|
|
* and silently change it to _RETURN. Since this is just a quick
|
|
|
|
* backwards-compatibility hack, limit the number of characters
|
|
|
|
* checked to a few less than NAMEDATALEN; this saves having to
|
|
|
|
* worry about where a multibyte character might have gotten
|
|
|
|
* truncated.
|
|
|
|
*/
|
2007-03-13 01:33:44 +01:00
|
|
|
if (strncmp(rulename, "_RET", 4) != 0 ||
|
2007-08-27 05:36:08 +02:00
|
|
|
strncmp(rulename + 4, RelationGetRelationName(event_relation),
|
2002-04-20 01:13:54 +02:00
|
|
|
NAMEDATALEN - 4 - 4) != 0)
|
2003-07-25 02:01:09 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
|
|
|
errmsg("view rule for \"%s\" must be named \"%s\"",
|
2007-08-27 05:36:08 +02:00
|
|
|
RelationGetRelationName(event_relation),
|
|
|
|
ViewSelectRuleName)));
|
2007-03-13 01:33:44 +01:00
|
|
|
rulename = pstrdup(ViewSelectRuleName);
|
1998-10-07 00:14:21 +02:00
|
|
|
}
|
2000-09-12 22:38:09 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Are we converting a relation to a view?
|
|
|
|
*
|
|
|
|
* If so, check that the relation is empty because the storage for the
|
Disallow converting an inheritance child table to a view.
Generally, members of inheritance trees must be plain tables (or,
in more recent versions, foreign tables). ALTER TABLE INHERIT
rejects creating an inheritance relationship that has a view at
either end. When DefineQueryRewrite attempts to convert a relation
to a view, it already had checks prohibiting doing so for partitioning
parents or children as well as traditional-inheritance parents ...
but it neglected to check that a traditional-inheritance child wasn't
being converted. Since the planner assumes that any inheritance
child is a table, this led to making plans that tried to do a physical
scan on a view, causing failures (or even crashes, in recent versions).
One could imagine trying to support such a case by expanding the view
normally, but since the rewriter runs before the planner does
inheritance expansion, it would take some very fundamental refactoring
to make that possible. There are probably a lot of other parts of the
system that don't cope well with such a situation, too. For now,
just forbid it.
Per bug #16856 from Yang Lin. Back-patch to all supported branches.
(In versions before v10, this includes back-patching the portion of
commit 501ed02cf that added has_superclass(). Perhaps the lack of
that infrastructure partially explains the missing check.)
Discussion: https://postgr.es/m/16856-0363e05c6e1612fd@postgresql.org
2021-02-06 21:17:01 +01:00
|
|
|
* relation is going to be deleted. Also insist that the rel not be
|
|
|
|
* involved in partitioning, nor have any triggers, indexes, child or
|
|
|
|
* parent tables, RLS policies, or RLS enabled. (Note: some of these
|
|
|
|
* tests are too strict, because they will reject relations that once
|
|
|
|
* had such but don't anymore. But we don't really care, because this
|
|
|
|
* whole business of converting relations to views is just an obsolete
|
|
|
|
* kluge to allow dump/reload of views that participate in circular
|
|
|
|
* dependencies.)
|
Disallow converting a table to a view within an outer SQL command.
We have long disallowed all forms of ALTER TABLE if the table is
already opened by some outer SQL command in the same session.
This has the same purpose as obtaining AccessExclusiveLock, but
since a session's own locks don't conflict the lock only blocks use
of the table by other sessions, not our own. Without this check,
the ALTER might confuse the outer SQL command since any previous
inspection of the table would potentially become invalid.
However, the RelisBecomingView code path in DefineQueryRewrite never
got that memo, and assumed that AccessExclusiveLock is sufficient
for performing something morally equivalent to a rather invasive
ALTER TABLE. Unsurprisingly, this can confuse an outer command
that is trying to do something with the table.
This was submitted as a security issue, but the security team
has been unable to identify any consequence worse than a null
pointer dereference (from trying to access rd_tableam methods
that the relation no longer has). Therefore, in accordance
with our usual policy, it's not security material and should
just be fixed as a routine bug.
Fix by disallowing the operation if the table is open locally,
exactly as ALTER TABLE does it.
Per an anonymous security researcher, via Bundesamt für Sicherheit
in der Informationstechnik.
Patch v12-v15 only. In v16 and later, we removed this code
altogether (cf. commit b23cd185f), so that there's no issue.
2024-04-30 21:22:55 +02:00
|
|
|
*
|
|
|
|
* Also ensure the relation isn't being manipulated in any outer SQL
|
|
|
|
* command of our own session.
|
2000-09-12 22:38:09 +02:00
|
|
|
*/
|
2013-03-04 01:23:31 +01:00
|
|
|
if (event_relation->rd_rel->relkind != RELKIND_VIEW &&
|
|
|
|
event_relation->rd_rel->relkind != RELKIND_MATVIEW)
|
2000-09-12 22:38:09 +02:00
|
|
|
{
|
tableam: Add and use scan APIs.
Too allow table accesses to be not directly dependent on heap, several
new abstractions are needed. Specifically:
1) Heap scans need to be generalized into table scans. Do this by
introducing TableScanDesc, which will be the "base class" for
individual AMs. This contains the AM independent fields from
HeapScanDesc.
The previous heap_{beginscan,rescan,endscan} et al. have been
replaced with a table_ version.
There's no direct replacement for heap_getnext(), as that returned
a HeapTuple, which is undesirable for a other AMs. Instead there's
table_scan_getnextslot(). But note that heap_getnext() lives on,
it's still used widely to access catalog tables.
This is achieved by new scan_begin, scan_end, scan_rescan,
scan_getnextslot callbacks.
2) The portion of parallel scans that's shared between backends need
to be able to do so without the user doing per-AM work. To achieve
that new parallelscan_{estimate, initialize, reinitialize}
callbacks are introduced, which operate on a new
ParallelTableScanDesc, which again can be subclassed by AMs.
As it is likely that several AMs are going to be block oriented,
block oriented callbacks that can be shared between such AMs are
provided and used by heap. table_block_parallelscan_{estimate,
intiialize, reinitialize} as callbacks, and
table_block_parallelscan_{nextpage, init} for use in AMs. These
operate on a ParallelBlockTableScanDesc.
3) Index scans need to be able to access tables to return a tuple, and
there needs to be state across individual accesses to the heap to
store state like buffers. That's now handled by introducing a
sort-of-scan IndexFetchTable, which again is intended to be
subclassed by individual AMs (for heap IndexFetchHeap).
The relevant callbacks for an AM are index_fetch_{end, begin,
reset} to create the necessary state, and index_fetch_tuple to
retrieve an indexed tuple. Note that index_fetch_tuple
implementations need to be smarter than just blindly fetching the
tuples for AMs that have optimizations similar to heap's HOT - the
currently alive tuple in the update chain needs to be fetched if
appropriate.
Similar to table_scan_getnextslot(), it's undesirable to continue
to return HeapTuples. Thus index_fetch_heap (might want to rename
that later) now accepts a slot as an argument. Core code doesn't
have a lot of call sites performing index scans without going
through the systable_* API (in contrast to loads of heap_getnext
calls and working directly with HeapTuples).
Index scans now store the result of a search in
IndexScanDesc->xs_heaptid, rather than xs_ctup->t_self. As the
target is not generally a HeapTuple anymore that seems cleaner.
To be able to sensible adapt code to use the above, two further
callbacks have been introduced:
a) slot_callbacks returns a TupleTableSlotOps* suitable for creating
slots capable of holding a tuple of the AMs
type. table_slot_callbacks() and table_slot_create() are based
upon that, but have additional logic to deal with views, foreign
tables, etc.
While this change could have been done separately, nearly all the
call sites that needed to be adapted for the rest of this commit
also would have been needed to be adapted for
table_slot_callbacks(), making separation not worthwhile.
b) tuple_satisfies_snapshot checks whether the tuple in a slot is
currently visible according to a snapshot. That's required as a few
places now don't have a buffer + HeapTuple around, but a
slot (which in heap's case internally has that information).
Additionally a few infrastructure changes were needed:
I) SysScanDesc, as used by systable_{beginscan, getnext} et al. now
internally uses a slot to keep track of tuples. While
systable_getnext() still returns HeapTuples, and will so for the
foreseeable future, the index API (see 1) above) now only deals with
slots.
The remainder, and largest part, of this commit is then adjusting all
scans in postgres to use the new APIs.
Author: Andres Freund, Haribabu Kommi, Alvaro Herrera
Discussion:
https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de
https://postgr.es/m/20160812231527.GA690404@alvherre.pgsql
2019-03-11 20:46:41 +01:00
|
|
|
TableScanDesc scanDesc;
|
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
|
|
|
Snapshot snapshot;
|
tableam: Add and use scan APIs.
Too allow table accesses to be not directly dependent on heap, several
new abstractions are needed. Specifically:
1) Heap scans need to be generalized into table scans. Do this by
introducing TableScanDesc, which will be the "base class" for
individual AMs. This contains the AM independent fields from
HeapScanDesc.
The previous heap_{beginscan,rescan,endscan} et al. have been
replaced with a table_ version.
There's no direct replacement for heap_getnext(), as that returned
a HeapTuple, which is undesirable for a other AMs. Instead there's
table_scan_getnextslot(). But note that heap_getnext() lives on,
it's still used widely to access catalog tables.
This is achieved by new scan_begin, scan_end, scan_rescan,
scan_getnextslot callbacks.
2) The portion of parallel scans that's shared between backends need
to be able to do so without the user doing per-AM work. To achieve
that new parallelscan_{estimate, initialize, reinitialize}
callbacks are introduced, which operate on a new
ParallelTableScanDesc, which again can be subclassed by AMs.
As it is likely that several AMs are going to be block oriented,
block oriented callbacks that can be shared between such AMs are
provided and used by heap. table_block_parallelscan_{estimate,
intiialize, reinitialize} as callbacks, and
table_block_parallelscan_{nextpage, init} for use in AMs. These
operate on a ParallelBlockTableScanDesc.
3) Index scans need to be able to access tables to return a tuple, and
there needs to be state across individual accesses to the heap to
store state like buffers. That's now handled by introducing a
sort-of-scan IndexFetchTable, which again is intended to be
subclassed by individual AMs (for heap IndexFetchHeap).
The relevant callbacks for an AM are index_fetch_{end, begin,
reset} to create the necessary state, and index_fetch_tuple to
retrieve an indexed tuple. Note that index_fetch_tuple
implementations need to be smarter than just blindly fetching the
tuples for AMs that have optimizations similar to heap's HOT - the
currently alive tuple in the update chain needs to be fetched if
appropriate.
Similar to table_scan_getnextslot(), it's undesirable to continue
to return HeapTuples. Thus index_fetch_heap (might want to rename
that later) now accepts a slot as an argument. Core code doesn't
have a lot of call sites performing index scans without going
through the systable_* API (in contrast to loads of heap_getnext
calls and working directly with HeapTuples).
Index scans now store the result of a search in
IndexScanDesc->xs_heaptid, rather than xs_ctup->t_self. As the
target is not generally a HeapTuple anymore that seems cleaner.
To be able to sensible adapt code to use the above, two further
callbacks have been introduced:
a) slot_callbacks returns a TupleTableSlotOps* suitable for creating
slots capable of holding a tuple of the AMs
type. table_slot_callbacks() and table_slot_create() are based
upon that, but have additional logic to deal with views, foreign
tables, etc.
While this change could have been done separately, nearly all the
call sites that needed to be adapted for the rest of this commit
also would have been needed to be adapted for
table_slot_callbacks(), making separation not worthwhile.
b) tuple_satisfies_snapshot checks whether the tuple in a slot is
currently visible according to a snapshot. That's required as a few
places now don't have a buffer + HeapTuple around, but a
slot (which in heap's case internally has that information).
Additionally a few infrastructure changes were needed:
I) SysScanDesc, as used by systable_{beginscan, getnext} et al. now
internally uses a slot to keep track of tuples. While
systable_getnext() still returns HeapTuples, and will so for the
foreseeable future, the index API (see 1) above) now only deals with
slots.
The remainder, and largest part, of this commit is then adjusting all
scans in postgres to use the new APIs.
Author: Andres Freund, Haribabu Kommi, Alvaro Herrera
Discussion:
https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de
https://postgr.es/m/20160812231527.GA690404@alvherre.pgsql
2019-03-11 20:46:41 +01:00
|
|
|
TupleTableSlot *slot;
|
2000-09-12 22:38:09 +02:00
|
|
|
|
Disallow converting a table to a view within an outer SQL command.
We have long disallowed all forms of ALTER TABLE if the table is
already opened by some outer SQL command in the same session.
This has the same purpose as obtaining AccessExclusiveLock, but
since a session's own locks don't conflict the lock only blocks use
of the table by other sessions, not our own. Without this check,
the ALTER might confuse the outer SQL command since any previous
inspection of the table would potentially become invalid.
However, the RelisBecomingView code path in DefineQueryRewrite never
got that memo, and assumed that AccessExclusiveLock is sufficient
for performing something morally equivalent to a rather invasive
ALTER TABLE. Unsurprisingly, this can confuse an outer command
that is trying to do something with the table.
This was submitted as a security issue, but the security team
has been unable to identify any consequence worse than a null
pointer dereference (from trying to access rd_tableam methods
that the relation no longer has). Therefore, in accordance
with our usual policy, it's not security material and should
just be fixed as a routine bug.
Fix by disallowing the operation if the table is open locally,
exactly as ALTER TABLE does it.
Per an anonymous security researcher, via Bundesamt für Sicherheit
in der Informationstechnik.
Patch v12-v15 only. In v16 and later, we removed this code
altogether (cf. commit b23cd185f), so that there's no issue.
2024-04-30 21:22:55 +02:00
|
|
|
CheckTableNotInUse(event_relation, "CREATE RULE");
|
|
|
|
|
2017-04-12 17:13:44 +02:00
|
|
|
if (event_relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
2017-09-11 17:20:47 +02:00
|
|
|
errmsg("cannot convert partitioned table \"%s\" to a view",
|
2017-04-12 17:13:44 +02:00
|
|
|
RelationGetRelationName(event_relation))));
|
|
|
|
|
Disallow converting an inheritance child table to a view.
Generally, members of inheritance trees must be plain tables (or,
in more recent versions, foreign tables). ALTER TABLE INHERIT
rejects creating an inheritance relationship that has a view at
either end. When DefineQueryRewrite attempts to convert a relation
to a view, it already had checks prohibiting doing so for partitioning
parents or children as well as traditional-inheritance parents ...
but it neglected to check that a traditional-inheritance child wasn't
being converted. Since the planner assumes that any inheritance
child is a table, this led to making plans that tried to do a physical
scan on a view, causing failures (or even crashes, in recent versions).
One could imagine trying to support such a case by expanding the view
normally, but since the rewriter runs before the planner does
inheritance expansion, it would take some very fundamental refactoring
to make that possible. There are probably a lot of other parts of the
system that don't cope well with such a situation, too. For now,
just forbid it.
Per bug #16856 from Yang Lin. Back-patch to all supported branches.
(In versions before v10, this includes back-patching the portion of
commit 501ed02cf that added has_superclass(). Perhaps the lack of
that infrastructure partially explains the missing check.)
Discussion: https://postgr.es/m/16856-0363e05c6e1612fd@postgresql.org
2021-02-06 21:17:01 +01:00
|
|
|
/* only case left: */
|
|
|
|
Assert(event_relation->rd_rel->relkind == RELKIND_RELATION);
|
|
|
|
|
2017-06-21 11:43:17 +02:00
|
|
|
if (event_relation->rd_rel->relispartition)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
2017-09-11 17:20:47 +02:00
|
|
|
errmsg("cannot convert partition \"%s\" to a view",
|
2017-06-21 11:43:17 +02:00
|
|
|
RelationGetRelationName(event_relation))));
|
|
|
|
|
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
|
|
|
snapshot = RegisterSnapshot(GetLatestSnapshot());
|
tableam: Add and use scan APIs.
Too allow table accesses to be not directly dependent on heap, several
new abstractions are needed. Specifically:
1) Heap scans need to be generalized into table scans. Do this by
introducing TableScanDesc, which will be the "base class" for
individual AMs. This contains the AM independent fields from
HeapScanDesc.
The previous heap_{beginscan,rescan,endscan} et al. have been
replaced with a table_ version.
There's no direct replacement for heap_getnext(), as that returned
a HeapTuple, which is undesirable for a other AMs. Instead there's
table_scan_getnextslot(). But note that heap_getnext() lives on,
it's still used widely to access catalog tables.
This is achieved by new scan_begin, scan_end, scan_rescan,
scan_getnextslot callbacks.
2) The portion of parallel scans that's shared between backends need
to be able to do so without the user doing per-AM work. To achieve
that new parallelscan_{estimate, initialize, reinitialize}
callbacks are introduced, which operate on a new
ParallelTableScanDesc, which again can be subclassed by AMs.
As it is likely that several AMs are going to be block oriented,
block oriented callbacks that can be shared between such AMs are
provided and used by heap. table_block_parallelscan_{estimate,
intiialize, reinitialize} as callbacks, and
table_block_parallelscan_{nextpage, init} for use in AMs. These
operate on a ParallelBlockTableScanDesc.
3) Index scans need to be able to access tables to return a tuple, and
there needs to be state across individual accesses to the heap to
store state like buffers. That's now handled by introducing a
sort-of-scan IndexFetchTable, which again is intended to be
subclassed by individual AMs (for heap IndexFetchHeap).
The relevant callbacks for an AM are index_fetch_{end, begin,
reset} to create the necessary state, and index_fetch_tuple to
retrieve an indexed tuple. Note that index_fetch_tuple
implementations need to be smarter than just blindly fetching the
tuples for AMs that have optimizations similar to heap's HOT - the
currently alive tuple in the update chain needs to be fetched if
appropriate.
Similar to table_scan_getnextslot(), it's undesirable to continue
to return HeapTuples. Thus index_fetch_heap (might want to rename
that later) now accepts a slot as an argument. Core code doesn't
have a lot of call sites performing index scans without going
through the systable_* API (in contrast to loads of heap_getnext
calls and working directly with HeapTuples).
Index scans now store the result of a search in
IndexScanDesc->xs_heaptid, rather than xs_ctup->t_self. As the
target is not generally a HeapTuple anymore that seems cleaner.
To be able to sensible adapt code to use the above, two further
callbacks have been introduced:
a) slot_callbacks returns a TupleTableSlotOps* suitable for creating
slots capable of holding a tuple of the AMs
type. table_slot_callbacks() and table_slot_create() are based
upon that, but have additional logic to deal with views, foreign
tables, etc.
While this change could have been done separately, nearly all the
call sites that needed to be adapted for the rest of this commit
also would have been needed to be adapted for
table_slot_callbacks(), making separation not worthwhile.
b) tuple_satisfies_snapshot checks whether the tuple in a slot is
currently visible according to a snapshot. That's required as a few
places now don't have a buffer + HeapTuple around, but a
slot (which in heap's case internally has that information).
Additionally a few infrastructure changes were needed:
I) SysScanDesc, as used by systable_{beginscan, getnext} et al. now
internally uses a slot to keep track of tuples. While
systable_getnext() still returns HeapTuples, and will so for the
foreseeable future, the index API (see 1) above) now only deals with
slots.
The remainder, and largest part, of this commit is then adjusting all
scans in postgres to use the new APIs.
Author: Andres Freund, Haribabu Kommi, Alvaro Herrera
Discussion:
https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de
https://postgr.es/m/20160812231527.GA690404@alvherre.pgsql
2019-03-11 20:46:41 +01:00
|
|
|
scanDesc = table_beginscan(event_relation, snapshot, 0, NULL);
|
|
|
|
slot = table_slot_create(event_relation, NULL);
|
|
|
|
if (table_scan_getnextslot(scanDesc, ForwardScanDirection, slot))
|
2003-07-25 02:01:09 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
2003-09-17 19:19:17 +02:00
|
|
|
errmsg("could not convert table \"%s\" to a view because it is not empty",
|
2007-08-27 05:36:08 +02:00
|
|
|
RelationGetRelationName(event_relation))));
|
tableam: Add and use scan APIs.
Too allow table accesses to be not directly dependent on heap, several
new abstractions are needed. Specifically:
1) Heap scans need to be generalized into table scans. Do this by
introducing TableScanDesc, which will be the "base class" for
individual AMs. This contains the AM independent fields from
HeapScanDesc.
The previous heap_{beginscan,rescan,endscan} et al. have been
replaced with a table_ version.
There's no direct replacement for heap_getnext(), as that returned
a HeapTuple, which is undesirable for a other AMs. Instead there's
table_scan_getnextslot(). But note that heap_getnext() lives on,
it's still used widely to access catalog tables.
This is achieved by new scan_begin, scan_end, scan_rescan,
scan_getnextslot callbacks.
2) The portion of parallel scans that's shared between backends need
to be able to do so without the user doing per-AM work. To achieve
that new parallelscan_{estimate, initialize, reinitialize}
callbacks are introduced, which operate on a new
ParallelTableScanDesc, which again can be subclassed by AMs.
As it is likely that several AMs are going to be block oriented,
block oriented callbacks that can be shared between such AMs are
provided and used by heap. table_block_parallelscan_{estimate,
intiialize, reinitialize} as callbacks, and
table_block_parallelscan_{nextpage, init} for use in AMs. These
operate on a ParallelBlockTableScanDesc.
3) Index scans need to be able to access tables to return a tuple, and
there needs to be state across individual accesses to the heap to
store state like buffers. That's now handled by introducing a
sort-of-scan IndexFetchTable, which again is intended to be
subclassed by individual AMs (for heap IndexFetchHeap).
The relevant callbacks for an AM are index_fetch_{end, begin,
reset} to create the necessary state, and index_fetch_tuple to
retrieve an indexed tuple. Note that index_fetch_tuple
implementations need to be smarter than just blindly fetching the
tuples for AMs that have optimizations similar to heap's HOT - the
currently alive tuple in the update chain needs to be fetched if
appropriate.
Similar to table_scan_getnextslot(), it's undesirable to continue
to return HeapTuples. Thus index_fetch_heap (might want to rename
that later) now accepts a slot as an argument. Core code doesn't
have a lot of call sites performing index scans without going
through the systable_* API (in contrast to loads of heap_getnext
calls and working directly with HeapTuples).
Index scans now store the result of a search in
IndexScanDesc->xs_heaptid, rather than xs_ctup->t_self. As the
target is not generally a HeapTuple anymore that seems cleaner.
To be able to sensible adapt code to use the above, two further
callbacks have been introduced:
a) slot_callbacks returns a TupleTableSlotOps* suitable for creating
slots capable of holding a tuple of the AMs
type. table_slot_callbacks() and table_slot_create() are based
upon that, but have additional logic to deal with views, foreign
tables, etc.
While this change could have been done separately, nearly all the
call sites that needed to be adapted for the rest of this commit
also would have been needed to be adapted for
table_slot_callbacks(), making separation not worthwhile.
b) tuple_satisfies_snapshot checks whether the tuple in a slot is
currently visible according to a snapshot. That's required as a few
places now don't have a buffer + HeapTuple around, but a
slot (which in heap's case internally has that information).
Additionally a few infrastructure changes were needed:
I) SysScanDesc, as used by systable_{beginscan, getnext} et al. now
internally uses a slot to keep track of tuples. While
systable_getnext() still returns HeapTuples, and will so for the
foreseeable future, the index API (see 1) above) now only deals with
slots.
The remainder, and largest part, of this commit is then adjusting all
scans in postgres to use the new APIs.
Author: Andres Freund, Haribabu Kommi, Alvaro Herrera
Discussion:
https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de
https://postgr.es/m/20160812231527.GA690404@alvherre.pgsql
2019-03-11 20:46:41 +01:00
|
|
|
ExecDropSingleTupleTableSlot(slot);
|
|
|
|
table_endscan(scanDesc);
|
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
|
|
|
UnregisterSnapshot(snapshot);
|
2000-09-12 22:38:09 +02:00
|
|
|
|
2008-11-09 22:24:33 +01:00
|
|
|
if (event_relation->rd_rel->relhastriggers)
|
2003-09-17 19:19:17 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
|
|
|
errmsg("could not convert table \"%s\" to a view because it has triggers",
|
2007-08-27 05:36:08 +02:00
|
|
|
RelationGetRelationName(event_relation)),
|
Wording cleanup for error messages. Also change can't -> cannot.
Standard English uses "may", "can", and "might" in different ways:
may - permission, "You may borrow my rake."
can - ability, "I can lift that log."
might - possibility, "It might rain today."
Unfortunately, in conversational English, their use is often mixed, as
in, "You may use this variable to do X", when in fact, "can" is a better
choice. Similarly, "It may crash" is better stated, "It might crash".
2007-02-01 20:10:30 +01:00
|
|
|
errhint("In particular, the table cannot be involved in any foreign key relationships.")));
|
2003-09-17 19:19:17 +02:00
|
|
|
|
|
|
|
if (event_relation->rd_rel->relhasindex)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
|
|
|
errmsg("could not convert table \"%s\" to a view because it has indexes",
|
2007-08-27 05:36:08 +02:00
|
|
|
RelationGetRelationName(event_relation))));
|
2003-09-17 19:19:17 +02:00
|
|
|
|
|
|
|
if (event_relation->rd_rel->relhassubclass)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
|
|
|
errmsg("could not convert table \"%s\" to a view because it has child tables",
|
2007-08-27 05:36:08 +02:00
|
|
|
RelationGetRelationName(event_relation))));
|
2003-09-17 19:19:17 +02:00
|
|
|
|
Disallow converting an inheritance child table to a view.
Generally, members of inheritance trees must be plain tables (or,
in more recent versions, foreign tables). ALTER TABLE INHERIT
rejects creating an inheritance relationship that has a view at
either end. When DefineQueryRewrite attempts to convert a relation
to a view, it already had checks prohibiting doing so for partitioning
parents or children as well as traditional-inheritance parents ...
but it neglected to check that a traditional-inheritance child wasn't
being converted. Since the planner assumes that any inheritance
child is a table, this led to making plans that tried to do a physical
scan on a view, causing failures (or even crashes, in recent versions).
One could imagine trying to support such a case by expanding the view
normally, but since the rewriter runs before the planner does
inheritance expansion, it would take some very fundamental refactoring
to make that possible. There are probably a lot of other parts of the
system that don't cope well with such a situation, too. For now,
just forbid it.
Per bug #16856 from Yang Lin. Back-patch to all supported branches.
(In versions before v10, this includes back-patching the portion of
commit 501ed02cf that added has_superclass(). Perhaps the lack of
that infrastructure partially explains the missing check.)
Discussion: https://postgr.es/m/16856-0363e05c6e1612fd@postgresql.org
2021-02-06 21:17:01 +01:00
|
|
|
if (has_superclass(RelationGetRelid(event_relation)))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
|
|
|
errmsg("could not convert table \"%s\" to a view because it has parent tables",
|
|
|
|
RelationGetRelationName(event_relation))));
|
|
|
|
|
2015-07-29 01:24:01 +02:00
|
|
|
if (event_relation->rd_rel->relrowsecurity)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
|
|
|
errmsg("could not convert table \"%s\" to a view because it has row security enabled",
|
|
|
|
RelationGetRelationName(event_relation))));
|
|
|
|
|
|
|
|
if (relation_has_policies(event_relation))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
|
|
|
errmsg("could not convert table \"%s\" to a view because it has row security policies",
|
|
|
|
RelationGetRelationName(event_relation))));
|
|
|
|
|
2000-09-12 22:38:09 +02:00
|
|
|
RelisBecomingView = true;
|
|
|
|
}
|
1998-08-24 03:38:11 +02:00
|
|
|
}
|
2006-09-02 19:06:52 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* For non-SELECT rules, a RETURNING list can appear in at most one of
|
|
|
|
* the actions ... and there can't be any RETURNING list at all in a
|
|
|
|
* conditional or non-INSTEAD rule. (Actually, there can be at most
|
|
|
|
* one RETURNING list across all rules on the same event, but it seems
|
|
|
|
* best to enforce that at rule expansion time.) If there is a
|
|
|
|
* RETURNING list, it must match the event relation.
|
|
|
|
*/
|
|
|
|
bool haveReturning = false;
|
|
|
|
|
|
|
|
foreach(l, action)
|
|
|
|
{
|
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
|
|
|
query = lfirst_node(Query, l);
|
2006-09-02 19:06:52 +02:00
|
|
|
|
|
|
|
if (!query->returningList)
|
|
|
|
continue;
|
|
|
|
if (haveReturning)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("cannot have multiple RETURNING lists in a rule")));
|
|
|
|
haveReturning = true;
|
|
|
|
if (event_qual != NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("RETURNING lists are not supported in conditional rules")));
|
|
|
|
if (!is_instead)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("RETURNING lists are not supported in non-INSTEAD rules")));
|
|
|
|
checkRuleResultList(query->returningList,
|
|
|
|
RelationGetDescr(event_relation),
|
2013-11-04 21:31:07 +01:00
|
|
|
false, false);
|
2006-09-02 19:06:52 +02:00
|
|
|
}
|
2022-10-17 18:14:39 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* And finally, if it's not an ON SELECT rule then it must *not* be
|
|
|
|
* named _RETURN. This prevents accidentally or maliciously replacing
|
|
|
|
* a view's ON SELECT rule with some other kind of rule.
|
|
|
|
*/
|
|
|
|
if (strcmp(rulename, ViewSelectRuleName) == 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
|
|
|
errmsg("non-view rule for \"%s\" must not be named \"%s\"",
|
|
|
|
RelationGetRelationName(event_relation),
|
|
|
|
ViewSelectRuleName)));
|
2006-09-02 19:06:52 +02:00
|
|
|
}
|
1998-09-01 06:40:42 +02:00
|
|
|
|
1998-08-24 03:38:11 +02:00
|
|
|
/*
|
2000-09-29 20:21:41 +02:00
|
|
|
* This rule is allowed - prepare to install it.
|
1998-08-24 03:38:11 +02:00
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-06-30 09:04:23 +02:00
|
|
|
/* discard rule if it's null action and not INSTEAD; it's a no-op */
|
2000-09-12 22:38:09 +02:00
|
|
|
if (action != NIL || is_instead)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2012-12-29 13:55:37 +01:00
|
|
|
ruleId = InsertRule(rulename,
|
|
|
|
event_type,
|
|
|
|
event_relid,
|
|
|
|
is_instead,
|
|
|
|
event_qual,
|
|
|
|
action,
|
|
|
|
replace);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-06-30 09:04:23 +02:00
|
|
|
/*
|
2017-08-16 06:22:32 +02:00
|
|
|
* Set pg_class 'relhasrules' field true for event relation.
|
2000-06-30 09:04:23 +02:00
|
|
|
*
|
|
|
|
* Important side effect: an SI notice is broadcast to force all
|
|
|
|
* backends (including me!) to update relcache entries with the new
|
|
|
|
* rule.
|
2000-09-12 06:49:17 +02:00
|
|
|
*/
|
2013-03-04 01:05:47 +01:00
|
|
|
SetRelationRuleStatus(event_relid, true);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
2000-06-30 09:04:23 +02:00
|
|
|
|
2013-03-04 01:05:47 +01:00
|
|
|
/* ---------------------------------------------------------------------
|
|
|
|
* If the relation is becoming a view:
|
|
|
|
* - delete the associated storage files
|
|
|
|
* - get rid of any system attributes in pg_attribute; a view shouldn't
|
|
|
|
* have any of those
|
|
|
|
* - remove the toast table; there is no need for it anymore, and its
|
|
|
|
* presence would make vacuum slightly more complicated
|
|
|
|
* - set relkind to RELKIND_VIEW, and adjust other pg_class fields
|
|
|
|
* to be appropriate for a view
|
2012-10-24 19:39:37 +02:00
|
|
|
*
|
|
|
|
* NB: we had better have AccessExclusiveLock to do this ...
|
2013-03-04 01:05:47 +01:00
|
|
|
* ---------------------------------------------------------------------
|
2000-09-12 06:49:17 +02:00
|
|
|
*/
|
|
|
|
if (RelisBecomingView)
|
2012-10-24 19:39:37 +02:00
|
|
|
{
|
2013-03-04 01:05:47 +01:00
|
|
|
Relation relationRelation;
|
|
|
|
Oid toastrelid;
|
|
|
|
HeapTuple classTup;
|
|
|
|
Form_pg_class classForm;
|
|
|
|
|
2019-01-21 19:32:19 +01:00
|
|
|
relationRelation = table_open(RelationRelationId, RowExclusiveLock);
|
2013-03-04 01:05:47 +01:00
|
|
|
toastrelid = event_relation->rd_rel->reltoastrelid;
|
|
|
|
|
|
|
|
/* drop storage while table still looks like a table */
|
2008-11-19 11:34:52 +01:00
|
|
|
RelationDropStorage(event_relation);
|
2012-10-24 19:39:37 +02:00
|
|
|
DeleteSystemAttributeTuples(event_relid);
|
2013-03-04 01:05:47 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Drop the toast table if any. (This won't take care of updating the
|
|
|
|
* toast fields in the relation's own pg_class entry; we handle that
|
|
|
|
* below.)
|
|
|
|
*/
|
|
|
|
if (OidIsValid(toastrelid))
|
|
|
|
{
|
|
|
|
ObjectAddress toastobject;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Delete the dependency of the toast relation on the main
|
|
|
|
* relation so we can drop the former without dropping the latter.
|
|
|
|
*/
|
|
|
|
deleteDependencyRecordsFor(RelationRelationId, toastrelid,
|
|
|
|
false);
|
|
|
|
|
|
|
|
/* Make deletion of dependency record visible */
|
|
|
|
CommandCounterIncrement();
|
|
|
|
|
|
|
|
/* Now drop toast table, including its index */
|
|
|
|
toastobject.classId = RelationRelationId;
|
|
|
|
toastobject.objectId = toastrelid;
|
|
|
|
toastobject.objectSubId = 0;
|
|
|
|
performDeletion(&toastobject, DROP_RESTRICT,
|
|
|
|
PERFORM_DELETION_INTERNAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SetRelationRuleStatus may have updated the pg_class row, so we must
|
|
|
|
* advance the command counter before trying to update it again.
|
|
|
|
*/
|
|
|
|
CommandCounterIncrement();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Fix pg_class entry to look like a normal view's, including setting
|
2013-07-03 20:24:09 +02:00
|
|
|
* the correct relkind and removal of reltoastrelid of the toast table
|
|
|
|
* we potentially removed above.
|
2013-03-04 01:05:47 +01:00
|
|
|
*/
|
|
|
|
classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(event_relid));
|
|
|
|
if (!HeapTupleIsValid(classTup))
|
|
|
|
elog(ERROR, "cache lookup failed for relation %u", event_relid);
|
|
|
|
classForm = (Form_pg_class) GETSTRUCT(classTup);
|
|
|
|
|
tableam: introduce table AM infrastructure.
This introduces the concept of table access methods, i.e. CREATE
ACCESS METHOD ... TYPE TABLE and
CREATE TABLE ... USING (storage-engine).
No table access functionality is delegated to table AMs as of this
commit, that'll be done in following commits.
Subsequent commits will incrementally abstract table access
functionality to be routed through table access methods. That change
is too large to be reviewed & committed at once, so it'll be done
incrementally.
Docs will be updated at the end, as adding them incrementally would
likely make them less coherent, and definitely is a lot more work,
without a lot of benefit.
Table access methods are specified similar to index access methods,
i.e. pg_am.amhandler returns, as INTERNAL, a pointer to a struct with
callbacks. In contrast to index AMs that struct needs to live as long
as a backend, typically that's achieved by just returning a pointer to
a constant struct.
Psql's \d+ now displays a table's access method. That can be disabled
with HIDE_TABLEAM=true, which is mainly useful so regression tests can
be run against different AMs. It's quite possible that this behaviour
still needs to be fine tuned.
For now it's not allowed to set a table AM for a partitioned table, as
we've not resolved how partitions would inherit that. Disallowing
allows us to introduce, if we decide that's the way forward, such a
behaviour without a compatibility break.
Catversion bumped, to add the heap table AM and references to it.
Author: Haribabu Kommi, Andres Freund, Alvaro Herrera, Dimitri Golgov and others
Discussion:
https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de
https://postgr.es/m/20160812231527.GA690404@alvherre.pgsql
https://postgr.es/m/20190107235616.6lur25ph22u5u5av@alap3.anarazel.de
https://postgr.es/m/20190304234700.w5tmhducs5wxgzls@alap3.anarazel.de
2019-03-06 18:54:38 +01:00
|
|
|
classForm->relam = InvalidOid;
|
2013-03-04 01:05:47 +01:00
|
|
|
classForm->reltablespace = InvalidOid;
|
|
|
|
classForm->relpages = 0;
|
|
|
|
classForm->reltuples = 0;
|
|
|
|
classForm->relallvisible = 0;
|
|
|
|
classForm->reltoastrelid = InvalidOid;
|
|
|
|
classForm->relhasindex = false;
|
|
|
|
classForm->relkind = RELKIND_VIEW;
|
|
|
|
classForm->relfrozenxid = InvalidTransactionId;
|
|
|
|
classForm->relminmxid = InvalidMultiXactId;
|
2015-05-01 19:03:23 +02:00
|
|
|
classForm->relreplident = REPLICA_IDENTITY_NOTHING;
|
2013-03-04 01:05:47 +01:00
|
|
|
|
2017-01-31 22:42:24 +01:00
|
|
|
CatalogTupleUpdate(relationRelation, &classTup->t_self, classTup);
|
2013-03-04 01:05:47 +01:00
|
|
|
|
|
|
|
heap_freetuple(classTup);
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(relationRelation, RowExclusiveLock);
|
2012-10-24 19:39:37 +02:00
|
|
|
}
|
2000-09-12 06:49:17 +02: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, RewriteRelationId, ruleId);
|
|
|
|
|
2000-06-30 09:04:23 +02:00
|
|
|
/* Close rel, but keep lock till commit... */
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(event_relation, NoLock);
|
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
|
|
|
return address;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
2000-09-29 20:21:41 +02:00
|
|
|
|
2006-09-02 19:06:52 +02:00
|
|
|
/*
|
|
|
|
* checkRuleResultList
|
|
|
|
* Verify that targetList produces output compatible with a tupledesc
|
|
|
|
*
|
|
|
|
* The targetList might be either a SELECT targetlist, or a RETURNING list;
|
2013-11-04 21:31:07 +01:00
|
|
|
* isSelect tells which. This is used for choosing error messages.
|
|
|
|
*
|
|
|
|
* A SELECT targetlist may optionally require that column names match.
|
2006-09-02 19:06:52 +02:00
|
|
|
*/
|
|
|
|
static void
|
2013-11-04 21:31:07 +01:00
|
|
|
checkRuleResultList(List *targetList, TupleDesc resultDesc, bool isSelect,
|
|
|
|
bool requireColumnNameMatch)
|
2006-09-02 19:06:52 +02:00
|
|
|
{
|
|
|
|
ListCell *tllist;
|
|
|
|
int i;
|
|
|
|
|
2013-11-04 21:31:07 +01:00
|
|
|
/* Only a SELECT may require a column name match. */
|
|
|
|
Assert(isSelect || !requireColumnNameMatch);
|
|
|
|
|
2006-09-02 19:06:52 +02:00
|
|
|
i = 0;
|
|
|
|
foreach(tllist, targetList)
|
|
|
|
{
|
|
|
|
TargetEntry *tle = (TargetEntry *) lfirst(tllist);
|
2014-07-02 18:31:24 +02:00
|
|
|
Oid tletypid;
|
2006-09-02 19:06:52 +02:00
|
|
|
int32 tletypmod;
|
|
|
|
Form_pg_attribute attr;
|
|
|
|
char *attname;
|
|
|
|
|
|
|
|
/* resjunk entries may be ignored */
|
|
|
|
if (tle->resjunk)
|
|
|
|
continue;
|
|
|
|
i++;
|
|
|
|
if (i > resultDesc->natts)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
|
|
|
isSelect ?
|
|
|
|
errmsg("SELECT rule's target list has too many entries") :
|
|
|
|
errmsg("RETURNING list has too many entries")));
|
|
|
|
|
2017-08-20 20:19:07 +02:00
|
|
|
attr = TupleDescAttr(resultDesc, i - 1);
|
2006-09-02 19:06:52 +02:00
|
|
|
attname = NameStr(attr->attname);
|
|
|
|
|
|
|
|
/*
|
2016-03-01 01:11:38 +01:00
|
|
|
* Disallow dropped columns in the relation. This is not really
|
|
|
|
* expected to happen when creating an ON SELECT rule. It'd be
|
|
|
|
* possible if someone tried to convert a relation with dropped
|
|
|
|
* columns to a view, but the only case we care about supporting
|
|
|
|
* table-to-view conversion for is pg_dump, and pg_dump won't do that.
|
|
|
|
*
|
|
|
|
* Unfortunately, the situation is also possible when adding a rule
|
|
|
|
* with RETURNING to a regular table, and rejecting that case is
|
|
|
|
* altogether more annoying. In principle we could support it by
|
|
|
|
* modifying the targetlist to include dummy NULL columns
|
|
|
|
* corresponding to the dropped columns in the tupdesc. However,
|
|
|
|
* places like ruleutils.c would have to be fixed to not process such
|
|
|
|
* entries, and that would take an uncertain and possibly rather large
|
|
|
|
* amount of work. (Note we could not dodge that by marking the dummy
|
|
|
|
* columns resjunk, since it's precisely the non-resjunk tlist columns
|
|
|
|
* that are expected to correspond to table columns.)
|
2006-09-02 19:06:52 +02:00
|
|
|
*/
|
|
|
|
if (attr->attisdropped)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
2016-03-01 01:11:38 +01:00
|
|
|
isSelect ?
|
|
|
|
errmsg("cannot convert relation containing dropped columns to view") :
|
|
|
|
errmsg("cannot create a RETURNING list for a relation containing dropped columns")));
|
2006-09-02 19:06:52 +02:00
|
|
|
|
2014-07-02 18:31:24 +02:00
|
|
|
/* Check name match if required; no need for two error texts here */
|
2013-11-04 21:31:07 +01:00
|
|
|
if (requireColumnNameMatch && strcmp(tle->resname, attname) != 0)
|
2006-09-02 19:06:52 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
2014-07-02 18:31:24 +02:00
|
|
|
errmsg("SELECT rule's target entry %d has different column name from column \"%s\"",
|
|
|
|
i, attname),
|
|
|
|
errdetail("SELECT target entry is named \"%s\".",
|
|
|
|
tle->resname)));
|
|
|
|
|
|
|
|
/* Check type match. */
|
|
|
|
tletypid = exprType((Node *) tle->expr);
|
|
|
|
if (attr->atttypid != tletypid)
|
2006-09-02 19:06:52 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
|
|
|
isSelect ?
|
|
|
|
errmsg("SELECT rule's target entry %d has different type from column \"%s\"",
|
|
|
|
i, attname) :
|
|
|
|
errmsg("RETURNING list's entry %d has different type from column \"%s\"",
|
2014-07-02 18:31:24 +02:00
|
|
|
i, attname),
|
|
|
|
isSelect ?
|
|
|
|
errdetail("SELECT target entry has type %s, but column has type %s.",
|
|
|
|
format_type_be(tletypid),
|
|
|
|
format_type_be(attr->atttypid)) :
|
|
|
|
errdetail("RETURNING list entry has type %s, but column has type %s.",
|
|
|
|
format_type_be(tletypid),
|
|
|
|
format_type_be(attr->atttypid))));
|
2006-09-02 19:06:52 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Allow typmods to be different only if one of them is -1, ie,
|
|
|
|
* "unspecified". This is necessary for cases like "numeric", where
|
|
|
|
* the table will have a filled-in default length but the select
|
|
|
|
* rule's expression will probably have typmod = -1.
|
|
|
|
*/
|
|
|
|
tletypmod = exprTypmod((Node *) tle->expr);
|
|
|
|
if (attr->atttypmod != tletypmod &&
|
|
|
|
attr->atttypmod != -1 && tletypmod != -1)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
|
|
|
isSelect ?
|
|
|
|
errmsg("SELECT rule's target entry %d has different size from column \"%s\"",
|
|
|
|
i, attname) :
|
|
|
|
errmsg("RETURNING list's entry %d has different size from column \"%s\"",
|
2014-07-02 18:31:24 +02:00
|
|
|
i, attname),
|
|
|
|
isSelect ?
|
|
|
|
errdetail("SELECT target entry has type %s, but column has type %s.",
|
|
|
|
format_type_with_typemod(tletypid, tletypmod),
|
|
|
|
format_type_with_typemod(attr->atttypid,
|
|
|
|
attr->atttypmod)) :
|
|
|
|
errdetail("RETURNING list entry has type %s, but column has type %s.",
|
|
|
|
format_type_with_typemod(tletypid, tletypmod),
|
|
|
|
format_type_with_typemod(attr->atttypid,
|
|
|
|
attr->atttypmod))));
|
2006-09-02 19:06:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (i != resultDesc->natts)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
|
|
|
isSelect ?
|
|
|
|
errmsg("SELECT rule's target list has too few entries") :
|
|
|
|
errmsg("RETURNING list has too few entries")));
|
|
|
|
}
|
|
|
|
|
2000-09-29 20:21:41 +02:00
|
|
|
/*
|
2006-09-05 23:08:36 +02:00
|
|
|
* setRuleCheckAsUser
|
|
|
|
* Recursively scan a query or expression tree and set the checkAsUser
|
|
|
|
* field to the given userid in all rtable entries.
|
2001-05-03 23:16:48 +02:00
|
|
|
*
|
2009-11-06 00:24:27 +01:00
|
|
|
* Note: for a view (ON SELECT rule), the checkAsUser field of the OLD
|
2001-05-03 23:16:48 +02:00
|
|
|
* RTE entry will be overridden when the view rule is expanded, and the
|
2009-11-06 00:24:27 +01:00
|
|
|
* checkAsUser field of the NEW entry is irrelevant because that entry's
|
2004-01-15 00:01:55 +01:00
|
|
|
* requiredPerms bits will always be zero. However, for other types of rules
|
|
|
|
* it's important to set these fields to match the rule owner. So we just set
|
2001-05-03 23:16:48 +02:00
|
|
|
* them always.
|
2000-09-29 20:21:41 +02:00
|
|
|
*/
|
2006-09-05 23:08:36 +02:00
|
|
|
void
|
|
|
|
setRuleCheckAsUser(Node *node, Oid userid)
|
|
|
|
{
|
|
|
|
(void) setRuleCheckAsUser_walker(node, &userid);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
setRuleCheckAsUser_walker(Node *node, Oid *context)
|
|
|
|
{
|
|
|
|
if (node == NULL)
|
|
|
|
return false;
|
|
|
|
if (IsA(node, Query))
|
|
|
|
{
|
|
|
|
setRuleCheckAsUser_Query((Query *) node, *context);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return expression_tree_walker(node, setRuleCheckAsUser_walker,
|
|
|
|
(void *) context);
|
|
|
|
}
|
|
|
|
|
2000-09-29 20:21:41 +02:00
|
|
|
static void
|
2005-06-28 07:09:14 +02:00
|
|
|
setRuleCheckAsUser_Query(Query *qry, Oid userid)
|
2000-09-29 20:21:41 +02:00
|
|
|
{
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
2000-09-29 20:21:41 +02:00
|
|
|
|
2001-05-03 23:16:48 +02:00
|
|
|
/* Set all the RTEs in this query node */
|
2000-09-29 20:21:41 +02:00
|
|
|
foreach(l, qry->rtable)
|
|
|
|
{
|
|
|
|
RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
|
|
|
|
|
2002-05-12 22:10:05 +02:00
|
|
|
if (rte->rtekind == RTE_SUBQUERY)
|
2000-09-29 20:21:41 +02:00
|
|
|
{
|
2001-05-03 23:16:48 +02:00
|
|
|
/* Recurse into subquery in FROM */
|
2004-05-19 00:49:51 +02:00
|
|
|
setRuleCheckAsUser_Query(rte->subquery, userid);
|
2000-09-29 20:21:41 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
rte->checkAsUser = userid;
|
|
|
|
}
|
|
|
|
|
2008-10-04 23:56:55 +02:00
|
|
|
/* Recurse into subquery-in-WITH */
|
|
|
|
foreach(l, qry->cteList)
|
|
|
|
{
|
|
|
|
CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
|
|
|
|
|
2017-01-27 04:09:34 +01:00
|
|
|
setRuleCheckAsUser_Query(castNode(Query, cte->ctequery), userid);
|
2008-10-04 23:56:55 +02:00
|
|
|
}
|
|
|
|
|
2000-09-29 20:21:41 +02:00
|
|
|
/* If there are sublinks, search for them and process their RTEs */
|
|
|
|
if (qry->hasSubLinks)
|
2000-10-05 21:11:39 +02:00
|
|
|
query_tree_walker(qry, setRuleCheckAsUser_walker, (void *) &userid,
|
2008-10-04 23:56:55 +02:00
|
|
|
QTW_IGNORE_RC_SUBQUERIES);
|
2000-09-29 20:21:41 +02:00
|
|
|
}
|
|
|
|
|
2001-08-12 23:35:19 +02:00
|
|
|
|
2007-03-20 00:38:32 +01:00
|
|
|
/*
|
|
|
|
* Change the firing semantics of an existing rule.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
EnableDisableRule(Relation rel, const char *rulename,
|
|
|
|
char fires_when)
|
|
|
|
{
|
|
|
|
Relation pg_rewrite_desc;
|
|
|
|
Oid owningRel = RelationGetRelid(rel);
|
|
|
|
Oid eventRelationOid;
|
|
|
|
HeapTuple ruletup;
|
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
|
|
|
Form_pg_rewrite ruleform;
|
2007-03-20 00:38:32 +01:00
|
|
|
bool changed = false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find the rule tuple to change.
|
|
|
|
*/
|
2019-01-21 19:32:19 +01:00
|
|
|
pg_rewrite_desc = table_open(RewriteRelationId, RowExclusiveLock);
|
2010-02-14 19:42:19 +01:00
|
|
|
ruletup = SearchSysCacheCopy2(RULERELNAME,
|
|
|
|
ObjectIdGetDatum(owningRel),
|
|
|
|
PointerGetDatum(rulename));
|
2007-03-20 00:38:32 +01:00
|
|
|
if (!HeapTupleIsValid(ruletup))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("rule \"%s\" for relation \"%s\" does not exist",
|
|
|
|
rulename, get_rel_name(owningRel))));
|
|
|
|
|
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
|
|
|
ruleform = (Form_pg_rewrite) GETSTRUCT(ruletup);
|
|
|
|
|
2007-03-20 00:38:32 +01:00
|
|
|
/*
|
|
|
|
* Verify that the user has appropriate permissions.
|
|
|
|
*/
|
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
|
|
|
eventRelationOid = ruleform->ev_class;
|
2007-03-20 00:38:32 +01:00
|
|
|
Assert(eventRelationOid == owningRel);
|
|
|
|
if (!pg_class_ownercheck(eventRelationOid, GetUserId()))
|
2017-12-02 15:26:34 +01:00
|
|
|
aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(get_rel_relkind(eventRelationOid)),
|
2007-03-20 00:38:32 +01:00
|
|
|
get_rel_name(eventRelationOid));
|
2007-11-15 22:14:46 +01:00
|
|
|
|
2007-03-20 00:38:32 +01:00
|
|
|
/*
|
|
|
|
* Change ev_enabled if it is different from the desired new state.
|
|
|
|
*/
|
Remove WITH OIDS support, change oid catalog column visibility.
Previously tables declared WITH OIDS, including a significant fraction
of the catalog tables, stored the oid column not as a normal column,
but as part of the tuple header.
This special column was not shown by default, which was somewhat odd,
as it's often (consider e.g. pg_class.oid) one of the more important
parts of a row. Neither pg_dump nor COPY included the contents of the
oid column by default.
The fact that the oid column was not an ordinary column necessitated a
significant amount of special case code to support oid columns. That
already was painful for the existing, but upcoming work aiming to make
table storage pluggable, would have required expanding and duplicating
that "specialness" significantly.
WITH OIDS has been deprecated since 2005 (commit ff02d0a05280e0).
Remove it.
Removing includes:
- CREATE TABLE and ALTER TABLE syntax for declaring the table to be
WITH OIDS has been removed (WITH (oids[ = true]) will error out)
- pg_dump does not support dumping tables declared WITH OIDS and will
issue a warning when dumping one (and ignore the oid column).
- restoring an pg_dump archive with pg_restore will warn when
restoring a table with oid contents (and ignore the oid column)
- COPY will refuse to load binary dump that includes oids.
- pg_upgrade will error out when encountering tables declared WITH
OIDS, they have to be altered to remove the oid column first.
- Functionality to access the oid of the last inserted row (like
plpgsql's RESULT_OID, spi's SPI_lastoid, ...) has been removed.
The syntax for declaring a table WITHOUT OIDS (or WITH (oids = false)
for CREATE TABLE) is still supported. While that requires a bit of
support code, it seems unnecessary to break applications / dumps that
do not use oids, and are explicit about not using them.
The biggest user of WITH OID columns was postgres' catalog. This
commit changes all 'magic' oid columns to be columns that are normally
declared and stored. To reduce unnecessary query breakage all the
newly added columns are still named 'oid', even if a table's column
naming scheme would indicate 'reloid' or such. This obviously
requires adapting a lot code, mostly replacing oid access via
HeapTupleGetOid() with access to the underlying Form_pg_*->oid column.
The bootstrap process now assigns oids for all oid columns in
genbki.pl that do not have an explicit value (starting at the largest
oid previously used), only oids assigned later by oids will be above
FirstBootstrapObjectId. As the oid column now is a normal column the
special bootstrap syntax for oids has been removed.
Oids are not automatically assigned during insertion anymore, all
backend code explicitly assigns oids with GetNewOidWithIndex(). For
the rare case that insertions into the catalog via SQL are called for
the new pg_nextoid() function can be used (which only works on catalog
tables).
The fact that oid columns on system tables are now normal columns
means that they will be included in the set of columns expanded
by * (i.e. SELECT * FROM pg_class will now include the table's oid,
previously it did not). It'd not technically be hard to hide oid
column by default, but that'd mean confusing behavior would either
have to be carried forward forever, or it'd cause breakage down the
line.
While it's not unlikely that further adjustments are needed, the
scope/invasiveness of the patch makes it worthwhile to get merge this
now. It's painful to maintain externally, too complicated to commit
after the code code freeze, and a dependency of a number of other
patches.
Catversion bump, for obvious reasons.
Author: Andres Freund, with contributions by John Naylor
Discussion: https://postgr.es/m/20180930034810.ywp2c7awz7opzcfr@alap3.anarazel.de
2018-11-21 00:36:57 +01:00
|
|
|
if (DatumGetChar(ruleform->ev_enabled) !=
|
2007-03-20 00:38:32 +01:00
|
|
|
fires_when)
|
|
|
|
{
|
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
|
|
|
ruleform->ev_enabled = CharGetDatum(fires_when);
|
2017-01-31 22:42:24 +01:00
|
|
|
CatalogTupleUpdate(pg_rewrite_desc, &ruletup->t_self, ruletup);
|
2007-03-20 00:38:32 +01:00
|
|
|
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
|
Remove WITH OIDS support, change oid catalog column visibility.
Previously tables declared WITH OIDS, including a significant fraction
of the catalog tables, stored the oid column not as a normal column,
but as part of the tuple header.
This special column was not shown by default, which was somewhat odd,
as it's often (consider e.g. pg_class.oid) one of the more important
parts of a row. Neither pg_dump nor COPY included the contents of the
oid column by default.
The fact that the oid column was not an ordinary column necessitated a
significant amount of special case code to support oid columns. That
already was painful for the existing, but upcoming work aiming to make
table storage pluggable, would have required expanding and duplicating
that "specialness" significantly.
WITH OIDS has been deprecated since 2005 (commit ff02d0a05280e0).
Remove it.
Removing includes:
- CREATE TABLE and ALTER TABLE syntax for declaring the table to be
WITH OIDS has been removed (WITH (oids[ = true]) will error out)
- pg_dump does not support dumping tables declared WITH OIDS and will
issue a warning when dumping one (and ignore the oid column).
- restoring an pg_dump archive with pg_restore will warn when
restoring a table with oid contents (and ignore the oid column)
- COPY will refuse to load binary dump that includes oids.
- pg_upgrade will error out when encountering tables declared WITH
OIDS, they have to be altered to remove the oid column first.
- Functionality to access the oid of the last inserted row (like
plpgsql's RESULT_OID, spi's SPI_lastoid, ...) has been removed.
The syntax for declaring a table WITHOUT OIDS (or WITH (oids = false)
for CREATE TABLE) is still supported. While that requires a bit of
support code, it seems unnecessary to break applications / dumps that
do not use oids, and are explicit about not using them.
The biggest user of WITH OID columns was postgres' catalog. This
commit changes all 'magic' oid columns to be columns that are normally
declared and stored. To reduce unnecessary query breakage all the
newly added columns are still named 'oid', even if a table's column
naming scheme would indicate 'reloid' or such. This obviously
requires adapting a lot code, mostly replacing oid access via
HeapTupleGetOid() with access to the underlying Form_pg_*->oid column.
The bootstrap process now assigns oids for all oid columns in
genbki.pl that do not have an explicit value (starting at the largest
oid previously used), only oids assigned later by oids will be above
FirstBootstrapObjectId. As the oid column now is a normal column the
special bootstrap syntax for oids has been removed.
Oids are not automatically assigned during insertion anymore, all
backend code explicitly assigns oids with GetNewOidWithIndex(). For
the rare case that insertions into the catalog via SQL are called for
the new pg_nextoid() function can be used (which only works on catalog
tables).
The fact that oid columns on system tables are now normal columns
means that they will be included in the set of columns expanded
by * (i.e. SELECT * FROM pg_class will now include the table's oid,
previously it did not). It'd not technically be hard to hide oid
column by default, but that'd mean confusing behavior would either
have to be carried forward forever, or it'd cause breakage down the
line.
While it's not unlikely that further adjustments are needed, the
scope/invasiveness of the patch makes it worthwhile to get merge this
now. It's painful to maintain externally, too complicated to commit
after the code code freeze, and a dependency of a number of other
patches.
Catversion bump, for obvious reasons.
Author: Andres Freund, with contributions by John Naylor
Discussion: https://postgr.es/m/20180930034810.ywp2c7awz7opzcfr@alap3.anarazel.de
2018-11-21 00:36:57 +01:00
|
|
|
InvokeObjectPostAlterHook(RewriteRelationId, ruleform->oid, 0);
|
2013-03-18 03:55:14 +01:00
|
|
|
|
2007-03-20 00:38:32 +01:00
|
|
|
heap_freetuple(ruletup);
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(pg_rewrite_desc, RowExclusiveLock);
|
2007-03-20 00:38:32 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If we changed anything, broadcast a SI inval message to force each
|
|
|
|
* backend (including our own!) to rebuild relation's relcache entry.
|
|
|
|
* Otherwise they will fail to apply the change promptly.
|
|
|
|
*/
|
|
|
|
if (changed)
|
|
|
|
CacheInvalidateRelcache(rel);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-09 05:58:40 +01:00
|
|
|
/*
|
|
|
|
* Perform permissions and integrity checks before acquiring a relation lock.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
RangeVarCallbackForRenameRule(const RangeVar *rv, Oid relid, Oid oldrelid,
|
|
|
|
void *arg)
|
|
|
|
{
|
|
|
|
HeapTuple tuple;
|
|
|
|
Form_pg_class form;
|
|
|
|
|
|
|
|
tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
|
|
|
|
if (!HeapTupleIsValid(tuple))
|
|
|
|
return; /* concurrently dropped */
|
|
|
|
form = (Form_pg_class) GETSTRUCT(tuple);
|
|
|
|
|
|
|
|
/* only tables and views can have rules */
|
2017-04-11 19:17:22 +02:00
|
|
|
if (form->relkind != RELKIND_RELATION &&
|
|
|
|
form->relkind != RELKIND_VIEW &&
|
|
|
|
form->relkind != RELKIND_PARTITIONED_TABLE)
|
2013-02-09 05:58:40 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
|
|
errmsg("\"%s\" is not a table or view", rv->relname)));
|
|
|
|
|
Refine our definition of what constitutes a system relation.
Although user-defined relations can't be directly created in
pg_catalog, it's possible for them to end up there, because you can
create them in some other schema and then use ALTER TABLE .. SET SCHEMA
to move them there. Previously, such relations couldn't afterwards
be manipulated, because IsSystemRelation()/IsSystemClass() rejected
all attempts to modify objects in the pg_catalog schema, regardless
of their origin. With this patch, they now reject only those
objects in pg_catalog which were created at initdb-time, allowing
most operations on user-created tables in pg_catalog to proceed
normally.
This patch also adds new functions IsCatalogRelation() and
IsCatalogClass(), which is similar to IsSystemRelation() and
IsSystemClass() but with a slightly narrower definition: only TOAST
tables of system catalogs are included, rather than *all* TOAST tables.
This is currently used only for making decisions about when
invalidation messages need to be sent, but upcoming logical decoding
patches will find other uses for this information.
Andres Freund, with some modifications by me.
2013-11-29 02:57:20 +01:00
|
|
|
if (!allowSystemTableMods && IsSystemClass(relid, form))
|
2013-02-09 05:58:40 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
|
|
|
errmsg("permission denied: \"%s\" is a system catalog",
|
|
|
|
rv->relname)));
|
|
|
|
|
|
|
|
/* you must own the table to rename one of its rules */
|
|
|
|
if (!pg_class_ownercheck(relid, GetUserId()))
|
2017-12-02 15:26:34 +01:00
|
|
|
aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(get_rel_relkind(relid)), rv->relname);
|
2013-02-09 05:58:40 +01:00
|
|
|
|
|
|
|
ReleaseSysCache(tuple);
|
|
|
|
}
|
|
|
|
|
2001-08-12 23:35:19 +02:00
|
|
|
/*
|
|
|
|
* Rename an existing rewrite rule.
|
|
|
|
*/
|
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
|
2013-02-09 05:58:40 +01:00
|
|
|
RenameRewriteRule(RangeVar *relation, const char *oldName,
|
2002-04-18 22:01:11 +02:00
|
|
|
const char *newName)
|
2001-08-12 23:35:19 +02:00
|
|
|
{
|
2013-02-09 05:58:40 +01:00
|
|
|
Oid relid;
|
|
|
|
Relation targetrel;
|
2001-08-12 23:35:19 +02:00
|
|
|
Relation pg_rewrite_desc;
|
|
|
|
HeapTuple ruletup;
|
2013-02-09 05:58:40 +01:00
|
|
|
Form_pg_rewrite ruleform;
|
|
|
|
Oid ruleOid;
|
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;
|
2001-08-12 23:35:19 +02:00
|
|
|
|
2013-02-09 05:58:40 +01:00
|
|
|
/*
|
|
|
|
* Look up name, check permissions, and acquire lock (which we will NOT
|
|
|
|
* release until end of transaction).
|
|
|
|
*/
|
|
|
|
relid = RangeVarGetRelidExtended(relation, AccessExclusiveLock,
|
2018-03-31 01:33:42 +02:00
|
|
|
0,
|
2013-02-09 05:58:40 +01:00
|
|
|
RangeVarCallbackForRenameRule,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* Have lock already, so just need to build relcache entry. */
|
|
|
|
targetrel = relation_open(relid, NoLock);
|
|
|
|
|
|
|
|
/* Prepare to modify pg_rewrite */
|
2019-01-21 19:32:19 +01:00
|
|
|
pg_rewrite_desc = table_open(RewriteRelationId, RowExclusiveLock);
|
2001-08-12 23:35:19 +02:00
|
|
|
|
2013-02-09 05:58:40 +01:00
|
|
|
/* Fetch the rule's entry (it had better exist) */
|
2010-02-14 19:42:19 +01:00
|
|
|
ruletup = SearchSysCacheCopy2(RULERELNAME,
|
2013-02-09 05:58:40 +01:00
|
|
|
ObjectIdGetDatum(relid),
|
2010-02-14 19:42:19 +01:00
|
|
|
PointerGetDatum(oldName));
|
2001-08-12 23:35:19 +02:00
|
|
|
if (!HeapTupleIsValid(ruletup))
|
2003-07-25 02:01:09 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("rule \"%s\" for relation \"%s\" does not exist",
|
2013-02-09 05:58:40 +01:00
|
|
|
oldName, RelationGetRelationName(targetrel))));
|
|
|
|
ruleform = (Form_pg_rewrite) GETSTRUCT(ruletup);
|
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
|
|
|
ruleOid = ruleform->oid;
|
2001-08-12 23:35:19 +02:00
|
|
|
|
2013-02-09 05:58:40 +01:00
|
|
|
/* rule with the new name should not already exist */
|
|
|
|
if (IsDefinedRewriteRule(relid, newName))
|
2003-07-25 02:01:09 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
|
|
|
errmsg("rule \"%s\" for relation \"%s\" already exists",
|
2013-02-09 05:58:40 +01:00
|
|
|
newName, RelationGetRelationName(targetrel))));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We disallow renaming ON SELECT rules, because they should always be
|
|
|
|
* named "_RETURN".
|
|
|
|
*/
|
|
|
|
if (ruleform->ev_type == CMD_SELECT + '0')
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
|
|
|
errmsg("renaming an ON SELECT rule is not allowed")));
|
2001-08-12 23:35:19 +02:00
|
|
|
|
2013-02-09 05:58:40 +01:00
|
|
|
/* OK, do the update */
|
|
|
|
namestrcpy(&(ruleform->rulename), newName);
|
2001-08-12 23:35:19 +02:00
|
|
|
|
2017-01-31 22:42:24 +01:00
|
|
|
CatalogTupleUpdate(pg_rewrite_desc, &ruletup->t_self, ruletup);
|
2001-08-12 23:35:19 +02:00
|
|
|
|
2020-05-23 07:03:04 +02:00
|
|
|
InvokeObjectPostAlterHook(RewriteRelationId, ruleOid, 0);
|
|
|
|
|
2001-08-12 23:35:19 +02:00
|
|
|
heap_freetuple(ruletup);
|
2019-01-21 19:32:19 +01:00
|
|
|
table_close(pg_rewrite_desc, RowExclusiveLock);
|
2006-10-04 02:30:14 +02:00
|
|
|
|
2013-02-09 05:58:40 +01:00
|
|
|
/*
|
|
|
|
* Invalidate relation's relcache entry so that other backends (and this
|
|
|
|
* one too!) are sent SI message to make them rebuild relcache entries.
|
|
|
|
* (Ideally this should happen automatically...)
|
|
|
|
*/
|
|
|
|
CacheInvalidateRelcache(targetrel);
|
|
|
|
|
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, RewriteRelationId, ruleOid);
|
|
|
|
|
2013-02-09 05:58:40 +01:00
|
|
|
/*
|
|
|
|
* Close rel, but keep exclusive lock!
|
|
|
|
*/
|
|
|
|
relation_close(targetrel, NoLock);
|
|
|
|
|
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;
|
2013-02-09 05:58:40 +01:00
|
|
|
}
|