2002-03-26 20:17:02 +01:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* namespace.c
|
|
|
|
* code to support accessing and searching namespaces
|
|
|
|
*
|
|
|
|
* This is separate from pg_namespace.c, which contains the routines that
|
|
|
|
* directly manipulate the pg_namespace system catalog. This module
|
|
|
|
* provides routines associated with defining a "namespace search path"
|
|
|
|
* and implementing search-path-controlled searches.
|
|
|
|
*
|
|
|
|
*
|
2023-01-02 21:00:37 +01:00
|
|
|
* Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
|
2002-03-26 20:17:02 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/catalog/namespace.c
|
2002-03-26 20:17:02 +01:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
2012-08-30 22:15:44 +02:00
|
|
|
#include "access/htup_details.h"
|
Create an infrastructure for parallel computation in PostgreSQL.
This does four basic things. First, it provides convenience routines
to coordinate the startup and shutdown of parallel workers. Second,
it synchronizes various pieces of state (e.g. GUCs, combo CID
mappings, transaction snapshot) from the parallel group leader to the
worker processes. Third, it prohibits various operations that would
result in unsafe changes to that state while parallelism is active.
Finally, it propagates events that would result in an ErrorResponse,
NoticeResponse, or NotifyResponse message being sent to the client
from the parallel workers back to the master, from which they can then
be sent on to the client.
Robert Haas, Amit Kapila, Noah Misch, Rushabh Lathia, Jeevan Chalke.
Suggestions and review from Andres Freund, Heikki Linnakangas, Noah
Misch, Simon Riggs, Euler Taveira, and Jim Nasby.
2015-04-30 21:02:14 +02:00
|
|
|
#include "access/parallel.h"
|
2002-03-31 08:26:32 +02:00
|
|
|
#include "access/xact.h"
|
2014-11-06 12:52:08 +01:00
|
|
|
#include "access/xlog.h"
|
2002-07-12 20:43:19 +02:00
|
|
|
#include "catalog/dependency.h"
|
2013-04-05 14:51:31 +02:00
|
|
|
#include "catalog/objectaccess.h"
|
2005-06-28 07:09:14 +02:00
|
|
|
#include "catalog/pg_authid.h"
|
2011-02-08 22:04:18 +01:00
|
|
|
#include "catalog/pg_collation.h"
|
2002-07-16 08:58:14 +02:00
|
|
|
#include "catalog/pg_conversion.h"
|
2022-11-13 08:11:17 +01:00
|
|
|
#include "catalog/pg_database.h"
|
2002-03-26 20:17:02 +01:00
|
|
|
#include "catalog/pg_namespace.h"
|
2002-04-17 22:57:57 +02:00
|
|
|
#include "catalog/pg_opclass.h"
|
2002-04-17 01:08:12 +02:00
|
|
|
#include "catalog/pg_operator.h"
|
2006-12-23 01:43:13 +01:00
|
|
|
#include "catalog/pg_opfamily.h"
|
2002-04-06 08:59:25 +02:00
|
|
|
#include "catalog/pg_proc.h"
|
2017-05-13 06:05:48 +02:00
|
|
|
#include "catalog/pg_statistic_ext.h"
|
2007-08-21 03:11:32 +02:00
|
|
|
#include "catalog/pg_ts_config.h"
|
|
|
|
#include "catalog/pg_ts_dict.h"
|
|
|
|
#include "catalog/pg_ts_parser.h"
|
|
|
|
#include "catalog/pg_ts_template.h"
|
2002-05-02 01:06:41 +02:00
|
|
|
#include "catalog/pg_type.h"
|
2003-06-27 19:07:03 +02:00
|
|
|
#include "commands/dbcommands.h"
|
2009-10-08 04:39:25 +02:00
|
|
|
#include "funcapi.h"
|
2011-02-08 22:04:18 +01:00
|
|
|
#include "mb/pg_wchar.h"
|
2002-03-26 20:17:02 +01:00
|
|
|
#include "miscadmin.h"
|
2002-03-29 20:06:29 +01:00
|
|
|
#include "nodes/makefuncs.h"
|
2008-07-16 03:30:23 +02:00
|
|
|
#include "parser/parse_func.h"
|
2002-05-05 02:03:29 +02:00
|
|
|
#include "storage/ipc.h"
|
2011-07-09 04:19:30 +02:00
|
|
|
#include "storage/lmgr.h"
|
Make autovacuum more aggressive to remove orphaned temp tables
Commit dafa084, added in 10, made the removal of temporary orphaned
tables more aggressive. This commit makes an extra step into the
aggressiveness by adding a flag in each backend's MyProc which tracks
down any temporary namespace currently in use. The flag is set when the
namespace gets created and can be reset if the temporary namespace has
been created in a transaction or sub-transaction which is aborted. The
flag value assignment is assumed to be atomic, so this can be done in a
lock-less fashion like other flags already present in PGPROC like
databaseId or backendId, still the fact that the temporary namespace and
table created are still locked until the transaction creating those
commits acts as a barrier for other backends.
This new flag gets used by autovacuum to discard more aggressively
orphaned tables by additionally checking for the database a backend is
connected to as well as its temporary namespace in-use, removing
orphaned temporary relations even if a backend reuses the same slot as
one which created temporary relations in a past session.
The base idea of this patch comes from Robert Haas, has been written in
its first version by Tsunakawa Takayuki, then heavily reviewed by me.
Author: Tsunakawa Takayuki
Reviewed-by: Michael Paquier, Kyotaro Horiguchi, Andres Freund
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F8A4DC6@G01JPEXMBYT05
Backpatch: 11-, as PGPROC gains a new flag and we don't want silent ABI
breakages on already released versions.
2018-08-13 11:49:04 +02:00
|
|
|
#include "storage/sinvaladt.h"
|
2002-04-27 05:45:03 +02:00
|
|
|
#include "utils/acl.h"
|
2002-04-01 05:34:27 +02:00
|
|
|
#include "utils/builtins.h"
|
2012-08-29 00:26:24 +02:00
|
|
|
#include "utils/catcache.h"
|
Split up guc.c for better build speed and ease of maintenance.
guc.c has grown to be one of our largest .c files, making it
a bottleneck for compilation. It's also acquired a bunch of
knowledge that'd be better kept elsewhere, because of our not
very good habit of putting variable-specific check hooks here.
Hence, split it up along these lines:
* guc.c itself retains just the core GUC housekeeping mechanisms.
* New file guc_funcs.c contains the SET/SHOW interfaces and some
SQL-accessible functions for GUC manipulation.
* New file guc_tables.c contains the data arrays that define the
built-in GUC variables, along with some already-exported constant
tables.
* GUC check/assign/show hook functions are moved to the variable's
home module, whenever that's clearly identifiable. A few hard-
to-classify hooks ended up in commands/variable.c, which was
already a home for miscellaneous GUC hook functions.
To avoid cluttering a lot more header files with #include "guc.h",
I also invented a new header file utils/guc_hooks.h and put all
the GUC hook functions' declarations there, regardless of their
originating module. That allowed removal of #include "guc.h"
from some existing headers. The fallout from that (hopefully
all caught here) demonstrates clearly why such inclusions are
best minimized: there are a lot of files that, for example,
were getting array.h at two or more levels of remove, despite
not having any connection at all to GUCs in themselves.
There is some very minor code beautification here, such as
renaming a couple of inconsistently-named hook functions
and improving some comments. But mostly this just moves
code from point A to point B and deals with the ensuing
needs for #include adjustments and exporting a few functions
that previously weren't exported.
Patch by me, per a suggestion from Andres Freund; thanks also
to Michael Paquier for the idea to invent guc_funcs.c.
Discussion: https://postgr.es/m/587607.1662836699@sss.pgh.pa.us
2022-09-13 17:05:07 +02:00
|
|
|
#include "utils/guc_hooks.h"
|
2002-04-30 00:15:07 +02:00
|
|
|
#include "utils/inval.h"
|
2002-03-26 20:17:02 +01:00
|
|
|
#include "utils/lsyscache.h"
|
2003-02-07 02:33:06 +01:00
|
|
|
#include "utils/memutils.h"
|
2022-02-21 17:57:34 +01:00
|
|
|
#include "utils/snapmgr.h"
|
2002-03-26 20:17:02 +01:00
|
|
|
#include "utils/syscache.h"
|
2017-01-21 02:29:53 +01:00
|
|
|
#include "utils/varlena.h"
|
2002-03-26 20:17:02 +01:00
|
|
|
|
|
|
|
|
2002-03-31 08:26:32 +02:00
|
|
|
/*
|
|
|
|
* The namespace search path is a possibly-empty list of namespace OIDs.
|
2007-03-23 20:53:52 +01:00
|
|
|
* In addition to the explicit list, implicitly-searched namespaces
|
2002-05-17 22:53:33 +02:00
|
|
|
* may be included:
|
2002-03-31 08:26:32 +02:00
|
|
|
*
|
2007-03-23 20:53:52 +01:00
|
|
|
* 1. If a TEMP table namespace has been initialized in this session, it
|
|
|
|
* is implicitly searched first. (The only time this doesn't happen is
|
|
|
|
* when we are obeying an override search path spec that says not to use the
|
|
|
|
* temp namespace, or the temp namespace is included in the explicit list.)
|
2002-05-17 22:53:33 +02:00
|
|
|
*
|
2007-03-23 20:53:52 +01:00
|
|
|
* 2. The system catalog namespace is always searched. If the system
|
2002-05-17 22:53:33 +02:00
|
|
|
* namespace is present in the explicit path then it will be searched in
|
|
|
|
* the specified order; otherwise it will be searched after TEMP tables and
|
|
|
|
* *before* the explicit list. (It might seem that the system namespace
|
|
|
|
* should be implicitly last, but this behavior appears to be required by
|
|
|
|
* SQL99. Also, this provides a way to search the system namespace first
|
|
|
|
* without thereby making it the default creation target namespace.)
|
|
|
|
*
|
2007-04-20 04:37:38 +02:00
|
|
|
* For security reasons, searches using the search path will ignore the temp
|
|
|
|
* namespace when searching for any object type other than relations and
|
|
|
|
* types. (We must allow types since temp tables have rowtypes.)
|
|
|
|
*
|
2007-03-23 20:53:52 +01:00
|
|
|
* The default creation target namespace is always the first element of the
|
|
|
|
* explicit list. If the explicit list is empty, there is no default target.
|
2002-03-31 08:26:32 +02:00
|
|
|
*
|
2007-04-20 04:37:38 +02:00
|
|
|
* The textual specification of search_path can include "$user" to refer to
|
|
|
|
* the namespace named the same as the current user, if any. (This is just
|
|
|
|
* ignored if there is no such namespace.) Also, it can include "pg_temp"
|
|
|
|
* to refer to the current backend's temp namespace. This is usually also
|
|
|
|
* ignorable if the temp namespace hasn't been set up, but there's a special
|
|
|
|
* case: if "pg_temp" appears first then it should be the default creation
|
|
|
|
* target. We kluge this case a little bit so that the temp namespace isn't
|
|
|
|
* set up until the first attempt to create something in it. (The reason for
|
|
|
|
* klugery is that we can't create the temp namespace outside a transaction,
|
|
|
|
* but initial GUC processing of search_path happens outside a transaction.)
|
2017-08-16 06:22:32 +02:00
|
|
|
* activeTempCreationPending is true if "pg_temp" appears first in the string
|
2007-04-20 04:37:38 +02:00
|
|
|
* but is not reflected in activeCreationNamespace because the namespace isn't
|
|
|
|
* set up yet.
|
|
|
|
*
|
|
|
|
* In bootstrap mode, the search path is set equal to "pg_catalog", so that
|
2002-04-16 00:33:21 +02:00
|
|
|
* the system namespace is the only one searched or inserted into.
|
2007-04-20 04:37:38 +02:00
|
|
|
* initdb is also careful to set search_path to "pg_catalog" for its
|
2007-03-23 20:53:52 +01:00
|
|
|
* post-bootstrap standalone backend runs. Otherwise the default search
|
2002-04-16 00:33:21 +02:00
|
|
|
* path is determined by GUC. The factory default path contains the PUBLIC
|
|
|
|
* namespace (if it exists), preceded by the user's personal namespace
|
|
|
|
* (if one exists).
|
2002-04-30 00:15:07 +02:00
|
|
|
*
|
2007-03-23 20:53:52 +01:00
|
|
|
* We support a stack of "override" search path settings for use within
|
|
|
|
* specific sections of backend code. namespace_search_path is ignored
|
|
|
|
* whenever the override stack is nonempty. activeSearchPath is always
|
|
|
|
* the actually active path; it points either to the search list of the
|
|
|
|
* topmost stack entry, or to baseSearchPath which is the list derived
|
|
|
|
* from namespace_search_path.
|
|
|
|
*
|
|
|
|
* If baseSearchPathValid is false, then baseSearchPath (and other
|
2002-04-30 00:15:07 +02:00
|
|
|
* derived variables) need to be recomputed from namespace_search_path.
|
|
|
|
* We mark it invalid upon an assignment to namespace_search_path or receipt
|
|
|
|
* of a syscache invalidation event for pg_namespace. The recomputation
|
2007-03-23 20:53:52 +01:00
|
|
|
* is done during the next non-overridden lookup attempt. Note that an
|
|
|
|
* override spec is never subject to recomputation.
|
2002-04-30 00:15:07 +02:00
|
|
|
*
|
|
|
|
* Any namespaces mentioned in namespace_search_path that are not readable
|
2007-03-23 20:53:52 +01:00
|
|
|
* by the current user ID are simply left out of baseSearchPath; so
|
2002-04-30 00:15:07 +02:00
|
|
|
* we have to be willing to recompute the path when current userid changes.
|
|
|
|
* namespaceUser is the userid the path has been computed for.
|
2007-03-23 20:53:52 +01:00
|
|
|
*
|
|
|
|
* Note: all data pointed to by these List variables is in TopMemoryContext.
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
*
|
|
|
|
* activePathGeneration is incremented whenever the effective values of
|
|
|
|
* activeSearchPath/activeCreationNamespace/activeTempCreationPending change.
|
|
|
|
* This can be used to quickly detect whether any change has happened since
|
|
|
|
* a previous examination of the search path state.
|
2002-03-31 08:26:32 +02:00
|
|
|
*/
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
/* These variables define the actually active state: */
|
2002-03-31 08:26:32 +02:00
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
static List *activeSearchPath = NIL;
|
2002-04-30 00:15:07 +02:00
|
|
|
|
2002-04-16 00:33:21 +02:00
|
|
|
/* default place to create stuff; if InvalidOid, no default */
|
2007-03-23 20:53:52 +01:00
|
|
|
static Oid activeCreationNamespace = InvalidOid;
|
2002-03-31 08:26:32 +02:00
|
|
|
|
2017-08-16 06:22:32 +02:00
|
|
|
/* if true, activeCreationNamespace is wrong, it should be temp namespace */
|
2007-04-20 04:37:38 +02:00
|
|
|
static bool activeTempCreationPending = false;
|
|
|
|
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
/* current generation counter; make sure this is never zero */
|
|
|
|
static uint64 activePathGeneration = 1;
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
/* These variables are the values last derived from namespace_search_path: */
|
2002-05-17 22:53:33 +02:00
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
static List *baseSearchPath = NIL;
|
|
|
|
|
|
|
|
static Oid baseCreationNamespace = InvalidOid;
|
|
|
|
|
2007-04-20 04:37:38 +02:00
|
|
|
static bool baseTempCreationPending = false;
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
static Oid namespaceUser = InvalidOid;
|
|
|
|
|
2007-04-20 04:37:38 +02:00
|
|
|
/* The above four values are valid only if baseSearchPathValid */
|
2007-03-23 20:53:52 +01:00
|
|
|
static bool baseSearchPathValid = true;
|
|
|
|
|
|
|
|
/* Override requests are remembered in a stack of OverrideStackEntry structs */
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
List *searchPath; /* the desired search path */
|
|
|
|
Oid creationNamespace; /* the desired creation namespace */
|
|
|
|
int nestLevel; /* subtransaction nesting level */
|
|
|
|
} OverrideStackEntry;
|
|
|
|
|
|
|
|
static List *overrideStack = NIL;
|
2002-05-17 22:53:33 +02:00
|
|
|
|
2002-03-31 08:26:32 +02:00
|
|
|
/*
|
|
|
|
* myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
|
|
|
|
* in a particular backend session (this happens when a CREATE TEMP TABLE
|
|
|
|
* command is first executed). Thereafter it's the OID of the temp namespace.
|
2004-07-28 16:23:31 +02:00
|
|
|
*
|
2007-07-26 00:16:18 +02:00
|
|
|
* myTempToastNamespace is the OID of the namespace for my temp tables' toast
|
|
|
|
* tables. It is set when myTempNamespace is, and is InvalidOid before that.
|
|
|
|
*
|
2004-09-16 18:58:44 +02:00
|
|
|
* myTempNamespaceSubID shows whether we've created the TEMP namespace in the
|
|
|
|
* current subtransaction. The flag propagates up the subtransaction tree,
|
2004-07-28 16:23:31 +02:00
|
|
|
* so the main transaction will correctly recognize the flag if all
|
2004-09-16 18:58:44 +02:00
|
|
|
* intermediate subtransactions commit. When it is InvalidSubTransactionId,
|
2004-07-28 16:23:31 +02:00
|
|
|
* we either haven't made the TEMP namespace yet, or have successfully
|
|
|
|
* committed its creation, depending on whether myTempNamespace is valid.
|
2002-03-31 08:26:32 +02:00
|
|
|
*/
|
|
|
|
static Oid myTempNamespace = InvalidOid;
|
|
|
|
|
2007-07-26 00:16:18 +02:00
|
|
|
static Oid myTempToastNamespace = InvalidOid;
|
|
|
|
|
2004-09-16 18:58:44 +02:00
|
|
|
static SubTransactionId myTempNamespaceSubID = InvalidSubTransactionId;
|
2002-05-17 22:53:33 +02:00
|
|
|
|
|
|
|
/*
|
2007-03-23 20:53:52 +01:00
|
|
|
* This is the user's textual search path specification --- it's the value
|
2002-04-01 05:34:27 +02:00
|
|
|
* of the GUC variable 'search_path'.
|
|
|
|
*/
|
|
|
|
char *namespace_search_path = NULL;
|
|
|
|
|
2002-03-31 08:26:32 +02:00
|
|
|
|
|
|
|
/* Local functions */
|
2002-04-30 00:15:07 +02:00
|
|
|
static void recomputeNamespacePath(void);
|
Restrict the use of temporary namespace in two-phase transactions
Attempting to use a temporary table within a two-phase transaction is
forbidden for ages. However, there have been uncovered grounds for
a couple of other object types and commands which work on temporary
objects with two-phase commit. In short, trying to create, lock or drop
an object on a temporary schema should not be authorized within a
two-phase transaction, as it would cause its state to create
dependencies with other sessions, causing all sorts of side effects with
the existing session or other sessions spawned later on trying to use
the same temporary schema name.
Regression tests are added to cover all the grounds found, the original
report mentioned function creation, but monitoring closer there are many
other patterns with LOCK, DROP or CREATE EXTENSION which are involved.
One of the symptoms resulting in combining both is that the session
which used the temporary schema is not able to shut down completely,
waiting for being able to drop the temporary schema, something that it
cannot complete because of the two-phase transaction involved with
temporary objects. In this case the client is able to disconnect but
the session remains alive on the backend-side, potentially blocking
connection backend slots from being used. Other problems reported could
also involve server crashes.
This is back-patched down to v10, which is where 9b013dc has introduced
MyXactFlags, something that this patch relies on.
Reported-by: Alexey Bashtanov
Author: Michael Paquier
Reviewed-by: Masahiko Sawada
Discussion: https://postgr.es/m/5d910e2e-0db8-ec06-dd5f-baec420513c3@imap.cc
Backpatch-through: 10
2019-01-18 01:21:44 +01:00
|
|
|
static void AccessTempTableNamespace(bool force);
|
2002-05-17 22:53:33 +02:00
|
|
|
static void InitTempTableNamespace(void);
|
2006-04-25 16:11:59 +02:00
|
|
|
static void RemoveTempRelations(Oid tempNamespaceId);
|
2003-12-12 19:45:10 +01:00
|
|
|
static void RemoveTempRelationsCallback(int code, Datum arg);
|
2011-08-17 01:27:46 +02:00
|
|
|
static void NamespaceCallback(Datum arg, int cacheid, uint32 hashvalue);
|
2009-10-08 04:39:25 +02:00
|
|
|
static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
bool include_out_arguments, int pronargs,
|
2009-10-08 04:39:25 +02:00
|
|
|
int **argnumbers);
|
2002-03-31 08:26:32 +02:00
|
|
|
|
2003-01-07 21:56:07 +01:00
|
|
|
|
2002-03-26 20:17:02 +01:00
|
|
|
/*
|
2018-03-07 05:36:26 +01:00
|
|
|
* RangeVarGetRelidExtended
|
2002-03-26 20:17:02 +01:00
|
|
|
* Given a RangeVar describing an existing relation,
|
|
|
|
* select the proper namespace and look up the relation OID.
|
|
|
|
*
|
2018-03-31 01:33:42 +02:00
|
|
|
* If the schema or relation is not found, return InvalidOid if flags contains
|
|
|
|
* RVR_MISSING_OK, otherwise raise an error.
|
2011-07-09 04:19:30 +02:00
|
|
|
*
|
2018-03-31 01:33:42 +02:00
|
|
|
* If flags contains RVR_NOWAIT, throw an error if we'd have to wait for a
|
|
|
|
* lock.
|
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
|
|
|
*
|
2018-03-31 01:56:41 +02:00
|
|
|
* If flags contains RVR_SKIP_LOCKED, return InvalidOid if we'd have to wait
|
|
|
|
* for a lock.
|
|
|
|
*
|
|
|
|
* flags cannot contain both RVR_NOWAIT and RVR_SKIP_LOCKED.
|
|
|
|
*
|
|
|
|
* Note that if RVR_MISSING_OK and RVR_SKIP_LOCKED are both specified, a
|
|
|
|
* return value of InvalidOid could either mean the relation is missing or it
|
|
|
|
* could not be locked.
|
|
|
|
*
|
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
|
|
|
* Callback allows caller to check permissions or acquire additional locks
|
|
|
|
* prior to grabbing the relation lock.
|
2002-03-26 20:17:02 +01:00
|
|
|
*/
|
|
|
|
Oid
|
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
|
|
|
RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode,
|
2018-03-31 01:33:42 +02:00
|
|
|
uint32 flags,
|
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
|
|
|
RangeVarGetRelidCallback callback, void *callback_arg)
|
2002-03-26 20:17:02 +01:00
|
|
|
{
|
2011-07-09 04:19:30 +02:00
|
|
|
uint64 inval_count;
|
2002-03-26 20:17:02 +01:00
|
|
|
Oid relId;
|
2011-07-09 04:19:30 +02:00
|
|
|
Oid oldRelId = InvalidOid;
|
|
|
|
bool retry = false;
|
2018-03-31 01:33:42 +02:00
|
|
|
bool missing_ok = (flags & RVR_MISSING_OK) != 0;
|
2002-03-26 20:17:02 +01:00
|
|
|
|
2018-03-31 01:56:41 +02:00
|
|
|
/* verify that flags do no conflict */
|
|
|
|
Assert(!((flags & RVR_NOWAIT) && (flags & RVR_SKIP_LOCKED)));
|
|
|
|
|
2002-03-26 20:17:02 +01:00
|
|
|
/*
|
|
|
|
* We check the catalog name and then ignore it.
|
|
|
|
*/
|
|
|
|
if (relation->catalogname)
|
|
|
|
{
|
2003-06-27 16:45:32 +02:00
|
|
|
if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
|
2003-07-21 03:59:11 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
2004-02-13 02:08:20 +01:00
|
|
|
errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
|
|
|
|
relation->catalogname, relation->schemaname,
|
|
|
|
relation->relname)));
|
2002-03-26 20:17:02 +01:00
|
|
|
}
|
|
|
|
|
2007-08-27 05:36:08 +02:00
|
|
|
/*
|
2011-07-09 04:19:30 +02:00
|
|
|
* DDL operations can change the results of a name lookup. Since all such
|
|
|
|
* operations will generate invalidation messages, we keep track of
|
|
|
|
* whether any such messages show up while we're performing the operation,
|
|
|
|
* and retry until either (1) no more invalidation messages show up or (2)
|
|
|
|
* the answer doesn't change.
|
|
|
|
*
|
|
|
|
* But if lockmode = NoLock, then we assume that either the caller is OK
|
|
|
|
* with the answer changing under them, or that they already hold some
|
|
|
|
* appropriate lock, and therefore return the first answer we get without
|
|
|
|
* checking for invalidation messages. Also, if the requested lock is
|
2015-02-20 06:11:42 +01:00
|
|
|
* already held, LockRelationOid will not AcceptInvalidationMessages, so
|
|
|
|
* we may fail to notice a change. We could protect against that case by
|
|
|
|
* calling AcceptInvalidationMessages() before beginning this loop, but
|
2011-07-09 04:19:30 +02:00
|
|
|
* that would add a significant amount overhead, so for now we don't.
|
2007-08-27 05:36:08 +02:00
|
|
|
*/
|
2011-07-09 04:19:30 +02:00
|
|
|
for (;;)
|
2002-03-26 20:17:02 +01:00
|
|
|
{
|
2011-07-09 04:19:30 +02:00
|
|
|
/*
|
|
|
|
* Remember this value, so that, after looking up the relation name
|
|
|
|
* and locking its OID, we can check whether any invalidation messages
|
|
|
|
* have been processed that might require a do-over.
|
|
|
|
*/
|
|
|
|
inval_count = SharedInvalidMessageCounter;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Some non-default relpersistence value may have been specified. The
|
|
|
|
* parser never generates such a RangeVar in simple DML, but it can
|
|
|
|
* happen in contexts such as "CREATE TEMP TABLE foo (f1 int PRIMARY
|
|
|
|
* KEY)". Such a command will generate an added CREATE INDEX
|
|
|
|
* operation, which must be careful to find the temp table, even when
|
|
|
|
* pg_temp is not first in the search path.
|
|
|
|
*/
|
|
|
|
if (relation->relpersistence == RELPERSISTENCE_TEMP)
|
|
|
|
{
|
2011-09-21 16:32:30 +02:00
|
|
|
if (!OidIsValid(myTempNamespace))
|
|
|
|
relId = InvalidOid; /* this probably can't happen? */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (relation->schemaname)
|
|
|
|
{
|
|
|
|
Oid namespaceId;
|
2012-06-10 21:20:04 +02:00
|
|
|
|
2013-01-26 19:24:50 +01:00
|
|
|
namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok);
|
2013-05-29 22:58:43 +02:00
|
|
|
|
2013-01-26 19:24:50 +01:00
|
|
|
/*
|
2016-06-03 16:13:36 +02:00
|
|
|
* For missing_ok, allow a non-existent schema name to
|
2013-01-26 20:51:59 +01:00
|
|
|
* return InvalidOid.
|
2013-01-26 19:24:50 +01:00
|
|
|
*/
|
2011-09-21 16:32:30 +02:00
|
|
|
if (namespaceId != myTempNamespace)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
|
|
|
errmsg("temporary tables cannot specify a schema name")));
|
|
|
|
}
|
|
|
|
|
2011-07-09 04:19:30 +02:00
|
|
|
relId = get_relname_relid(relation->relname, myTempNamespace);
|
2011-09-21 16:32:30 +02:00
|
|
|
}
|
2011-07-09 04:19:30 +02:00
|
|
|
}
|
|
|
|
else if (relation->schemaname)
|
|
|
|
{
|
2011-09-21 16:32:30 +02:00
|
|
|
Oid namespaceId;
|
|
|
|
|
2011-07-09 04:19:30 +02:00
|
|
|
/* use exact schema given */
|
2013-01-26 19:24:50 +01:00
|
|
|
namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok);
|
|
|
|
if (missing_ok && !OidIsValid(namespaceId))
|
|
|
|
relId = InvalidOid;
|
|
|
|
else
|
|
|
|
relId = get_relname_relid(relation->relname, namespaceId);
|
2011-07-09 04:19:30 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* search the namespace path */
|
|
|
|
relId = RelnameGetRelid(relation->relname);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
/*
|
|
|
|
* Invoke caller-supplied callback, if any.
|
|
|
|
*
|
|
|
|
* This callback is a good place to check permissions: we haven't
|
|
|
|
* taken the table lock yet (and it's really best to check permissions
|
|
|
|
* before locking anything!), but we've gotten far enough to know what
|
2011-12-06 21:50:02 +01:00
|
|
|
* OID we think we should lock. Of course, concurrent DDL might
|
|
|
|
* change things while we're waiting for the lock, but in that case
|
|
|
|
* the callback will be invoked again for the new OID.
|
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
|
|
|
*/
|
|
|
|
if (callback)
|
|
|
|
callback(relation, relId, oldRelId, callback_arg);
|
|
|
|
|
2011-07-09 04:19:30 +02:00
|
|
|
/*
|
|
|
|
* If no lock requested, we assume the caller knows what they're
|
|
|
|
* doing. They should have already acquired a heavyweight lock on
|
|
|
|
* this relation earlier in the processing of this same statement, so
|
|
|
|
* it wouldn't be appropriate to AcceptInvalidationMessages() here, as
|
|
|
|
* that might pull the rug out from under them.
|
|
|
|
*/
|
|
|
|
if (lockmode == NoLock)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If, upon retry, we get back the same OID we did last time, then the
|
|
|
|
* invalidation messages we processed did not change the final answer.
|
|
|
|
* So we're done.
|
2011-11-12 07:22:45 +01:00
|
|
|
*
|
|
|
|
* If we got a different OID, we've locked the relation that used to
|
|
|
|
* have this name rather than the one that does now. So release the
|
|
|
|
* lock.
|
2011-07-09 04:19:30 +02:00
|
|
|
*/
|
2011-11-12 07:22:45 +01:00
|
|
|
if (retry)
|
|
|
|
{
|
|
|
|
if (relId == oldRelId)
|
|
|
|
break;
|
|
|
|
if (OidIsValid(oldRelId))
|
|
|
|
UnlockRelationOid(oldRelId, lockmode);
|
|
|
|
}
|
2011-07-09 04:19:30 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Lock relation. This will also accept any pending invalidation
|
|
|
|
* messages. If we got back InvalidOid, indicating not found, then
|
|
|
|
* there's nothing to lock, but we accept invalidation messages
|
|
|
|
* anyway, to flush any negative catcache entries that may be
|
|
|
|
* lingering.
|
|
|
|
*/
|
|
|
|
if (!OidIsValid(relId))
|
|
|
|
AcceptInvalidationMessages();
|
2018-03-31 01:56:41 +02:00
|
|
|
else if (!(flags & (RVR_NOWAIT | RVR_SKIP_LOCKED)))
|
2011-07-09 04:19:30 +02:00
|
|
|
LockRelationOid(relId, lockmode);
|
|
|
|
else if (!ConditionalLockRelationOid(relId, lockmode))
|
|
|
|
{
|
2018-03-31 01:56:41 +02:00
|
|
|
int elevel = (flags & RVR_SKIP_LOCKED) ? DEBUG1 : ERROR;
|
|
|
|
|
2011-07-09 04:19:30 +02:00
|
|
|
if (relation->schemaname)
|
2018-03-31 01:56:41 +02:00
|
|
|
ereport(elevel,
|
2011-07-09 04:19:30 +02:00
|
|
|
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
|
|
|
|
errmsg("could not obtain lock on relation \"%s.%s\"",
|
|
|
|
relation->schemaname, relation->relname)));
|
|
|
|
else
|
2018-03-31 01:56:41 +02:00
|
|
|
ereport(elevel,
|
2011-07-09 04:19:30 +02:00
|
|
|
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
|
|
|
|
errmsg("could not obtain lock on relation \"%s\"",
|
|
|
|
relation->relname)));
|
2018-03-31 01:56:41 +02:00
|
|
|
|
|
|
|
return InvalidOid;
|
2011-07-09 04:19:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If no invalidation message were processed, we're done!
|
|
|
|
*/
|
|
|
|
if (inval_count == SharedInvalidMessageCounter)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Something may have changed. Let's repeat the name lookup, to make
|
|
|
|
* sure this name still references the same relation it did
|
|
|
|
* previously.
|
|
|
|
*/
|
|
|
|
retry = true;
|
|
|
|
oldRelId = relId;
|
2002-03-26 20:17:02 +01:00
|
|
|
}
|
|
|
|
|
2018-03-31 01:33:42 +02:00
|
|
|
if (!OidIsValid(relId))
|
2002-03-26 20:17:02 +01:00
|
|
|
{
|
2018-03-31 01:33:42 +02:00
|
|
|
int elevel = missing_ok ? DEBUG1 : ERROR;
|
|
|
|
|
2002-03-26 20:17:02 +01:00
|
|
|
if (relation->schemaname)
|
2018-03-31 01:33:42 +02:00
|
|
|
ereport(elevel,
|
2003-07-21 03:59:11 +02:00
|
|
|
(errcode(ERRCODE_UNDEFINED_TABLE),
|
|
|
|
errmsg("relation \"%s.%s\" does not exist",
|
|
|
|
relation->schemaname, relation->relname)));
|
2002-03-26 20:17:02 +01:00
|
|
|
else
|
2018-03-31 01:33:42 +02:00
|
|
|
ereport(elevel,
|
2003-07-21 03:59:11 +02:00
|
|
|
(errcode(ERRCODE_UNDEFINED_TABLE),
|
|
|
|
errmsg("relation \"%s\" does not exist",
|
|
|
|
relation->relname)));
|
2002-03-26 20:17:02 +01:00
|
|
|
}
|
|
|
|
return relId;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* RangeVarGetCreationNamespace
|
|
|
|
* Given a RangeVar describing a to-be-created relation,
|
|
|
|
* choose which namespace to create it in.
|
2002-03-30 02:02:42 +01:00
|
|
|
*
|
|
|
|
* Note: calling this may result in a CommandCounterIncrement operation.
|
|
|
|
* That will happen on the first request for a temp table in any particular
|
|
|
|
* backend run; we will need to either create or clean out the temp schema.
|
2002-03-26 20:17:02 +01:00
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
RangeVarGetCreationNamespace(const RangeVar *newRelation)
|
|
|
|
{
|
|
|
|
Oid namespaceId;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We check the catalog name and then ignore it.
|
|
|
|
*/
|
|
|
|
if (newRelation->catalogname)
|
|
|
|
{
|
2003-06-27 16:45:32 +02:00
|
|
|
if (strcmp(newRelation->catalogname, get_database_name(MyDatabaseId)) != 0)
|
2003-07-21 03:59:11 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
2004-02-13 02:08:20 +01:00
|
|
|
errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
|
|
|
|
newRelation->catalogname, newRelation->schemaname,
|
|
|
|
newRelation->relname)));
|
2002-03-26 20:17:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (newRelation->schemaname)
|
|
|
|
{
|
2007-04-20 04:37:38 +02:00
|
|
|
/* check for pg_temp alias */
|
|
|
|
if (strcmp(newRelation->schemaname, "pg_temp") == 0)
|
|
|
|
{
|
Restrict the use of temporary namespace in two-phase transactions
Attempting to use a temporary table within a two-phase transaction is
forbidden for ages. However, there have been uncovered grounds for
a couple of other object types and commands which work on temporary
objects with two-phase commit. In short, trying to create, lock or drop
an object on a temporary schema should not be authorized within a
two-phase transaction, as it would cause its state to create
dependencies with other sessions, causing all sorts of side effects with
the existing session or other sessions spawned later on trying to use
the same temporary schema name.
Regression tests are added to cover all the grounds found, the original
report mentioned function creation, but monitoring closer there are many
other patterns with LOCK, DROP or CREATE EXTENSION which are involved.
One of the symptoms resulting in combining both is that the session
which used the temporary schema is not able to shut down completely,
waiting for being able to drop the temporary schema, something that it
cannot complete because of the two-phase transaction involved with
temporary objects. In this case the client is able to disconnect but
the session remains alive on the backend-side, potentially blocking
connection backend slots from being used. Other problems reported could
also involve server crashes.
This is back-patched down to v10, which is where 9b013dc has introduced
MyXactFlags, something that this patch relies on.
Reported-by: Alexey Bashtanov
Author: Michael Paquier
Reviewed-by: Masahiko Sawada
Discussion: https://postgr.es/m/5d910e2e-0db8-ec06-dd5f-baec420513c3@imap.cc
Backpatch-through: 10
2019-01-18 01:21:44 +01:00
|
|
|
/* Initialize temp namespace */
|
|
|
|
AccessTempTableNamespace(false);
|
2007-04-20 04:37:38 +02:00
|
|
|
return myTempNamespace;
|
|
|
|
}
|
2002-03-31 08:26:32 +02:00
|
|
|
/* use exact schema given */
|
2010-08-05 16:45:09 +02:00
|
|
|
namespaceId = get_namespace_oid(newRelation->schemaname, false);
|
2002-07-30 01:46:35 +02:00
|
|
|
/* we do not check for USAGE rights here! */
|
2002-03-26 20:17:02 +01:00
|
|
|
}
|
Fix bugs in relpersistence handling during table creation.
Unlike the relistemp field which it replaced, relpersistence must be
set correctly quite early during the table creation process, as we
rely on it quite early on for a number of purposes, including security
checks. Normally, this is set based on whether the user enters CREATE
TABLE, CREATE UNLOGGED TABLE, or CREATE TEMPORARY TABLE, but a
relation may also be made implicitly temporary by creating it in
pg_temp. This patch fixes the handling of that case, and also
disables creation of unlogged tables in temporary tablespace (such
table indeed skip WAL-logging, but we reject an explicit
specification) and creation of relations in the temporary schemas of
other sessions (which is not very sensible, and didn't work right
anyway).
Report by Amit Khandekar.
2011-07-03 23:34:47 +02:00
|
|
|
else if (newRelation->relpersistence == RELPERSISTENCE_TEMP)
|
|
|
|
{
|
Restrict the use of temporary namespace in two-phase transactions
Attempting to use a temporary table within a two-phase transaction is
forbidden for ages. However, there have been uncovered grounds for
a couple of other object types and commands which work on temporary
objects with two-phase commit. In short, trying to create, lock or drop
an object on a temporary schema should not be authorized within a
two-phase transaction, as it would cause its state to create
dependencies with other sessions, causing all sorts of side effects with
the existing session or other sessions spawned later on trying to use
the same temporary schema name.
Regression tests are added to cover all the grounds found, the original
report mentioned function creation, but monitoring closer there are many
other patterns with LOCK, DROP or CREATE EXTENSION which are involved.
One of the symptoms resulting in combining both is that the session
which used the temporary schema is not able to shut down completely,
waiting for being able to drop the temporary schema, something that it
cannot complete because of the two-phase transaction involved with
temporary objects. In this case the client is able to disconnect but
the session remains alive on the backend-side, potentially blocking
connection backend slots from being used. Other problems reported could
also involve server crashes.
This is back-patched down to v10, which is where 9b013dc has introduced
MyXactFlags, something that this patch relies on.
Reported-by: Alexey Bashtanov
Author: Michael Paquier
Reviewed-by: Masahiko Sawada
Discussion: https://postgr.es/m/5d910e2e-0db8-ec06-dd5f-baec420513c3@imap.cc
Backpatch-through: 10
2019-01-18 01:21:44 +01:00
|
|
|
/* Initialize temp namespace */
|
|
|
|
AccessTempTableNamespace(false);
|
Fix bugs in relpersistence handling during table creation.
Unlike the relistemp field which it replaced, relpersistence must be
set correctly quite early during the table creation process, as we
rely on it quite early on for a number of purposes, including security
checks. Normally, this is set based on whether the user enters CREATE
TABLE, CREATE UNLOGGED TABLE, or CREATE TEMPORARY TABLE, but a
relation may also be made implicitly temporary by creating it in
pg_temp. This patch fixes the handling of that case, and also
disables creation of unlogged tables in temporary tablespace (such
table indeed skip WAL-logging, but we reject an explicit
specification) and creation of relations in the temporary schemas of
other sessions (which is not very sensible, and didn't work right
anyway).
Report by Amit Khandekar.
2011-07-03 23:34:47 +02:00
|
|
|
return myTempNamespace;
|
|
|
|
}
|
2002-03-26 20:17:02 +01:00
|
|
|
else
|
|
|
|
{
|
2002-03-31 08:26:32 +02:00
|
|
|
/* use the default creation namespace */
|
2002-04-30 00:15:07 +02:00
|
|
|
recomputeNamespacePath();
|
2007-04-20 04:37:38 +02:00
|
|
|
if (activeTempCreationPending)
|
|
|
|
{
|
|
|
|
/* Need to initialize temp namespace */
|
Restrict the use of temporary namespace in two-phase transactions
Attempting to use a temporary table within a two-phase transaction is
forbidden for ages. However, there have been uncovered grounds for
a couple of other object types and commands which work on temporary
objects with two-phase commit. In short, trying to create, lock or drop
an object on a temporary schema should not be authorized within a
two-phase transaction, as it would cause its state to create
dependencies with other sessions, causing all sorts of side effects with
the existing session or other sessions spawned later on trying to use
the same temporary schema name.
Regression tests are added to cover all the grounds found, the original
report mentioned function creation, but monitoring closer there are many
other patterns with LOCK, DROP or CREATE EXTENSION which are involved.
One of the symptoms resulting in combining both is that the session
which used the temporary schema is not able to shut down completely,
waiting for being able to drop the temporary schema, something that it
cannot complete because of the two-phase transaction involved with
temporary objects. In this case the client is able to disconnect but
the session remains alive on the backend-side, potentially blocking
connection backend slots from being used. Other problems reported could
also involve server crashes.
This is back-patched down to v10, which is where 9b013dc has introduced
MyXactFlags, something that this patch relies on.
Reported-by: Alexey Bashtanov
Author: Michael Paquier
Reviewed-by: Masahiko Sawada
Discussion: https://postgr.es/m/5d910e2e-0db8-ec06-dd5f-baec420513c3@imap.cc
Backpatch-through: 10
2019-01-18 01:21:44 +01:00
|
|
|
AccessTempTableNamespace(true);
|
2007-04-20 04:37:38 +02:00
|
|
|
return myTempNamespace;
|
|
|
|
}
|
2007-03-23 20:53:52 +01:00
|
|
|
namespaceId = activeCreationNamespace;
|
2002-04-16 00:33:21 +02:00
|
|
|
if (!OidIsValid(namespaceId))
|
2003-07-21 03:59:11 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_SCHEMA),
|
|
|
|
errmsg("no schema has been selected to create in")));
|
2002-03-26 20:17:02 +01:00
|
|
|
}
|
|
|
|
|
2002-04-30 00:15:07 +02:00
|
|
|
/* Note: callers will check for CREATE rights when appropriate */
|
|
|
|
|
2002-03-26 20:17:02 +01:00
|
|
|
return namespaceId;
|
|
|
|
}
|
|
|
|
|
2011-04-25 22:55:11 +02:00
|
|
|
/*
|
|
|
|
* RangeVarGetAndCheckCreationNamespace
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
*
|
|
|
|
* This function returns the OID of the namespace in which a new relation
|
|
|
|
* with a given name should be created. If the user does not have CREATE
|
|
|
|
* permission on the target namespace, this function will instead signal
|
|
|
|
* an ERROR.
|
|
|
|
*
|
2019-07-08 06:15:09 +02:00
|
|
|
* If non-NULL, *existing_relation_id is set to the OID of any existing relation
|
|
|
|
* with the same name which already exists in that namespace, or to InvalidOid
|
|
|
|
* if no such relation exists.
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
*
|
2014-06-12 01:50:29 +02:00
|
|
|
* If lockmode != NoLock, the specified lock mode is acquired on the existing
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
* relation, if any, provided that the current user owns the target relation.
|
|
|
|
* However, if lockmode != NoLock and the user does not own the target
|
|
|
|
* relation, we throw an ERROR, as we must not try to lock relations the
|
|
|
|
* user does not have permissions on.
|
|
|
|
*
|
|
|
|
* As a side effect, this function acquires AccessShareLock on the target
|
|
|
|
* namespace. Without this, the namespace could be dropped before our
|
|
|
|
* transaction commits, leaving behind relations with relnamespace pointing
|
2016-01-06 17:06:42 +01:00
|
|
|
* to a no-longer-existent namespace.
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
*
|
2016-01-06 17:06:42 +01:00
|
|
|
* As a further side-effect, if the selected namespace is a temporary namespace,
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
* we mark the RangeVar as RELPERSISTENCE_TEMP.
|
2011-04-25 22:55:11 +02:00
|
|
|
*/
|
|
|
|
Oid
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
RangeVarGetAndCheckCreationNamespace(RangeVar *relation,
|
|
|
|
LOCKMODE lockmode,
|
|
|
|
Oid *existing_relation_id)
|
2011-04-25 22:55:11 +02:00
|
|
|
{
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
uint64 inval_count;
|
|
|
|
Oid relid;
|
|
|
|
Oid oldrelid = InvalidOid;
|
|
|
|
Oid nspid;
|
|
|
|
Oid oldnspid = InvalidOid;
|
|
|
|
bool retry = false;
|
2011-04-25 22:55:11 +02:00
|
|
|
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
/*
|
|
|
|
* We check the catalog name and then ignore it.
|
|
|
|
*/
|
|
|
|
if (relation->catalogname)
|
|
|
|
{
|
|
|
|
if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
|
|
|
|
relation->catalogname, relation->schemaname,
|
|
|
|
relation->relname)));
|
|
|
|
}
|
2011-04-25 22:55:11 +02:00
|
|
|
|
|
|
|
/*
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
* As in RangeVarGetRelidExtended(), we guard against concurrent DDL
|
|
|
|
* operations by tracking whether any invalidation messages are processed
|
|
|
|
* while we're doing the name lookups and acquiring locks. See comments
|
|
|
|
* in that function for a more detailed explanation of this logic.
|
2011-04-25 22:55:11 +02:00
|
|
|
*/
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
for (;;)
|
2011-04-25 22:55:11 +02:00
|
|
|
{
|
|
|
|
AclResult aclresult;
|
|
|
|
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
inval_count = SharedInvalidMessageCounter;
|
|
|
|
|
|
|
|
/* Look up creation namespace and check for existing relation. */
|
|
|
|
nspid = RangeVarGetCreationNamespace(relation);
|
|
|
|
Assert(OidIsValid(nspid));
|
|
|
|
if (existing_relation_id != NULL)
|
|
|
|
relid = get_relname_relid(relation->relname, nspid);
|
|
|
|
else
|
|
|
|
relid = InvalidOid;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In bootstrap processing mode, we don't bother with permissions or
|
|
|
|
* locking. Permissions might not be working yet, and locking is
|
|
|
|
* unnecessary.
|
|
|
|
*/
|
|
|
|
if (IsBootstrapProcessingMode())
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Check namespace permissions. */
|
2022-11-13 08:11:17 +01:00
|
|
|
aclresult = object_aclcheck(NamespaceRelationId, nspid, GetUserId(), ACL_CREATE);
|
2011-04-25 22:55:11 +02:00
|
|
|
if (aclresult != ACLCHECK_OK)
|
2017-12-02 15:26:34 +01:00
|
|
|
aclcheck_error(aclresult, OBJECT_SCHEMA,
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
get_namespace_name(nspid));
|
|
|
|
|
|
|
|
if (retry)
|
|
|
|
{
|
|
|
|
/* If nothing changed, we're done. */
|
|
|
|
if (relid == oldrelid && nspid == oldnspid)
|
|
|
|
break;
|
|
|
|
/* If creation namespace has changed, give up old lock. */
|
|
|
|
if (nspid != oldnspid)
|
|
|
|
UnlockDatabaseObject(NamespaceRelationId, oldnspid, 0,
|
|
|
|
AccessShareLock);
|
|
|
|
/* If name points to something different, give up old lock. */
|
|
|
|
if (relid != oldrelid && OidIsValid(oldrelid) && lockmode != NoLock)
|
|
|
|
UnlockRelationOid(oldrelid, lockmode);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Lock namespace. */
|
|
|
|
if (nspid != oldnspid)
|
|
|
|
LockDatabaseObject(NamespaceRelationId, nspid, 0, AccessShareLock);
|
|
|
|
|
|
|
|
/* Lock relation, if required if and we have permission. */
|
|
|
|
if (lockmode != NoLock && OidIsValid(relid))
|
|
|
|
{
|
2022-11-13 08:11:17 +01:00
|
|
|
if (!object_ownercheck(RelationRelationId, relid, GetUserId()))
|
2017-12-02 15:26:34 +01:00
|
|
|
aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(get_rel_relkind(relid)),
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
relation->relname);
|
|
|
|
if (relid != oldrelid)
|
|
|
|
LockRelationOid(relid, lockmode);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If no invalidation message were processed, we're done! */
|
|
|
|
if (inval_count == SharedInvalidMessageCounter)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Something may have changed, so recheck our work. */
|
|
|
|
retry = true;
|
|
|
|
oldrelid = relid;
|
|
|
|
oldnspid = nspid;
|
2011-04-25 22:55:11 +02:00
|
|
|
}
|
|
|
|
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
RangeVarAdjustRelationPersistence(relation, nspid);
|
|
|
|
if (existing_relation_id != NULL)
|
|
|
|
*existing_relation_id = relid;
|
|
|
|
return nspid;
|
2011-04-25 22:55:11 +02:00
|
|
|
}
|
|
|
|
|
Fix bugs in relpersistence handling during table creation.
Unlike the relistemp field which it replaced, relpersistence must be
set correctly quite early during the table creation process, as we
rely on it quite early on for a number of purposes, including security
checks. Normally, this is set based on whether the user enters CREATE
TABLE, CREATE UNLOGGED TABLE, or CREATE TEMPORARY TABLE, but a
relation may also be made implicitly temporary by creating it in
pg_temp. This patch fixes the handling of that case, and also
disables creation of unlogged tables in temporary tablespace (such
table indeed skip WAL-logging, but we reject an explicit
specification) and creation of relations in the temporary schemas of
other sessions (which is not very sensible, and didn't work right
anyway).
Report by Amit Khandekar.
2011-07-03 23:34:47 +02:00
|
|
|
/*
|
|
|
|
* Adjust the relpersistence for an about-to-be-created relation based on the
|
|
|
|
* creation namespace, and throw an error for invalid combinations.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid)
|
|
|
|
{
|
|
|
|
switch (newRelation->relpersistence)
|
|
|
|
{
|
|
|
|
case RELPERSISTENCE_TEMP:
|
2014-08-26 03:28:19 +02:00
|
|
|
if (!isTempOrTempToastNamespace(nspid))
|
Fix bugs in relpersistence handling during table creation.
Unlike the relistemp field which it replaced, relpersistence must be
set correctly quite early during the table creation process, as we
rely on it quite early on for a number of purposes, including security
checks. Normally, this is set based on whether the user enters CREATE
TABLE, CREATE UNLOGGED TABLE, or CREATE TEMPORARY TABLE, but a
relation may also be made implicitly temporary by creating it in
pg_temp. This patch fixes the handling of that case, and also
disables creation of unlogged tables in temporary tablespace (such
table indeed skip WAL-logging, but we reject an explicit
specification) and creation of relations in the temporary schemas of
other sessions (which is not very sensible, and didn't work right
anyway).
Report by Amit Khandekar.
2011-07-03 23:34:47 +02:00
|
|
|
{
|
|
|
|
if (isAnyTempNamespace(nspid))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
|
|
|
errmsg("cannot create relations in temporary schemas of other sessions")));
|
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
|
|
|
errmsg("cannot create temporary relation in non-temporary schema")));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case RELPERSISTENCE_PERMANENT:
|
2014-08-26 03:28:19 +02:00
|
|
|
if (isTempOrTempToastNamespace(nspid))
|
Fix bugs in relpersistence handling during table creation.
Unlike the relistemp field which it replaced, relpersistence must be
set correctly quite early during the table creation process, as we
rely on it quite early on for a number of purposes, including security
checks. Normally, this is set based on whether the user enters CREATE
TABLE, CREATE UNLOGGED TABLE, or CREATE TEMPORARY TABLE, but a
relation may also be made implicitly temporary by creating it in
pg_temp. This patch fixes the handling of that case, and also
disables creation of unlogged tables in temporary tablespace (such
table indeed skip WAL-logging, but we reject an explicit
specification) and creation of relations in the temporary schemas of
other sessions (which is not very sensible, and didn't work right
anyway).
Report by Amit Khandekar.
2011-07-03 23:34:47 +02:00
|
|
|
newRelation->relpersistence = RELPERSISTENCE_TEMP;
|
|
|
|
else if (isAnyTempNamespace(nspid))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
|
|
|
errmsg("cannot create relations in temporary schemas of other sessions")));
|
|
|
|
break;
|
|
|
|
default:
|
2011-07-22 22:15:43 +02:00
|
|
|
if (isAnyTempNamespace(nspid))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
|
|
|
errmsg("only temporary relations may be created in temporary schemas")));
|
Fix bugs in relpersistence handling during table creation.
Unlike the relistemp field which it replaced, relpersistence must be
set correctly quite early during the table creation process, as we
rely on it quite early on for a number of purposes, including security
checks. Normally, this is set based on whether the user enters CREATE
TABLE, CREATE UNLOGGED TABLE, or CREATE TEMPORARY TABLE, but a
relation may also be made implicitly temporary by creating it in
pg_temp. This patch fixes the handling of that case, and also
disables creation of unlogged tables in temporary tablespace (such
table indeed skip WAL-logging, but we reject an explicit
specification) and creation of relations in the temporary schemas of
other sessions (which is not very sensible, and didn't work right
anyway).
Report by Amit Khandekar.
2011-07-03 23:34:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-03-26 20:17:02 +01:00
|
|
|
/*
|
|
|
|
* RelnameGetRelid
|
|
|
|
* Try to resolve an unqualified relation name.
|
|
|
|
* Returns OID if relation found in search path, else InvalidOid.
|
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
RelnameGetRelid(const char *relname)
|
|
|
|
{
|
2002-03-31 08:26:32 +02:00
|
|
|
Oid relid;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
2002-03-31 08:26:32 +02:00
|
|
|
|
2002-04-30 00:15:07 +02:00
|
|
|
recomputeNamespacePath();
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
foreach(l, activeSearchPath)
|
2002-03-31 08:26:32 +02:00
|
|
|
{
|
2004-05-26 06:41:50 +02:00
|
|
|
Oid namespaceId = lfirst_oid(l);
|
2002-03-31 08:26:32 +02:00
|
|
|
|
|
|
|
relid = get_relname_relid(relname, namespaceId);
|
|
|
|
if (OidIsValid(relid))
|
|
|
|
return relid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Not found in path */
|
|
|
|
return InvalidOid;
|
2002-03-26 20:17:02 +01:00
|
|
|
}
|
2002-03-29 20:06:29 +01:00
|
|
|
|
2003-01-10 23:03:30 +01:00
|
|
|
|
2002-05-02 01:06:41 +02:00
|
|
|
/*
|
|
|
|
* RelationIsVisible
|
|
|
|
* Determine whether a relation (identified by OID) is visible in the
|
|
|
|
* current search path. Visible means "would be found by searching
|
|
|
|
* for the unqualified relation name".
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
RelationIsVisible(Oid relid)
|
|
|
|
{
|
|
|
|
HeapTuple reltup;
|
|
|
|
Form_pg_class relform;
|
|
|
|
Oid relnamespace;
|
|
|
|
bool visible;
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
reltup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
|
2002-05-02 01:06:41 +02:00
|
|
|
if (!HeapTupleIsValid(reltup))
|
2003-07-21 03:59:11 +02:00
|
|
|
elog(ERROR, "cache lookup failed for relation %u", relid);
|
2002-05-02 01:06:41 +02:00
|
|
|
relform = (Form_pg_class) GETSTRUCT(reltup);
|
|
|
|
|
2002-05-17 22:53:33 +02:00
|
|
|
recomputeNamespacePath();
|
|
|
|
|
2002-05-02 01:06:41 +02:00
|
|
|
/*
|
|
|
|
* Quick check: if it ain't in the path at all, it ain't visible. Items in
|
2002-05-17 22:53:33 +02:00
|
|
|
* the system namespace are surely in the path and so we needn't even do
|
2004-05-26 06:41:50 +02:00
|
|
|
* list_member_oid() for them.
|
2002-05-02 01:06:41 +02:00
|
|
|
*/
|
|
|
|
relnamespace = relform->relnamespace;
|
2002-05-17 22:53:33 +02:00
|
|
|
if (relnamespace != PG_CATALOG_NAMESPACE &&
|
2007-03-23 20:53:52 +01:00
|
|
|
!list_member_oid(activeSearchPath, relnamespace))
|
2002-05-02 01:06:41 +02:00
|
|
|
visible = false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If it is in the path, it might still not be visible; it could be
|
|
|
|
* hidden by another relation of the same name earlier in the path. So
|
2005-10-07 00:43:16 +02:00
|
|
|
* we must do a slow check for conflicting relations.
|
2002-05-02 01:06:41 +02:00
|
|
|
*/
|
|
|
|
char *relname = NameStr(relform->relname);
|
2005-10-07 00:43:16 +02:00
|
|
|
ListCell *l;
|
2002-05-02 01:06:41 +02:00
|
|
|
|
2005-10-07 00:43:16 +02:00
|
|
|
visible = false;
|
2007-03-23 20:53:52 +01:00
|
|
|
foreach(l, activeSearchPath)
|
2005-10-07 00:43:16 +02:00
|
|
|
{
|
|
|
|
Oid namespaceId = lfirst_oid(l);
|
|
|
|
|
|
|
|
if (namespaceId == relnamespace)
|
|
|
|
{
|
|
|
|
/* Found it first in path */
|
|
|
|
visible = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (OidIsValid(get_relname_relid(relname, namespaceId)))
|
|
|
|
{
|
|
|
|
/* Found something else first in path */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-05-02 01:06:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(reltup);
|
|
|
|
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-03-30 02:02:42 +01:00
|
|
|
/*
|
|
|
|
* TypenameGetTypid
|
2019-08-05 16:48:41 +02:00
|
|
|
* Wrapper for binary compatibility.
|
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
TypenameGetTypid(const char *typname)
|
|
|
|
{
|
|
|
|
return TypenameGetTypidExtended(typname, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TypenameGetTypidExtended
|
2002-03-30 02:02:42 +01:00
|
|
|
* Try to resolve an unqualified datatype name.
|
|
|
|
* Returns OID if type found in search path, else InvalidOid.
|
2002-03-31 08:26:32 +02:00
|
|
|
*
|
2002-05-17 22:53:33 +02:00
|
|
|
* This is essentially the same as RelnameGetRelid.
|
2002-03-30 02:02:42 +01:00
|
|
|
*/
|
|
|
|
Oid
|
2019-08-05 16:48:41 +02:00
|
|
|
TypenameGetTypidExtended(const char *typname, bool temp_ok)
|
2002-03-30 02:02:42 +01:00
|
|
|
{
|
2002-03-31 08:26:32 +02:00
|
|
|
Oid typid;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
2002-03-31 08:26:32 +02:00
|
|
|
|
2002-04-30 00:15:07 +02:00
|
|
|
recomputeNamespacePath();
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
foreach(l, activeSearchPath)
|
2002-03-31 08:26:32 +02:00
|
|
|
{
|
2004-05-26 06:41:50 +02:00
|
|
|
Oid namespaceId = lfirst_oid(l);
|
2002-03-31 08:26:32 +02:00
|
|
|
|
2019-08-05 16:48:41 +02:00
|
|
|
if (!temp_ok && namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
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
|
|
|
typid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
|
2010-02-14 19:42:19 +01:00
|
|
|
PointerGetDatum(typname),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
2002-03-31 08:26:32 +02:00
|
|
|
if (OidIsValid(typid))
|
|
|
|
return typid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Not found in path */
|
|
|
|
return InvalidOid;
|
2002-03-30 02:02:42 +01:00
|
|
|
}
|
|
|
|
|
2002-04-17 22:57:57 +02:00
|
|
|
/*
|
2002-05-02 01:06:41 +02:00
|
|
|
* TypeIsVisible
|
|
|
|
* Determine whether a type (identified by OID) is visible in the
|
|
|
|
* current search path. Visible means "would be found by searching
|
|
|
|
* for the unqualified type name".
|
2002-04-17 22:57:57 +02:00
|
|
|
*/
|
2002-05-02 01:06:41 +02:00
|
|
|
bool
|
|
|
|
TypeIsVisible(Oid typid)
|
2002-04-17 22:57:57 +02:00
|
|
|
{
|
2002-05-02 01:06:41 +02:00
|
|
|
HeapTuple typtup;
|
|
|
|
Form_pg_type typform;
|
|
|
|
Oid typnamespace;
|
|
|
|
bool visible;
|
2002-04-17 22:57:57 +02:00
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
typtup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
|
2002-05-02 01:06:41 +02:00
|
|
|
if (!HeapTupleIsValid(typtup))
|
2003-07-21 03:59:11 +02:00
|
|
|
elog(ERROR, "cache lookup failed for type %u", typid);
|
2002-05-02 01:06:41 +02:00
|
|
|
typform = (Form_pg_type) GETSTRUCT(typtup);
|
2002-04-17 22:57:57 +02:00
|
|
|
|
2002-05-17 22:53:33 +02:00
|
|
|
recomputeNamespacePath();
|
|
|
|
|
2002-04-17 22:57:57 +02:00
|
|
|
/*
|
2002-05-02 01:06:41 +02:00
|
|
|
* Quick check: if it ain't in the path at all, it ain't visible. Items in
|
2002-05-17 22:53:33 +02:00
|
|
|
* the system namespace are surely in the path and so we needn't even do
|
2004-05-26 06:41:50 +02:00
|
|
|
* list_member_oid() for them.
|
2002-04-17 22:57:57 +02:00
|
|
|
*/
|
2002-05-02 01:06:41 +02:00
|
|
|
typnamespace = typform->typnamespace;
|
|
|
|
if (typnamespace != PG_CATALOG_NAMESPACE &&
|
2007-03-23 20:53:52 +01:00
|
|
|
!list_member_oid(activeSearchPath, typnamespace))
|
2002-05-02 01:06:41 +02:00
|
|
|
visible = false;
|
|
|
|
else
|
2002-04-17 22:57:57 +02:00
|
|
|
{
|
2002-05-02 01:06:41 +02:00
|
|
|
/*
|
|
|
|
* If it is in the path, it might still not be visible; it could be
|
|
|
|
* hidden by another type of the same name earlier in the path. So we
|
2005-10-07 00:43:16 +02:00
|
|
|
* must do a slow check for conflicting types.
|
2002-05-02 01:06:41 +02:00
|
|
|
*/
|
|
|
|
char *typname = NameStr(typform->typname);
|
2005-10-07 00:43:16 +02:00
|
|
|
ListCell *l;
|
2002-04-17 22:57:57 +02:00
|
|
|
|
2005-10-07 00:43:16 +02:00
|
|
|
visible = false;
|
2007-03-23 20:53:52 +01:00
|
|
|
foreach(l, activeSearchPath)
|
2005-10-07 00:43:16 +02:00
|
|
|
{
|
|
|
|
Oid namespaceId = lfirst_oid(l);
|
|
|
|
|
|
|
|
if (namespaceId == typnamespace)
|
|
|
|
{
|
|
|
|
/* Found it first in path */
|
|
|
|
visible = true;
|
|
|
|
break;
|
|
|
|
}
|
2010-02-14 19:42:19 +01:00
|
|
|
if (SearchSysCacheExists2(TYPENAMENSP,
|
|
|
|
PointerGetDatum(typname),
|
|
|
|
ObjectIdGetDatum(namespaceId)))
|
2005-10-07 00:43:16 +02:00
|
|
|
{
|
|
|
|
/* Found something else first in path */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-04-17 22:57:57 +02:00
|
|
|
}
|
|
|
|
|
2002-05-02 01:06:41 +02:00
|
|
|
ReleaseSysCache(typtup);
|
|
|
|
|
|
|
|
return visible;
|
2002-04-17 22:57:57 +02:00
|
|
|
}
|
|
|
|
|
2002-05-02 01:06:41 +02:00
|
|
|
|
2002-04-06 08:59:25 +02:00
|
|
|
/*
|
|
|
|
* FuncnameGetCandidates
|
|
|
|
* Given a possibly-qualified function name and argument count,
|
|
|
|
* retrieve a list of the possible matches.
|
|
|
|
*
|
2002-04-25 04:56:56 +02:00
|
|
|
* If nargs is -1, we return all functions matching the given name,
|
2009-10-08 04:39:25 +02:00
|
|
|
* regardless of argument count. (argnames must be NIL, and expand_variadic
|
|
|
|
* and expand_defaults must be false, in this case.)
|
|
|
|
*
|
|
|
|
* If argnames isn't NIL, we are considering a named- or mixed-notation call,
|
|
|
|
* and only functions having all the listed argument names will be returned.
|
|
|
|
* (We assume that length(argnames) <= nargs and all the passed-in names are
|
|
|
|
* distinct.) The returned structs will include an argnumbers array showing
|
|
|
|
* the actual argument index for each logical argument position.
|
2008-07-16 03:30:23 +02:00
|
|
|
*
|
|
|
|
* If expand_variadic is true, then variadic functions having the same number
|
|
|
|
* or fewer arguments will be retrieved, with the variadic argument and any
|
|
|
|
* additional argument positions filled with the variadic element type.
|
|
|
|
* nvargs in the returned struct is set to the number of such arguments.
|
|
|
|
* If expand_variadic is false, variadic arguments are not treated specially,
|
|
|
|
* and the returned nvargs will always be zero.
|
2002-04-25 04:56:56 +02:00
|
|
|
*
|
2008-12-18 19:20:35 +01:00
|
|
|
* If expand_defaults is true, functions that could match after insertion of
|
|
|
|
* default argument values will also be retrieved. In this case the returned
|
|
|
|
* structs could have nargs > passed-in nargs, and ndargs is set to the number
|
|
|
|
* of additional args (which can be retrieved from the function's
|
|
|
|
* proargdefaults entry).
|
|
|
|
*
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
* If include_out_arguments is true, then OUT-mode arguments are considered to
|
|
|
|
* be included in the argument list. Their types are included in the returned
|
|
|
|
* arrays, and argnumbers are indexes in proallargtypes not proargtypes.
|
|
|
|
* We also set nominalnargs to be the length of proallargtypes not proargtypes.
|
|
|
|
* Otherwise OUT-mode arguments are ignored.
|
|
|
|
*
|
2008-12-18 19:20:35 +01:00
|
|
|
* It is not possible for nvargs and ndargs to both be nonzero in the same
|
|
|
|
* list entry, since default insertion allows matches to functions with more
|
|
|
|
* than nargs arguments while the variadic transformation requires the same
|
|
|
|
* number or less.
|
2008-12-04 18:51:28 +01:00
|
|
|
*
|
2009-10-08 04:39:25 +02:00
|
|
|
* When argnames isn't NIL, the returned args[] type arrays are not ordered
|
|
|
|
* according to the functions' declarations, but rather according to the call:
|
|
|
|
* first any positional arguments, then the named arguments, then defaulted
|
|
|
|
* arguments (if needed and allowed by expand_defaults). The argnumbers[]
|
|
|
|
* array can be used to map this back to the catalog information.
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
* argnumbers[k] is set to the proargtypes or proallargtypes index of the
|
|
|
|
* k'th call argument.
|
2009-10-08 04:39:25 +02:00
|
|
|
*
|
2002-04-06 08:59:25 +02:00
|
|
|
* We search a single namespace if the function name is qualified, else
|
2008-12-18 19:20:35 +01:00
|
|
|
* all namespaces in the search path. In the multiple-namespace case,
|
|
|
|
* we arrange for entries in earlier namespaces to mask identical entries in
|
|
|
|
* later namespaces.
|
|
|
|
*
|
|
|
|
* When expanding variadics, we arrange for non-variadic functions to mask
|
|
|
|
* variadic ones if the expanded argument list is the same. It is still
|
|
|
|
* possible for there to be conflicts between different variadic functions,
|
|
|
|
* however.
|
|
|
|
*
|
|
|
|
* It is guaranteed that the return list will never contain multiple entries
|
|
|
|
* with identical argument lists. When expand_defaults is true, the entries
|
|
|
|
* could have more than nargs positions, but we still guarantee that they are
|
2009-10-08 04:39:25 +02:00
|
|
|
* distinct in the first nargs positions. However, if argnames isn't NIL or
|
|
|
|
* either expand_variadic or expand_defaults is true, there might be multiple
|
|
|
|
* candidate functions that expand to identical argument lists. Rather than
|
|
|
|
* throw error here, we report such situations by returning a single entry
|
|
|
|
* with oid = 0 that represents a set of such conflicting candidates.
|
2008-12-18 19:20:35 +01:00
|
|
|
* The caller might end up discarding such an entry anyway, but if it selects
|
|
|
|
* such an entry it should react as though the call were ambiguous.
|
2014-01-23 18:40:29 +01:00
|
|
|
*
|
|
|
|
* If missing_ok is true, an empty list (NULL) is returned if the name was
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
* schema-qualified with a schema that does not exist. Likewise if no
|
2014-01-23 18:40:29 +01:00
|
|
|
* candidate is found for other reasons.
|
2002-04-06 08:59:25 +02:00
|
|
|
*/
|
|
|
|
FuncCandidateList
|
2009-10-08 04:39:25 +02:00
|
|
|
FuncnameGetCandidates(List *names, int nargs, List *argnames,
|
2014-01-23 18:40:29 +01:00
|
|
|
bool expand_variadic, bool expand_defaults,
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
bool include_out_arguments, bool missing_ok)
|
2002-04-06 08:59:25 +02:00
|
|
|
{
|
|
|
|
FuncCandidateList resultList = NULL;
|
2008-12-18 19:20:35 +01:00
|
|
|
bool any_special = false;
|
2002-07-30 01:46:35 +02:00
|
|
|
char *schemaname;
|
|
|
|
char *funcname;
|
2002-04-06 08:59:25 +02:00
|
|
|
Oid namespaceId;
|
|
|
|
CatCList *catlist;
|
|
|
|
int i;
|
|
|
|
|
2008-07-16 03:30:23 +02:00
|
|
|
/* check for caller error */
|
2008-12-18 19:20:35 +01:00
|
|
|
Assert(nargs >= 0 || !(expand_variadic | expand_defaults));
|
2008-07-16 03:30:23 +02:00
|
|
|
|
2002-04-06 08:59:25 +02:00
|
|
|
/* deconstruct the name list */
|
2002-07-30 01:46:35 +02:00
|
|
|
DeconstructQualifiedName(names, &schemaname, &funcname);
|
2002-04-06 08:59:25 +02:00
|
|
|
|
|
|
|
if (schemaname)
|
|
|
|
{
|
|
|
|
/* use exact schema given */
|
2014-01-23 18:40:29 +01:00
|
|
|
namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
|
|
|
|
if (!OidIsValid(namespaceId))
|
|
|
|
return NULL;
|
2002-04-06 08:59:25 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* flag to indicate we need namespace search */
|
|
|
|
namespaceId = InvalidOid;
|
2002-04-30 00:15:07 +02:00
|
|
|
recomputeNamespacePath();
|
2002-04-06 08:59:25 +02:00
|
|
|
}
|
|
|
|
|
2005-03-29 02:17:27 +02:00
|
|
|
/* Search syscache by name only */
|
2010-02-14 19:42:19 +01:00
|
|
|
catlist = SearchSysCacheList1(PROCNAMEARGSNSP, CStringGetDatum(funcname));
|
2002-04-06 08:59:25 +02:00
|
|
|
|
|
|
|
for (i = 0; i < catlist->n_members; i++)
|
|
|
|
{
|
|
|
|
HeapTuple proctup = &catlist->members[i]->tuple;
|
|
|
|
Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
Oid *proargtypes = procform->proargtypes.values;
|
2005-03-29 02:17:27 +02:00
|
|
|
int pronargs = procform->pronargs;
|
2008-07-16 03:30:23 +02:00
|
|
|
int effective_nargs;
|
2002-04-06 08:59:25 +02:00
|
|
|
int pathpos = 0;
|
2008-07-16 18:55:24 +02:00
|
|
|
bool variadic;
|
2008-12-18 19:20:35 +01:00
|
|
|
bool use_defaults;
|
2008-07-16 18:55:24 +02:00
|
|
|
Oid va_elem_type;
|
2009-10-08 04:39:25 +02:00
|
|
|
int *argnumbers = NULL;
|
2002-04-06 08:59:25 +02:00
|
|
|
FuncCandidateList newResult;
|
|
|
|
|
|
|
|
if (OidIsValid(namespaceId))
|
|
|
|
{
|
|
|
|
/* Consider only procs in specified namespace */
|
|
|
|
if (procform->pronamespace != namespaceId)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-04-20 04:37:38 +02:00
|
|
|
/*
|
|
|
|
* Consider only procs that are in the search path and are not in
|
|
|
|
* the temp namespace.
|
|
|
|
*/
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *nsp;
|
2002-04-06 08:59:25 +02:00
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
foreach(nsp, activeSearchPath)
|
2002-05-17 22:53:33 +02:00
|
|
|
{
|
2007-04-20 04:37:38 +02:00
|
|
|
if (procform->pronamespace == lfirst_oid(nsp) &&
|
|
|
|
procform->pronamespace != myTempNamespace)
|
2002-05-17 22:53:33 +02:00
|
|
|
break;
|
|
|
|
pathpos++;
|
2002-04-06 08:59:25 +02:00
|
|
|
}
|
2004-05-26 06:41:50 +02:00
|
|
|
if (nsp == NULL)
|
2002-05-17 22:53:33 +02:00
|
|
|
continue; /* proc is not in search path */
|
2008-07-16 03:30:23 +02:00
|
|
|
}
|
|
|
|
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
/*
|
|
|
|
* If we are asked to match to OUT arguments, then use the
|
|
|
|
* proallargtypes array (which includes those); otherwise use
|
|
|
|
* proargtypes (which doesn't). Of course, if proallargtypes is null,
|
|
|
|
* we always use proargtypes.
|
|
|
|
*/
|
|
|
|
if (include_out_arguments)
|
|
|
|
{
|
|
|
|
Datum proallargtypes;
|
|
|
|
bool isNull;
|
|
|
|
|
|
|
|
proallargtypes = SysCacheGetAttr(PROCNAMEARGSNSP, proctup,
|
|
|
|
Anum_pg_proc_proallargtypes,
|
|
|
|
&isNull);
|
|
|
|
if (!isNull)
|
|
|
|
{
|
|
|
|
ArrayType *arr = DatumGetArrayTypeP(proallargtypes);
|
|
|
|
|
|
|
|
pronargs = ARR_DIMS(arr)[0];
|
|
|
|
if (ARR_NDIM(arr) != 1 ||
|
|
|
|
pronargs < 0 ||
|
|
|
|
ARR_HASNULL(arr) ||
|
|
|
|
ARR_ELEMTYPE(arr) != OIDOID)
|
|
|
|
elog(ERROR, "proallargtypes is not a 1-D Oid array or it contains nulls");
|
|
|
|
Assert(pronargs >= procform->pronargs);
|
|
|
|
proargtypes = (Oid *) ARR_DATA_PTR(arr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-08 04:39:25 +02:00
|
|
|
if (argnames != NIL)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Call uses named or mixed notation
|
|
|
|
*
|
|
|
|
* Named or mixed notation can match a variadic function only if
|
|
|
|
* expand_variadic is off; otherwise there is no way to match the
|
|
|
|
* presumed-nameless parameters expanded from the variadic array.
|
|
|
|
*/
|
|
|
|
if (OidIsValid(procform->provariadic) && expand_variadic)
|
|
|
|
continue;
|
|
|
|
va_elem_type = InvalidOid;
|
|
|
|
variadic = false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check argument count.
|
|
|
|
*/
|
|
|
|
Assert(nargs >= 0); /* -1 not supported with argnames */
|
|
|
|
|
|
|
|
if (pronargs > nargs && expand_defaults)
|
|
|
|
{
|
|
|
|
/* Ignore if not enough default expressions */
|
|
|
|
if (nargs + procform->pronargdefaults < pronargs)
|
|
|
|
continue;
|
|
|
|
use_defaults = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
use_defaults = false;
|
|
|
|
|
|
|
|
/* Ignore if it doesn't match requested argument count */
|
|
|
|
if (pronargs != nargs && !use_defaults)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Check for argument name match, generate positional mapping */
|
|
|
|
if (!MatchNamedCall(proctup, nargs, argnames,
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
include_out_arguments, pronargs,
|
2009-10-08 04:39:25 +02:00
|
|
|
&argnumbers))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Named argument matching is always "special" */
|
|
|
|
any_special = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Call uses positional notation
|
|
|
|
*
|
|
|
|
* Check if function is variadic, and get variadic element type if
|
|
|
|
* so. If expand_variadic is false, we should just ignore
|
|
|
|
* variadic-ness.
|
|
|
|
*/
|
|
|
|
if (pronargs <= nargs && expand_variadic)
|
|
|
|
{
|
|
|
|
va_elem_type = procform->provariadic;
|
|
|
|
variadic = OidIsValid(va_elem_type);
|
|
|
|
any_special |= variadic;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
va_elem_type = InvalidOid;
|
|
|
|
variadic = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if function can match by using parameter defaults.
|
|
|
|
*/
|
|
|
|
if (pronargs > nargs && expand_defaults)
|
|
|
|
{
|
|
|
|
/* Ignore if not enough default expressions */
|
|
|
|
if (nargs + procform->pronargdefaults < pronargs)
|
|
|
|
continue;
|
|
|
|
use_defaults = true;
|
|
|
|
any_special = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
use_defaults = false;
|
|
|
|
|
|
|
|
/* Ignore if it doesn't match requested argument count */
|
|
|
|
if (nargs >= 0 && pronargs != nargs && !variadic && !use_defaults)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2008-07-16 03:30:23 +02:00
|
|
|
/*
|
|
|
|
* We must compute the effective argument list so that we can easily
|
|
|
|
* compare it to earlier results. We waste a palloc cycle if it gets
|
|
|
|
* masked by an earlier result, but really that's a pretty infrequent
|
|
|
|
* case so it's not worth worrying about.
|
|
|
|
*/
|
|
|
|
effective_nargs = Max(pronargs, nargs);
|
|
|
|
newResult = (FuncCandidateList)
|
2015-02-20 06:11:42 +01:00
|
|
|
palloc(offsetof(struct _FuncCandidateList, args) +
|
|
|
|
effective_nargs * sizeof(Oid));
|
2008-07-16 03:30:23 +02:00
|
|
|
newResult->pathpos = pathpos;
|
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
|
|
|
newResult->oid = procform->oid;
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
newResult->nominalnargs = pronargs;
|
2008-07-16 03:30:23 +02:00
|
|
|
newResult->nargs = effective_nargs;
|
2009-10-08 04:39:25 +02:00
|
|
|
newResult->argnumbers = argnumbers;
|
|
|
|
if (argnumbers)
|
|
|
|
{
|
|
|
|
/* Re-order the argument types into call's logical order */
|
2022-10-05 10:01:41 +02:00
|
|
|
for (int j = 0; j < pronargs; j++)
|
|
|
|
newResult->args[j] = proargtypes[argnumbers[j]];
|
2009-10-08 04:39:25 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Simple positional case, just copy proargtypes as-is */
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
memcpy(newResult->args, proargtypes, pronargs * sizeof(Oid));
|
2009-10-08 04:39:25 +02:00
|
|
|
}
|
2008-07-16 03:30:23 +02:00
|
|
|
if (variadic)
|
|
|
|
{
|
|
|
|
newResult->nvargs = effective_nargs - pronargs + 1;
|
|
|
|
/* Expand variadic argument into N copies of element type */
|
2022-10-05 10:01:41 +02:00
|
|
|
for (int j = pronargs - 1; j < effective_nargs; j++)
|
|
|
|
newResult->args[j] = va_elem_type;
|
2008-07-16 03:30:23 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
newResult->nvargs = 0;
|
2008-12-18 19:20:35 +01:00
|
|
|
newResult->ndargs = use_defaults ? pronargs - nargs : 0;
|
2008-12-04 18:51:28 +01:00
|
|
|
|
2008-07-16 03:30:23 +02:00
|
|
|
/*
|
|
|
|
* Does it have the same arguments as something we already accepted?
|
2008-12-18 19:20:35 +01:00
|
|
|
* If so, decide what to do to avoid returning duplicate argument
|
|
|
|
* lists. We can skip this check for the single-namespace case if no
|
2009-10-08 04:39:25 +02:00
|
|
|
* special (named, variadic or defaults) match has been made, since
|
|
|
|
* then the unique index on pg_proc guarantees all the matches have
|
|
|
|
* different argument lists.
|
2008-07-16 03:30:23 +02:00
|
|
|
*/
|
2008-12-18 19:20:35 +01:00
|
|
|
if (resultList != NULL &&
|
|
|
|
(any_special || !OidIsValid(namespaceId)))
|
2008-07-16 03:30:23 +02:00
|
|
|
{
|
2002-04-06 08:59:25 +02:00
|
|
|
/*
|
|
|
|
* If we have an ordered list from SearchSysCacheList (the normal
|
|
|
|
* case), then any conflicting proc must immediately adjoin this
|
|
|
|
* one in the list, so we only need to look at the newest result
|
|
|
|
* item. If we have an unordered list, we have to scan the whole
|
2008-07-16 03:30:23 +02:00
|
|
|
* result list. Also, if either the current candidate or any
|
2008-12-18 19:20:35 +01:00
|
|
|
* previous candidate is a special match, we can't assume that
|
2008-07-16 03:30:23 +02:00
|
|
|
* conflicts are adjacent.
|
2008-12-18 19:20:35 +01:00
|
|
|
*
|
|
|
|
* We ignore defaulted arguments in deciding what is a match.
|
2002-04-06 08:59:25 +02:00
|
|
|
*/
|
2008-12-18 19:20:35 +01:00
|
|
|
FuncCandidateList prevResult;
|
|
|
|
|
|
|
|
if (catlist->ordered && !any_special)
|
2002-04-06 08:59:25 +02:00
|
|
|
{
|
2008-12-18 19:20:35 +01:00
|
|
|
/* ndargs must be 0 if !any_special */
|
|
|
|
if (effective_nargs == resultList->nargs &&
|
|
|
|
memcmp(newResult->args,
|
|
|
|
resultList->args,
|
|
|
|
effective_nargs * sizeof(Oid)) == 0)
|
|
|
|
prevResult = resultList;
|
|
|
|
else
|
|
|
|
prevResult = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int cmp_nargs = newResult->nargs - newResult->ndargs;
|
2002-04-06 08:59:25 +02:00
|
|
|
|
2008-12-18 19:20:35 +01:00
|
|
|
for (prevResult = resultList;
|
|
|
|
prevResult;
|
|
|
|
prevResult = prevResult->next)
|
2002-04-06 08:59:25 +02:00
|
|
|
{
|
2008-12-18 19:20:35 +01:00
|
|
|
if (cmp_nargs == prevResult->nargs - prevResult->ndargs &&
|
2008-07-16 03:30:23 +02:00
|
|
|
memcmp(newResult->args,
|
2008-12-18 19:20:35 +01:00
|
|
|
prevResult->args,
|
|
|
|
cmp_nargs * sizeof(Oid)) == 0)
|
|
|
|
break;
|
2002-04-06 08:59:25 +02:00
|
|
|
}
|
2008-12-18 19:20:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (prevResult)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We have a match with a previous result. Decide which one
|
|
|
|
* to keep, or mark it ambiguous if we can't decide. The
|
|
|
|
* logic here is preference > 0 means prefer the old result,
|
|
|
|
* preference < 0 means prefer the new, preference = 0 means
|
|
|
|
* ambiguous.
|
|
|
|
*/
|
|
|
|
int preference;
|
|
|
|
|
|
|
|
if (pathpos != prevResult->pathpos)
|
2002-04-06 08:59:25 +02:00
|
|
|
{
|
2008-12-18 19:20:35 +01:00
|
|
|
/*
|
|
|
|
* Prefer the one that's earlier in the search path.
|
|
|
|
*/
|
|
|
|
preference = pathpos - prevResult->pathpos;
|
2002-04-06 08:59:25 +02:00
|
|
|
}
|
2008-12-18 19:20:35 +01:00
|
|
|
else if (variadic && prevResult->nvargs == 0)
|
2002-04-06 08:59:25 +02:00
|
|
|
{
|
2008-07-16 03:30:23 +02:00
|
|
|
/*
|
2008-12-18 19:20:35 +01:00
|
|
|
* With variadic functions we could have, for example,
|
|
|
|
* both foo(numeric) and foo(variadic numeric[]) in the
|
|
|
|
* same namespace; if so we prefer the non-variadic match
|
|
|
|
* on efficiency grounds.
|
2008-07-16 03:30:23 +02:00
|
|
|
*/
|
2008-12-18 19:20:35 +01:00
|
|
|
preference = 1;
|
|
|
|
}
|
|
|
|
else if (!variadic && prevResult->nvargs > 0)
|
|
|
|
{
|
|
|
|
preference = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*----------
|
|
|
|
* We can't decide. This can happen with, for example,
|
|
|
|
* both foo(numeric, variadic numeric[]) and
|
|
|
|
* foo(variadic numeric[]) in the same namespace, or
|
|
|
|
* both foo(int) and foo (int, int default something)
|
2009-10-08 04:39:25 +02:00
|
|
|
* in the same namespace, or both foo(a int, b text)
|
|
|
|
* and foo(b text, a int) in the same namespace.
|
2008-12-18 19:20:35 +01:00
|
|
|
*----------
|
|
|
|
*/
|
|
|
|
preference = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (preference > 0)
|
|
|
|
{
|
|
|
|
/* keep previous result */
|
|
|
|
pfree(newResult);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (preference < 0)
|
|
|
|
{
|
|
|
|
/* remove previous result from the list */
|
|
|
|
if (prevResult == resultList)
|
|
|
|
resultList = prevResult->next;
|
|
|
|
else
|
2008-07-16 03:30:23 +02:00
|
|
|
{
|
2008-12-18 19:20:35 +01:00
|
|
|
FuncCandidateList prevPrevResult;
|
2008-12-04 18:51:28 +01:00
|
|
|
|
2008-12-18 19:20:35 +01:00
|
|
|
for (prevPrevResult = resultList;
|
|
|
|
prevPrevResult;
|
|
|
|
prevPrevResult = prevPrevResult->next)
|
2008-12-04 18:51:28 +01:00
|
|
|
{
|
2008-12-18 19:20:35 +01:00
|
|
|
if (prevResult == prevPrevResult->next)
|
|
|
|
{
|
|
|
|
prevPrevResult->next = prevResult->next;
|
|
|
|
break;
|
|
|
|
}
|
2008-12-04 18:51:28 +01:00
|
|
|
}
|
2008-12-18 19:20:35 +01:00
|
|
|
Assert(prevPrevResult); /* assert we found it */
|
2008-07-16 03:30:23 +02:00
|
|
|
}
|
2008-12-18 19:20:35 +01:00
|
|
|
pfree(prevResult);
|
|
|
|
/* fall through to add newResult to list */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* mark old result as ambiguous, discard new */
|
|
|
|
prevResult->oid = InvalidOid;
|
2008-07-16 03:30:23 +02:00
|
|
|
pfree(newResult);
|
2008-12-18 19:20:35 +01:00
|
|
|
continue;
|
2002-04-06 08:59:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Okay to add it to result list
|
|
|
|
*/
|
|
|
|
newResult->next = resultList;
|
|
|
|
resultList = newResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCacheList(catlist);
|
2002-04-17 01:08:12 +02:00
|
|
|
|
|
|
|
return resultList;
|
|
|
|
}
|
|
|
|
|
2009-10-08 04:39:25 +02:00
|
|
|
/*
|
|
|
|
* MatchNamedCall
|
|
|
|
* Given a pg_proc heap tuple and a call's list of argument names,
|
|
|
|
* check whether the function could match the call.
|
|
|
|
*
|
|
|
|
* The call could match if all supplied argument names are accepted by
|
|
|
|
* the function, in positions after the last positional argument, and there
|
|
|
|
* are defaults for all unsupplied arguments.
|
|
|
|
*
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
* If include_out_arguments is true, we are treating OUT arguments as
|
|
|
|
* included in the argument list. pronargs is the number of arguments
|
|
|
|
* we're considering (the length of either proargtypes or proallargtypes).
|
|
|
|
*
|
2009-10-08 04:39:25 +02:00
|
|
|
* The number of positional arguments is nargs - list_length(argnames).
|
|
|
|
* Note caller has already done basic checks on argument count.
|
|
|
|
*
|
|
|
|
* On match, return true and fill *argnumbers with a palloc'd array showing
|
|
|
|
* the mapping from call argument positions to actual function argument
|
|
|
|
* numbers. Defaulted arguments are included in this map, at positions
|
|
|
|
* after the last supplied argument.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
bool include_out_arguments, int pronargs,
|
2009-10-08 04:39:25 +02:00
|
|
|
int **argnumbers)
|
|
|
|
{
|
|
|
|
Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
|
|
|
|
int numposargs = nargs - list_length(argnames);
|
|
|
|
int pronallargs;
|
|
|
|
Oid *p_argtypes;
|
|
|
|
char **p_argnames;
|
|
|
|
char *p_argmodes;
|
|
|
|
bool arggiven[FUNC_MAX_ARGS];
|
|
|
|
bool isnull;
|
|
|
|
int ap; /* call args position */
|
|
|
|
int pp; /* proargs position */
|
|
|
|
ListCell *lc;
|
|
|
|
|
|
|
|
Assert(argnames != NIL);
|
|
|
|
Assert(numposargs >= 0);
|
|
|
|
Assert(nargs <= pronargs);
|
|
|
|
|
|
|
|
/* Ignore this function if its proargnames is null */
|
|
|
|
(void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proargnames,
|
|
|
|
&isnull);
|
|
|
|
if (isnull)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/* OK, let's extract the argument names and types */
|
|
|
|
pronallargs = get_func_arg_info(proctup,
|
|
|
|
&p_argtypes, &p_argnames, &p_argmodes);
|
|
|
|
Assert(p_argnames != NULL);
|
|
|
|
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
Assert(include_out_arguments ? (pronargs == pronallargs) : (pronargs <= pronallargs));
|
|
|
|
|
2009-10-08 04:39:25 +02:00
|
|
|
/* initialize state for matching */
|
|
|
|
*argnumbers = (int *) palloc(pronargs * sizeof(int));
|
|
|
|
memset(arggiven, false, pronargs * sizeof(bool));
|
|
|
|
|
|
|
|
/* there are numposargs positional args before the named args */
|
|
|
|
for (ap = 0; ap < numposargs; ap++)
|
|
|
|
{
|
|
|
|
(*argnumbers)[ap] = ap;
|
|
|
|
arggiven[ap] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now examine the named args */
|
|
|
|
foreach(lc, argnames)
|
|
|
|
{
|
|
|
|
char *argname = (char *) lfirst(lc);
|
|
|
|
bool found;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
pp = 0;
|
|
|
|
found = false;
|
|
|
|
for (i = 0; i < pronallargs; i++)
|
|
|
|
{
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
/* consider only input params, except with include_out_arguments */
|
|
|
|
if (!include_out_arguments &&
|
|
|
|
p_argmodes &&
|
2009-10-08 04:39:25 +02:00
|
|
|
(p_argmodes[i] != FUNC_PARAM_IN &&
|
|
|
|
p_argmodes[i] != FUNC_PARAM_INOUT &&
|
|
|
|
p_argmodes[i] != FUNC_PARAM_VARIADIC))
|
|
|
|
continue;
|
|
|
|
if (p_argnames[i] && strcmp(p_argnames[i], argname) == 0)
|
|
|
|
{
|
|
|
|
/* fail if argname matches a positional argument */
|
|
|
|
if (arggiven[pp])
|
|
|
|
return false;
|
|
|
|
arggiven[pp] = true;
|
|
|
|
(*argnumbers)[ap] = pp;
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
/* increase pp only for considered parameters */
|
2009-10-08 04:39:25 +02:00
|
|
|
pp++;
|
|
|
|
}
|
|
|
|
/* if name isn't in proargnames, fail */
|
|
|
|
if (!found)
|
|
|
|
return false;
|
|
|
|
ap++;
|
|
|
|
}
|
|
|
|
|
|
|
|
Assert(ap == nargs); /* processed all actual parameters */
|
|
|
|
|
|
|
|
/* Check for default arguments */
|
|
|
|
if (nargs < pronargs)
|
|
|
|
{
|
|
|
|
int first_arg_with_default = pronargs - procform->pronargdefaults;
|
|
|
|
|
|
|
|
for (pp = numposargs; pp < pronargs; pp++)
|
|
|
|
{
|
|
|
|
if (arggiven[pp])
|
|
|
|
continue;
|
|
|
|
/* fail if arg not given and no default available */
|
|
|
|
if (pp < first_arg_with_default)
|
|
|
|
return false;
|
|
|
|
(*argnumbers)[ap++] = pp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Assert(ap == pronargs); /* processed all function parameters */
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2002-05-02 01:06:41 +02:00
|
|
|
/*
|
|
|
|
* FunctionIsVisible
|
|
|
|
* Determine whether a function (identified by OID) is visible in the
|
|
|
|
* current search path. Visible means "would be found by searching
|
|
|
|
* for the unqualified function name with exact argument matches".
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
FunctionIsVisible(Oid funcid)
|
|
|
|
{
|
|
|
|
HeapTuple proctup;
|
|
|
|
Form_pg_proc procform;
|
|
|
|
Oid pronamespace;
|
|
|
|
bool visible;
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
|
2002-05-02 01:06:41 +02:00
|
|
|
if (!HeapTupleIsValid(proctup))
|
2003-07-21 03:59:11 +02:00
|
|
|
elog(ERROR, "cache lookup failed for function %u", funcid);
|
2002-05-02 01:06:41 +02:00
|
|
|
procform = (Form_pg_proc) GETSTRUCT(proctup);
|
|
|
|
|
2002-05-17 22:53:33 +02:00
|
|
|
recomputeNamespacePath();
|
|
|
|
|
2002-05-02 01:06:41 +02:00
|
|
|
/*
|
|
|
|
* Quick check: if it ain't in the path at all, it ain't visible. Items in
|
2002-05-17 22:53:33 +02:00
|
|
|
* the system namespace are surely in the path and so we needn't even do
|
2004-05-26 06:41:50 +02:00
|
|
|
* list_member_oid() for them.
|
2002-05-02 01:06:41 +02:00
|
|
|
*/
|
|
|
|
pronamespace = procform->pronamespace;
|
|
|
|
if (pronamespace != PG_CATALOG_NAMESPACE &&
|
2007-03-23 20:53:52 +01:00
|
|
|
!list_member_oid(activeSearchPath, pronamespace))
|
2002-05-02 01:06:41 +02:00
|
|
|
visible = false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If it is in the path, it might still not be visible; it could be
|
|
|
|
* hidden by another proc of the same name and arguments earlier in
|
|
|
|
* the path. So we must do a slow check to see if this is the same
|
|
|
|
* proc that would be found by FuncnameGetCandidates.
|
|
|
|
*/
|
|
|
|
char *proname = NameStr(procform->proname);
|
|
|
|
int nargs = procform->pronargs;
|
|
|
|
FuncCandidateList clist;
|
|
|
|
|
|
|
|
visible = false;
|
|
|
|
|
2008-07-16 03:30:23 +02:00
|
|
|
clist = FuncnameGetCandidates(list_make1(makeString(proname)),
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
nargs, NIL, false, false, false, false);
|
2002-05-02 01:06:41 +02:00
|
|
|
|
|
|
|
for (; clist; clist = clist->next)
|
|
|
|
{
|
2005-03-29 02:17:27 +02:00
|
|
|
if (memcmp(clist->args, procform->proargtypes.values,
|
2002-05-02 01:06:41 +02:00
|
|
|
nargs * sizeof(Oid)) == 0)
|
|
|
|
{
|
|
|
|
/* Found the expected entry; is it the right proc? */
|
|
|
|
visible = (clist->oid == funcid);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(proctup);
|
|
|
|
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-02 01:22:43 +02:00
|
|
|
/*
|
|
|
|
* OpernameGetOprid
|
|
|
|
* Given a possibly-qualified operator name and exact input datatypes,
|
|
|
|
* look up the operator. Returns InvalidOid if not found.
|
|
|
|
*
|
Remove support for postfix (right-unary) operators.
This feature has been a thorn in our sides for a long time, causing
many grammatical ambiguity problems. It doesn't seem worth the
pain to continue to support it, so remove it.
There are some follow-on improvements we can make in the grammar,
but this commit only removes the bare minimum number of productions,
plus assorted backend support code.
Note that pg_dump and psql continue to have full support, since
they may be used against older servers. However, pg_dump warns
about postfix operators. There is also a check in pg_upgrade.
Documentation-wise, I (tgl) largely removed the "left unary"
terminology in favor of saying "prefix operator", which is
a more standard and IMO less confusing term.
I included a catversion bump, although no initial catalog data
changes here, to mark the boundary at which oprkind = 'r'
stopped being valid in pg_operator.
Mark Dilger, based on work by myself and Robert Haas;
review by John Naylor
Discussion: https://postgr.es/m/38ca86db-42ab-9b48-2902-337a0d6b8311@2ndquadrant.com
2020-09-18 01:38:05 +02:00
|
|
|
* Pass oprleft = InvalidOid for a prefix op.
|
2006-05-02 01:22:43 +02:00
|
|
|
*
|
|
|
|
* If the operator name is not schema-qualified, it is sought in the current
|
2014-01-23 18:40:29 +01:00
|
|
|
* namespace search path. If the name is schema-qualified and the given
|
|
|
|
* schema does not exist, InvalidOid is returned.
|
2006-05-02 01:22:43 +02:00
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
|
|
|
|
{
|
|
|
|
char *schemaname;
|
|
|
|
char *opername;
|
|
|
|
CatCList *catlist;
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
/* deconstruct the name list */
|
|
|
|
DeconstructQualifiedName(names, &schemaname, &opername);
|
|
|
|
|
|
|
|
if (schemaname)
|
|
|
|
{
|
|
|
|
/* search only in exact schema given */
|
|
|
|
Oid namespaceId;
|
|
|
|
|
2014-01-23 18:40:29 +01:00
|
|
|
namespaceId = LookupExplicitNamespace(schemaname, true);
|
|
|
|
if (OidIsValid(namespaceId))
|
2006-05-02 01:22:43 +02:00
|
|
|
{
|
2014-01-23 18:40:29 +01:00
|
|
|
HeapTuple opertup;
|
|
|
|
|
|
|
|
opertup = SearchSysCache4(OPERNAMENSP,
|
|
|
|
CStringGetDatum(opername),
|
|
|
|
ObjectIdGetDatum(oprleft),
|
|
|
|
ObjectIdGetDatum(oprright),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
|
|
|
if (HeapTupleIsValid(opertup))
|
|
|
|
{
|
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_operator operclass = (Form_pg_operator) GETSTRUCT(opertup);
|
|
|
|
Oid result = operclass->oid;
|
2006-05-02 01:22:43 +02:00
|
|
|
|
2014-01-23 18:40:29 +01:00
|
|
|
ReleaseSysCache(opertup);
|
|
|
|
return result;
|
|
|
|
}
|
2006-05-02 01:22:43 +02:00
|
|
|
}
|
2014-01-23 18:40:29 +01:00
|
|
|
|
2006-05-02 01:22:43 +02:00
|
|
|
return InvalidOid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Search syscache by name and argument types */
|
2010-02-14 19:42:19 +01:00
|
|
|
catlist = SearchSysCacheList3(OPERNAMENSP,
|
|
|
|
CStringGetDatum(opername),
|
|
|
|
ObjectIdGetDatum(oprleft),
|
|
|
|
ObjectIdGetDatum(oprright));
|
2006-05-02 01:22:43 +02:00
|
|
|
|
|
|
|
if (catlist->n_members == 0)
|
|
|
|
{
|
|
|
|
/* no hope, fall out early */
|
|
|
|
ReleaseSysCacheList(catlist);
|
|
|
|
return InvalidOid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have to find the list member that is first in the search path, if
|
|
|
|
* there's more than one. This doubly-nested loop looks ugly, but in
|
|
|
|
* practice there should usually be few catlist members.
|
|
|
|
*/
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
foreach(l, activeSearchPath)
|
2006-05-02 01:22:43 +02:00
|
|
|
{
|
|
|
|
Oid namespaceId = lfirst_oid(l);
|
|
|
|
int i;
|
|
|
|
|
2007-04-20 04:37:38 +02:00
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
2006-05-02 01:22:43 +02:00
|
|
|
for (i = 0; i < catlist->n_members; i++)
|
|
|
|
{
|
|
|
|
HeapTuple opertup = &catlist->members[i]->tuple;
|
|
|
|
Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
|
|
|
|
|
|
|
|
if (operform->oprnamespace == namespaceId)
|
|
|
|
{
|
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
|
|
|
Oid result = operform->oid;
|
2006-05-02 01:22:43 +02:00
|
|
|
|
|
|
|
ReleaseSysCacheList(catlist);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCacheList(catlist);
|
|
|
|
return InvalidOid;
|
|
|
|
}
|
|
|
|
|
2002-04-17 01:08:12 +02:00
|
|
|
/*
|
|
|
|
* OpernameGetCandidates
|
|
|
|
* Given a possibly-qualified operator name and operator kind,
|
|
|
|
* retrieve a list of the possible matches.
|
|
|
|
*
|
2002-04-25 04:56:56 +02:00
|
|
|
* If oprkind is '\0', we return all operators matching the given name,
|
|
|
|
* regardless of arguments.
|
|
|
|
*
|
2002-04-17 01:08:12 +02:00
|
|
|
* We search a single namespace if the operator name is qualified, else
|
|
|
|
* all namespaces in the search path. The return list will never contain
|
2002-04-25 04:56:56 +02:00
|
|
|
* multiple entries with identical argument lists --- in the multiple-
|
2002-04-17 01:08:12 +02:00
|
|
|
* namespace case, we arrange for entries in earlier namespaces to mask
|
|
|
|
* identical entries in later namespaces.
|
|
|
|
*
|
Remove support for postfix (right-unary) operators.
This feature has been a thorn in our sides for a long time, causing
many grammatical ambiguity problems. It doesn't seem worth the
pain to continue to support it, so remove it.
There are some follow-on improvements we can make in the grammar,
but this commit only removes the bare minimum number of productions,
plus assorted backend support code.
Note that pg_dump and psql continue to have full support, since
they may be used against older servers. However, pg_dump warns
about postfix operators. There is also a check in pg_upgrade.
Documentation-wise, I (tgl) largely removed the "left unary"
terminology in favor of saying "prefix operator", which is
a more standard and IMO less confusing term.
I included a catversion bump, although no initial catalog data
changes here, to mark the boundary at which oprkind = 'r'
stopped being valid in pg_operator.
Mark Dilger, based on work by myself and Robert Haas;
review by John Naylor
Discussion: https://postgr.es/m/38ca86db-42ab-9b48-2902-337a0d6b8311@2ndquadrant.com
2020-09-18 01:38:05 +02:00
|
|
|
* The returned items always have two args[] entries --- the first will be
|
|
|
|
* InvalidOid for a prefix oprkind. nargs is always 2, too.
|
2002-04-17 01:08:12 +02:00
|
|
|
*/
|
|
|
|
FuncCandidateList
|
2014-04-08 16:27:56 +02:00
|
|
|
OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
|
2002-04-17 01:08:12 +02:00
|
|
|
{
|
|
|
|
FuncCandidateList resultList = NULL;
|
2003-12-29 22:33:09 +01:00
|
|
|
char *resultSpace = NULL;
|
|
|
|
int nextResult = 0;
|
2002-07-30 01:46:35 +02:00
|
|
|
char *schemaname;
|
|
|
|
char *opername;
|
2002-04-17 01:08:12 +02:00
|
|
|
Oid namespaceId;
|
|
|
|
CatCList *catlist;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* deconstruct the name list */
|
2002-07-30 01:46:35 +02:00
|
|
|
DeconstructQualifiedName(names, &schemaname, &opername);
|
2002-04-17 01:08:12 +02:00
|
|
|
|
|
|
|
if (schemaname)
|
|
|
|
{
|
|
|
|
/* use exact schema given */
|
2014-04-08 16:27:56 +02:00
|
|
|
namespaceId = LookupExplicitNamespace(schemaname, missing_schema_ok);
|
|
|
|
if (missing_schema_ok && !OidIsValid(namespaceId))
|
|
|
|
return NULL;
|
2002-04-17 01:08:12 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* flag to indicate we need namespace search */
|
|
|
|
namespaceId = InvalidOid;
|
2002-04-30 00:15:07 +02:00
|
|
|
recomputeNamespacePath();
|
2002-04-17 01:08:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Search syscache by name only */
|
2010-02-14 19:42:19 +01:00
|
|
|
catlist = SearchSysCacheList1(OPERNAMENSP, CStringGetDatum(opername));
|
2002-04-17 01:08:12 +02:00
|
|
|
|
2003-12-29 22:33:09 +01:00
|
|
|
/*
|
|
|
|
* In typical scenarios, most if not all of the operators found by the
|
|
|
|
* catcache search will end up getting returned; and there can be quite a
|
|
|
|
* few, for common operator names such as '=' or '+'. To reduce the time
|
|
|
|
* spent in palloc, we allocate the result space as an array large enough
|
|
|
|
* to hold all the operators. The original coding of this routine did a
|
|
|
|
* separate palloc for each operator, but profiling revealed that the
|
|
|
|
* pallocs used an unreasonably large fraction of parsing time.
|
|
|
|
*/
|
2015-02-20 06:11:42 +01:00
|
|
|
#define SPACE_PER_OP MAXALIGN(offsetof(struct _FuncCandidateList, args) + \
|
|
|
|
2 * sizeof(Oid))
|
2003-12-29 22:33:09 +01:00
|
|
|
|
|
|
|
if (catlist->n_members > 0)
|
|
|
|
resultSpace = palloc(catlist->n_members * SPACE_PER_OP);
|
|
|
|
|
2002-04-17 01:08:12 +02:00
|
|
|
for (i = 0; i < catlist->n_members; i++)
|
|
|
|
{
|
|
|
|
HeapTuple opertup = &catlist->members[i]->tuple;
|
|
|
|
Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
|
|
|
|
int pathpos = 0;
|
|
|
|
FuncCandidateList newResult;
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/* Ignore operators of wrong kind, if specific kind requested */
|
|
|
|
if (oprkind && operform->oprkind != oprkind)
|
2002-04-17 01:08:12 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (OidIsValid(namespaceId))
|
|
|
|
{
|
|
|
|
/* Consider only opers in specified namespace */
|
|
|
|
if (operform->oprnamespace != namespaceId)
|
|
|
|
continue;
|
|
|
|
/* No need to check args, they must all be different */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-04-20 04:37:38 +02:00
|
|
|
/*
|
|
|
|
* Consider only opers that are in the search path and are not in
|
|
|
|
* the temp namespace.
|
|
|
|
*/
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *nsp;
|
2002-04-17 01:08:12 +02:00
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
foreach(nsp, activeSearchPath)
|
2002-05-17 22:53:33 +02:00
|
|
|
{
|
2007-04-20 04:37:38 +02:00
|
|
|
if (operform->oprnamespace == lfirst_oid(nsp) &&
|
|
|
|
operform->oprnamespace != myTempNamespace)
|
2002-05-17 22:53:33 +02:00
|
|
|
break;
|
|
|
|
pathpos++;
|
2002-04-17 01:08:12 +02:00
|
|
|
}
|
2004-05-26 06:41:50 +02:00
|
|
|
if (nsp == NULL)
|
2002-05-17 22:53:33 +02:00
|
|
|
continue; /* oper is not in search path */
|
2002-04-17 01:08:12 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Okay, it's in the search path, but does it have the same
|
|
|
|
* arguments as something we already accepted? If so, keep only
|
|
|
|
* the one that appears earlier in the search path.
|
|
|
|
*
|
|
|
|
* If we have an ordered list from SearchSysCacheList (the normal
|
|
|
|
* case), then any conflicting oper must immediately adjoin this
|
|
|
|
* one in the list, so we only need to look at the newest result
|
|
|
|
* item. If we have an unordered list, we have to scan the whole
|
|
|
|
* result list.
|
|
|
|
*/
|
|
|
|
if (resultList)
|
|
|
|
{
|
|
|
|
FuncCandidateList prevResult;
|
|
|
|
|
|
|
|
if (catlist->ordered)
|
|
|
|
{
|
|
|
|
if (operform->oprleft == resultList->args[0] &&
|
|
|
|
operform->oprright == resultList->args[1])
|
|
|
|
prevResult = resultList;
|
|
|
|
else
|
|
|
|
prevResult = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (prevResult = resultList;
|
|
|
|
prevResult;
|
|
|
|
prevResult = prevResult->next)
|
|
|
|
{
|
|
|
|
if (operform->oprleft == prevResult->args[0] &&
|
|
|
|
operform->oprright == prevResult->args[1])
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (prevResult)
|
|
|
|
{
|
|
|
|
/* We have a match with a previous result */
|
|
|
|
Assert(pathpos != prevResult->pathpos);
|
|
|
|
if (pathpos > prevResult->pathpos)
|
|
|
|
continue; /* keep previous result */
|
|
|
|
/* replace previous result */
|
|
|
|
prevResult->pathpos = pathpos;
|
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
|
|
|
prevResult->oid = operform->oid;
|
2002-04-17 01:08:12 +02:00
|
|
|
continue; /* args are same, of course */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Okay to add it to result list
|
|
|
|
*/
|
2003-12-29 22:33:09 +01:00
|
|
|
newResult = (FuncCandidateList) (resultSpace + nextResult);
|
|
|
|
nextResult += SPACE_PER_OP;
|
|
|
|
|
2002-04-17 01:08:12 +02:00
|
|
|
newResult->pathpos = pathpos;
|
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
|
|
|
newResult->oid = operform->oid;
|
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of
OUT parameters, for procedures only. While that had some advantages
for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty
disastrous from a number of other perspectives. Notably, since the
primary key of pg_proc is name + proargtypes, this made it possible to
have multiple procedures with identical names + input arguments and
differing output argument types. That would make it impossible to call
any one of the procedures by writing just NULL (or "?", or any other
data-type-free notation) for the output argument(s). The change also
seems likely to cause grave confusion for client applications that
examine pg_proc and expect the traditional definition of proargtypes.
Hence, revert the definition of proargtypes to what it was, and
undo a number of complications that had been added to support that.
To support the SQL-spec behavior of DROP PROCEDURE, when there are
no argmode markers in the command's parameter list, we perform the
lookup both ways (that is, matching against both proargtypes and
proallargtypes), succeeding if we get just one unique match.
In principle this could result in ambiguous-function failures
that would not happen when using only one of the two rules.
However, overloading of procedure names is thought to be a pretty
rare usage, so this shouldn't cause many problems in practice.
Postgres-specific code such as pg_dump can defend against any
possibility of such failures by being careful to specify argmodes
for all procedure arguments.
This also fixes a few other bugs in the area of CALL statements
with named parameters, and improves the documentation a little.
catversion bump forced because the representation of procedures
with OUT arguments changes.
Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
2021-06-10 23:11:36 +02:00
|
|
|
newResult->nominalnargs = 2;
|
2002-04-25 04:56:56 +02:00
|
|
|
newResult->nargs = 2;
|
2008-07-16 03:30:23 +02:00
|
|
|
newResult->nvargs = 0;
|
2008-12-18 19:20:35 +01:00
|
|
|
newResult->ndargs = 0;
|
2009-10-08 04:39:25 +02:00
|
|
|
newResult->argnumbers = NULL;
|
2002-04-17 01:08:12 +02:00
|
|
|
newResult->args[0] = operform->oprleft;
|
|
|
|
newResult->args[1] = operform->oprright;
|
|
|
|
newResult->next = resultList;
|
|
|
|
resultList = newResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCacheList(catlist);
|
2002-04-06 08:59:25 +02:00
|
|
|
|
|
|
|
return resultList;
|
|
|
|
}
|
|
|
|
|
2002-05-02 01:06:41 +02:00
|
|
|
/*
|
|
|
|
* OperatorIsVisible
|
|
|
|
* Determine whether an operator (identified by OID) is visible in the
|
|
|
|
* current search path. Visible means "would be found by searching
|
|
|
|
* for the unqualified operator name with exact argument matches".
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
OperatorIsVisible(Oid oprid)
|
|
|
|
{
|
|
|
|
HeapTuple oprtup;
|
|
|
|
Form_pg_operator oprform;
|
|
|
|
Oid oprnamespace;
|
|
|
|
bool visible;
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
oprtup = SearchSysCache1(OPEROID, ObjectIdGetDatum(oprid));
|
2002-05-02 01:06:41 +02:00
|
|
|
if (!HeapTupleIsValid(oprtup))
|
2003-07-21 03:59:11 +02:00
|
|
|
elog(ERROR, "cache lookup failed for operator %u", oprid);
|
2002-05-02 01:06:41 +02:00
|
|
|
oprform = (Form_pg_operator) GETSTRUCT(oprtup);
|
|
|
|
|
2002-05-17 22:53:33 +02:00
|
|
|
recomputeNamespacePath();
|
|
|
|
|
2002-05-02 01:06:41 +02:00
|
|
|
/*
|
|
|
|
* Quick check: if it ain't in the path at all, it ain't visible. Items in
|
2002-05-17 22:53:33 +02:00
|
|
|
* the system namespace are surely in the path and so we needn't even do
|
2004-05-26 06:41:50 +02:00
|
|
|
* list_member_oid() for them.
|
2002-05-02 01:06:41 +02:00
|
|
|
*/
|
|
|
|
oprnamespace = oprform->oprnamespace;
|
|
|
|
if (oprnamespace != PG_CATALOG_NAMESPACE &&
|
2007-03-23 20:53:52 +01:00
|
|
|
!list_member_oid(activeSearchPath, oprnamespace))
|
2002-05-02 01:06:41 +02:00
|
|
|
visible = false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If it is in the path, it might still not be visible; it could be
|
|
|
|
* hidden by another operator of the same name and arguments earlier
|
|
|
|
* in the path. So we must do a slow check to see if this is the same
|
2014-01-23 18:40:29 +01:00
|
|
|
* operator that would be found by OpernameGetOprid.
|
2002-05-02 01:06:41 +02:00
|
|
|
*/
|
|
|
|
char *oprname = NameStr(oprform->oprname);
|
|
|
|
|
2006-05-02 01:22:43 +02:00
|
|
|
visible = (OpernameGetOprid(list_make1(makeString(oprname)),
|
|
|
|
oprform->oprleft, oprform->oprright)
|
|
|
|
== oprid);
|
2002-05-02 01:06:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(oprtup);
|
|
|
|
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* OpclassnameGetOpcid
|
|
|
|
* Try to resolve an unqualified index opclass name.
|
|
|
|
* Returns OID if opclass found in search path, else InvalidOid.
|
|
|
|
*
|
|
|
|
* This is essentially the same as TypenameGetTypid, but we have to have
|
|
|
|
* an extra argument for the index AM OID.
|
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
OpclassnameGetOpcid(Oid amid, const char *opcname)
|
|
|
|
{
|
|
|
|
Oid opcid;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
2002-05-02 01:06:41 +02:00
|
|
|
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
foreach(l, activeSearchPath)
|
2002-05-02 01:06:41 +02:00
|
|
|
{
|
2004-05-26 06:41:50 +02:00
|
|
|
Oid namespaceId = lfirst_oid(l);
|
2002-05-02 01:06:41 +02:00
|
|
|
|
2007-04-20 04:37:38 +02:00
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
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
|
|
|
opcid = GetSysCacheOid3(CLAAMNAMENSP, Anum_pg_opclass_oid,
|
2010-02-14 19:42:19 +01:00
|
|
|
ObjectIdGetDatum(amid),
|
|
|
|
PointerGetDatum(opcname),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
2002-05-02 01:06:41 +02:00
|
|
|
if (OidIsValid(opcid))
|
|
|
|
return opcid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Not found in path */
|
|
|
|
return InvalidOid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* OpclassIsVisible
|
|
|
|
* Determine whether an opclass (identified by OID) is visible in the
|
|
|
|
* current search path. Visible means "would be found by searching
|
|
|
|
* for the unqualified opclass name".
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
OpclassIsVisible(Oid opcid)
|
|
|
|
{
|
|
|
|
HeapTuple opctup;
|
|
|
|
Form_pg_opclass opcform;
|
|
|
|
Oid opcnamespace;
|
|
|
|
bool visible;
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
opctup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opcid));
|
2002-05-02 01:06:41 +02:00
|
|
|
if (!HeapTupleIsValid(opctup))
|
2003-07-21 03:59:11 +02:00
|
|
|
elog(ERROR, "cache lookup failed for opclass %u", opcid);
|
2002-05-02 01:06:41 +02:00
|
|
|
opcform = (Form_pg_opclass) GETSTRUCT(opctup);
|
|
|
|
|
2002-05-17 22:53:33 +02:00
|
|
|
recomputeNamespacePath();
|
|
|
|
|
2002-05-02 01:06:41 +02:00
|
|
|
/*
|
|
|
|
* Quick check: if it ain't in the path at all, it ain't visible. Items in
|
2002-05-17 22:53:33 +02:00
|
|
|
* the system namespace are surely in the path and so we needn't even do
|
2004-05-26 06:41:50 +02:00
|
|
|
* list_member_oid() for them.
|
2002-05-02 01:06:41 +02:00
|
|
|
*/
|
|
|
|
opcnamespace = opcform->opcnamespace;
|
|
|
|
if (opcnamespace != PG_CATALOG_NAMESPACE &&
|
2007-03-23 20:53:52 +01:00
|
|
|
!list_member_oid(activeSearchPath, opcnamespace))
|
2002-05-02 01:06:41 +02:00
|
|
|
visible = false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If it is in the path, it might still not be visible; it could be
|
|
|
|
* hidden by another opclass of the same name earlier in the path. So
|
|
|
|
* we must do a slow check to see if this opclass would be found by
|
|
|
|
* OpclassnameGetOpcid.
|
|
|
|
*/
|
|
|
|
char *opcname = NameStr(opcform->opcname);
|
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
visible = (OpclassnameGetOpcid(opcform->opcmethod, opcname) == opcid);
|
2002-05-02 01:06:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(opctup);
|
|
|
|
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
/*
|
|
|
|
* OpfamilynameGetOpfid
|
|
|
|
* Try to resolve an unqualified index opfamily name.
|
|
|
|
* Returns OID if opfamily found in search path, else InvalidOid.
|
|
|
|
*
|
|
|
|
* This is essentially the same as TypenameGetTypid, but we have to have
|
|
|
|
* an extra argument for the index AM OID.
|
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
OpfamilynameGetOpfid(Oid amid, const char *opfname)
|
|
|
|
{
|
|
|
|
Oid opfid;
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
foreach(l, activeSearchPath)
|
2006-12-23 01:43:13 +01:00
|
|
|
{
|
|
|
|
Oid namespaceId = lfirst_oid(l);
|
|
|
|
|
2007-04-20 04:37:38 +02:00
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
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
|
|
|
opfid = GetSysCacheOid3(OPFAMILYAMNAMENSP, Anum_pg_opfamily_oid,
|
2010-02-14 19:42:19 +01:00
|
|
|
ObjectIdGetDatum(amid),
|
|
|
|
PointerGetDatum(opfname),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
2006-12-23 01:43:13 +01:00
|
|
|
if (OidIsValid(opfid))
|
|
|
|
return opfid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Not found in path */
|
|
|
|
return InvalidOid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* OpfamilyIsVisible
|
|
|
|
* Determine whether an opfamily (identified by OID) is visible in the
|
|
|
|
* current search path. Visible means "would be found by searching
|
|
|
|
* for the unqualified opfamily name".
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
OpfamilyIsVisible(Oid opfid)
|
|
|
|
{
|
|
|
|
HeapTuple opftup;
|
|
|
|
Form_pg_opfamily opfform;
|
|
|
|
Oid opfnamespace;
|
|
|
|
bool visible;
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
opftup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
|
2006-12-23 01:43:13 +01:00
|
|
|
if (!HeapTupleIsValid(opftup))
|
|
|
|
elog(ERROR, "cache lookup failed for opfamily %u", opfid);
|
|
|
|
opfform = (Form_pg_opfamily) GETSTRUCT(opftup);
|
|
|
|
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Quick check: if it ain't in the path at all, it ain't visible. Items in
|
|
|
|
* the system namespace are surely in the path and so we needn't even do
|
|
|
|
* list_member_oid() for them.
|
|
|
|
*/
|
|
|
|
opfnamespace = opfform->opfnamespace;
|
|
|
|
if (opfnamespace != PG_CATALOG_NAMESPACE &&
|
2007-03-23 20:53:52 +01:00
|
|
|
!list_member_oid(activeSearchPath, opfnamespace))
|
2006-12-23 01:43:13 +01:00
|
|
|
visible = false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If it is in the path, it might still not be visible; it could be
|
|
|
|
* hidden by another opfamily of the same name earlier in the path. So
|
|
|
|
* we must do a slow check to see if this opfamily would be found by
|
|
|
|
* OpfamilynameGetOpfid.
|
|
|
|
*/
|
|
|
|
char *opfname = NameStr(opfform->opfname);
|
|
|
|
|
|
|
|
visible = (OpfamilynameGetOpfid(opfform->opfmethod, opfname) == opfid);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(opftup);
|
|
|
|
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
|
Further hacking on ICU collation creation and usage.
pg_import_system_collations() refused to create any ICU collations if
the current database's encoding didn't support ICU. This is wrongheaded:
initdb must initialize pg_collation in an encoding-independent way
since it might be used in other databases with different encodings.
The reason for the restriction seems to be that get_icu_locale_comment()
used icu_from_uchar() to convert the UChar-format display name, and that
unsurprisingly doesn't know what to do in unsupported encodings.
But by the same token that the initial catalog contents must be
encoding-independent, we can't allow non-ASCII characters in the comment
strings. So we don't really need icu_from_uchar() here: just check for
Unicode codes outside the ASCII range, and if there are none, the format
conversion is trivial. If there are some, we can simply not install the
comment. (In my testing, this affects only Norwegian Bokmål, which has
given us trouble before.)
For paranoia's sake, also check for non-ASCII characters in ICU locale
names, and skip such locales, as we do for libc locales. I don't
currently have a reason to believe that this will ever reject anything,
but then again the libc maintainers should have known better too.
With just the import changes, ICU collations can be found in pg_collation
in databases with unsupported encodings. This resulted in more or less
clean failures at runtime, but that's not how things act for unsupported
encodings with libc collations. Make it work the same as our traditional
behavior for libc collations by having collation lookup take into account
whether is_encoding_supported_by_icu().
Adjust documentation to match. Also, expand Table 23.1 to show which
encodings are supported by ICU.
catversion bump because of likely change in pg_collation/pg_description
initial contents in ICU-enabled builds.
Discussion: https://postgr.es/m/20c74bc3-d6ca-243d-1bbc-12f17fa4fe9a@gmail.com
2017-06-24 19:54:15 +02:00
|
|
|
/*
|
|
|
|
* lookup_collation
|
|
|
|
* If there's a collation of the given name/namespace, and it works
|
|
|
|
* with the given encoding, return its OID. Else return InvalidOid.
|
|
|
|
*/
|
|
|
|
static Oid
|
|
|
|
lookup_collation(const char *collname, Oid collnamespace, int32 encoding)
|
|
|
|
{
|
|
|
|
Oid collid;
|
|
|
|
HeapTuple colltup;
|
|
|
|
Form_pg_collation collform;
|
|
|
|
|
|
|
|
/* Check for encoding-specific entry (exact match) */
|
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
|
|
|
collid = GetSysCacheOid3(COLLNAMEENCNSP, Anum_pg_collation_oid,
|
Further hacking on ICU collation creation and usage.
pg_import_system_collations() refused to create any ICU collations if
the current database's encoding didn't support ICU. This is wrongheaded:
initdb must initialize pg_collation in an encoding-independent way
since it might be used in other databases with different encodings.
The reason for the restriction seems to be that get_icu_locale_comment()
used icu_from_uchar() to convert the UChar-format display name, and that
unsurprisingly doesn't know what to do in unsupported encodings.
But by the same token that the initial catalog contents must be
encoding-independent, we can't allow non-ASCII characters in the comment
strings. So we don't really need icu_from_uchar() here: just check for
Unicode codes outside the ASCII range, and if there are none, the format
conversion is trivial. If there are some, we can simply not install the
comment. (In my testing, this affects only Norwegian Bokmål, which has
given us trouble before.)
For paranoia's sake, also check for non-ASCII characters in ICU locale
names, and skip such locales, as we do for libc locales. I don't
currently have a reason to believe that this will ever reject anything,
but then again the libc maintainers should have known better too.
With just the import changes, ICU collations can be found in pg_collation
in databases with unsupported encodings. This resulted in more or less
clean failures at runtime, but that's not how things act for unsupported
encodings with libc collations. Make it work the same as our traditional
behavior for libc collations by having collation lookup take into account
whether is_encoding_supported_by_icu().
Adjust documentation to match. Also, expand Table 23.1 to show which
encodings are supported by ICU.
catversion bump because of likely change in pg_collation/pg_description
initial contents in ICU-enabled builds.
Discussion: https://postgr.es/m/20c74bc3-d6ca-243d-1bbc-12f17fa4fe9a@gmail.com
2017-06-24 19:54:15 +02:00
|
|
|
PointerGetDatum(collname),
|
|
|
|
Int32GetDatum(encoding),
|
|
|
|
ObjectIdGetDatum(collnamespace));
|
|
|
|
if (OidIsValid(collid))
|
|
|
|
return collid;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for any-encoding entry. This takes a bit more work: while libc
|
|
|
|
* collations with collencoding = -1 do work with all encodings, ICU
|
|
|
|
* collations only work with certain encodings, so we have to check that
|
|
|
|
* aspect before deciding it's a match.
|
|
|
|
*/
|
|
|
|
colltup = SearchSysCache3(COLLNAMEENCNSP,
|
|
|
|
PointerGetDatum(collname),
|
|
|
|
Int32GetDatum(-1),
|
|
|
|
ObjectIdGetDatum(collnamespace));
|
|
|
|
if (!HeapTupleIsValid(colltup))
|
|
|
|
return InvalidOid;
|
|
|
|
collform = (Form_pg_collation) GETSTRUCT(colltup);
|
|
|
|
if (collform->collprovider == COLLPROVIDER_ICU)
|
|
|
|
{
|
|
|
|
if (is_encoding_supported_by_icu(encoding))
|
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
|
|
|
collid = collform->oid;
|
Further hacking on ICU collation creation and usage.
pg_import_system_collations() refused to create any ICU collations if
the current database's encoding didn't support ICU. This is wrongheaded:
initdb must initialize pg_collation in an encoding-independent way
since it might be used in other databases with different encodings.
The reason for the restriction seems to be that get_icu_locale_comment()
used icu_from_uchar() to convert the UChar-format display name, and that
unsurprisingly doesn't know what to do in unsupported encodings.
But by the same token that the initial catalog contents must be
encoding-independent, we can't allow non-ASCII characters in the comment
strings. So we don't really need icu_from_uchar() here: just check for
Unicode codes outside the ASCII range, and if there are none, the format
conversion is trivial. If there are some, we can simply not install the
comment. (In my testing, this affects only Norwegian Bokmål, which has
given us trouble before.)
For paranoia's sake, also check for non-ASCII characters in ICU locale
names, and skip such locales, as we do for libc locales. I don't
currently have a reason to believe that this will ever reject anything,
but then again the libc maintainers should have known better too.
With just the import changes, ICU collations can be found in pg_collation
in databases with unsupported encodings. This resulted in more or less
clean failures at runtime, but that's not how things act for unsupported
encodings with libc collations. Make it work the same as our traditional
behavior for libc collations by having collation lookup take into account
whether is_encoding_supported_by_icu().
Adjust documentation to match. Also, expand Table 23.1 to show which
encodings are supported by ICU.
catversion bump because of likely change in pg_collation/pg_description
initial contents in ICU-enabled builds.
Discussion: https://postgr.es/m/20c74bc3-d6ca-243d-1bbc-12f17fa4fe9a@gmail.com
2017-06-24 19:54:15 +02:00
|
|
|
else
|
|
|
|
collid = InvalidOid;
|
|
|
|
}
|
|
|
|
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
|
|
|
collid = collform->oid;
|
Further hacking on ICU collation creation and usage.
pg_import_system_collations() refused to create any ICU collations if
the current database's encoding didn't support ICU. This is wrongheaded:
initdb must initialize pg_collation in an encoding-independent way
since it might be used in other databases with different encodings.
The reason for the restriction seems to be that get_icu_locale_comment()
used icu_from_uchar() to convert the UChar-format display name, and that
unsurprisingly doesn't know what to do in unsupported encodings.
But by the same token that the initial catalog contents must be
encoding-independent, we can't allow non-ASCII characters in the comment
strings. So we don't really need icu_from_uchar() here: just check for
Unicode codes outside the ASCII range, and if there are none, the format
conversion is trivial. If there are some, we can simply not install the
comment. (In my testing, this affects only Norwegian Bokmål, which has
given us trouble before.)
For paranoia's sake, also check for non-ASCII characters in ICU locale
names, and skip such locales, as we do for libc locales. I don't
currently have a reason to believe that this will ever reject anything,
but then again the libc maintainers should have known better too.
With just the import changes, ICU collations can be found in pg_collation
in databases with unsupported encodings. This resulted in more or less
clean failures at runtime, but that's not how things act for unsupported
encodings with libc collations. Make it work the same as our traditional
behavior for libc collations by having collation lookup take into account
whether is_encoding_supported_by_icu().
Adjust documentation to match. Also, expand Table 23.1 to show which
encodings are supported by ICU.
catversion bump because of likely change in pg_collation/pg_description
initial contents in ICU-enabled builds.
Discussion: https://postgr.es/m/20c74bc3-d6ca-243d-1bbc-12f17fa4fe9a@gmail.com
2017-06-24 19:54:15 +02:00
|
|
|
}
|
|
|
|
ReleaseSysCache(colltup);
|
|
|
|
return collid;
|
|
|
|
}
|
|
|
|
|
2011-02-08 22:04:18 +01:00
|
|
|
/*
|
|
|
|
* CollationGetCollid
|
|
|
|
* Try to resolve an unqualified collation name.
|
|
|
|
* Returns OID if collation found in search path, else InvalidOid.
|
Further hacking on ICU collation creation and usage.
pg_import_system_collations() refused to create any ICU collations if
the current database's encoding didn't support ICU. This is wrongheaded:
initdb must initialize pg_collation in an encoding-independent way
since it might be used in other databases with different encodings.
The reason for the restriction seems to be that get_icu_locale_comment()
used icu_from_uchar() to convert the UChar-format display name, and that
unsurprisingly doesn't know what to do in unsupported encodings.
But by the same token that the initial catalog contents must be
encoding-independent, we can't allow non-ASCII characters in the comment
strings. So we don't really need icu_from_uchar() here: just check for
Unicode codes outside the ASCII range, and if there are none, the format
conversion is trivial. If there are some, we can simply not install the
comment. (In my testing, this affects only Norwegian Bokmål, which has
given us trouble before.)
For paranoia's sake, also check for non-ASCII characters in ICU locale
names, and skip such locales, as we do for libc locales. I don't
currently have a reason to believe that this will ever reject anything,
but then again the libc maintainers should have known better too.
With just the import changes, ICU collations can be found in pg_collation
in databases with unsupported encodings. This resulted in more or less
clean failures at runtime, but that's not how things act for unsupported
encodings with libc collations. Make it work the same as our traditional
behavior for libc collations by having collation lookup take into account
whether is_encoding_supported_by_icu().
Adjust documentation to match. Also, expand Table 23.1 to show which
encodings are supported by ICU.
catversion bump because of likely change in pg_collation/pg_description
initial contents in ICU-enabled builds.
Discussion: https://postgr.es/m/20c74bc3-d6ca-243d-1bbc-12f17fa4fe9a@gmail.com
2017-06-24 19:54:15 +02:00
|
|
|
*
|
|
|
|
* Note that this will only find collations that work with the current
|
|
|
|
* database's encoding.
|
2011-02-08 22:04:18 +01:00
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
CollationGetCollid(const char *collname)
|
|
|
|
{
|
2011-03-11 19:20:11 +01:00
|
|
|
int32 dbencoding = GetDatabaseEncoding();
|
2011-02-08 22:04:18 +01:00
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
foreach(l, activeSearchPath)
|
|
|
|
{
|
|
|
|
Oid namespaceId = lfirst_oid(l);
|
2011-03-11 19:20:11 +01:00
|
|
|
Oid collid;
|
2011-02-08 22:04:18 +01:00
|
|
|
|
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
Further hacking on ICU collation creation and usage.
pg_import_system_collations() refused to create any ICU collations if
the current database's encoding didn't support ICU. This is wrongheaded:
initdb must initialize pg_collation in an encoding-independent way
since it might be used in other databases with different encodings.
The reason for the restriction seems to be that get_icu_locale_comment()
used icu_from_uchar() to convert the UChar-format display name, and that
unsurprisingly doesn't know what to do in unsupported encodings.
But by the same token that the initial catalog contents must be
encoding-independent, we can't allow non-ASCII characters in the comment
strings. So we don't really need icu_from_uchar() here: just check for
Unicode codes outside the ASCII range, and if there are none, the format
conversion is trivial. If there are some, we can simply not install the
comment. (In my testing, this affects only Norwegian Bokmål, which has
given us trouble before.)
For paranoia's sake, also check for non-ASCII characters in ICU locale
names, and skip such locales, as we do for libc locales. I don't
currently have a reason to believe that this will ever reject anything,
but then again the libc maintainers should have known better too.
With just the import changes, ICU collations can be found in pg_collation
in databases with unsupported encodings. This resulted in more or less
clean failures at runtime, but that's not how things act for unsupported
encodings with libc collations. Make it work the same as our traditional
behavior for libc collations by having collation lookup take into account
whether is_encoding_supported_by_icu().
Adjust documentation to match. Also, expand Table 23.1 to show which
encodings are supported by ICU.
catversion bump because of likely change in pg_collation/pg_description
initial contents in ICU-enabled builds.
Discussion: https://postgr.es/m/20c74bc3-d6ca-243d-1bbc-12f17fa4fe9a@gmail.com
2017-06-24 19:54:15 +02:00
|
|
|
collid = lookup_collation(collname, namespaceId, dbencoding);
|
2011-02-08 22:04:18 +01:00
|
|
|
if (OidIsValid(collid))
|
|
|
|
return collid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Not found in path */
|
|
|
|
return InvalidOid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* CollationIsVisible
|
|
|
|
* Determine whether a collation (identified by OID) is visible in the
|
|
|
|
* current search path. Visible means "would be found by searching
|
|
|
|
* for the unqualified collation name".
|
Further hacking on ICU collation creation and usage.
pg_import_system_collations() refused to create any ICU collations if
the current database's encoding didn't support ICU. This is wrongheaded:
initdb must initialize pg_collation in an encoding-independent way
since it might be used in other databases with different encodings.
The reason for the restriction seems to be that get_icu_locale_comment()
used icu_from_uchar() to convert the UChar-format display name, and that
unsurprisingly doesn't know what to do in unsupported encodings.
But by the same token that the initial catalog contents must be
encoding-independent, we can't allow non-ASCII characters in the comment
strings. So we don't really need icu_from_uchar() here: just check for
Unicode codes outside the ASCII range, and if there are none, the format
conversion is trivial. If there are some, we can simply not install the
comment. (In my testing, this affects only Norwegian Bokmål, which has
given us trouble before.)
For paranoia's sake, also check for non-ASCII characters in ICU locale
names, and skip such locales, as we do for libc locales. I don't
currently have a reason to believe that this will ever reject anything,
but then again the libc maintainers should have known better too.
With just the import changes, ICU collations can be found in pg_collation
in databases with unsupported encodings. This resulted in more or less
clean failures at runtime, but that's not how things act for unsupported
encodings with libc collations. Make it work the same as our traditional
behavior for libc collations by having collation lookup take into account
whether is_encoding_supported_by_icu().
Adjust documentation to match. Also, expand Table 23.1 to show which
encodings are supported by ICU.
catversion bump because of likely change in pg_collation/pg_description
initial contents in ICU-enabled builds.
Discussion: https://postgr.es/m/20c74bc3-d6ca-243d-1bbc-12f17fa4fe9a@gmail.com
2017-06-24 19:54:15 +02:00
|
|
|
*
|
|
|
|
* Note that only collations that work with the current database's encoding
|
|
|
|
* will be considered visible.
|
2011-02-08 22:04:18 +01:00
|
|
|
*/
|
|
|
|
bool
|
|
|
|
CollationIsVisible(Oid collid)
|
|
|
|
{
|
|
|
|
HeapTuple colltup;
|
|
|
|
Form_pg_collation collform;
|
|
|
|
Oid collnamespace;
|
|
|
|
bool visible;
|
|
|
|
|
|
|
|
colltup = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
|
|
|
|
if (!HeapTupleIsValid(colltup))
|
|
|
|
elog(ERROR, "cache lookup failed for collation %u", collid);
|
|
|
|
collform = (Form_pg_collation) GETSTRUCT(colltup);
|
|
|
|
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Quick check: if it ain't in the path at all, it ain't visible. Items in
|
|
|
|
* the system namespace are surely in the path and so we needn't even do
|
|
|
|
* list_member_oid() for them.
|
|
|
|
*/
|
|
|
|
collnamespace = collform->collnamespace;
|
|
|
|
if (collnamespace != PG_CATALOG_NAMESPACE &&
|
|
|
|
!list_member_oid(activeSearchPath, collnamespace))
|
|
|
|
visible = false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If it is in the path, it might still not be visible; it could be
|
Further hacking on ICU collation creation and usage.
pg_import_system_collations() refused to create any ICU collations if
the current database's encoding didn't support ICU. This is wrongheaded:
initdb must initialize pg_collation in an encoding-independent way
since it might be used in other databases with different encodings.
The reason for the restriction seems to be that get_icu_locale_comment()
used icu_from_uchar() to convert the UChar-format display name, and that
unsurprisingly doesn't know what to do in unsupported encodings.
But by the same token that the initial catalog contents must be
encoding-independent, we can't allow non-ASCII characters in the comment
strings. So we don't really need icu_from_uchar() here: just check for
Unicode codes outside the ASCII range, and if there are none, the format
conversion is trivial. If there are some, we can simply not install the
comment. (In my testing, this affects only Norwegian Bokmål, which has
given us trouble before.)
For paranoia's sake, also check for non-ASCII characters in ICU locale
names, and skip such locales, as we do for libc locales. I don't
currently have a reason to believe that this will ever reject anything,
but then again the libc maintainers should have known better too.
With just the import changes, ICU collations can be found in pg_collation
in databases with unsupported encodings. This resulted in more or less
clean failures at runtime, but that's not how things act for unsupported
encodings with libc collations. Make it work the same as our traditional
behavior for libc collations by having collation lookup take into account
whether is_encoding_supported_by_icu().
Adjust documentation to match. Also, expand Table 23.1 to show which
encodings are supported by ICU.
catversion bump because of likely change in pg_collation/pg_description
initial contents in ICU-enabled builds.
Discussion: https://postgr.es/m/20c74bc3-d6ca-243d-1bbc-12f17fa4fe9a@gmail.com
2017-06-24 19:54:15 +02:00
|
|
|
* hidden by another collation of the same name earlier in the path,
|
|
|
|
* or it might not work with the current DB encoding. So we must do a
|
|
|
|
* slow check to see if this collation would be found by
|
|
|
|
* CollationGetCollid.
|
2011-02-08 22:04:18 +01:00
|
|
|
*/
|
|
|
|
char *collname = NameStr(collform->collname);
|
|
|
|
|
|
|
|
visible = (CollationGetCollid(collname) == collid);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(colltup);
|
|
|
|
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-12-12 22:02:25 +01:00
|
|
|
/*
|
|
|
|
* ConversionGetConid
|
|
|
|
* Try to resolve an unqualified conversion name.
|
|
|
|
* Returns OID if conversion found in search path, else InvalidOid.
|
|
|
|
*
|
|
|
|
* This is essentially the same as RelnameGetRelid.
|
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
ConversionGetConid(const char *conname)
|
|
|
|
{
|
|
|
|
Oid conid;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
2002-12-12 22:02:25 +01:00
|
|
|
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
foreach(l, activeSearchPath)
|
2002-12-12 22:02:25 +01:00
|
|
|
{
|
2004-05-26 06:41:50 +02:00
|
|
|
Oid namespaceId = lfirst_oid(l);
|
2002-12-12 22:02:25 +01:00
|
|
|
|
2007-04-20 04:37:38 +02:00
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
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
|
|
|
conid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
|
2010-02-14 19:42:19 +01:00
|
|
|
PointerGetDatum(conname),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
2002-12-12 22:02:25 +01:00
|
|
|
if (OidIsValid(conid))
|
|
|
|
return conid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Not found in path */
|
|
|
|
return InvalidOid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ConversionIsVisible
|
|
|
|
* Determine whether a conversion (identified by OID) is visible in the
|
|
|
|
* current search path. Visible means "would be found by searching
|
|
|
|
* for the unqualified conversion name".
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
ConversionIsVisible(Oid conid)
|
|
|
|
{
|
|
|
|
HeapTuple contup;
|
|
|
|
Form_pg_conversion conform;
|
|
|
|
Oid connamespace;
|
|
|
|
bool visible;
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
contup = SearchSysCache1(CONVOID, ObjectIdGetDatum(conid));
|
2002-12-12 22:02:25 +01:00
|
|
|
if (!HeapTupleIsValid(contup))
|
2003-07-21 03:59:11 +02:00
|
|
|
elog(ERROR, "cache lookup failed for conversion %u", conid);
|
2002-12-12 22:02:25 +01:00
|
|
|
conform = (Form_pg_conversion) GETSTRUCT(contup);
|
|
|
|
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Quick check: if it ain't in the path at all, it ain't visible. Items in
|
|
|
|
* the system namespace are surely in the path and so we needn't even do
|
2004-05-26 06:41:50 +02:00
|
|
|
* list_member_oid() for them.
|
2002-12-12 22:02:25 +01:00
|
|
|
*/
|
|
|
|
connamespace = conform->connamespace;
|
|
|
|
if (connamespace != PG_CATALOG_NAMESPACE &&
|
2007-03-23 20:53:52 +01:00
|
|
|
!list_member_oid(activeSearchPath, connamespace))
|
2002-12-12 22:02:25 +01:00
|
|
|
visible = false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If it is in the path, it might still not be visible; it could be
|
|
|
|
* hidden by another conversion of the same name earlier in the path.
|
|
|
|
* So we must do a slow check to see if this conversion would be found
|
2003-01-07 21:56:07 +01:00
|
|
|
* by ConversionGetConid.
|
2002-12-12 22:02:25 +01:00
|
|
|
*/
|
|
|
|
char *conname = NameStr(conform->conname);
|
2003-08-04 02:43:34 +02:00
|
|
|
|
2002-12-12 22:02:25 +01:00
|
|
|
visible = (ConversionGetConid(conname) == conid);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(contup);
|
|
|
|
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
|
Implement multivariate n-distinct coefficients
Add support for explicitly declared statistic objects (CREATE
STATISTICS), allowing collection of statistics on more complex
combinations that individual table columns. Companion commands DROP
STATISTICS and ALTER STATISTICS ... OWNER TO / SET SCHEMA / RENAME are
added too. All this DDL has been designed so that more statistic types
can be added later on, such as multivariate most-common-values and
multivariate histograms between columns of a single table, leaving room
for permitting columns on multiple tables, too, as well as expressions.
This commit only adds support for collection of n-distinct coefficient
on user-specified sets of columns in a single table. This is useful to
estimate number of distinct groups in GROUP BY and DISTINCT clauses;
estimation errors there can cause over-allocation of memory in hashed
aggregates, for instance, so it's a worthwhile problem to solve. A new
special pseudo-type pg_ndistinct is used.
(num-distinct estimation was deemed sufficiently useful by itself that
this is worthwhile even if no further statistic types are added
immediately; so much so that another version of essentially the same
functionality was submitted by Kyotaro Horiguchi:
https://postgr.es/m/20150828.173334.114731693.horiguchi.kyotaro@lab.ntt.co.jp
though this commit does not use that code.)
Author: Tomas Vondra. Some code rework by Álvaro.
Reviewed-by: Dean Rasheed, David Rowley, Kyotaro Horiguchi, Jeff Janes,
Ideriha Takeshi
Discussion: https://postgr.es/m/543AFA15.4080608@fuzzy.cz
https://postgr.es/m/20170320190220.ixlaueanxegqd5gr@alvherre.pgsql
2017-03-24 18:06:10 +01:00
|
|
|
/*
|
2017-05-14 16:54:47 +02:00
|
|
|
* get_statistics_object_oid - find a statistics object by possibly qualified name
|
Implement multivariate n-distinct coefficients
Add support for explicitly declared statistic objects (CREATE
STATISTICS), allowing collection of statistics on more complex
combinations that individual table columns. Companion commands DROP
STATISTICS and ALTER STATISTICS ... OWNER TO / SET SCHEMA / RENAME are
added too. All this DDL has been designed so that more statistic types
can be added later on, such as multivariate most-common-values and
multivariate histograms between columns of a single table, leaving room
for permitting columns on multiple tables, too, as well as expressions.
This commit only adds support for collection of n-distinct coefficient
on user-specified sets of columns in a single table. This is useful to
estimate number of distinct groups in GROUP BY and DISTINCT clauses;
estimation errors there can cause over-allocation of memory in hashed
aggregates, for instance, so it's a worthwhile problem to solve. A new
special pseudo-type pg_ndistinct is used.
(num-distinct estimation was deemed sufficiently useful by itself that
this is worthwhile even if no further statistic types are added
immediately; so much so that another version of essentially the same
functionality was submitted by Kyotaro Horiguchi:
https://postgr.es/m/20150828.173334.114731693.horiguchi.kyotaro@lab.ntt.co.jp
though this commit does not use that code.)
Author: Tomas Vondra. Some code rework by Álvaro.
Reviewed-by: Dean Rasheed, David Rowley, Kyotaro Horiguchi, Jeff Janes,
Ideriha Takeshi
Discussion: https://postgr.es/m/543AFA15.4080608@fuzzy.cz
https://postgr.es/m/20170320190220.ixlaueanxegqd5gr@alvherre.pgsql
2017-03-24 18:06:10 +01:00
|
|
|
*
|
|
|
|
* If not found, returns InvalidOid if missing_ok, else throws error
|
|
|
|
*/
|
|
|
|
Oid
|
2017-05-14 16:54:47 +02:00
|
|
|
get_statistics_object_oid(List *names, bool missing_ok)
|
Implement multivariate n-distinct coefficients
Add support for explicitly declared statistic objects (CREATE
STATISTICS), allowing collection of statistics on more complex
combinations that individual table columns. Companion commands DROP
STATISTICS and ALTER STATISTICS ... OWNER TO / SET SCHEMA / RENAME are
added too. All this DDL has been designed so that more statistic types
can be added later on, such as multivariate most-common-values and
multivariate histograms between columns of a single table, leaving room
for permitting columns on multiple tables, too, as well as expressions.
This commit only adds support for collection of n-distinct coefficient
on user-specified sets of columns in a single table. This is useful to
estimate number of distinct groups in GROUP BY and DISTINCT clauses;
estimation errors there can cause over-allocation of memory in hashed
aggregates, for instance, so it's a worthwhile problem to solve. A new
special pseudo-type pg_ndistinct is used.
(num-distinct estimation was deemed sufficiently useful by itself that
this is worthwhile even if no further statistic types are added
immediately; so much so that another version of essentially the same
functionality was submitted by Kyotaro Horiguchi:
https://postgr.es/m/20150828.173334.114731693.horiguchi.kyotaro@lab.ntt.co.jp
though this commit does not use that code.)
Author: Tomas Vondra. Some code rework by Álvaro.
Reviewed-by: Dean Rasheed, David Rowley, Kyotaro Horiguchi, Jeff Janes,
Ideriha Takeshi
Discussion: https://postgr.es/m/543AFA15.4080608@fuzzy.cz
https://postgr.es/m/20170320190220.ixlaueanxegqd5gr@alvherre.pgsql
2017-03-24 18:06:10 +01:00
|
|
|
{
|
|
|
|
char *schemaname;
|
|
|
|
char *stats_name;
|
|
|
|
Oid namespaceId;
|
|
|
|
Oid stats_oid = InvalidOid;
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
/* deconstruct the name list */
|
|
|
|
DeconstructQualifiedName(names, &schemaname, &stats_name);
|
|
|
|
|
|
|
|
if (schemaname)
|
|
|
|
{
|
|
|
|
/* use exact schema given */
|
|
|
|
namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
|
|
|
|
if (missing_ok && !OidIsValid(namespaceId))
|
|
|
|
stats_oid = InvalidOid;
|
|
|
|
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
|
|
|
stats_oid = GetSysCacheOid2(STATEXTNAMENSP, Anum_pg_statistic_ext_oid,
|
Implement multivariate n-distinct coefficients
Add support for explicitly declared statistic objects (CREATE
STATISTICS), allowing collection of statistics on more complex
combinations that individual table columns. Companion commands DROP
STATISTICS and ALTER STATISTICS ... OWNER TO / SET SCHEMA / RENAME are
added too. All this DDL has been designed so that more statistic types
can be added later on, such as multivariate most-common-values and
multivariate histograms between columns of a single table, leaving room
for permitting columns on multiple tables, too, as well as expressions.
This commit only adds support for collection of n-distinct coefficient
on user-specified sets of columns in a single table. This is useful to
estimate number of distinct groups in GROUP BY and DISTINCT clauses;
estimation errors there can cause over-allocation of memory in hashed
aggregates, for instance, so it's a worthwhile problem to solve. A new
special pseudo-type pg_ndistinct is used.
(num-distinct estimation was deemed sufficiently useful by itself that
this is worthwhile even if no further statistic types are added
immediately; so much so that another version of essentially the same
functionality was submitted by Kyotaro Horiguchi:
https://postgr.es/m/20150828.173334.114731693.horiguchi.kyotaro@lab.ntt.co.jp
though this commit does not use that code.)
Author: Tomas Vondra. Some code rework by Álvaro.
Reviewed-by: Dean Rasheed, David Rowley, Kyotaro Horiguchi, Jeff Janes,
Ideriha Takeshi
Discussion: https://postgr.es/m/543AFA15.4080608@fuzzy.cz
https://postgr.es/m/20170320190220.ixlaueanxegqd5gr@alvherre.pgsql
2017-03-24 18:06:10 +01:00
|
|
|
PointerGetDatum(stats_name),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* search for it in search path */
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
foreach(l, activeSearchPath)
|
|
|
|
{
|
|
|
|
namespaceId = lfirst_oid(l);
|
|
|
|
|
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
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
|
|
|
stats_oid = GetSysCacheOid2(STATEXTNAMENSP, Anum_pg_statistic_ext_oid,
|
Implement multivariate n-distinct coefficients
Add support for explicitly declared statistic objects (CREATE
STATISTICS), allowing collection of statistics on more complex
combinations that individual table columns. Companion commands DROP
STATISTICS and ALTER STATISTICS ... OWNER TO / SET SCHEMA / RENAME are
added too. All this DDL has been designed so that more statistic types
can be added later on, such as multivariate most-common-values and
multivariate histograms between columns of a single table, leaving room
for permitting columns on multiple tables, too, as well as expressions.
This commit only adds support for collection of n-distinct coefficient
on user-specified sets of columns in a single table. This is useful to
estimate number of distinct groups in GROUP BY and DISTINCT clauses;
estimation errors there can cause over-allocation of memory in hashed
aggregates, for instance, so it's a worthwhile problem to solve. A new
special pseudo-type pg_ndistinct is used.
(num-distinct estimation was deemed sufficiently useful by itself that
this is worthwhile even if no further statistic types are added
immediately; so much so that another version of essentially the same
functionality was submitted by Kyotaro Horiguchi:
https://postgr.es/m/20150828.173334.114731693.horiguchi.kyotaro@lab.ntt.co.jp
though this commit does not use that code.)
Author: Tomas Vondra. Some code rework by Álvaro.
Reviewed-by: Dean Rasheed, David Rowley, Kyotaro Horiguchi, Jeff Janes,
Ideriha Takeshi
Discussion: https://postgr.es/m/543AFA15.4080608@fuzzy.cz
https://postgr.es/m/20170320190220.ixlaueanxegqd5gr@alvherre.pgsql
2017-03-24 18:06:10 +01:00
|
|
|
PointerGetDatum(stats_name),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
|
|
|
if (OidIsValid(stats_oid))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!OidIsValid(stats_oid) && !missing_ok)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
2017-05-14 16:54:47 +02:00
|
|
|
errmsg("statistics object \"%s\" does not exist",
|
Implement multivariate n-distinct coefficients
Add support for explicitly declared statistic objects (CREATE
STATISTICS), allowing collection of statistics on more complex
combinations that individual table columns. Companion commands DROP
STATISTICS and ALTER STATISTICS ... OWNER TO / SET SCHEMA / RENAME are
added too. All this DDL has been designed so that more statistic types
can be added later on, such as multivariate most-common-values and
multivariate histograms between columns of a single table, leaving room
for permitting columns on multiple tables, too, as well as expressions.
This commit only adds support for collection of n-distinct coefficient
on user-specified sets of columns in a single table. This is useful to
estimate number of distinct groups in GROUP BY and DISTINCT clauses;
estimation errors there can cause over-allocation of memory in hashed
aggregates, for instance, so it's a worthwhile problem to solve. A new
special pseudo-type pg_ndistinct is used.
(num-distinct estimation was deemed sufficiently useful by itself that
this is worthwhile even if no further statistic types are added
immediately; so much so that another version of essentially the same
functionality was submitted by Kyotaro Horiguchi:
https://postgr.es/m/20150828.173334.114731693.horiguchi.kyotaro@lab.ntt.co.jp
though this commit does not use that code.)
Author: Tomas Vondra. Some code rework by Álvaro.
Reviewed-by: Dean Rasheed, David Rowley, Kyotaro Horiguchi, Jeff Janes,
Ideriha Takeshi
Discussion: https://postgr.es/m/543AFA15.4080608@fuzzy.cz
https://postgr.es/m/20170320190220.ixlaueanxegqd5gr@alvherre.pgsql
2017-03-24 18:06:10 +01:00
|
|
|
NameListToString(names))));
|
|
|
|
|
|
|
|
return stats_oid;
|
|
|
|
}
|
|
|
|
|
2017-05-13 06:05:48 +02:00
|
|
|
/*
|
|
|
|
* StatisticsObjIsVisible
|
|
|
|
* Determine whether a statistics object (identified by OID) is visible in
|
|
|
|
* the current search path. Visible means "would be found by searching
|
|
|
|
* for the unqualified statistics object name".
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
StatisticsObjIsVisible(Oid relid)
|
|
|
|
{
|
|
|
|
HeapTuple stxtup;
|
|
|
|
Form_pg_statistic_ext stxform;
|
|
|
|
Oid stxnamespace;
|
|
|
|
bool visible;
|
|
|
|
|
|
|
|
stxtup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(relid));
|
|
|
|
if (!HeapTupleIsValid(stxtup))
|
|
|
|
elog(ERROR, "cache lookup failed for statistics object %u", relid);
|
|
|
|
stxform = (Form_pg_statistic_ext) GETSTRUCT(stxtup);
|
|
|
|
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Quick check: if it ain't in the path at all, it ain't visible. Items in
|
|
|
|
* the system namespace are surely in the path and so we needn't even do
|
|
|
|
* list_member_oid() for them.
|
|
|
|
*/
|
|
|
|
stxnamespace = stxform->stxnamespace;
|
|
|
|
if (stxnamespace != PG_CATALOG_NAMESPACE &&
|
|
|
|
!list_member_oid(activeSearchPath, stxnamespace))
|
|
|
|
visible = false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If it is in the path, it might still not be visible; it could be
|
|
|
|
* hidden by another statistics object of the same name earlier in the
|
|
|
|
* path. So we must do a slow check for conflicting objects.
|
|
|
|
*/
|
|
|
|
char *stxname = NameStr(stxform->stxname);
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
visible = false;
|
|
|
|
foreach(l, activeSearchPath)
|
|
|
|
{
|
|
|
|
Oid namespaceId = lfirst_oid(l);
|
|
|
|
|
|
|
|
if (namespaceId == stxnamespace)
|
|
|
|
{
|
|
|
|
/* Found it first in path */
|
|
|
|
visible = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (SearchSysCacheExists2(STATEXTNAMENSP,
|
|
|
|
PointerGetDatum(stxname),
|
|
|
|
ObjectIdGetDatum(namespaceId)))
|
|
|
|
{
|
|
|
|
/* Found something else first in path */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(stxtup);
|
|
|
|
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
|
2007-08-21 03:11:32 +02:00
|
|
|
/*
|
2010-08-05 17:25:36 +02:00
|
|
|
* get_ts_parser_oid - find a TS parser by possibly qualified name
|
2007-08-21 03:11:32 +02:00
|
|
|
*
|
2010-08-05 17:25:36 +02:00
|
|
|
* If not found, returns InvalidOid if missing_ok, else throws error
|
2007-08-21 03:11:32 +02:00
|
|
|
*/
|
|
|
|
Oid
|
2010-08-05 17:25:36 +02:00
|
|
|
get_ts_parser_oid(List *names, bool missing_ok)
|
2007-08-21 03:11:32 +02:00
|
|
|
{
|
|
|
|
char *schemaname;
|
|
|
|
char *parser_name;
|
|
|
|
Oid namespaceId;
|
|
|
|
Oid prsoid = InvalidOid;
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
/* deconstruct the name list */
|
|
|
|
DeconstructQualifiedName(names, &schemaname, &parser_name);
|
|
|
|
|
|
|
|
if (schemaname)
|
|
|
|
{
|
|
|
|
/* use exact schema given */
|
2013-01-26 19:24:50 +01:00
|
|
|
namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
|
|
|
|
if (missing_ok && !OidIsValid(namespaceId))
|
|
|
|
prsoid = InvalidOid;
|
|
|
|
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
|
|
|
prsoid = GetSysCacheOid2(TSPARSERNAMENSP, Anum_pg_ts_parser_oid,
|
2013-01-26 19:24:50 +01:00
|
|
|
PointerGetDatum(parser_name),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
2007-08-21 03:11:32 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* search for it in search path */
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
foreach(l, activeSearchPath)
|
|
|
|
{
|
|
|
|
namespaceId = lfirst_oid(l);
|
|
|
|
|
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
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
|
|
|
prsoid = GetSysCacheOid2(TSPARSERNAMENSP, Anum_pg_ts_parser_oid,
|
2010-02-14 19:42:19 +01:00
|
|
|
PointerGetDatum(parser_name),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
2007-08-21 03:11:32 +02:00
|
|
|
if (OidIsValid(prsoid))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-05 17:25:36 +02:00
|
|
|
if (!OidIsValid(prsoid) && !missing_ok)
|
2007-08-21 03:11:32 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("text search parser \"%s\" does not exist",
|
|
|
|
NameListToString(names))));
|
|
|
|
|
|
|
|
return prsoid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TSParserIsVisible
|
|
|
|
* Determine whether a parser (identified by OID) is visible in the
|
|
|
|
* current search path. Visible means "would be found by searching
|
|
|
|
* for the unqualified parser name".
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
TSParserIsVisible(Oid prsId)
|
|
|
|
{
|
|
|
|
HeapTuple tup;
|
|
|
|
Form_pg_ts_parser form;
|
|
|
|
Oid namespace;
|
|
|
|
bool visible;
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
tup = SearchSysCache1(TSPARSEROID, ObjectIdGetDatum(prsId));
|
2007-08-21 03:11:32 +02:00
|
|
|
if (!HeapTupleIsValid(tup))
|
|
|
|
elog(ERROR, "cache lookup failed for text search parser %u", prsId);
|
|
|
|
form = (Form_pg_ts_parser) GETSTRUCT(tup);
|
|
|
|
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Quick check: if it ain't in the path at all, it ain't visible. Items in
|
|
|
|
* the system namespace are surely in the path and so we needn't even do
|
|
|
|
* list_member_oid() for them.
|
|
|
|
*/
|
|
|
|
namespace = form->prsnamespace;
|
|
|
|
if (namespace != PG_CATALOG_NAMESPACE &&
|
|
|
|
!list_member_oid(activeSearchPath, namespace))
|
|
|
|
visible = false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If it is in the path, it might still not be visible; it could be
|
|
|
|
* hidden by another parser of the same name earlier in the path. So
|
|
|
|
* we must do a slow check for conflicting parsers.
|
|
|
|
*/
|
|
|
|
char *name = NameStr(form->prsname);
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
visible = false;
|
|
|
|
foreach(l, activeSearchPath)
|
|
|
|
{
|
|
|
|
Oid namespaceId = lfirst_oid(l);
|
|
|
|
|
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
|
|
|
if (namespaceId == namespace)
|
|
|
|
{
|
|
|
|
/* Found it first in path */
|
|
|
|
visible = true;
|
|
|
|
break;
|
|
|
|
}
|
2010-02-14 19:42:19 +01:00
|
|
|
if (SearchSysCacheExists2(TSPARSERNAMENSP,
|
|
|
|
PointerGetDatum(name),
|
|
|
|
ObjectIdGetDatum(namespaceId)))
|
2007-08-21 03:11:32 +02:00
|
|
|
{
|
|
|
|
/* Found something else first in path */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(tup);
|
|
|
|
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-08-05 17:25:36 +02:00
|
|
|
* get_ts_dict_oid - find a TS dictionary by possibly qualified name
|
2007-08-21 03:11:32 +02:00
|
|
|
*
|
2019-07-16 06:23:53 +02:00
|
|
|
* If not found, returns InvalidOid if missing_ok, else throws error
|
2007-08-21 03:11:32 +02:00
|
|
|
*/
|
|
|
|
Oid
|
2010-08-05 17:25:36 +02:00
|
|
|
get_ts_dict_oid(List *names, bool missing_ok)
|
2007-08-21 03:11:32 +02:00
|
|
|
{
|
|
|
|
char *schemaname;
|
|
|
|
char *dict_name;
|
|
|
|
Oid namespaceId;
|
|
|
|
Oid dictoid = InvalidOid;
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
/* deconstruct the name list */
|
|
|
|
DeconstructQualifiedName(names, &schemaname, &dict_name);
|
|
|
|
|
|
|
|
if (schemaname)
|
|
|
|
{
|
|
|
|
/* use exact schema given */
|
2013-01-26 19:24:50 +01:00
|
|
|
namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
|
|
|
|
if (missing_ok && !OidIsValid(namespaceId))
|
|
|
|
dictoid = InvalidOid;
|
|
|
|
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
|
|
|
dictoid = GetSysCacheOid2(TSDICTNAMENSP, Anum_pg_ts_dict_oid,
|
2013-01-26 19:24:50 +01:00
|
|
|
PointerGetDatum(dict_name),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
2007-08-21 03:11:32 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* search for it in search path */
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
foreach(l, activeSearchPath)
|
|
|
|
{
|
|
|
|
namespaceId = lfirst_oid(l);
|
|
|
|
|
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
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
|
|
|
dictoid = GetSysCacheOid2(TSDICTNAMENSP, Anum_pg_ts_dict_oid,
|
2010-02-14 19:42:19 +01:00
|
|
|
PointerGetDatum(dict_name),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
2007-08-21 03:11:32 +02:00
|
|
|
if (OidIsValid(dictoid))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-05 17:25:36 +02:00
|
|
|
if (!OidIsValid(dictoid) && !missing_ok)
|
2007-08-21 03:11:32 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("text search dictionary \"%s\" does not exist",
|
|
|
|
NameListToString(names))));
|
|
|
|
|
|
|
|
return dictoid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TSDictionaryIsVisible
|
|
|
|
* Determine whether a dictionary (identified by OID) is visible in the
|
|
|
|
* current search path. Visible means "would be found by searching
|
|
|
|
* for the unqualified dictionary name".
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
TSDictionaryIsVisible(Oid dictId)
|
|
|
|
{
|
|
|
|
HeapTuple tup;
|
|
|
|
Form_pg_ts_dict form;
|
|
|
|
Oid namespace;
|
|
|
|
bool visible;
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
tup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictId));
|
2007-08-21 03:11:32 +02:00
|
|
|
if (!HeapTupleIsValid(tup))
|
|
|
|
elog(ERROR, "cache lookup failed for text search dictionary %u",
|
|
|
|
dictId);
|
|
|
|
form = (Form_pg_ts_dict) GETSTRUCT(tup);
|
|
|
|
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Quick check: if it ain't in the path at all, it ain't visible. Items in
|
|
|
|
* the system namespace are surely in the path and so we needn't even do
|
|
|
|
* list_member_oid() for them.
|
|
|
|
*/
|
|
|
|
namespace = form->dictnamespace;
|
|
|
|
if (namespace != PG_CATALOG_NAMESPACE &&
|
|
|
|
!list_member_oid(activeSearchPath, namespace))
|
|
|
|
visible = false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If it is in the path, it might still not be visible; it could be
|
|
|
|
* hidden by another dictionary of the same name earlier in the path.
|
|
|
|
* So we must do a slow check for conflicting dictionaries.
|
|
|
|
*/
|
|
|
|
char *name = NameStr(form->dictname);
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
visible = false;
|
|
|
|
foreach(l, activeSearchPath)
|
|
|
|
{
|
|
|
|
Oid namespaceId = lfirst_oid(l);
|
|
|
|
|
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
|
|
|
if (namespaceId == namespace)
|
|
|
|
{
|
|
|
|
/* Found it first in path */
|
|
|
|
visible = true;
|
|
|
|
break;
|
|
|
|
}
|
2010-02-14 19:42:19 +01:00
|
|
|
if (SearchSysCacheExists2(TSDICTNAMENSP,
|
|
|
|
PointerGetDatum(name),
|
|
|
|
ObjectIdGetDatum(namespaceId)))
|
2007-08-21 03:11:32 +02:00
|
|
|
{
|
|
|
|
/* Found something else first in path */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(tup);
|
|
|
|
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-08-05 17:25:36 +02:00
|
|
|
* get_ts_template_oid - find a TS template by possibly qualified name
|
2007-08-21 03:11:32 +02:00
|
|
|
*
|
2010-08-05 17:25:36 +02:00
|
|
|
* If not found, returns InvalidOid if missing_ok, else throws error
|
2007-08-21 03:11:32 +02:00
|
|
|
*/
|
|
|
|
Oid
|
2010-08-05 17:25:36 +02:00
|
|
|
get_ts_template_oid(List *names, bool missing_ok)
|
2007-08-21 03:11:32 +02:00
|
|
|
{
|
|
|
|
char *schemaname;
|
|
|
|
char *template_name;
|
|
|
|
Oid namespaceId;
|
|
|
|
Oid tmploid = InvalidOid;
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
/* deconstruct the name list */
|
|
|
|
DeconstructQualifiedName(names, &schemaname, &template_name);
|
|
|
|
|
|
|
|
if (schemaname)
|
|
|
|
{
|
|
|
|
/* use exact schema given */
|
2013-01-26 19:24:50 +01:00
|
|
|
namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
|
|
|
|
if (missing_ok && !OidIsValid(namespaceId))
|
|
|
|
tmploid = InvalidOid;
|
|
|
|
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
|
|
|
tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP, Anum_pg_ts_template_oid,
|
2013-01-26 19:24:50 +01:00
|
|
|
PointerGetDatum(template_name),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
2007-08-21 03:11:32 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* search for it in search path */
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
foreach(l, activeSearchPath)
|
|
|
|
{
|
|
|
|
namespaceId = lfirst_oid(l);
|
|
|
|
|
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
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
|
|
|
tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP, Anum_pg_ts_template_oid,
|
2010-02-14 19:42:19 +01:00
|
|
|
PointerGetDatum(template_name),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
2007-08-21 03:11:32 +02:00
|
|
|
if (OidIsValid(tmploid))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-05 17:25:36 +02:00
|
|
|
if (!OidIsValid(tmploid) && !missing_ok)
|
2007-08-21 03:11:32 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("text search template \"%s\" does not exist",
|
|
|
|
NameListToString(names))));
|
|
|
|
|
|
|
|
return tmploid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TSTemplateIsVisible
|
|
|
|
* Determine whether a template (identified by OID) is visible in the
|
|
|
|
* current search path. Visible means "would be found by searching
|
|
|
|
* for the unqualified template name".
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
TSTemplateIsVisible(Oid tmplId)
|
|
|
|
{
|
|
|
|
HeapTuple tup;
|
|
|
|
Form_pg_ts_template form;
|
|
|
|
Oid namespace;
|
|
|
|
bool visible;
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
tup = SearchSysCache1(TSTEMPLATEOID, ObjectIdGetDatum(tmplId));
|
2007-08-21 03:11:32 +02:00
|
|
|
if (!HeapTupleIsValid(tup))
|
|
|
|
elog(ERROR, "cache lookup failed for text search template %u", tmplId);
|
|
|
|
form = (Form_pg_ts_template) GETSTRUCT(tup);
|
|
|
|
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Quick check: if it ain't in the path at all, it ain't visible. Items in
|
|
|
|
* the system namespace are surely in the path and so we needn't even do
|
|
|
|
* list_member_oid() for them.
|
|
|
|
*/
|
|
|
|
namespace = form->tmplnamespace;
|
|
|
|
if (namespace != PG_CATALOG_NAMESPACE &&
|
|
|
|
!list_member_oid(activeSearchPath, namespace))
|
|
|
|
visible = false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If it is in the path, it might still not be visible; it could be
|
|
|
|
* hidden by another template of the same name earlier in the path. So
|
|
|
|
* we must do a slow check for conflicting templates.
|
|
|
|
*/
|
|
|
|
char *name = NameStr(form->tmplname);
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
visible = false;
|
|
|
|
foreach(l, activeSearchPath)
|
|
|
|
{
|
|
|
|
Oid namespaceId = lfirst_oid(l);
|
|
|
|
|
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
|
|
|
if (namespaceId == namespace)
|
|
|
|
{
|
|
|
|
/* Found it first in path */
|
|
|
|
visible = true;
|
|
|
|
break;
|
|
|
|
}
|
2010-02-14 19:42:19 +01:00
|
|
|
if (SearchSysCacheExists2(TSTEMPLATENAMENSP,
|
|
|
|
PointerGetDatum(name),
|
|
|
|
ObjectIdGetDatum(namespaceId)))
|
2007-08-21 03:11:32 +02:00
|
|
|
{
|
|
|
|
/* Found something else first in path */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(tup);
|
|
|
|
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-08-05 17:25:36 +02:00
|
|
|
* get_ts_config_oid - find a TS config by possibly qualified name
|
2007-08-21 03:11:32 +02:00
|
|
|
*
|
2010-08-05 17:25:36 +02:00
|
|
|
* If not found, returns InvalidOid if missing_ok, else throws error
|
2007-08-21 03:11:32 +02:00
|
|
|
*/
|
|
|
|
Oid
|
2010-08-05 17:25:36 +02:00
|
|
|
get_ts_config_oid(List *names, bool missing_ok)
|
2007-08-21 03:11:32 +02:00
|
|
|
{
|
|
|
|
char *schemaname;
|
|
|
|
char *config_name;
|
|
|
|
Oid namespaceId;
|
|
|
|
Oid cfgoid = InvalidOid;
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
/* deconstruct the name list */
|
|
|
|
DeconstructQualifiedName(names, &schemaname, &config_name);
|
|
|
|
|
|
|
|
if (schemaname)
|
|
|
|
{
|
|
|
|
/* use exact schema given */
|
2013-01-26 19:24:50 +01:00
|
|
|
namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
|
|
|
|
if (missing_ok && !OidIsValid(namespaceId))
|
|
|
|
cfgoid = InvalidOid;
|
|
|
|
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
|
|
|
cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP, Anum_pg_ts_config_oid,
|
2013-01-26 19:24:50 +01:00
|
|
|
PointerGetDatum(config_name),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
2007-08-21 03:11:32 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* search for it in search path */
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
foreach(l, activeSearchPath)
|
|
|
|
{
|
|
|
|
namespaceId = lfirst_oid(l);
|
|
|
|
|
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
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
|
|
|
cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP, Anum_pg_ts_config_oid,
|
2010-02-14 19:42:19 +01:00
|
|
|
PointerGetDatum(config_name),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
2007-08-21 03:11:32 +02:00
|
|
|
if (OidIsValid(cfgoid))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-05 17:25:36 +02:00
|
|
|
if (!OidIsValid(cfgoid) && !missing_ok)
|
2007-08-21 03:11:32 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("text search configuration \"%s\" does not exist",
|
|
|
|
NameListToString(names))));
|
|
|
|
|
|
|
|
return cfgoid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TSConfigIsVisible
|
|
|
|
* Determine whether a text search configuration (identified by OID)
|
|
|
|
* is visible in the current search path. Visible means "would be found
|
|
|
|
* by searching for the unqualified text search configuration name".
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
TSConfigIsVisible(Oid cfgid)
|
|
|
|
{
|
|
|
|
HeapTuple tup;
|
|
|
|
Form_pg_ts_config form;
|
|
|
|
Oid namespace;
|
|
|
|
bool visible;
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
tup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgid));
|
2007-08-21 03:11:32 +02:00
|
|
|
if (!HeapTupleIsValid(tup))
|
|
|
|
elog(ERROR, "cache lookup failed for text search configuration %u",
|
|
|
|
cfgid);
|
|
|
|
form = (Form_pg_ts_config) GETSTRUCT(tup);
|
|
|
|
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Quick check: if it ain't in the path at all, it ain't visible. Items in
|
|
|
|
* the system namespace are surely in the path and so we needn't even do
|
|
|
|
* list_member_oid() for them.
|
|
|
|
*/
|
|
|
|
namespace = form->cfgnamespace;
|
|
|
|
if (namespace != PG_CATALOG_NAMESPACE &&
|
|
|
|
!list_member_oid(activeSearchPath, namespace))
|
|
|
|
visible = false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If it is in the path, it might still not be visible; it could be
|
|
|
|
* hidden by another configuration of the same name earlier in the
|
|
|
|
* path. So we must do a slow check for conflicting configurations.
|
|
|
|
*/
|
|
|
|
char *name = NameStr(form->cfgname);
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
visible = false;
|
|
|
|
foreach(l, activeSearchPath)
|
|
|
|
{
|
|
|
|
Oid namespaceId = lfirst_oid(l);
|
|
|
|
|
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
|
|
|
if (namespaceId == namespace)
|
|
|
|
{
|
|
|
|
/* Found it first in path */
|
|
|
|
visible = true;
|
|
|
|
break;
|
|
|
|
}
|
2010-02-14 19:42:19 +01:00
|
|
|
if (SearchSysCacheExists2(TSCONFIGNAMENSP,
|
|
|
|
PointerGetDatum(name),
|
|
|
|
ObjectIdGetDatum(namespaceId)))
|
2007-08-21 03:11:32 +02:00
|
|
|
{
|
|
|
|
/* Found something else first in path */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(tup);
|
|
|
|
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-03-29 20:06:29 +01:00
|
|
|
/*
|
2002-07-30 01:46:35 +02:00
|
|
|
* DeconstructQualifiedName
|
|
|
|
* Given a possibly-qualified name expressed as a list of String nodes,
|
|
|
|
* extract the schema name and object name.
|
2002-03-31 08:26:32 +02:00
|
|
|
*
|
2002-07-30 01:46:35 +02:00
|
|
|
* *nspname_p is set to NULL if there is no explicit schema name.
|
2002-03-29 20:06:29 +01:00
|
|
|
*/
|
2002-07-30 01:46:35 +02:00
|
|
|
void
|
|
|
|
DeconstructQualifiedName(List *names,
|
|
|
|
char **nspname_p,
|
|
|
|
char **objname_p)
|
2002-03-29 20:06:29 +01:00
|
|
|
{
|
|
|
|
char *catalogname;
|
|
|
|
char *schemaname = NULL;
|
|
|
|
char *objname = NULL;
|
|
|
|
|
2004-05-26 06:41:50 +02:00
|
|
|
switch (list_length(names))
|
2002-03-29 20:06:29 +01:00
|
|
|
{
|
|
|
|
case 1:
|
2004-05-26 06:41:50 +02:00
|
|
|
objname = strVal(linitial(names));
|
2002-03-29 20:06:29 +01:00
|
|
|
break;
|
|
|
|
case 2:
|
2004-05-26 06:41:50 +02:00
|
|
|
schemaname = strVal(linitial(names));
|
2002-03-29 20:06:29 +01:00
|
|
|
objname = strVal(lsecond(names));
|
|
|
|
break;
|
|
|
|
case 3:
|
2004-05-26 06:41:50 +02:00
|
|
|
catalogname = strVal(linitial(names));
|
2002-03-29 20:06:29 +01:00
|
|
|
schemaname = strVal(lsecond(names));
|
2003-02-09 07:56:28 +01:00
|
|
|
objname = strVal(lthird(names));
|
2002-09-04 22:31:48 +02:00
|
|
|
|
2002-03-29 20:06:29 +01:00
|
|
|
/*
|
|
|
|
* We check the catalog name and then ignore it.
|
|
|
|
*/
|
2003-06-27 16:45:32 +02:00
|
|
|
if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
|
2003-07-21 03:59:11 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
2004-02-13 02:08:20 +01:00
|
|
|
errmsg("cross-database references are not implemented: %s",
|
|
|
|
NameListToString(names))));
|
2002-03-29 20:06:29 +01:00
|
|
|
break;
|
|
|
|
default:
|
2003-07-21 03:59:11 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("improper qualified name (too many dotted names): %s",
|
|
|
|
NameListToString(names))));
|
2002-03-29 20:06:29 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2002-07-30 01:46:35 +02:00
|
|
|
*nspname_p = schemaname;
|
|
|
|
*objname_p = objname;
|
|
|
|
}
|
|
|
|
|
2009-10-31 02:41:31 +01:00
|
|
|
/*
|
|
|
|
* LookupNamespaceNoError
|
|
|
|
* Look up a schema name.
|
|
|
|
*
|
|
|
|
* Returns the namespace OID, or InvalidOid if not found.
|
|
|
|
*
|
|
|
|
* Note this does NOT perform any permissions check --- callers are
|
|
|
|
* responsible for being sure that an appropriate check is made.
|
|
|
|
* In the majority of cases LookupExplicitNamespace is preferable.
|
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
LookupNamespaceNoError(const char *nspname)
|
|
|
|
{
|
|
|
|
/* check for pg_temp alias */
|
|
|
|
if (strcmp(nspname, "pg_temp") == 0)
|
|
|
|
{
|
|
|
|
if (OidIsValid(myTempNamespace))
|
2013-04-05 14:51:31 +02:00
|
|
|
{
|
|
|
|
InvokeNamespaceSearchHook(myTempNamespace, true);
|
2009-10-31 02:41:31 +01:00
|
|
|
return myTempNamespace;
|
2013-04-05 14:51:31 +02:00
|
|
|
}
|
2009-10-31 02:41:31 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Since this is used only for looking up existing objects, there is
|
|
|
|
* no point in trying to initialize the temp namespace here; and doing
|
|
|
|
* so might create problems for some callers. Just report "not found".
|
|
|
|
*/
|
|
|
|
return InvalidOid;
|
|
|
|
}
|
|
|
|
|
2010-08-05 16:45:09 +02:00
|
|
|
return get_namespace_oid(nspname, true);
|
2009-10-31 02:41:31 +01:00
|
|
|
}
|
|
|
|
|
2002-07-30 01:46:35 +02:00
|
|
|
/*
|
|
|
|
* LookupExplicitNamespace
|
|
|
|
* Process an explicitly-specified schema name: look up the schema
|
|
|
|
* and verify we have USAGE (lookup) rights in it.
|
|
|
|
*
|
2013-01-26 19:47:50 +01:00
|
|
|
* Returns the namespace OID
|
2002-07-30 01:46:35 +02:00
|
|
|
*/
|
|
|
|
Oid
|
2013-01-26 19:24:50 +01:00
|
|
|
LookupExplicitNamespace(const char *nspname, bool missing_ok)
|
2002-07-30 01:46:35 +02:00
|
|
|
{
|
|
|
|
Oid namespaceId;
|
|
|
|
AclResult aclresult;
|
|
|
|
|
2007-04-20 04:37:38 +02:00
|
|
|
/* check for pg_temp alias */
|
|
|
|
if (strcmp(nspname, "pg_temp") == 0)
|
|
|
|
{
|
|
|
|
if (OidIsValid(myTempNamespace))
|
|
|
|
return myTempNamespace;
|
2007-11-15 22:14:46 +01:00
|
|
|
|
2007-04-20 04:37:38 +02:00
|
|
|
/*
|
|
|
|
* Since this is used only for looking up existing objects, there is
|
|
|
|
* no point in trying to initialize the temp namespace here; and doing
|
2013-01-26 19:47:50 +01:00
|
|
|
* so might create problems for some callers --- just fall through.
|
2007-04-20 04:37:38 +02:00
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2013-01-26 19:24:50 +01:00
|
|
|
namespaceId = get_namespace_oid(nspname, missing_ok);
|
|
|
|
if (missing_ok && !OidIsValid(namespaceId))
|
|
|
|
return InvalidOid;
|
2013-05-29 22:58:43 +02:00
|
|
|
|
2022-11-13 08:11:17 +01:00
|
|
|
aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(), ACL_USAGE);
|
2002-07-30 01:46:35 +02:00
|
|
|
if (aclresult != ACLCHECK_OK)
|
2017-12-02 15:26:34 +01:00
|
|
|
aclcheck_error(aclresult, OBJECT_SCHEMA,
|
2003-08-01 02:15:26 +02:00
|
|
|
nspname);
|
2013-04-05 14:51:31 +02:00
|
|
|
/* Schema search hook for this lookup */
|
|
|
|
InvokeNamespaceSearchHook(namespaceId, true);
|
2002-07-30 01:46:35 +02:00
|
|
|
|
|
|
|
return namespaceId;
|
|
|
|
}
|
|
|
|
|
2005-08-01 06:03:59 +02:00
|
|
|
/*
|
|
|
|
* LookupCreationNamespace
|
|
|
|
* Look up the schema and verify we have CREATE rights on it.
|
|
|
|
*
|
2009-10-31 02:41:31 +01:00
|
|
|
* This is just like LookupExplicitNamespace except for the different
|
|
|
|
* permission check, and that we are willing to create pg_temp if needed.
|
2007-04-20 04:37:38 +02:00
|
|
|
*
|
|
|
|
* Note: calling this may result in a CommandCounterIncrement operation,
|
|
|
|
* if we have to create or clean out the temp namespace.
|
2005-08-01 06:03:59 +02:00
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
LookupCreationNamespace(const char *nspname)
|
|
|
|
{
|
|
|
|
Oid namespaceId;
|
|
|
|
AclResult aclresult;
|
|
|
|
|
2007-04-20 04:37:38 +02:00
|
|
|
/* check for pg_temp alias */
|
|
|
|
if (strcmp(nspname, "pg_temp") == 0)
|
|
|
|
{
|
Restrict the use of temporary namespace in two-phase transactions
Attempting to use a temporary table within a two-phase transaction is
forbidden for ages. However, there have been uncovered grounds for
a couple of other object types and commands which work on temporary
objects with two-phase commit. In short, trying to create, lock or drop
an object on a temporary schema should not be authorized within a
two-phase transaction, as it would cause its state to create
dependencies with other sessions, causing all sorts of side effects with
the existing session or other sessions spawned later on trying to use
the same temporary schema name.
Regression tests are added to cover all the grounds found, the original
report mentioned function creation, but monitoring closer there are many
other patterns with LOCK, DROP or CREATE EXTENSION which are involved.
One of the symptoms resulting in combining both is that the session
which used the temporary schema is not able to shut down completely,
waiting for being able to drop the temporary schema, something that it
cannot complete because of the two-phase transaction involved with
temporary objects. In this case the client is able to disconnect but
the session remains alive on the backend-side, potentially blocking
connection backend slots from being used. Other problems reported could
also involve server crashes.
This is back-patched down to v10, which is where 9b013dc has introduced
MyXactFlags, something that this patch relies on.
Reported-by: Alexey Bashtanov
Author: Michael Paquier
Reviewed-by: Masahiko Sawada
Discussion: https://postgr.es/m/5d910e2e-0db8-ec06-dd5f-baec420513c3@imap.cc
Backpatch-through: 10
2019-01-18 01:21:44 +01:00
|
|
|
/* Initialize temp namespace */
|
|
|
|
AccessTempTableNamespace(false);
|
2007-04-20 04:37:38 +02:00
|
|
|
return myTempNamespace;
|
|
|
|
}
|
|
|
|
|
2010-08-05 16:45:09 +02:00
|
|
|
namespaceId = get_namespace_oid(nspname, false);
|
2005-08-01 06:03:59 +02:00
|
|
|
|
2022-11-13 08:11:17 +01:00
|
|
|
aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(), ACL_CREATE);
|
2005-08-01 06:03:59 +02:00
|
|
|
if (aclresult != ACLCHECK_OK)
|
2017-12-02 15:26:34 +01:00
|
|
|
aclcheck_error(aclresult, OBJECT_SCHEMA,
|
2005-08-01 06:03:59 +02:00
|
|
|
nspname);
|
|
|
|
|
|
|
|
return namespaceId;
|
|
|
|
}
|
|
|
|
|
2010-11-23 01:46:15 +01:00
|
|
|
/*
|
|
|
|
* Common checks on switching namespaces.
|
|
|
|
*
|
2015-11-19 20:59:01 +01:00
|
|
|
* We complain if either the old or new namespaces is a temporary schema
|
|
|
|
* (or temporary toast schema), or if either the old or new namespaces is the
|
2015-11-19 16:49:25 +01:00
|
|
|
* TOAST schema.
|
2010-11-23 01:46:15 +01:00
|
|
|
*/
|
|
|
|
void
|
2015-11-19 16:49:25 +01:00
|
|
|
CheckSetNamespace(Oid oldNspOid, Oid nspOid)
|
2010-11-23 01:46:15 +01:00
|
|
|
{
|
|
|
|
/* disallow renaming into or out of temp schemas */
|
|
|
|
if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("cannot move objects into or out of temporary schemas")));
|
|
|
|
|
|
|
|
/* same for TOAST schema */
|
|
|
|
if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("cannot move objects into or out of TOAST schema")));
|
|
|
|
}
|
|
|
|
|
2002-07-30 01:46:35 +02:00
|
|
|
/*
|
|
|
|
* QualifiedNameGetCreationNamespace
|
Remove Value node struct
The Value node struct is a weird construct. It is its own node type,
but most of the time, it actually has a node type of Integer, Float,
String, or BitString. As a consequence, the struct name and the node
type don't match most of the time, and so it has to be treated
specially a lot. There doesn't seem to be any value in the special
construct. There is very little code that wants to accept all Value
variants but nothing else (and even if it did, this doesn't provide
any convenient way to check it), and most code wants either just one
particular node type (usually String), or it accepts a broader set of
node types besides just Value.
This change removes the Value struct and node type and replaces them
by separate Integer, Float, String, and BitString node types that are
proper node types and structs of their own and behave mostly like
normal node types.
Also, this removes the T_Null node tag, which was previously also a
possible variant of Value but wasn't actually used outside of the
Value contained in A_Const. Replace that by an isnull field in
A_Const.
Reviewed-by: Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>
Reviewed-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/5ba6bc5b-3f95-04f2-2419-f8ddb4c046fb@enterprisedb.com
2021-09-09 07:58:12 +02:00
|
|
|
* Given a possibly-qualified name for an object (in List-of-Strings
|
2002-07-30 01:46:35 +02:00
|
|
|
* format), determine what namespace the object should be created in.
|
|
|
|
* Also extract and return the object name (last component of list).
|
|
|
|
*
|
2005-08-01 06:03:59 +02:00
|
|
|
* Note: this does not apply any permissions check. Callers must check
|
|
|
|
* for CREATE rights on the selected namespace when appropriate.
|
|
|
|
*
|
2007-04-20 04:37:38 +02:00
|
|
|
* Note: calling this may result in a CommandCounterIncrement operation,
|
|
|
|
* if we have to create or clean out the temp namespace.
|
2002-07-30 01:46:35 +02:00
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
QualifiedNameGetCreationNamespace(List *names, char **objname_p)
|
|
|
|
{
|
|
|
|
char *schemaname;
|
|
|
|
Oid namespaceId;
|
|
|
|
|
|
|
|
/* deconstruct the name list */
|
2007-04-20 04:37:38 +02:00
|
|
|
DeconstructQualifiedName(names, &schemaname, objname_p);
|
2002-07-30 01:46:35 +02:00
|
|
|
|
2002-03-29 20:06:29 +01:00
|
|
|
if (schemaname)
|
|
|
|
{
|
2007-04-20 04:37:38 +02:00
|
|
|
/* check for pg_temp alias */
|
|
|
|
if (strcmp(schemaname, "pg_temp") == 0)
|
|
|
|
{
|
Restrict the use of temporary namespace in two-phase transactions
Attempting to use a temporary table within a two-phase transaction is
forbidden for ages. However, there have been uncovered grounds for
a couple of other object types and commands which work on temporary
objects with two-phase commit. In short, trying to create, lock or drop
an object on a temporary schema should not be authorized within a
two-phase transaction, as it would cause its state to create
dependencies with other sessions, causing all sorts of side effects with
the existing session or other sessions spawned later on trying to use
the same temporary schema name.
Regression tests are added to cover all the grounds found, the original
report mentioned function creation, but monitoring closer there are many
other patterns with LOCK, DROP or CREATE EXTENSION which are involved.
One of the symptoms resulting in combining both is that the session
which used the temporary schema is not able to shut down completely,
waiting for being able to drop the temporary schema, something that it
cannot complete because of the two-phase transaction involved with
temporary objects. In this case the client is able to disconnect but
the session remains alive on the backend-side, potentially blocking
connection backend slots from being used. Other problems reported could
also involve server crashes.
This is back-patched down to v10, which is where 9b013dc has introduced
MyXactFlags, something that this patch relies on.
Reported-by: Alexey Bashtanov
Author: Michael Paquier
Reviewed-by: Masahiko Sawada
Discussion: https://postgr.es/m/5d910e2e-0db8-ec06-dd5f-baec420513c3@imap.cc
Backpatch-through: 10
2019-01-18 01:21:44 +01:00
|
|
|
/* Initialize temp namespace */
|
|
|
|
AccessTempTableNamespace(false);
|
2007-04-20 04:37:38 +02:00
|
|
|
return myTempNamespace;
|
|
|
|
}
|
2002-03-31 08:26:32 +02:00
|
|
|
/* use exact schema given */
|
2010-08-05 16:45:09 +02:00
|
|
|
namespaceId = get_namespace_oid(schemaname, false);
|
2002-07-30 01:46:35 +02:00
|
|
|
/* we do not check for USAGE rights here! */
|
2002-03-29 20:06:29 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-03-31 08:26:32 +02:00
|
|
|
/* use the default creation namespace */
|
2002-04-30 00:15:07 +02:00
|
|
|
recomputeNamespacePath();
|
2007-04-20 04:37:38 +02:00
|
|
|
if (activeTempCreationPending)
|
|
|
|
{
|
|
|
|
/* Need to initialize temp namespace */
|
Restrict the use of temporary namespace in two-phase transactions
Attempting to use a temporary table within a two-phase transaction is
forbidden for ages. However, there have been uncovered grounds for
a couple of other object types and commands which work on temporary
objects with two-phase commit. In short, trying to create, lock or drop
an object on a temporary schema should not be authorized within a
two-phase transaction, as it would cause its state to create
dependencies with other sessions, causing all sorts of side effects with
the existing session or other sessions spawned later on trying to use
the same temporary schema name.
Regression tests are added to cover all the grounds found, the original
report mentioned function creation, but monitoring closer there are many
other patterns with LOCK, DROP or CREATE EXTENSION which are involved.
One of the symptoms resulting in combining both is that the session
which used the temporary schema is not able to shut down completely,
waiting for being able to drop the temporary schema, something that it
cannot complete because of the two-phase transaction involved with
temporary objects. In this case the client is able to disconnect but
the session remains alive on the backend-side, potentially blocking
connection backend slots from being used. Other problems reported could
also involve server crashes.
This is back-patched down to v10, which is where 9b013dc has introduced
MyXactFlags, something that this patch relies on.
Reported-by: Alexey Bashtanov
Author: Michael Paquier
Reviewed-by: Masahiko Sawada
Discussion: https://postgr.es/m/5d910e2e-0db8-ec06-dd5f-baec420513c3@imap.cc
Backpatch-through: 10
2019-01-18 01:21:44 +01:00
|
|
|
AccessTempTableNamespace(true);
|
2007-04-20 04:37:38 +02:00
|
|
|
return myTempNamespace;
|
|
|
|
}
|
2007-03-23 20:53:52 +01:00
|
|
|
namespaceId = activeCreationNamespace;
|
2002-04-16 00:33:21 +02:00
|
|
|
if (!OidIsValid(namespaceId))
|
2003-07-21 03:59:11 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_SCHEMA),
|
|
|
|
errmsg("no schema has been selected to create in")));
|
2002-03-29 20:06:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return namespaceId;
|
|
|
|
}
|
|
|
|
|
2010-08-05 16:45:09 +02:00
|
|
|
/*
|
|
|
|
* get_namespace_oid - given a namespace name, look up the OID
|
|
|
|
*
|
|
|
|
* If missing_ok is false, throw an error if namespace name not found. If
|
|
|
|
* true, just return InvalidOid.
|
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
get_namespace_oid(const char *nspname, bool missing_ok)
|
|
|
|
{
|
|
|
|
Oid oid;
|
|
|
|
|
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
|
|
|
oid = GetSysCacheOid1(NAMESPACENAME, Anum_pg_namespace_oid,
|
|
|
|
CStringGetDatum(nspname));
|
2010-08-05 16:45:09 +02:00
|
|
|
if (!OidIsValid(oid) && !missing_ok)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_SCHEMA),
|
|
|
|
errmsg("schema \"%s\" does not exist", nspname)));
|
|
|
|
|
|
|
|
return oid;
|
|
|
|
}
|
|
|
|
|
2002-03-29 20:06:29 +01:00
|
|
|
/*
|
|
|
|
* makeRangeVarFromNameList
|
|
|
|
* Utility routine to convert a qualified-name list into RangeVar form.
|
|
|
|
*/
|
|
|
|
RangeVar *
|
|
|
|
makeRangeVarFromNameList(List *names)
|
|
|
|
{
|
2008-09-01 22:42:46 +02:00
|
|
|
RangeVar *rel = makeRangeVar(NULL, NULL, -1);
|
2002-03-29 20:06:29 +01:00
|
|
|
|
2004-05-26 06:41:50 +02:00
|
|
|
switch (list_length(names))
|
2002-03-29 20:06:29 +01:00
|
|
|
{
|
|
|
|
case 1:
|
2004-05-26 06:41:50 +02:00
|
|
|
rel->relname = strVal(linitial(names));
|
2002-03-29 20:06:29 +01:00
|
|
|
break;
|
|
|
|
case 2:
|
2004-05-26 06:41:50 +02:00
|
|
|
rel->schemaname = strVal(linitial(names));
|
2002-03-29 20:06:29 +01:00
|
|
|
rel->relname = strVal(lsecond(names));
|
|
|
|
break;
|
|
|
|
case 3:
|
2004-05-26 06:41:50 +02:00
|
|
|
rel->catalogname = strVal(linitial(names));
|
2002-03-29 20:06:29 +01:00
|
|
|
rel->schemaname = strVal(lsecond(names));
|
2003-02-09 07:56:28 +01:00
|
|
|
rel->relname = strVal(lthird(names));
|
2002-03-29 20:06:29 +01:00
|
|
|
break;
|
|
|
|
default:
|
2003-07-21 03:59:11 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("improper relation name (too many dotted names): %s",
|
|
|
|
NameListToString(names))));
|
2002-03-29 20:06:29 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rel;
|
|
|
|
}
|
2002-03-31 08:26:32 +02:00
|
|
|
|
2002-04-09 22:35:55 +02:00
|
|
|
/*
|
|
|
|
* NameListToString
|
|
|
|
* Utility routine to convert a qualified-name list into a string.
|
2002-11-02 19:41:22 +01:00
|
|
|
*
|
|
|
|
* This is used primarily to form error messages, and so we do not quote
|
|
|
|
* the list elements, for the sake of legibility.
|
2008-08-30 03:39:14 +02:00
|
|
|
*
|
Remove Value node struct
The Value node struct is a weird construct. It is its own node type,
but most of the time, it actually has a node type of Integer, Float,
String, or BitString. As a consequence, the struct name and the node
type don't match most of the time, and so it has to be treated
specially a lot. There doesn't seem to be any value in the special
construct. There is very little code that wants to accept all Value
variants but nothing else (and even if it did, this doesn't provide
any convenient way to check it), and most code wants either just one
particular node type (usually String), or it accepts a broader set of
node types besides just Value.
This change removes the Value struct and node type and replaces them
by separate Integer, Float, String, and BitString node types that are
proper node types and structs of their own and behave mostly like
normal node types.
Also, this removes the T_Null node tag, which was previously also a
possible variant of Value but wasn't actually used outside of the
Value contained in A_Const. Replace that by an isnull field in
A_Const.
Reviewed-by: Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>
Reviewed-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/5ba6bc5b-3f95-04f2-2419-f8ddb4c046fb@enterprisedb.com
2021-09-09 07:58:12 +02:00
|
|
|
* In most scenarios the list elements should always be String values,
|
2008-08-30 03:39:14 +02:00
|
|
|
* but we also allow A_Star for the convenience of ColumnRef processing.
|
2002-04-09 22:35:55 +02:00
|
|
|
*/
|
|
|
|
char *
|
|
|
|
NameListToString(List *names)
|
|
|
|
{
|
|
|
|
StringInfoData string;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
2002-04-09 22:35:55 +02:00
|
|
|
|
|
|
|
initStringInfo(&string);
|
|
|
|
|
|
|
|
foreach(l, names)
|
|
|
|
{
|
2008-08-30 03:39:14 +02:00
|
|
|
Node *name = (Node *) lfirst(l);
|
|
|
|
|
2004-05-26 06:41:50 +02:00
|
|
|
if (l != list_head(names))
|
2002-04-09 22:35:55 +02:00
|
|
|
appendStringInfoChar(&string, '.');
|
2008-08-30 03:39:14 +02:00
|
|
|
|
|
|
|
if (IsA(name, String))
|
|
|
|
appendStringInfoString(&string, strVal(name));
|
|
|
|
else if (IsA(name, A_Star))
|
2015-05-12 02:38:55 +02:00
|
|
|
appendStringInfoChar(&string, '*');
|
2008-08-30 03:39:14 +02:00
|
|
|
else
|
|
|
|
elog(ERROR, "unexpected node type in name list: %d",
|
|
|
|
(int) nodeTag(name));
|
2002-04-09 22:35:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return string.data;
|
|
|
|
}
|
|
|
|
|
2002-11-02 19:41:22 +01:00
|
|
|
/*
|
|
|
|
* NameListToQuotedString
|
|
|
|
* Utility routine to convert a qualified-name list into a string.
|
|
|
|
*
|
|
|
|
* Same as above except that names will be double-quoted where necessary,
|
|
|
|
* so the string could be re-parsed (eg, by textToQualifiedNameList).
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
NameListToQuotedString(List *names)
|
|
|
|
{
|
|
|
|
StringInfoData string;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
2002-11-02 19:41:22 +01:00
|
|
|
|
|
|
|
initStringInfo(&string);
|
|
|
|
|
|
|
|
foreach(l, names)
|
|
|
|
{
|
2004-05-26 06:41:50 +02:00
|
|
|
if (l != list_head(names))
|
2002-11-02 19:41:22 +01:00
|
|
|
appendStringInfoChar(&string, '.');
|
2003-04-24 23:16:45 +02:00
|
|
|
appendStringInfoString(&string, quote_identifier(strVal(lfirst(l))));
|
2002-11-02 19:41:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return string.data;
|
|
|
|
}
|
|
|
|
|
2002-03-31 08:26:32 +02:00
|
|
|
/*
|
|
|
|
* isTempNamespace - is the given namespace my temporary-table namespace?
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
isTempNamespace(Oid namespaceId)
|
|
|
|
{
|
|
|
|
if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-07-26 00:16:18 +02:00
|
|
|
/*
|
|
|
|
* isTempToastNamespace - is the given namespace my temporary-toast-table
|
|
|
|
* namespace?
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
isTempToastNamespace(Oid namespaceId)
|
|
|
|
{
|
|
|
|
if (OidIsValid(myTempToastNamespace) && myTempToastNamespace == namespaceId)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2014-08-26 03:28:19 +02:00
|
|
|
* isTempOrTempToastNamespace - is the given namespace my temporary-table
|
2007-07-26 00:16:18 +02:00
|
|
|
* namespace or my temporary-toast-table namespace?
|
|
|
|
*/
|
|
|
|
bool
|
2014-08-26 03:28:19 +02:00
|
|
|
isTempOrTempToastNamespace(Oid namespaceId)
|
2007-07-26 00:16:18 +02:00
|
|
|
{
|
|
|
|
if (OidIsValid(myTempNamespace) &&
|
|
|
|
(myTempNamespace == namespaceId || myTempToastNamespace == namespaceId))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2002-09-23 22:43:41 +02:00
|
|
|
/*
|
2005-08-01 06:03:59 +02:00
|
|
|
* isAnyTempNamespace - is the given namespace a temporary-table namespace
|
2007-07-26 00:16:18 +02:00
|
|
|
* (either my own, or another backend's)? Temporary-toast-table namespaces
|
|
|
|
* are included, too.
|
2002-09-23 22:43:41 +02:00
|
|
|
*/
|
|
|
|
bool
|
2005-08-01 06:03:59 +02:00
|
|
|
isAnyTempNamespace(Oid namespaceId)
|
2002-09-23 22:43:41 +02:00
|
|
|
{
|
|
|
|
bool result;
|
|
|
|
char *nspname;
|
|
|
|
|
2007-07-26 00:16:18 +02:00
|
|
|
/* True if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
|
2002-09-23 22:43:41 +02:00
|
|
|
nspname = get_namespace_name(namespaceId);
|
|
|
|
if (!nspname)
|
|
|
|
return false; /* no such namespace? */
|
2007-07-26 00:16:18 +02:00
|
|
|
result = (strncmp(nspname, "pg_temp_", 8) == 0) ||
|
|
|
|
(strncmp(nspname, "pg_toast_temp_", 14) == 0);
|
2002-09-23 22:43:41 +02:00
|
|
|
pfree(nspname);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2005-08-01 06:03:59 +02:00
|
|
|
/*
|
|
|
|
* isOtherTempNamespace - is the given namespace some other backend's
|
2007-07-26 00:16:18 +02:00
|
|
|
* temporary-table namespace (including temporary-toast-table namespaces)?
|
2009-04-01 00:12:48 +02:00
|
|
|
*
|
|
|
|
* Note: for most purposes in the C code, this function is obsolete. Use
|
|
|
|
* RELATION_IS_OTHER_TEMP() instead to detect non-local temp relations.
|
2005-08-01 06:03:59 +02:00
|
|
|
*/
|
|
|
|
bool
|
|
|
|
isOtherTempNamespace(Oid namespaceId)
|
|
|
|
{
|
|
|
|
/* If it's my own temp namespace, say "false" */
|
2014-08-26 03:28:19 +02:00
|
|
|
if (isTempOrTempToastNamespace(namespaceId))
|
2005-08-01 06:03:59 +02:00
|
|
|
return false;
|
2007-07-26 00:16:18 +02:00
|
|
|
/* Else, if it's any temp namespace, say "true" */
|
2005-08-01 06:03:59 +02:00
|
|
|
return isAnyTempNamespace(namespaceId);
|
|
|
|
}
|
|
|
|
|
Make autovacuum more aggressive to remove orphaned temp tables
Commit dafa084, added in 10, made the removal of temporary orphaned
tables more aggressive. This commit makes an extra step into the
aggressiveness by adding a flag in each backend's MyProc which tracks
down any temporary namespace currently in use. The flag is set when the
namespace gets created and can be reset if the temporary namespace has
been created in a transaction or sub-transaction which is aborted. The
flag value assignment is assumed to be atomic, so this can be done in a
lock-less fashion like other flags already present in PGPROC like
databaseId or backendId, still the fact that the temporary namespace and
table created are still locked until the transaction creating those
commits acts as a barrier for other backends.
This new flag gets used by autovacuum to discard more aggressively
orphaned tables by additionally checking for the database a backend is
connected to as well as its temporary namespace in-use, removing
orphaned temporary relations even if a backend reuses the same slot as
one which created temporary relations in a past session.
The base idea of this patch comes from Robert Haas, has been written in
its first version by Tsunakawa Takayuki, then heavily reviewed by me.
Author: Tsunakawa Takayuki
Reviewed-by: Michael Paquier, Kyotaro Horiguchi, Andres Freund
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F8A4DC6@G01JPEXMBYT05
Backpatch: 11-, as PGPROC gains a new flag and we don't want silent ABI
breakages on already released versions.
2018-08-13 11:49:04 +02:00
|
|
|
/*
|
Avoid failure if autovacuum tries to access a just-dropped temp namespace.
Such an access became possible when commit 246a6c8f7 added more
aggressive cleanup of orphaned temp relations by autovacuum.
Since autovacuum's snapshot might be slightly stale, it could
attempt to access an already-dropped temp namespace, resulting in
an assertion failure or null-pointer dereference. (In practice,
since we don't drop temp namespaces automatically but merely
recycle them, this situation could only arise if a superuser does
a manual drop of a temp namespace. Still, that should be allowed.)
The core of the bug, IMO, is that isTempNamespaceInUse and its callers
failed to think hard about whether to treat "temp namespace isn't there"
differently from "temp namespace isn't in use". In hopes of forestalling
future mistakes of the same ilk, replace that function with a new one
checkTempNamespaceStatus, which makes the same tests but returns a
three-way enum rather than just a bool. isTempNamespaceInUse is gone
entirely in HEAD; but just in case some external code is relying on it,
keep it in the back branches, as a bug-compatible wrapper around the
new function.
Per report originally from Prabhat Kumar Sahu, investigated by Mahendra
Singh and Michael Paquier; the final form of the patch is my fault.
This replaces the failed fix attempt in a052f6cbb.
Backpatch as far as v11, as 246a6c8f7 was.
Discussion: https://postgr.es/m/CAKYtNAr9Zq=1-ww4etHo-VCC-k120YxZy5OS01VkaLPaDbv2tg@mail.gmail.com
2020-02-29 02:28:34 +01:00
|
|
|
* checkTempNamespaceStatus - is the given namespace owned and actively used
|
Make autovacuum more aggressive to remove orphaned temp tables
Commit dafa084, added in 10, made the removal of temporary orphaned
tables more aggressive. This commit makes an extra step into the
aggressiveness by adding a flag in each backend's MyProc which tracks
down any temporary namespace currently in use. The flag is set when the
namespace gets created and can be reset if the temporary namespace has
been created in a transaction or sub-transaction which is aborted. The
flag value assignment is assumed to be atomic, so this can be done in a
lock-less fashion like other flags already present in PGPROC like
databaseId or backendId, still the fact that the temporary namespace and
table created are still locked until the transaction creating those
commits acts as a barrier for other backends.
This new flag gets used by autovacuum to discard more aggressively
orphaned tables by additionally checking for the database a backend is
connected to as well as its temporary namespace in-use, removing
orphaned temporary relations even if a backend reuses the same slot as
one which created temporary relations in a past session.
The base idea of this patch comes from Robert Haas, has been written in
its first version by Tsunakawa Takayuki, then heavily reviewed by me.
Author: Tsunakawa Takayuki
Reviewed-by: Michael Paquier, Kyotaro Horiguchi, Andres Freund
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F8A4DC6@G01JPEXMBYT05
Backpatch: 11-, as PGPROC gains a new flag and we don't want silent ABI
breakages on already released versions.
2018-08-13 11:49:04 +02:00
|
|
|
* by a backend?
|
|
|
|
*
|
|
|
|
* Note: this can be used while scanning relations in pg_class to detect
|
|
|
|
* orphaned temporary tables or namespaces with a backend connected to a
|
|
|
|
* given database. The result may be out of date quickly, so the caller
|
|
|
|
* must be careful how to handle this information.
|
|
|
|
*/
|
Avoid failure if autovacuum tries to access a just-dropped temp namespace.
Such an access became possible when commit 246a6c8f7 added more
aggressive cleanup of orphaned temp relations by autovacuum.
Since autovacuum's snapshot might be slightly stale, it could
attempt to access an already-dropped temp namespace, resulting in
an assertion failure or null-pointer dereference. (In practice,
since we don't drop temp namespaces automatically but merely
recycle them, this situation could only arise if a superuser does
a manual drop of a temp namespace. Still, that should be allowed.)
The core of the bug, IMO, is that isTempNamespaceInUse and its callers
failed to think hard about whether to treat "temp namespace isn't there"
differently from "temp namespace isn't in use". In hopes of forestalling
future mistakes of the same ilk, replace that function with a new one
checkTempNamespaceStatus, which makes the same tests but returns a
three-way enum rather than just a bool. isTempNamespaceInUse is gone
entirely in HEAD; but just in case some external code is relying on it,
keep it in the back branches, as a bug-compatible wrapper around the
new function.
Per report originally from Prabhat Kumar Sahu, investigated by Mahendra
Singh and Michael Paquier; the final form of the patch is my fault.
This replaces the failed fix attempt in a052f6cbb.
Backpatch as far as v11, as 246a6c8f7 was.
Discussion: https://postgr.es/m/CAKYtNAr9Zq=1-ww4etHo-VCC-k120YxZy5OS01VkaLPaDbv2tg@mail.gmail.com
2020-02-29 02:28:34 +01:00
|
|
|
TempNamespaceStatus
|
|
|
|
checkTempNamespaceStatus(Oid namespaceId)
|
Make autovacuum more aggressive to remove orphaned temp tables
Commit dafa084, added in 10, made the removal of temporary orphaned
tables more aggressive. This commit makes an extra step into the
aggressiveness by adding a flag in each backend's MyProc which tracks
down any temporary namespace currently in use. The flag is set when the
namespace gets created and can be reset if the temporary namespace has
been created in a transaction or sub-transaction which is aborted. The
flag value assignment is assumed to be atomic, so this can be done in a
lock-less fashion like other flags already present in PGPROC like
databaseId or backendId, still the fact that the temporary namespace and
table created are still locked until the transaction creating those
commits acts as a barrier for other backends.
This new flag gets used by autovacuum to discard more aggressively
orphaned tables by additionally checking for the database a backend is
connected to as well as its temporary namespace in-use, removing
orphaned temporary relations even if a backend reuses the same slot as
one which created temporary relations in a past session.
The base idea of this patch comes from Robert Haas, has been written in
its first version by Tsunakawa Takayuki, then heavily reviewed by me.
Author: Tsunakawa Takayuki
Reviewed-by: Michael Paquier, Kyotaro Horiguchi, Andres Freund
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F8A4DC6@G01JPEXMBYT05
Backpatch: 11-, as PGPROC gains a new flag and we don't want silent ABI
breakages on already released versions.
2018-08-13 11:49:04 +02:00
|
|
|
{
|
|
|
|
PGPROC *proc;
|
|
|
|
int backendId;
|
|
|
|
|
|
|
|
Assert(OidIsValid(MyDatabaseId));
|
|
|
|
|
|
|
|
backendId = GetTempNamespaceBackendId(namespaceId);
|
|
|
|
|
Avoid failure if autovacuum tries to access a just-dropped temp namespace.
Such an access became possible when commit 246a6c8f7 added more
aggressive cleanup of orphaned temp relations by autovacuum.
Since autovacuum's snapshot might be slightly stale, it could
attempt to access an already-dropped temp namespace, resulting in
an assertion failure or null-pointer dereference. (In practice,
since we don't drop temp namespaces automatically but merely
recycle them, this situation could only arise if a superuser does
a manual drop of a temp namespace. Still, that should be allowed.)
The core of the bug, IMO, is that isTempNamespaceInUse and its callers
failed to think hard about whether to treat "temp namespace isn't there"
differently from "temp namespace isn't in use". In hopes of forestalling
future mistakes of the same ilk, replace that function with a new one
checkTempNamespaceStatus, which makes the same tests but returns a
three-way enum rather than just a bool. isTempNamespaceInUse is gone
entirely in HEAD; but just in case some external code is relying on it,
keep it in the back branches, as a bug-compatible wrapper around the
new function.
Per report originally from Prabhat Kumar Sahu, investigated by Mahendra
Singh and Michael Paquier; the final form of the patch is my fault.
This replaces the failed fix attempt in a052f6cbb.
Backpatch as far as v11, as 246a6c8f7 was.
Discussion: https://postgr.es/m/CAKYtNAr9Zq=1-ww4etHo-VCC-k120YxZy5OS01VkaLPaDbv2tg@mail.gmail.com
2020-02-29 02:28:34 +01:00
|
|
|
/* No such namespace, or its name shows it's not temp? */
|
2020-01-15 05:58:33 +01:00
|
|
|
if (backendId == InvalidBackendId)
|
Avoid failure if autovacuum tries to access a just-dropped temp namespace.
Such an access became possible when commit 246a6c8f7 added more
aggressive cleanup of orphaned temp relations by autovacuum.
Since autovacuum's snapshot might be slightly stale, it could
attempt to access an already-dropped temp namespace, resulting in
an assertion failure or null-pointer dereference. (In practice,
since we don't drop temp namespaces automatically but merely
recycle them, this situation could only arise if a superuser does
a manual drop of a temp namespace. Still, that should be allowed.)
The core of the bug, IMO, is that isTempNamespaceInUse and its callers
failed to think hard about whether to treat "temp namespace isn't there"
differently from "temp namespace isn't in use". In hopes of forestalling
future mistakes of the same ilk, replace that function with a new one
checkTempNamespaceStatus, which makes the same tests but returns a
three-way enum rather than just a bool. isTempNamespaceInUse is gone
entirely in HEAD; but just in case some external code is relying on it,
keep it in the back branches, as a bug-compatible wrapper around the
new function.
Per report originally from Prabhat Kumar Sahu, investigated by Mahendra
Singh and Michael Paquier; the final form of the patch is my fault.
This replaces the failed fix attempt in a052f6cbb.
Backpatch as far as v11, as 246a6c8f7 was.
Discussion: https://postgr.es/m/CAKYtNAr9Zq=1-ww4etHo-VCC-k120YxZy5OS01VkaLPaDbv2tg@mail.gmail.com
2020-02-29 02:28:34 +01:00
|
|
|
return TEMP_NAMESPACE_NOT_TEMP;
|
Make autovacuum more aggressive to remove orphaned temp tables
Commit dafa084, added in 10, made the removal of temporary orphaned
tables more aggressive. This commit makes an extra step into the
aggressiveness by adding a flag in each backend's MyProc which tracks
down any temporary namespace currently in use. The flag is set when the
namespace gets created and can be reset if the temporary namespace has
been created in a transaction or sub-transaction which is aborted. The
flag value assignment is assumed to be atomic, so this can be done in a
lock-less fashion like other flags already present in PGPROC like
databaseId or backendId, still the fact that the temporary namespace and
table created are still locked until the transaction creating those
commits acts as a barrier for other backends.
This new flag gets used by autovacuum to discard more aggressively
orphaned tables by additionally checking for the database a backend is
connected to as well as its temporary namespace in-use, removing
orphaned temporary relations even if a backend reuses the same slot as
one which created temporary relations in a past session.
The base idea of this patch comes from Robert Haas, has been written in
its first version by Tsunakawa Takayuki, then heavily reviewed by me.
Author: Tsunakawa Takayuki
Reviewed-by: Michael Paquier, Kyotaro Horiguchi, Andres Freund
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F8A4DC6@G01JPEXMBYT05
Backpatch: 11-, as PGPROC gains a new flag and we don't want silent ABI
breakages on already released versions.
2018-08-13 11:49:04 +02:00
|
|
|
|
|
|
|
/* Is the backend alive? */
|
|
|
|
proc = BackendIdGetProc(backendId);
|
|
|
|
if (proc == NULL)
|
Avoid failure if autovacuum tries to access a just-dropped temp namespace.
Such an access became possible when commit 246a6c8f7 added more
aggressive cleanup of orphaned temp relations by autovacuum.
Since autovacuum's snapshot might be slightly stale, it could
attempt to access an already-dropped temp namespace, resulting in
an assertion failure or null-pointer dereference. (In practice,
since we don't drop temp namespaces automatically but merely
recycle them, this situation could only arise if a superuser does
a manual drop of a temp namespace. Still, that should be allowed.)
The core of the bug, IMO, is that isTempNamespaceInUse and its callers
failed to think hard about whether to treat "temp namespace isn't there"
differently from "temp namespace isn't in use". In hopes of forestalling
future mistakes of the same ilk, replace that function with a new one
checkTempNamespaceStatus, which makes the same tests but returns a
three-way enum rather than just a bool. isTempNamespaceInUse is gone
entirely in HEAD; but just in case some external code is relying on it,
keep it in the back branches, as a bug-compatible wrapper around the
new function.
Per report originally from Prabhat Kumar Sahu, investigated by Mahendra
Singh and Michael Paquier; the final form of the patch is my fault.
This replaces the failed fix attempt in a052f6cbb.
Backpatch as far as v11, as 246a6c8f7 was.
Discussion: https://postgr.es/m/CAKYtNAr9Zq=1-ww4etHo-VCC-k120YxZy5OS01VkaLPaDbv2tg@mail.gmail.com
2020-02-29 02:28:34 +01:00
|
|
|
return TEMP_NAMESPACE_IDLE;
|
Make autovacuum more aggressive to remove orphaned temp tables
Commit dafa084, added in 10, made the removal of temporary orphaned
tables more aggressive. This commit makes an extra step into the
aggressiveness by adding a flag in each backend's MyProc which tracks
down any temporary namespace currently in use. The flag is set when the
namespace gets created and can be reset if the temporary namespace has
been created in a transaction or sub-transaction which is aborted. The
flag value assignment is assumed to be atomic, so this can be done in a
lock-less fashion like other flags already present in PGPROC like
databaseId or backendId, still the fact that the temporary namespace and
table created are still locked until the transaction creating those
commits acts as a barrier for other backends.
This new flag gets used by autovacuum to discard more aggressively
orphaned tables by additionally checking for the database a backend is
connected to as well as its temporary namespace in-use, removing
orphaned temporary relations even if a backend reuses the same slot as
one which created temporary relations in a past session.
The base idea of this patch comes from Robert Haas, has been written in
its first version by Tsunakawa Takayuki, then heavily reviewed by me.
Author: Tsunakawa Takayuki
Reviewed-by: Michael Paquier, Kyotaro Horiguchi, Andres Freund
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F8A4DC6@G01JPEXMBYT05
Backpatch: 11-, as PGPROC gains a new flag and we don't want silent ABI
breakages on already released versions.
2018-08-13 11:49:04 +02:00
|
|
|
|
|
|
|
/* Is the backend connected to the same database we are looking at? */
|
|
|
|
if (proc->databaseId != MyDatabaseId)
|
Avoid failure if autovacuum tries to access a just-dropped temp namespace.
Such an access became possible when commit 246a6c8f7 added more
aggressive cleanup of orphaned temp relations by autovacuum.
Since autovacuum's snapshot might be slightly stale, it could
attempt to access an already-dropped temp namespace, resulting in
an assertion failure or null-pointer dereference. (In practice,
since we don't drop temp namespaces automatically but merely
recycle them, this situation could only arise if a superuser does
a manual drop of a temp namespace. Still, that should be allowed.)
The core of the bug, IMO, is that isTempNamespaceInUse and its callers
failed to think hard about whether to treat "temp namespace isn't there"
differently from "temp namespace isn't in use". In hopes of forestalling
future mistakes of the same ilk, replace that function with a new one
checkTempNamespaceStatus, which makes the same tests but returns a
three-way enum rather than just a bool. isTempNamespaceInUse is gone
entirely in HEAD; but just in case some external code is relying on it,
keep it in the back branches, as a bug-compatible wrapper around the
new function.
Per report originally from Prabhat Kumar Sahu, investigated by Mahendra
Singh and Michael Paquier; the final form of the patch is my fault.
This replaces the failed fix attempt in a052f6cbb.
Backpatch as far as v11, as 246a6c8f7 was.
Discussion: https://postgr.es/m/CAKYtNAr9Zq=1-ww4etHo-VCC-k120YxZy5OS01VkaLPaDbv2tg@mail.gmail.com
2020-02-29 02:28:34 +01:00
|
|
|
return TEMP_NAMESPACE_IDLE;
|
Make autovacuum more aggressive to remove orphaned temp tables
Commit dafa084, added in 10, made the removal of temporary orphaned
tables more aggressive. This commit makes an extra step into the
aggressiveness by adding a flag in each backend's MyProc which tracks
down any temporary namespace currently in use. The flag is set when the
namespace gets created and can be reset if the temporary namespace has
been created in a transaction or sub-transaction which is aborted. The
flag value assignment is assumed to be atomic, so this can be done in a
lock-less fashion like other flags already present in PGPROC like
databaseId or backendId, still the fact that the temporary namespace and
table created are still locked until the transaction creating those
commits acts as a barrier for other backends.
This new flag gets used by autovacuum to discard more aggressively
orphaned tables by additionally checking for the database a backend is
connected to as well as its temporary namespace in-use, removing
orphaned temporary relations even if a backend reuses the same slot as
one which created temporary relations in a past session.
The base idea of this patch comes from Robert Haas, has been written in
its first version by Tsunakawa Takayuki, then heavily reviewed by me.
Author: Tsunakawa Takayuki
Reviewed-by: Michael Paquier, Kyotaro Horiguchi, Andres Freund
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F8A4DC6@G01JPEXMBYT05
Backpatch: 11-, as PGPROC gains a new flag and we don't want silent ABI
breakages on already released versions.
2018-08-13 11:49:04 +02:00
|
|
|
|
|
|
|
/* Does the backend own the temporary namespace? */
|
|
|
|
if (proc->tempNamespaceId != namespaceId)
|
Avoid failure if autovacuum tries to access a just-dropped temp namespace.
Such an access became possible when commit 246a6c8f7 added more
aggressive cleanup of orphaned temp relations by autovacuum.
Since autovacuum's snapshot might be slightly stale, it could
attempt to access an already-dropped temp namespace, resulting in
an assertion failure or null-pointer dereference. (In practice,
since we don't drop temp namespaces automatically but merely
recycle them, this situation could only arise if a superuser does
a manual drop of a temp namespace. Still, that should be allowed.)
The core of the bug, IMO, is that isTempNamespaceInUse and its callers
failed to think hard about whether to treat "temp namespace isn't there"
differently from "temp namespace isn't in use". In hopes of forestalling
future mistakes of the same ilk, replace that function with a new one
checkTempNamespaceStatus, which makes the same tests but returns a
three-way enum rather than just a bool. isTempNamespaceInUse is gone
entirely in HEAD; but just in case some external code is relying on it,
keep it in the back branches, as a bug-compatible wrapper around the
new function.
Per report originally from Prabhat Kumar Sahu, investigated by Mahendra
Singh and Michael Paquier; the final form of the patch is my fault.
This replaces the failed fix attempt in a052f6cbb.
Backpatch as far as v11, as 246a6c8f7 was.
Discussion: https://postgr.es/m/CAKYtNAr9Zq=1-ww4etHo-VCC-k120YxZy5OS01VkaLPaDbv2tg@mail.gmail.com
2020-02-29 02:28:34 +01:00
|
|
|
return TEMP_NAMESPACE_IDLE;
|
Make autovacuum more aggressive to remove orphaned temp tables
Commit dafa084, added in 10, made the removal of temporary orphaned
tables more aggressive. This commit makes an extra step into the
aggressiveness by adding a flag in each backend's MyProc which tracks
down any temporary namespace currently in use. The flag is set when the
namespace gets created and can be reset if the temporary namespace has
been created in a transaction or sub-transaction which is aborted. The
flag value assignment is assumed to be atomic, so this can be done in a
lock-less fashion like other flags already present in PGPROC like
databaseId or backendId, still the fact that the temporary namespace and
table created are still locked until the transaction creating those
commits acts as a barrier for other backends.
This new flag gets used by autovacuum to discard more aggressively
orphaned tables by additionally checking for the database a backend is
connected to as well as its temporary namespace in-use, removing
orphaned temporary relations even if a backend reuses the same slot as
one which created temporary relations in a past session.
The base idea of this patch comes from Robert Haas, has been written in
its first version by Tsunakawa Takayuki, then heavily reviewed by me.
Author: Tsunakawa Takayuki
Reviewed-by: Michael Paquier, Kyotaro Horiguchi, Andres Freund
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F8A4DC6@G01JPEXMBYT05
Backpatch: 11-, as PGPROC gains a new flag and we don't want silent ABI
breakages on already released versions.
2018-08-13 11:49:04 +02:00
|
|
|
|
Avoid failure if autovacuum tries to access a just-dropped temp namespace.
Such an access became possible when commit 246a6c8f7 added more
aggressive cleanup of orphaned temp relations by autovacuum.
Since autovacuum's snapshot might be slightly stale, it could
attempt to access an already-dropped temp namespace, resulting in
an assertion failure or null-pointer dereference. (In practice,
since we don't drop temp namespaces automatically but merely
recycle them, this situation could only arise if a superuser does
a manual drop of a temp namespace. Still, that should be allowed.)
The core of the bug, IMO, is that isTempNamespaceInUse and its callers
failed to think hard about whether to treat "temp namespace isn't there"
differently from "temp namespace isn't in use". In hopes of forestalling
future mistakes of the same ilk, replace that function with a new one
checkTempNamespaceStatus, which makes the same tests but returns a
three-way enum rather than just a bool. isTempNamespaceInUse is gone
entirely in HEAD; but just in case some external code is relying on it,
keep it in the back branches, as a bug-compatible wrapper around the
new function.
Per report originally from Prabhat Kumar Sahu, investigated by Mahendra
Singh and Michael Paquier; the final form of the patch is my fault.
This replaces the failed fix attempt in a052f6cbb.
Backpatch as far as v11, as 246a6c8f7 was.
Discussion: https://postgr.es/m/CAKYtNAr9Zq=1-ww4etHo-VCC-k120YxZy5OS01VkaLPaDbv2tg@mail.gmail.com
2020-02-29 02:28:34 +01:00
|
|
|
/* Yup, so namespace is busy */
|
|
|
|
return TEMP_NAMESPACE_IN_USE;
|
Make autovacuum more aggressive to remove orphaned temp tables
Commit dafa084, added in 10, made the removal of temporary orphaned
tables more aggressive. This commit makes an extra step into the
aggressiveness by adding a flag in each backend's MyProc which tracks
down any temporary namespace currently in use. The flag is set when the
namespace gets created and can be reset if the temporary namespace has
been created in a transaction or sub-transaction which is aborted. The
flag value assignment is assumed to be atomic, so this can be done in a
lock-less fashion like other flags already present in PGPROC like
databaseId or backendId, still the fact that the temporary namespace and
table created are still locked until the transaction creating those
commits acts as a barrier for other backends.
This new flag gets used by autovacuum to discard more aggressively
orphaned tables by additionally checking for the database a backend is
connected to as well as its temporary namespace in-use, removing
orphaned temporary relations even if a backend reuses the same slot as
one which created temporary relations in a past session.
The base idea of this patch comes from Robert Haas, has been written in
its first version by Tsunakawa Takayuki, then heavily reviewed by me.
Author: Tsunakawa Takayuki
Reviewed-by: Michael Paquier, Kyotaro Horiguchi, Andres Freund
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F8A4DC6@G01JPEXMBYT05
Backpatch: 11-, as PGPROC gains a new flag and we don't want silent ABI
breakages on already released versions.
2018-08-13 11:49:04 +02:00
|
|
|
}
|
|
|
|
|
2008-07-01 04:09:34 +02:00
|
|
|
/*
|
|
|
|
* GetTempNamespaceBackendId - if the given namespace is a temporary-table
|
|
|
|
* namespace (either my own, or another backend's), return the BackendId
|
|
|
|
* that owns it. Temporary-toast-table namespaces are included, too.
|
2010-08-13 22:10:54 +02:00
|
|
|
* If it isn't a temp namespace, return InvalidBackendId.
|
2008-07-01 04:09:34 +02:00
|
|
|
*/
|
|
|
|
int
|
|
|
|
GetTempNamespaceBackendId(Oid namespaceId)
|
|
|
|
{
|
|
|
|
int result;
|
|
|
|
char *nspname;
|
|
|
|
|
|
|
|
/* See if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
|
|
|
|
nspname = get_namespace_name(namespaceId);
|
|
|
|
if (!nspname)
|
2010-08-13 22:10:54 +02:00
|
|
|
return InvalidBackendId; /* no such namespace? */
|
2008-07-01 04:09:34 +02:00
|
|
|
if (strncmp(nspname, "pg_temp_", 8) == 0)
|
|
|
|
result = atoi(nspname + 8);
|
|
|
|
else if (strncmp(nspname, "pg_toast_temp_", 14) == 0)
|
|
|
|
result = atoi(nspname + 14);
|
|
|
|
else
|
2010-08-13 22:10:54 +02:00
|
|
|
result = InvalidBackendId;
|
2008-07-01 04:09:34 +02:00
|
|
|
pfree(nspname);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2007-07-26 00:16:18 +02:00
|
|
|
/*
|
|
|
|
* GetTempToastNamespace - get the OID of my temporary-toast-table namespace,
|
|
|
|
* which must already be assigned. (This is only used when creating a toast
|
|
|
|
* table for a temp table, so we must have already done InitTempTableNamespace)
|
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
GetTempToastNamespace(void)
|
|
|
|
{
|
|
|
|
Assert(OidIsValid(myTempToastNamespace));
|
|
|
|
return myTempToastNamespace;
|
|
|
|
}
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
|
Improve the situation for parallel query versus temp relations.
Transmit the leader's temp-namespace state to workers. This is important
because without it, the workers do not really have the same search path
as the leader. For example, there is no good reason (and no extant code
either) to prevent a worker from executing a temp function that the
leader created previously; but as things stood it would fail to find the
temp function, and then either fail or execute the wrong function entirely.
We still prohibit a worker from creating a temp namespace on its own.
In effect, a worker can only see the session's temp namespace if the leader
had created it before starting the worker, which seems like the right
semantics.
Also, transmit the leader's BackendId to workers, and arrange for workers
to use that when determining the physical file path of a temp relation
belonging to their session. While the original intent was to prevent such
accesses entirely, there were a number of holes in that, notably in places
like dbsize.c which assume they can safely access temp rels of other
sessions anyway. We might as well get this right, as a small down payment
on someday allowing workers to access the leader's temp tables. (With
this change, directly using "MyBackendId" as a relation or buffer backend
ID is deprecated; you should use BackendIdForTempRelations() instead.
I left a couple of such uses alone though, as they're not going to be
reachable in parallel workers until we do something about localbuf.c.)
Move the thou-shalt-not-access-thy-leader's-temp-tables prohibition down
into localbuf.c, which is where it actually matters, instead of having it
in relation_open(). This amounts to recognizing that access to temp
tables' catalog entries is perfectly safe in a worker, it's only the data
in local buffers that is problematic.
Having done all that, we can get rid of the test in has_parallel_hazard()
that says that use of a temp table's rowtype is unsafe in parallel workers.
That test was unduly expensive, and if we really did need such a
prohibition, that was not even close to being a bulletproof guard for it.
(For example, any user-defined function executed in a parallel worker
might have attempted such access.)
2016-06-10 02:16:11 +02:00
|
|
|
/*
|
|
|
|
* GetTempNamespaceState - fetch status of session's temporary namespace
|
|
|
|
*
|
|
|
|
* This is used for conveying state to a parallel worker, and is not meant
|
|
|
|
* for general-purpose access.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
GetTempNamespaceState(Oid *tempNamespaceId, Oid *tempToastNamespaceId)
|
|
|
|
{
|
|
|
|
/* Return namespace OIDs, or 0 if session has not created temp namespace */
|
|
|
|
*tempNamespaceId = myTempNamespace;
|
|
|
|
*tempToastNamespaceId = myTempToastNamespace;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SetTempNamespaceState - set status of session's temporary namespace
|
|
|
|
*
|
|
|
|
* This is used for conveying state to a parallel worker, and is not meant for
|
|
|
|
* general-purpose access. By transferring these namespace OIDs to workers,
|
|
|
|
* we ensure they will have the same notion of the search path as their leader
|
|
|
|
* does.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SetTempNamespaceState(Oid tempNamespaceId, Oid tempToastNamespaceId)
|
|
|
|
{
|
|
|
|
/* Worker should not have created its own namespaces ... */
|
|
|
|
Assert(myTempNamespace == InvalidOid);
|
|
|
|
Assert(myTempToastNamespace == InvalidOid);
|
|
|
|
Assert(myTempNamespaceSubID == InvalidSubTransactionId);
|
|
|
|
|
|
|
|
/* Assign same namespace OIDs that leader has */
|
|
|
|
myTempNamespace = tempNamespaceId;
|
|
|
|
myTempToastNamespace = tempToastNamespaceId;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* It's fine to leave myTempNamespaceSubID == InvalidSubTransactionId.
|
|
|
|
* Even if the namespace is new so far as the leader is concerned, it's
|
|
|
|
* not new to the worker, and we certainly wouldn't want the worker trying
|
|
|
|
* to destroy it.
|
|
|
|
*/
|
|
|
|
|
|
|
|
baseSearchPathValid = false; /* may need to rebuild list */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-17 22:53:33 +02:00
|
|
|
/*
|
2007-03-23 20:53:52 +01:00
|
|
|
* GetOverrideSearchPath - fetch current search path definition in form
|
|
|
|
* used by PushOverrideSearchPath.
|
2002-05-17 22:53:33 +02:00
|
|
|
*
|
2007-03-23 20:53:52 +01:00
|
|
|
* The result structure is allocated in the specified memory context
|
|
|
|
* (which might or might not be equal to CurrentMemoryContext); but any
|
|
|
|
* junk created by revalidation calculations will be in CurrentMemoryContext.
|
|
|
|
*/
|
|
|
|
OverrideSearchPath *
|
|
|
|
GetOverrideSearchPath(MemoryContext context)
|
|
|
|
{
|
|
|
|
OverrideSearchPath *result;
|
|
|
|
List *schemas;
|
|
|
|
MemoryContext oldcxt;
|
|
|
|
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
oldcxt = MemoryContextSwitchTo(context);
|
|
|
|
|
|
|
|
result = (OverrideSearchPath *) palloc0(sizeof(OverrideSearchPath));
|
|
|
|
schemas = list_copy(activeSearchPath);
|
|
|
|
while (schemas && linitial_oid(schemas) != activeCreationNamespace)
|
|
|
|
{
|
|
|
|
if (linitial_oid(schemas) == myTempNamespace)
|
|
|
|
result->addTemp = true;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Assert(linitial_oid(schemas) == PG_CATALOG_NAMESPACE);
|
|
|
|
result->addCatalog = true;
|
|
|
|
}
|
|
|
|
schemas = list_delete_first(schemas);
|
|
|
|
}
|
|
|
|
result->schemas = schemas;
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
result->generation = activePathGeneration;
|
2007-03-23 20:53:52 +01:00
|
|
|
|
|
|
|
MemoryContextSwitchTo(oldcxt);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-09-16 06:42:53 +02:00
|
|
|
/*
|
|
|
|
* CopyOverrideSearchPath - copy the specified OverrideSearchPath.
|
|
|
|
*
|
|
|
|
* The result structure is allocated in CurrentMemoryContext.
|
|
|
|
*/
|
|
|
|
OverrideSearchPath *
|
|
|
|
CopyOverrideSearchPath(OverrideSearchPath *path)
|
|
|
|
{
|
|
|
|
OverrideSearchPath *result;
|
|
|
|
|
|
|
|
result = (OverrideSearchPath *) palloc(sizeof(OverrideSearchPath));
|
|
|
|
result->schemas = list_copy(path->schemas);
|
|
|
|
result->addCatalog = path->addCatalog;
|
|
|
|
result->addTemp = path->addTemp;
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
result->generation = path->generation;
|
2011-09-16 06:42:53 +02:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
Change plan caching to honor, not resist, changes in search_path.
In the initial implementation of plan caching, we saved the active
search_path when a plan was first cached, then reinstalled that path
anytime we needed to reparse or replan. The idea of that was to try to
reselect the same referenced objects, in somewhat the same way that views
continue to refer to the same objects in the face of schema or name
changes. Of course, that analogy doesn't bear close inspection, since
holding the search_path fixed doesn't cope with object drops or renames.
Moreover sticking with the old path seems to create more surprises than
it avoids. So instead of doing that, consider that the cached plan depends
on search_path, and force reparse/replan if the active search_path is
different than it was when we last saved the plan.
This gets us fairly close to having "transparency" of plan caching, in the
sense that the cached statement acts the same as if you'd just resubmitted
the original query text for another execution. There are still some corner
cases where this fails though: a new object added in the search path
schema(s) might capture a reference in the query text, but we'd not realize
that and force a reparse. We might try to fix that in the future, but for
the moment it looks too expensive and complicated.
2013-01-25 20:14:41 +01:00
|
|
|
/*
|
|
|
|
* OverrideSearchPathMatchesCurrent - does path match current setting?
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
*
|
|
|
|
* This is tested over and over in some common code paths, and in the typical
|
|
|
|
* scenario where the active search path seldom changes, it'll always succeed.
|
|
|
|
* We make that case fast by keeping a generation counter that is advanced
|
|
|
|
* whenever the active search path changes.
|
Change plan caching to honor, not resist, changes in search_path.
In the initial implementation of plan caching, we saved the active
search_path when a plan was first cached, then reinstalled that path
anytime we needed to reparse or replan. The idea of that was to try to
reselect the same referenced objects, in somewhat the same way that views
continue to refer to the same objects in the face of schema or name
changes. Of course, that analogy doesn't bear close inspection, since
holding the search_path fixed doesn't cope with object drops or renames.
Moreover sticking with the old path seems to create more surprises than
it avoids. So instead of doing that, consider that the cached plan depends
on search_path, and force reparse/replan if the active search_path is
different than it was when we last saved the plan.
This gets us fairly close to having "transparency" of plan caching, in the
sense that the cached statement acts the same as if you'd just resubmitted
the original query text for another execution. There are still some corner
cases where this fails though: a new object added in the search path
schema(s) might capture a reference in the query text, but we'd not realize
that and force a reparse. We might try to fix that in the future, but for
the moment it looks too expensive and complicated.
2013-01-25 20:14:41 +01:00
|
|
|
*/
|
|
|
|
bool
|
|
|
|
OverrideSearchPathMatchesCurrent(OverrideSearchPath *path)
|
|
|
|
{
|
2014-11-28 18:37:27 +01:00
|
|
|
ListCell *lc,
|
|
|
|
*lcp;
|
Change plan caching to honor, not resist, changes in search_path.
In the initial implementation of plan caching, we saved the active
search_path when a plan was first cached, then reinstalled that path
anytime we needed to reparse or replan. The idea of that was to try to
reselect the same referenced objects, in somewhat the same way that views
continue to refer to the same objects in the face of schema or name
changes. Of course, that analogy doesn't bear close inspection, since
holding the search_path fixed doesn't cope with object drops or renames.
Moreover sticking with the old path seems to create more surprises than
it avoids. So instead of doing that, consider that the cached plan depends
on search_path, and force reparse/replan if the active search_path is
different than it was when we last saved the plan.
This gets us fairly close to having "transparency" of plan caching, in the
sense that the cached statement acts the same as if you'd just resubmitted
the original query text for another execution. There are still some corner
cases where this fails though: a new object added in the search path
schema(s) might capture a reference in the query text, but we'd not realize
that and force a reparse. We might try to fix that in the future, but for
the moment it looks too expensive and complicated.
2013-01-25 20:14:41 +01:00
|
|
|
|
2014-11-28 18:37:27 +01:00
|
|
|
recomputeNamespacePath();
|
|
|
|
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
/* Quick out if already known equal to active path. */
|
|
|
|
if (path->generation == activePathGeneration)
|
|
|
|
return true;
|
|
|
|
|
2014-11-28 18:37:27 +01:00
|
|
|
/* We scan down the activeSearchPath to see if it matches the input. */
|
|
|
|
lc = list_head(activeSearchPath);
|
|
|
|
|
|
|
|
/* If path->addTemp, first item should be my temp namespace. */
|
|
|
|
if (path->addTemp)
|
|
|
|
{
|
|
|
|
if (lc && lfirst_oid(lc) == myTempNamespace)
|
Represent Lists as expansible arrays, not chains of cons-cells.
Originally, Postgres Lists were a more or less exact reimplementation of
Lisp lists, which consist of chains of separately-allocated cons cells,
each having a value and a next-cell link. We'd hacked that once before
(commit d0b4399d8) to add a separate List header, but the data was still
in cons cells. That makes some operations -- notably list_nth() -- O(N),
and it's bulky because of the next-cell pointers and per-cell palloc
overhead, and it's very cache-unfriendly if the cons cells end up
scattered around rather than being adjacent.
In this rewrite, we still have List headers, but the data is in a
resizable array of values, with no next-cell links. Now we need at
most two palloc's per List, and often only one, since we can allocate
some values in the same palloc call as the List header. (Of course,
extending an existing List may require repalloc's to enlarge the array.
But this involves just O(log N) allocations not O(N).)
Of course this is not without downsides. The key difficulty is that
addition or deletion of a list entry may now cause other entries to
move, which it did not before.
For example, that breaks foreach() and sister macros, which historically
used a pointer to the current cons-cell as loop state. We can repair
those macros transparently by making their actual loop state be an
integer list index; the exposed "ListCell *" pointer is no longer state
carried across loop iterations, but is just a derived value. (In
practice, modern compilers can optimize things back to having just one
loop state value, at least for simple cases with inline loop bodies.)
In principle, this is a semantics change for cases where the loop body
inserts or deletes list entries ahead of the current loop index; but
I found no such cases in the Postgres code.
The change is not at all transparent for code that doesn't use foreach()
but chases lists "by hand" using lnext(). The largest share of such
code in the backend is in loops that were maintaining "prev" and "next"
variables in addition to the current-cell pointer, in order to delete
list cells efficiently using list_delete_cell(). However, we no longer
need a previous-cell pointer to delete a list cell efficiently. Keeping
a next-cell pointer doesn't work, as explained above, but we can improve
matters by changing such code to use a regular foreach() loop and then
using the new macro foreach_delete_current() to delete the current cell.
(This macro knows how to update the associated foreach loop's state so
that no cells will be missed in the traversal.)
There remains a nontrivial risk of code assuming that a ListCell *
pointer will remain good over an operation that could now move the list
contents. To help catch such errors, list.c can be compiled with a new
define symbol DEBUG_LIST_MEMORY_USAGE that forcibly moves list contents
whenever that could possibly happen. This makes list operations
significantly more expensive so it's not normally turned on (though it
is on by default if USE_VALGRIND is on).
There are two notable API differences from the previous code:
* lnext() now requires the List's header pointer in addition to the
current cell's address.
* list_delete_cell() no longer requires a previous-cell argument.
These changes are somewhat unfortunate, but on the other hand code using
either function needs inspection to see if it is assuming anything
it shouldn't, so it's not all bad.
Programmers should be aware of these significant performance changes:
* list_nth() and related functions are now O(1); so there's no
major access-speed difference between a list and an array.
* Inserting or deleting a list element now takes time proportional to
the distance to the end of the list, due to moving the array elements.
(However, it typically *doesn't* require palloc or pfree, so except in
long lists it's probably still faster than before.) Notably, lcons()
used to be about the same cost as lappend(), but that's no longer true
if the list is long. Code that uses lcons() and list_delete_first()
to maintain a stack might usefully be rewritten to push and pop at the
end of the list rather than the beginning.
* There are now list_insert_nth...() and list_delete_nth...() functions
that add or remove a list cell identified by index. These have the
data-movement penalty explained above, but there's no search penalty.
* list_concat() and variants now copy the second list's data into
storage belonging to the first list, so there is no longer any
sharing of cells between the input lists. The second argument is
now declared "const List *" to reflect that it isn't changed.
This patch just does the minimum needed to get the new implementation
in place and fix bugs exposed by the regression tests. As suggested
by the foregoing, there's a fair amount of followup work remaining to
do.
Also, the ENABLE_LIST_COMPAT macros are finally removed in this
commit. Code using those should have been gone a dozen years ago.
Patch by me; thanks to David Rowley, Jesper Pedersen, and others
for review.
Discussion: https://postgr.es/m/11587.1550975080@sss.pgh.pa.us
2019-07-15 19:41:58 +02:00
|
|
|
lc = lnext(activeSearchPath, lc);
|
2014-11-28 18:37:27 +01:00
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
/* If path->addCatalog, next item should be pg_catalog. */
|
|
|
|
if (path->addCatalog)
|
|
|
|
{
|
|
|
|
if (lc && lfirst_oid(lc) == PG_CATALOG_NAMESPACE)
|
Represent Lists as expansible arrays, not chains of cons-cells.
Originally, Postgres Lists were a more or less exact reimplementation of
Lisp lists, which consist of chains of separately-allocated cons cells,
each having a value and a next-cell link. We'd hacked that once before
(commit d0b4399d8) to add a separate List header, but the data was still
in cons cells. That makes some operations -- notably list_nth() -- O(N),
and it's bulky because of the next-cell pointers and per-cell palloc
overhead, and it's very cache-unfriendly if the cons cells end up
scattered around rather than being adjacent.
In this rewrite, we still have List headers, but the data is in a
resizable array of values, with no next-cell links. Now we need at
most two palloc's per List, and often only one, since we can allocate
some values in the same palloc call as the List header. (Of course,
extending an existing List may require repalloc's to enlarge the array.
But this involves just O(log N) allocations not O(N).)
Of course this is not without downsides. The key difficulty is that
addition or deletion of a list entry may now cause other entries to
move, which it did not before.
For example, that breaks foreach() and sister macros, which historically
used a pointer to the current cons-cell as loop state. We can repair
those macros transparently by making their actual loop state be an
integer list index; the exposed "ListCell *" pointer is no longer state
carried across loop iterations, but is just a derived value. (In
practice, modern compilers can optimize things back to having just one
loop state value, at least for simple cases with inline loop bodies.)
In principle, this is a semantics change for cases where the loop body
inserts or deletes list entries ahead of the current loop index; but
I found no such cases in the Postgres code.
The change is not at all transparent for code that doesn't use foreach()
but chases lists "by hand" using lnext(). The largest share of such
code in the backend is in loops that were maintaining "prev" and "next"
variables in addition to the current-cell pointer, in order to delete
list cells efficiently using list_delete_cell(). However, we no longer
need a previous-cell pointer to delete a list cell efficiently. Keeping
a next-cell pointer doesn't work, as explained above, but we can improve
matters by changing such code to use a regular foreach() loop and then
using the new macro foreach_delete_current() to delete the current cell.
(This macro knows how to update the associated foreach loop's state so
that no cells will be missed in the traversal.)
There remains a nontrivial risk of code assuming that a ListCell *
pointer will remain good over an operation that could now move the list
contents. To help catch such errors, list.c can be compiled with a new
define symbol DEBUG_LIST_MEMORY_USAGE that forcibly moves list contents
whenever that could possibly happen. This makes list operations
significantly more expensive so it's not normally turned on (though it
is on by default if USE_VALGRIND is on).
There are two notable API differences from the previous code:
* lnext() now requires the List's header pointer in addition to the
current cell's address.
* list_delete_cell() no longer requires a previous-cell argument.
These changes are somewhat unfortunate, but on the other hand code using
either function needs inspection to see if it is assuming anything
it shouldn't, so it's not all bad.
Programmers should be aware of these significant performance changes:
* list_nth() and related functions are now O(1); so there's no
major access-speed difference between a list and an array.
* Inserting or deleting a list element now takes time proportional to
the distance to the end of the list, due to moving the array elements.
(However, it typically *doesn't* require palloc or pfree, so except in
long lists it's probably still faster than before.) Notably, lcons()
used to be about the same cost as lappend(), but that's no longer true
if the list is long. Code that uses lcons() and list_delete_first()
to maintain a stack might usefully be rewritten to push and pop at the
end of the list rather than the beginning.
* There are now list_insert_nth...() and list_delete_nth...() functions
that add or remove a list cell identified by index. These have the
data-movement penalty explained above, but there's no search penalty.
* list_concat() and variants now copy the second list's data into
storage belonging to the first list, so there is no longer any
sharing of cells between the input lists. The second argument is
now declared "const List *" to reflect that it isn't changed.
This patch just does the minimum needed to get the new implementation
in place and fix bugs exposed by the regression tests. As suggested
by the foregoing, there's a fair amount of followup work remaining to
do.
Also, the ENABLE_LIST_COMPAT macros are finally removed in this
commit. Code using those should have been gone a dozen years ago.
Patch by me; thanks to David Rowley, Jesper Pedersen, and others
for review.
Discussion: https://postgr.es/m/11587.1550975080@sss.pgh.pa.us
2019-07-15 19:41:58 +02:00
|
|
|
lc = lnext(activeSearchPath, lc);
|
2014-11-28 18:37:27 +01:00
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
/* We should now be looking at the activeCreationNamespace. */
|
|
|
|
if (activeCreationNamespace != (lc ? lfirst_oid(lc) : InvalidOid))
|
|
|
|
return false;
|
|
|
|
/* The remainder of activeSearchPath should match path->schemas. */
|
|
|
|
foreach(lcp, path->schemas)
|
|
|
|
{
|
|
|
|
if (lc && lfirst_oid(lc) == lfirst_oid(lcp))
|
Represent Lists as expansible arrays, not chains of cons-cells.
Originally, Postgres Lists were a more or less exact reimplementation of
Lisp lists, which consist of chains of separately-allocated cons cells,
each having a value and a next-cell link. We'd hacked that once before
(commit d0b4399d8) to add a separate List header, but the data was still
in cons cells. That makes some operations -- notably list_nth() -- O(N),
and it's bulky because of the next-cell pointers and per-cell palloc
overhead, and it's very cache-unfriendly if the cons cells end up
scattered around rather than being adjacent.
In this rewrite, we still have List headers, but the data is in a
resizable array of values, with no next-cell links. Now we need at
most two palloc's per List, and often only one, since we can allocate
some values in the same palloc call as the List header. (Of course,
extending an existing List may require repalloc's to enlarge the array.
But this involves just O(log N) allocations not O(N).)
Of course this is not without downsides. The key difficulty is that
addition or deletion of a list entry may now cause other entries to
move, which it did not before.
For example, that breaks foreach() and sister macros, which historically
used a pointer to the current cons-cell as loop state. We can repair
those macros transparently by making their actual loop state be an
integer list index; the exposed "ListCell *" pointer is no longer state
carried across loop iterations, but is just a derived value. (In
practice, modern compilers can optimize things back to having just one
loop state value, at least for simple cases with inline loop bodies.)
In principle, this is a semantics change for cases where the loop body
inserts or deletes list entries ahead of the current loop index; but
I found no such cases in the Postgres code.
The change is not at all transparent for code that doesn't use foreach()
but chases lists "by hand" using lnext(). The largest share of such
code in the backend is in loops that were maintaining "prev" and "next"
variables in addition to the current-cell pointer, in order to delete
list cells efficiently using list_delete_cell(). However, we no longer
need a previous-cell pointer to delete a list cell efficiently. Keeping
a next-cell pointer doesn't work, as explained above, but we can improve
matters by changing such code to use a regular foreach() loop and then
using the new macro foreach_delete_current() to delete the current cell.
(This macro knows how to update the associated foreach loop's state so
that no cells will be missed in the traversal.)
There remains a nontrivial risk of code assuming that a ListCell *
pointer will remain good over an operation that could now move the list
contents. To help catch such errors, list.c can be compiled with a new
define symbol DEBUG_LIST_MEMORY_USAGE that forcibly moves list contents
whenever that could possibly happen. This makes list operations
significantly more expensive so it's not normally turned on (though it
is on by default if USE_VALGRIND is on).
There are two notable API differences from the previous code:
* lnext() now requires the List's header pointer in addition to the
current cell's address.
* list_delete_cell() no longer requires a previous-cell argument.
These changes are somewhat unfortunate, but on the other hand code using
either function needs inspection to see if it is assuming anything
it shouldn't, so it's not all bad.
Programmers should be aware of these significant performance changes:
* list_nth() and related functions are now O(1); so there's no
major access-speed difference between a list and an array.
* Inserting or deleting a list element now takes time proportional to
the distance to the end of the list, due to moving the array elements.
(However, it typically *doesn't* require palloc or pfree, so except in
long lists it's probably still faster than before.) Notably, lcons()
used to be about the same cost as lappend(), but that's no longer true
if the list is long. Code that uses lcons() and list_delete_first()
to maintain a stack might usefully be rewritten to push and pop at the
end of the list rather than the beginning.
* There are now list_insert_nth...() and list_delete_nth...() functions
that add or remove a list cell identified by index. These have the
data-movement penalty explained above, but there's no search penalty.
* list_concat() and variants now copy the second list's data into
storage belonging to the first list, so there is no longer any
sharing of cells between the input lists. The second argument is
now declared "const List *" to reflect that it isn't changed.
This patch just does the minimum needed to get the new implementation
in place and fix bugs exposed by the regression tests. As suggested
by the foregoing, there's a fair amount of followup work remaining to
do.
Also, the ENABLE_LIST_COMPAT macros are finally removed in this
commit. Code using those should have been gone a dozen years ago.
Patch by me; thanks to David Rowley, Jesper Pedersen, and others
for review.
Discussion: https://postgr.es/m/11587.1550975080@sss.pgh.pa.us
2019-07-15 19:41:58 +02:00
|
|
|
lc = lnext(activeSearchPath, lc);
|
2014-11-28 18:37:27 +01:00
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (lc)
|
|
|
|
return false;
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Update path->generation so that future tests will return quickly, so
|
|
|
|
* long as the active search path doesn't change.
|
|
|
|
*/
|
|
|
|
path->generation = activePathGeneration;
|
|
|
|
|
2014-11-28 18:37:27 +01:00
|
|
|
return true;
|
Change plan caching to honor, not resist, changes in search_path.
In the initial implementation of plan caching, we saved the active
search_path when a plan was first cached, then reinstalled that path
anytime we needed to reparse or replan. The idea of that was to try to
reselect the same referenced objects, in somewhat the same way that views
continue to refer to the same objects in the face of schema or name
changes. Of course, that analogy doesn't bear close inspection, since
holding the search_path fixed doesn't cope with object drops or renames.
Moreover sticking with the old path seems to create more surprises than
it avoids. So instead of doing that, consider that the cached plan depends
on search_path, and force reparse/replan if the active search_path is
different than it was when we last saved the plan.
This gets us fairly close to having "transparency" of plan caching, in the
sense that the cached statement acts the same as if you'd just resubmitted
the original query text for another execution. There are still some corner
cases where this fails though: a new object added in the search path
schema(s) might capture a reference in the query text, but we'd not realize
that and force a reparse. We might try to fix that in the future, but for
the moment it looks too expensive and complicated.
2013-01-25 20:14:41 +01:00
|
|
|
}
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
/*
|
|
|
|
* PushOverrideSearchPath - temporarily override the search path
|
2002-05-17 22:53:33 +02:00
|
|
|
*
|
2023-05-08 15:14:07 +02:00
|
|
|
* Do not use this function; almost any usage introduces a security
|
|
|
|
* vulnerability. It exists for the benefit of legacy code running in
|
|
|
|
* non-security-sensitive environments.
|
|
|
|
*
|
2007-03-23 20:53:52 +01:00
|
|
|
* We allow nested overrides, hence the push/pop terminology. The GUC
|
|
|
|
* search_path variable is ignored while an override is active.
|
2010-08-13 18:27:11 +02:00
|
|
|
*
|
|
|
|
* It's possible that newpath->useTemp is set but there is no longer any
|
|
|
|
* active temp namespace, if the path was saved during a transaction that
|
|
|
|
* created a temp namespace and was later rolled back. In that case we just
|
|
|
|
* ignore useTemp. A plausible alternative would be to create a new temp
|
|
|
|
* namespace, but for existing callers that's not necessary because an empty
|
|
|
|
* temp namespace wouldn't affect their results anyway.
|
|
|
|
*
|
|
|
|
* It's also worth noting that other schemas listed in newpath might not
|
|
|
|
* exist anymore either. We don't worry about this because OIDs that match
|
|
|
|
* no existing namespace will simply not produce any hits during searches.
|
2002-05-17 22:53:33 +02:00
|
|
|
*/
|
|
|
|
void
|
2007-03-23 20:53:52 +01:00
|
|
|
PushOverrideSearchPath(OverrideSearchPath *newpath)
|
2002-05-17 22:53:33 +02:00
|
|
|
{
|
2007-03-23 20:53:52 +01:00
|
|
|
OverrideStackEntry *entry;
|
|
|
|
List *oidlist;
|
|
|
|
Oid firstNS;
|
|
|
|
MemoryContext oldcxt;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy the list for safekeeping, and insert implicitly-searched
|
|
|
|
* namespaces as needed. This code should track recomputeNamespacePath.
|
|
|
|
*/
|
|
|
|
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
|
|
|
|
|
|
|
|
oidlist = list_copy(newpath->schemas);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remember the first member of the explicit list.
|
|
|
|
*/
|
|
|
|
if (oidlist == NIL)
|
|
|
|
firstNS = InvalidOid;
|
|
|
|
else
|
|
|
|
firstNS = linitial_oid(oidlist);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add any implicitly-searched namespaces to the list. Note these go on
|
|
|
|
* the front, not the back; also notice that we do not check USAGE
|
|
|
|
* permissions for these.
|
|
|
|
*/
|
|
|
|
if (newpath->addCatalog)
|
|
|
|
oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
|
|
|
|
|
2010-08-13 18:27:11 +02:00
|
|
|
if (newpath->addTemp && OidIsValid(myTempNamespace))
|
2007-03-23 20:53:52 +01:00
|
|
|
oidlist = lcons_oid(myTempNamespace, oidlist);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Build the new stack entry, then insert it at the head of the list.
|
|
|
|
*/
|
|
|
|
entry = (OverrideStackEntry *) palloc(sizeof(OverrideStackEntry));
|
|
|
|
entry->searchPath = oidlist;
|
|
|
|
entry->creationNamespace = firstNS;
|
|
|
|
entry->nestLevel = GetCurrentTransactionNestLevel();
|
|
|
|
|
|
|
|
overrideStack = lcons(entry, overrideStack);
|
|
|
|
|
|
|
|
/* And make it active. */
|
|
|
|
activeSearchPath = entry->searchPath;
|
|
|
|
activeCreationNamespace = entry->creationNamespace;
|
2007-04-20 04:37:38 +02:00
|
|
|
activeTempCreationPending = false; /* XXX is this OK? */
|
2007-03-23 20:53:52 +01:00
|
|
|
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
/*
|
|
|
|
* We always increment activePathGeneration when pushing/popping an
|
|
|
|
* override path. In current usage, these actions always change the
|
|
|
|
* effective path state, so there's no value in checking to see if it
|
|
|
|
* didn't change.
|
|
|
|
*/
|
|
|
|
activePathGeneration++;
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
MemoryContextSwitchTo(oldcxt);
|
2002-05-17 22:53:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2007-03-23 20:53:52 +01:00
|
|
|
* PopOverrideSearchPath - undo a previous PushOverrideSearchPath
|
|
|
|
*
|
|
|
|
* Any push during a (sub)transaction will be popped automatically at abort.
|
|
|
|
* But it's caller error if a push isn't popped in normal control flow.
|
2002-05-17 22:53:33 +02:00
|
|
|
*/
|
|
|
|
void
|
2007-03-23 20:53:52 +01:00
|
|
|
PopOverrideSearchPath(void)
|
2002-05-17 22:53:33 +02:00
|
|
|
{
|
2007-03-23 20:53:52 +01:00
|
|
|
OverrideStackEntry *entry;
|
|
|
|
|
|
|
|
/* Sanity checks. */
|
|
|
|
if (overrideStack == NIL)
|
|
|
|
elog(ERROR, "bogus PopOverrideSearchPath call");
|
|
|
|
entry = (OverrideStackEntry *) linitial(overrideStack);
|
|
|
|
if (entry->nestLevel != GetCurrentTransactionNestLevel())
|
|
|
|
elog(ERROR, "bogus PopOverrideSearchPath call");
|
|
|
|
|
|
|
|
/* Pop the stack and free storage. */
|
|
|
|
overrideStack = list_delete_first(overrideStack);
|
|
|
|
list_free(entry->searchPath);
|
|
|
|
pfree(entry);
|
|
|
|
|
|
|
|
/* Activate the next level down. */
|
|
|
|
if (overrideStack)
|
|
|
|
{
|
|
|
|
entry = (OverrideStackEntry *) linitial(overrideStack);
|
|
|
|
activeSearchPath = entry->searchPath;
|
|
|
|
activeCreationNamespace = entry->creationNamespace;
|
2007-04-20 04:37:38 +02:00
|
|
|
activeTempCreationPending = false; /* XXX is this OK? */
|
2007-03-23 20:53:52 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If not baseSearchPathValid, this is useless but harmless */
|
|
|
|
activeSearchPath = baseSearchPath;
|
|
|
|
activeCreationNamespace = baseCreationNamespace;
|
2007-04-20 04:37:38 +02:00
|
|
|
activeTempCreationPending = baseTempCreationPending;
|
2007-03-23 20:53:52 +01:00
|
|
|
}
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
|
|
|
|
/* As above, the generation always increments. */
|
|
|
|
activePathGeneration++;
|
2002-05-17 22:53:33 +02:00
|
|
|
}
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
|
2011-02-08 22:04:18 +01:00
|
|
|
/*
|
|
|
|
* get_collation_oid - find a collation by possibly qualified name
|
Further hacking on ICU collation creation and usage.
pg_import_system_collations() refused to create any ICU collations if
the current database's encoding didn't support ICU. This is wrongheaded:
initdb must initialize pg_collation in an encoding-independent way
since it might be used in other databases with different encodings.
The reason for the restriction seems to be that get_icu_locale_comment()
used icu_from_uchar() to convert the UChar-format display name, and that
unsurprisingly doesn't know what to do in unsupported encodings.
But by the same token that the initial catalog contents must be
encoding-independent, we can't allow non-ASCII characters in the comment
strings. So we don't really need icu_from_uchar() here: just check for
Unicode codes outside the ASCII range, and if there are none, the format
conversion is trivial. If there are some, we can simply not install the
comment. (In my testing, this affects only Norwegian Bokmål, which has
given us trouble before.)
For paranoia's sake, also check for non-ASCII characters in ICU locale
names, and skip such locales, as we do for libc locales. I don't
currently have a reason to believe that this will ever reject anything,
but then again the libc maintainers should have known better too.
With just the import changes, ICU collations can be found in pg_collation
in databases with unsupported encodings. This resulted in more or less
clean failures at runtime, but that's not how things act for unsupported
encodings with libc collations. Make it work the same as our traditional
behavior for libc collations by having collation lookup take into account
whether is_encoding_supported_by_icu().
Adjust documentation to match. Also, expand Table 23.1 to show which
encodings are supported by ICU.
catversion bump because of likely change in pg_collation/pg_description
initial contents in ICU-enabled builds.
Discussion: https://postgr.es/m/20c74bc3-d6ca-243d-1bbc-12f17fa4fe9a@gmail.com
2017-06-24 19:54:15 +02:00
|
|
|
*
|
|
|
|
* Note that this will only find collations that work with the current
|
|
|
|
* database's encoding.
|
2011-02-08 22:04:18 +01:00
|
|
|
*/
|
|
|
|
Oid
|
2022-09-20 04:18:36 +02:00
|
|
|
get_collation_oid(List *collname, bool missing_ok)
|
2011-02-08 22:04:18 +01:00
|
|
|
{
|
|
|
|
char *schemaname;
|
|
|
|
char *collation_name;
|
2011-03-11 19:20:11 +01:00
|
|
|
int32 dbencoding = GetDatabaseEncoding();
|
2011-02-08 22:04:18 +01:00
|
|
|
Oid namespaceId;
|
2011-03-11 19:20:11 +01:00
|
|
|
Oid colloid;
|
2011-02-08 22:04:18 +01:00
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
/* deconstruct the name list */
|
2022-09-20 04:18:36 +02:00
|
|
|
DeconstructQualifiedName(collname, &schemaname, &collation_name);
|
2011-02-08 22:04:18 +01:00
|
|
|
|
|
|
|
if (schemaname)
|
|
|
|
{
|
|
|
|
/* use exact schema given */
|
2013-01-26 19:24:50 +01:00
|
|
|
namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
|
|
|
|
if (missing_ok && !OidIsValid(namespaceId))
|
|
|
|
return InvalidOid;
|
2011-03-11 19:20:11 +01:00
|
|
|
|
Further hacking on ICU collation creation and usage.
pg_import_system_collations() refused to create any ICU collations if
the current database's encoding didn't support ICU. This is wrongheaded:
initdb must initialize pg_collation in an encoding-independent way
since it might be used in other databases with different encodings.
The reason for the restriction seems to be that get_icu_locale_comment()
used icu_from_uchar() to convert the UChar-format display name, and that
unsurprisingly doesn't know what to do in unsupported encodings.
But by the same token that the initial catalog contents must be
encoding-independent, we can't allow non-ASCII characters in the comment
strings. So we don't really need icu_from_uchar() here: just check for
Unicode codes outside the ASCII range, and if there are none, the format
conversion is trivial. If there are some, we can simply not install the
comment. (In my testing, this affects only Norwegian Bokmål, which has
given us trouble before.)
For paranoia's sake, also check for non-ASCII characters in ICU locale
names, and skip such locales, as we do for libc locales. I don't
currently have a reason to believe that this will ever reject anything,
but then again the libc maintainers should have known better too.
With just the import changes, ICU collations can be found in pg_collation
in databases with unsupported encodings. This resulted in more or less
clean failures at runtime, but that's not how things act for unsupported
encodings with libc collations. Make it work the same as our traditional
behavior for libc collations by having collation lookup take into account
whether is_encoding_supported_by_icu().
Adjust documentation to match. Also, expand Table 23.1 to show which
encodings are supported by ICU.
catversion bump because of likely change in pg_collation/pg_description
initial contents in ICU-enabled builds.
Discussion: https://postgr.es/m/20c74bc3-d6ca-243d-1bbc-12f17fa4fe9a@gmail.com
2017-06-24 19:54:15 +02:00
|
|
|
colloid = lookup_collation(collation_name, namespaceId, dbencoding);
|
2011-03-11 19:20:11 +01:00
|
|
|
if (OidIsValid(colloid))
|
|
|
|
return colloid;
|
2011-02-08 22:04:18 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* search for it in search path */
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
foreach(l, activeSearchPath)
|
|
|
|
{
|
|
|
|
namespaceId = lfirst_oid(l);
|
|
|
|
|
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
Further hacking on ICU collation creation and usage.
pg_import_system_collations() refused to create any ICU collations if
the current database's encoding didn't support ICU. This is wrongheaded:
initdb must initialize pg_collation in an encoding-independent way
since it might be used in other databases with different encodings.
The reason for the restriction seems to be that get_icu_locale_comment()
used icu_from_uchar() to convert the UChar-format display name, and that
unsurprisingly doesn't know what to do in unsupported encodings.
But by the same token that the initial catalog contents must be
encoding-independent, we can't allow non-ASCII characters in the comment
strings. So we don't really need icu_from_uchar() here: just check for
Unicode codes outside the ASCII range, and if there are none, the format
conversion is trivial. If there are some, we can simply not install the
comment. (In my testing, this affects only Norwegian Bokmål, which has
given us trouble before.)
For paranoia's sake, also check for non-ASCII characters in ICU locale
names, and skip such locales, as we do for libc locales. I don't
currently have a reason to believe that this will ever reject anything,
but then again the libc maintainers should have known better too.
With just the import changes, ICU collations can be found in pg_collation
in databases with unsupported encodings. This resulted in more or less
clean failures at runtime, but that's not how things act for unsupported
encodings with libc collations. Make it work the same as our traditional
behavior for libc collations by having collation lookup take into account
whether is_encoding_supported_by_icu().
Adjust documentation to match. Also, expand Table 23.1 to show which
encodings are supported by ICU.
catversion bump because of likely change in pg_collation/pg_description
initial contents in ICU-enabled builds.
Discussion: https://postgr.es/m/20c74bc3-d6ca-243d-1bbc-12f17fa4fe9a@gmail.com
2017-06-24 19:54:15 +02:00
|
|
|
colloid = lookup_collation(collation_name, namespaceId, dbencoding);
|
2011-02-08 22:04:18 +01:00
|
|
|
if (OidIsValid(colloid))
|
|
|
|
return colloid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Not found in path */
|
2011-03-11 19:20:11 +01:00
|
|
|
if (!missing_ok)
|
2011-02-08 22:04:18 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
2011-03-11 19:20:11 +01:00
|
|
|
errmsg("collation \"%s\" for encoding \"%s\" does not exist",
|
2022-09-20 04:18:36 +02:00
|
|
|
NameListToString(collname), GetDatabaseEncodingName())));
|
2011-03-11 19:20:11 +01:00
|
|
|
return InvalidOid;
|
2011-02-08 22:04:18 +01:00
|
|
|
}
|
|
|
|
|
2002-08-06 07:40:47 +02:00
|
|
|
/*
|
2010-08-05 17:25:36 +02:00
|
|
|
* get_conversion_oid - find a conversion by possibly qualified name
|
2002-08-06 07:40:47 +02:00
|
|
|
*/
|
|
|
|
Oid
|
2022-09-20 04:18:36 +02:00
|
|
|
get_conversion_oid(List *conname, bool missing_ok)
|
2002-08-06 07:40:47 +02:00
|
|
|
{
|
2002-11-02 03:33:03 +01:00
|
|
|
char *schemaname;
|
2002-08-06 07:40:47 +02:00
|
|
|
char *conversion_name;
|
|
|
|
Oid namespaceId;
|
2010-08-05 17:25:36 +02:00
|
|
|
Oid conoid = InvalidOid;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
2002-08-06 07:40:47 +02:00
|
|
|
|
2002-11-02 03:33:03 +01:00
|
|
|
/* deconstruct the name list */
|
2022-09-20 04:18:36 +02:00
|
|
|
DeconstructQualifiedName(conname, &schemaname, &conversion_name);
|
2002-08-06 07:40:47 +02:00
|
|
|
|
2002-11-02 03:33:03 +01:00
|
|
|
if (schemaname)
|
2002-08-06 07:40:47 +02:00
|
|
|
{
|
2002-11-02 03:33:03 +01:00
|
|
|
/* use exact schema given */
|
2013-01-26 19:24:50 +01:00
|
|
|
namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
|
|
|
|
if (missing_ok && !OidIsValid(namespaceId))
|
|
|
|
conoid = InvalidOid;
|
|
|
|
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
|
|
|
conoid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
|
2013-01-26 19:24:50 +01:00
|
|
|
PointerGetDatum(conversion_name),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
2002-08-06 07:40:47 +02:00
|
|
|
}
|
2002-11-02 03:33:03 +01:00
|
|
|
else
|
2002-08-06 07:40:47 +02:00
|
|
|
{
|
2002-11-02 03:33:03 +01:00
|
|
|
/* search for it in search path */
|
|
|
|
recomputeNamespacePath();
|
2002-08-06 07:40:47 +02:00
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
foreach(l, activeSearchPath)
|
2002-11-02 03:33:03 +01:00
|
|
|
{
|
2004-05-26 06:41:50 +02:00
|
|
|
namespaceId = lfirst_oid(l);
|
2007-04-20 04:37:38 +02:00
|
|
|
|
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
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
|
|
|
conoid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
|
2010-02-14 19:42:19 +01:00
|
|
|
PointerGetDatum(conversion_name),
|
|
|
|
ObjectIdGetDatum(namespaceId));
|
2002-11-02 03:33:03 +01:00
|
|
|
if (OidIsValid(conoid))
|
|
|
|
return conoid;
|
|
|
|
}
|
2002-08-06 07:40:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Not found in path */
|
2010-08-05 17:25:36 +02:00
|
|
|
if (!OidIsValid(conoid) && !missing_ok)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("conversion \"%s\" does not exist",
|
2022-09-20 04:18:36 +02:00
|
|
|
NameListToString(conname))));
|
2010-08-05 17:25:36 +02:00
|
|
|
return conoid;
|
2002-08-06 07:40:47 +02:00
|
|
|
}
|
|
|
|
|
2002-07-16 08:58:14 +02:00
|
|
|
/*
|
2002-11-02 03:33:03 +01:00
|
|
|
* FindDefaultConversionProc - find default encoding conversion proc
|
2002-07-16 08:58:14 +02:00
|
|
|
*/
|
|
|
|
Oid
|
2012-06-25 00:51:46 +02:00
|
|
|
FindDefaultConversionProc(int32 for_encoding, int32 to_encoding)
|
2002-07-16 08:58:14 +02:00
|
|
|
{
|
|
|
|
Oid proc;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
2002-07-16 08:58:14 +02:00
|
|
|
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
foreach(l, activeSearchPath)
|
2002-07-16 08:58:14 +02:00
|
|
|
{
|
2004-05-26 06:41:50 +02:00
|
|
|
Oid namespaceId = lfirst_oid(l);
|
2002-07-16 08:58:14 +02:00
|
|
|
|
2007-04-20 04:37:38 +02:00
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not look in temp namespace */
|
|
|
|
|
2002-07-16 08:58:14 +02:00
|
|
|
proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
|
|
|
|
if (OidIsValid(proc))
|
|
|
|
return proc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Not found in path */
|
|
|
|
return InvalidOid;
|
|
|
|
}
|
2002-05-02 01:06:41 +02:00
|
|
|
|
2002-04-30 00:15:07 +02:00
|
|
|
/*
|
|
|
|
* recomputeNamespacePath - recompute path derived variables if needed.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
recomputeNamespacePath(void)
|
|
|
|
{
|
2005-06-28 07:09:14 +02:00
|
|
|
Oid roleid = GetUserId();
|
2002-04-30 00:15:07 +02:00
|
|
|
char *rawname;
|
|
|
|
List *namelist;
|
|
|
|
List *oidlist;
|
|
|
|
List *newpath;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
2007-04-20 04:37:38 +02:00
|
|
|
bool temp_missing;
|
2002-05-17 22:53:33 +02:00
|
|
|
Oid firstNS;
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
bool pathChanged;
|
2002-04-30 00:15:07 +02:00
|
|
|
MemoryContext oldcxt;
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
/* Do nothing if an override search spec is active. */
|
|
|
|
if (overrideStack)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Do nothing if path is already valid. */
|
|
|
|
if (baseSearchPathValid && namespaceUser == roleid)
|
2002-04-30 00:15:07 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* Need a modifiable copy of namespace_search_path string */
|
|
|
|
rawname = pstrdup(namespace_search_path);
|
|
|
|
|
|
|
|
/* Parse string into list of identifiers */
|
|
|
|
if (!SplitIdentifierString(rawname, ',', &namelist))
|
|
|
|
{
|
|
|
|
/* syntax error in name list */
|
|
|
|
/* this should not happen if GUC checked check_search_path */
|
2003-07-21 03:59:11 +02:00
|
|
|
elog(ERROR, "invalid list syntax");
|
2002-04-30 00:15:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert the list of names to a list of OIDs. If any names are not
|
|
|
|
* recognizable or we don't have read access, just leave them out of the
|
|
|
|
* list. (We can't raise an error, since the search_path setting has
|
2002-05-17 22:53:33 +02:00
|
|
|
* already been accepted.) Don't make duplicate entries, either.
|
2002-04-30 00:15:07 +02:00
|
|
|
*/
|
|
|
|
oidlist = NIL;
|
2007-04-20 04:37:38 +02:00
|
|
|
temp_missing = false;
|
2002-04-30 00:15:07 +02:00
|
|
|
foreach(l, namelist)
|
|
|
|
{
|
|
|
|
char *curname = (char *) lfirst(l);
|
|
|
|
Oid namespaceId;
|
|
|
|
|
|
|
|
if (strcmp(curname, "$user") == 0)
|
|
|
|
{
|
|
|
|
/* $user --- substitute namespace matching user name, if any */
|
|
|
|
HeapTuple tuple;
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
|
2002-04-30 00:15:07 +02:00
|
|
|
if (HeapTupleIsValid(tuple))
|
|
|
|
{
|
2005-06-28 07:09:14 +02:00
|
|
|
char *rname;
|
2002-04-30 00:15:07 +02:00
|
|
|
|
2005-06-28 07:09:14 +02:00
|
|
|
rname = NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname);
|
2010-08-05 16:45:09 +02:00
|
|
|
namespaceId = get_namespace_oid(rname, true);
|
2002-04-30 00:15:07 +02:00
|
|
|
ReleaseSysCache(tuple);
|
|
|
|
if (OidIsValid(namespaceId) &&
|
2004-05-26 06:41:50 +02:00
|
|
|
!list_member_oid(oidlist, namespaceId) &&
|
2022-11-13 08:11:17 +01:00
|
|
|
object_aclcheck(NamespaceRelationId, namespaceId, roleid,
|
2023-05-19 23:24:48 +02:00
|
|
|
ACL_USAGE) == ACLCHECK_OK &&
|
2013-04-05 14:51:31 +02:00
|
|
|
InvokeNamespaceSearchHook(namespaceId, false))
|
2004-05-26 06:41:50 +02:00
|
|
|
oidlist = lappend_oid(oidlist, namespaceId);
|
2002-04-30 00:15:07 +02:00
|
|
|
}
|
|
|
|
}
|
2007-04-20 04:37:38 +02:00
|
|
|
else if (strcmp(curname, "pg_temp") == 0)
|
|
|
|
{
|
|
|
|
/* pg_temp --- substitute temp namespace, if any */
|
|
|
|
if (OidIsValid(myTempNamespace))
|
|
|
|
{
|
2013-04-05 14:51:31 +02:00
|
|
|
if (!list_member_oid(oidlist, myTempNamespace) &&
|
|
|
|
InvokeNamespaceSearchHook(myTempNamespace, false))
|
2007-04-20 04:37:38 +02:00
|
|
|
oidlist = lappend_oid(oidlist, myTempNamespace);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If it ought to be the creation namespace, set flag */
|
|
|
|
if (oidlist == NIL)
|
|
|
|
temp_missing = true;
|
|
|
|
}
|
|
|
|
}
|
2002-04-30 00:15:07 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* normal namespace reference */
|
2010-08-05 16:45:09 +02:00
|
|
|
namespaceId = get_namespace_oid(curname, true);
|
2002-04-30 00:15:07 +02:00
|
|
|
if (OidIsValid(namespaceId) &&
|
2004-05-26 06:41:50 +02:00
|
|
|
!list_member_oid(oidlist, namespaceId) &&
|
2022-11-13 08:11:17 +01:00
|
|
|
object_aclcheck(NamespaceRelationId, namespaceId, roleid,
|
2023-05-19 23:24:48 +02:00
|
|
|
ACL_USAGE) == ACLCHECK_OK &&
|
2013-04-05 14:51:31 +02:00
|
|
|
InvokeNamespaceSearchHook(namespaceId, false))
|
2004-05-26 06:41:50 +02:00
|
|
|
oidlist = lappend_oid(oidlist, namespaceId);
|
2002-04-30 00:15:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-05-17 22:53:33 +02:00
|
|
|
/*
|
2007-04-20 04:37:38 +02:00
|
|
|
* Remember the first member of the explicit list. (Note: this is
|
|
|
|
* nominally wrong if temp_missing, but we need it anyway to distinguish
|
|
|
|
* explicit from implicit mention of pg_catalog.)
|
2002-05-17 22:53:33 +02:00
|
|
|
*/
|
|
|
|
if (oidlist == NIL)
|
|
|
|
firstNS = InvalidOid;
|
|
|
|
else
|
2004-05-26 06:41:50 +02:00
|
|
|
firstNS = linitial_oid(oidlist);
|
2002-05-17 22:53:33 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Add any implicitly-searched namespaces to the list. Note these go on
|
|
|
|
* the front, not the back; also notice that we do not check USAGE
|
|
|
|
* permissions for these.
|
|
|
|
*/
|
2004-05-26 06:41:50 +02:00
|
|
|
if (!list_member_oid(oidlist, PG_CATALOG_NAMESPACE))
|
|
|
|
oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
|
2002-05-17 22:53:33 +02:00
|
|
|
|
|
|
|
if (OidIsValid(myTempNamespace) &&
|
2004-05-26 06:41:50 +02:00
|
|
|
!list_member_oid(oidlist, myTempNamespace))
|
|
|
|
oidlist = lcons_oid(myTempNamespace, oidlist);
|
2002-05-17 22:53:33 +02:00
|
|
|
|
2002-04-30 00:15:07 +02:00
|
|
|
/*
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
* We want to detect the case where the effective value of the base search
|
|
|
|
* path variables didn't change. As long as we're doing so, we can avoid
|
2020-11-02 07:14:41 +01:00
|
|
|
* copying the OID list unnecessarily.
|
2002-04-30 00:15:07 +02:00
|
|
|
*/
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
if (baseCreationNamespace == firstNS &&
|
|
|
|
baseTempCreationPending == temp_missing &&
|
|
|
|
equal(oidlist, baseSearchPath))
|
|
|
|
{
|
|
|
|
pathChanged = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pathChanged = true;
|
|
|
|
|
|
|
|
/* Must save OID list in permanent storage. */
|
|
|
|
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
|
|
|
|
newpath = list_copy(oidlist);
|
|
|
|
MemoryContextSwitchTo(oldcxt);
|
2002-04-30 00:15:07 +02:00
|
|
|
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
/* Now safe to assign to state variables. */
|
|
|
|
list_free(baseSearchPath);
|
|
|
|
baseSearchPath = newpath;
|
|
|
|
baseCreationNamespace = firstNS;
|
|
|
|
baseTempCreationPending = temp_missing;
|
|
|
|
}
|
2002-04-30 00:15:07 +02:00
|
|
|
|
|
|
|
/* Mark the path valid. */
|
2007-03-23 20:53:52 +01:00
|
|
|
baseSearchPathValid = true;
|
2005-06-28 07:09:14 +02:00
|
|
|
namespaceUser = roleid;
|
2002-04-30 00:15:07 +02:00
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
/* And make it active. */
|
|
|
|
activeSearchPath = baseSearchPath;
|
|
|
|
activeCreationNamespace = baseCreationNamespace;
|
2007-04-20 04:37:38 +02:00
|
|
|
activeTempCreationPending = baseTempCreationPending;
|
2007-03-23 20:53:52 +01:00
|
|
|
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
/*
|
|
|
|
* Bump the generation only if something actually changed. (Notice that
|
|
|
|
* what we compared to was the old state of the base path variables; so
|
|
|
|
* this does not deal with the situation where we have just popped an
|
|
|
|
* override path and restored the prior state of the base path. Instead
|
|
|
|
* we rely on the override-popping logic to have bumped the generation.)
|
|
|
|
*/
|
|
|
|
if (pathChanged)
|
|
|
|
activePathGeneration++;
|
|
|
|
|
2002-04-30 00:15:07 +02:00
|
|
|
/* Clean up. */
|
|
|
|
pfree(rawname);
|
2004-05-26 06:41:50 +02:00
|
|
|
list_free(namelist);
|
|
|
|
list_free(oidlist);
|
2002-04-30 00:15:07 +02:00
|
|
|
}
|
|
|
|
|
Restrict the use of temporary namespace in two-phase transactions
Attempting to use a temporary table within a two-phase transaction is
forbidden for ages. However, there have been uncovered grounds for
a couple of other object types and commands which work on temporary
objects with two-phase commit. In short, trying to create, lock or drop
an object on a temporary schema should not be authorized within a
two-phase transaction, as it would cause its state to create
dependencies with other sessions, causing all sorts of side effects with
the existing session or other sessions spawned later on trying to use
the same temporary schema name.
Regression tests are added to cover all the grounds found, the original
report mentioned function creation, but monitoring closer there are many
other patterns with LOCK, DROP or CREATE EXTENSION which are involved.
One of the symptoms resulting in combining both is that the session
which used the temporary schema is not able to shut down completely,
waiting for being able to drop the temporary schema, something that it
cannot complete because of the two-phase transaction involved with
temporary objects. In this case the client is able to disconnect but
the session remains alive on the backend-side, potentially blocking
connection backend slots from being used. Other problems reported could
also involve server crashes.
This is back-patched down to v10, which is where 9b013dc has introduced
MyXactFlags, something that this patch relies on.
Reported-by: Alexey Bashtanov
Author: Michael Paquier
Reviewed-by: Masahiko Sawada
Discussion: https://postgr.es/m/5d910e2e-0db8-ec06-dd5f-baec420513c3@imap.cc
Backpatch-through: 10
2019-01-18 01:21:44 +01:00
|
|
|
/*
|
|
|
|
* AccessTempTableNamespace
|
|
|
|
* Provide access to a temporary namespace, potentially creating it
|
|
|
|
* if not present yet. This routine registers if the namespace gets
|
|
|
|
* in use in this transaction. 'force' can be set to true to allow
|
|
|
|
* the caller to enforce the creation of the temporary namespace for
|
|
|
|
* use in this backend, which happens if its creation is pending.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
AccessTempTableNamespace(bool force)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Make note that this temporary namespace has been accessed in this
|
|
|
|
* transaction.
|
|
|
|
*/
|
|
|
|
MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the caller attempting to access a temporary schema expects the
|
|
|
|
* creation of the namespace to be pending and should be enforced, then go
|
|
|
|
* through the creation.
|
|
|
|
*/
|
|
|
|
if (!force && OidIsValid(myTempNamespace))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The temporary tablespace does not exist yet and is wanted, so
|
|
|
|
* initialize it.
|
|
|
|
*/
|
|
|
|
InitTempTableNamespace();
|
|
|
|
}
|
|
|
|
|
2002-03-31 08:26:32 +02:00
|
|
|
/*
|
2002-05-17 22:53:33 +02:00
|
|
|
* InitTempTableNamespace
|
2002-03-31 08:26:32 +02:00
|
|
|
* Initialize temp table namespace on first use in a particular backend
|
|
|
|
*/
|
2002-05-17 22:53:33 +02:00
|
|
|
static void
|
|
|
|
InitTempTableNamespace(void)
|
2002-03-31 08:26:32 +02:00
|
|
|
{
|
|
|
|
char namespaceName[NAMEDATALEN];
|
|
|
|
Oid namespaceId;
|
2007-07-26 00:16:18 +02:00
|
|
|
Oid toastspaceId;
|
2002-03-31 08:26:32 +02:00
|
|
|
|
2007-04-20 04:37:38 +02:00
|
|
|
Assert(!OidIsValid(myTempNamespace));
|
|
|
|
|
2002-04-27 05:45:03 +02:00
|
|
|
/*
|
|
|
|
* First, do permission check to see if we are authorized to make temp
|
|
|
|
* tables. We use a nonstandard error message here since "databasename:
|
|
|
|
* permission denied" might be a tad cryptic.
|
2002-04-30 00:15:07 +02:00
|
|
|
*
|
2004-05-28 18:17:14 +02:00
|
|
|
* Note that ACL_CREATE_TEMP rights are rechecked in pg_namespace_aclmask;
|
|
|
|
* that's necessary since current user ID could change during the session.
|
|
|
|
* But there's no need to make the namespace in the first place until a
|
|
|
|
* temp table creation request is made by someone with appropriate rights.
|
2002-04-27 05:45:03 +02:00
|
|
|
*/
|
2022-11-13 08:11:17 +01:00
|
|
|
if (object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(),
|
2023-05-19 23:24:48 +02:00
|
|
|
ACL_CREATE_TEMP) != ACLCHECK_OK)
|
2003-07-21 03:59:11 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
2003-09-25 08:58:07 +02:00
|
|
|
errmsg("permission denied to create temporary tables in database \"%s\"",
|
2003-07-21 03:59:11 +02:00
|
|
|
get_database_name(MyDatabaseId))));
|
2002-04-27 05:45:03 +02:00
|
|
|
|
2010-02-20 22:24:02 +01:00
|
|
|
/*
|
2017-08-07 23:42:47 +02:00
|
|
|
* Do not allow a Hot Standby session to make temp tables. Aside from
|
2010-02-20 22:24:02 +01:00
|
|
|
* problems with modifying the system catalogs, there is a naming
|
|
|
|
* conflict: pg_temp_N belongs to the session with BackendId N on the
|
2020-06-14 23:05:18 +02:00
|
|
|
* primary, not to a hot standby session with the same BackendId. We
|
2010-02-20 22:24:02 +01:00
|
|
|
* should not be able to get here anyway due to XactReadOnly checks, but
|
|
|
|
* let's just make real sure. Note that this also backstops various
|
|
|
|
* operations that allow XactReadOnly transactions to modify temp tables;
|
|
|
|
* they'd need RecoveryInProgress checks if not for this.
|
|
|
|
*/
|
|
|
|
if (RecoveryInProgress())
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
|
|
|
|
errmsg("cannot create temporary tables during recovery")));
|
|
|
|
|
Create an infrastructure for parallel computation in PostgreSQL.
This does four basic things. First, it provides convenience routines
to coordinate the startup and shutdown of parallel workers. Second,
it synchronizes various pieces of state (e.g. GUCs, combo CID
mappings, transaction snapshot) from the parallel group leader to the
worker processes. Third, it prohibits various operations that would
result in unsafe changes to that state while parallelism is active.
Finally, it propagates events that would result in an ErrorResponse,
NoticeResponse, or NotifyResponse message being sent to the client
from the parallel workers back to the master, from which they can then
be sent on to the client.
Robert Haas, Amit Kapila, Noah Misch, Rushabh Lathia, Jeevan Chalke.
Suggestions and review from Andres Freund, Heikki Linnakangas, Noah
Misch, Simon Riggs, Euler Taveira, and Jim Nasby.
2015-04-30 21:02:14 +02:00
|
|
|
/* Parallel workers can't create temporary tables, either. */
|
|
|
|
if (IsParallelWorker())
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
|
2017-06-04 17:41:16 +02:00
|
|
|
errmsg("cannot create temporary tables during a parallel operation")));
|
Create an infrastructure for parallel computation in PostgreSQL.
This does four basic things. First, it provides convenience routines
to coordinate the startup and shutdown of parallel workers. Second,
it synchronizes various pieces of state (e.g. GUCs, combo CID
mappings, transaction snapshot) from the parallel group leader to the
worker processes. Third, it prohibits various operations that would
result in unsafe changes to that state while parallelism is active.
Finally, it propagates events that would result in an ErrorResponse,
NoticeResponse, or NotifyResponse message being sent to the client
from the parallel workers back to the master, from which they can then
be sent on to the client.
Robert Haas, Amit Kapila, Noah Misch, Rushabh Lathia, Jeevan Chalke.
Suggestions and review from Andres Freund, Heikki Linnakangas, Noah
Misch, Simon Riggs, Euler Taveira, and Jim Nasby.
2015-04-30 21:02:14 +02:00
|
|
|
|
2003-03-20 04:34:57 +01:00
|
|
|
snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
|
2002-03-31 08:26:32 +02:00
|
|
|
|
2010-08-05 16:45:09 +02:00
|
|
|
namespaceId = get_namespace_oid(namespaceName, true);
|
2002-03-31 08:26:32 +02:00
|
|
|
if (!OidIsValid(namespaceId))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* First use of this temp namespace in this database; create it. The
|
2002-04-30 03:26:26 +02:00
|
|
|
* temp namespaces are always owned by the superuser. We leave their
|
|
|
|
* permissions at default --- i.e., no access except to superuser ---
|
|
|
|
* to ensure that unprivileged users can't peek at other backends'
|
|
|
|
* temp tables. This works because the places that access the temp
|
|
|
|
* namespace for my own backend skip permissions checks on it.
|
2002-03-31 08:26:32 +02:00
|
|
|
*/
|
2012-03-08 21:52:26 +01:00
|
|
|
namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
|
|
|
|
true);
|
2002-03-31 08:26:32 +02:00
|
|
|
/* Advance command counter to make namespace visible */
|
|
|
|
CommandCounterIncrement();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If the namespace already exists, clean it out (in case the former
|
|
|
|
* owner crashed without doing so).
|
|
|
|
*/
|
|
|
|
RemoveTempRelations(namespaceId);
|
|
|
|
}
|
|
|
|
|
2007-07-26 00:16:18 +02:00
|
|
|
/*
|
2007-11-25 03:09:46 +01:00
|
|
|
* If the corresponding toast-table namespace doesn't exist yet, create
|
2007-07-26 00:16:18 +02:00
|
|
|
* it. (We assume there is no need to clean it out if it does exist, since
|
|
|
|
* dropping a parent table should make its toast table go away.)
|
|
|
|
*/
|
|
|
|
snprintf(namespaceName, sizeof(namespaceName), "pg_toast_temp_%d",
|
|
|
|
MyBackendId);
|
|
|
|
|
2010-08-05 16:45:09 +02:00
|
|
|
toastspaceId = get_namespace_oid(namespaceName, true);
|
2007-07-26 00:16:18 +02:00
|
|
|
if (!OidIsValid(toastspaceId))
|
|
|
|
{
|
2012-03-08 21:52:26 +01:00
|
|
|
toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
|
|
|
|
true);
|
2007-07-26 00:16:18 +02:00
|
|
|
/* Advance command counter to make namespace visible */
|
|
|
|
CommandCounterIncrement();
|
|
|
|
}
|
|
|
|
|
2002-03-31 08:26:32 +02:00
|
|
|
/*
|
2002-05-17 22:53:33 +02:00
|
|
|
* Okay, we've prepared the temp namespace ... but it's not committed yet,
|
|
|
|
* so all our work could be undone by transaction rollback. Set flag for
|
|
|
|
* AtEOXact_Namespace to know what to do.
|
2002-03-31 08:26:32 +02:00
|
|
|
*/
|
2002-05-17 22:53:33 +02:00
|
|
|
myTempNamespace = namespaceId;
|
2007-07-26 00:16:18 +02:00
|
|
|
myTempToastNamespace = toastspaceId;
|
2002-03-31 08:26:32 +02:00
|
|
|
|
Make autovacuum more aggressive to remove orphaned temp tables
Commit dafa084, added in 10, made the removal of temporary orphaned
tables more aggressive. This commit makes an extra step into the
aggressiveness by adding a flag in each backend's MyProc which tracks
down any temporary namespace currently in use. The flag is set when the
namespace gets created and can be reset if the temporary namespace has
been created in a transaction or sub-transaction which is aborted. The
flag value assignment is assumed to be atomic, so this can be done in a
lock-less fashion like other flags already present in PGPROC like
databaseId or backendId, still the fact that the temporary namespace and
table created are still locked until the transaction creating those
commits acts as a barrier for other backends.
This new flag gets used by autovacuum to discard more aggressively
orphaned tables by additionally checking for the database a backend is
connected to as well as its temporary namespace in-use, removing
orphaned temporary relations even if a backend reuses the same slot as
one which created temporary relations in a past session.
The base idea of this patch comes from Robert Haas, has been written in
its first version by Tsunakawa Takayuki, then heavily reviewed by me.
Author: Tsunakawa Takayuki
Reviewed-by: Michael Paquier, Kyotaro Horiguchi, Andres Freund
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F8A4DC6@G01JPEXMBYT05
Backpatch: 11-, as PGPROC gains a new flag and we don't want silent ABI
breakages on already released versions.
2018-08-13 11:49:04 +02:00
|
|
|
/*
|
|
|
|
* Mark MyProc as owning this namespace which other processes can use to
|
|
|
|
* decide if a temporary namespace is in use or not. We assume that
|
|
|
|
* assignment of namespaceId is an atomic operation. Even if it is not,
|
|
|
|
* the temporary relation which resulted in the creation of this temporary
|
2018-08-21 01:32:18 +02:00
|
|
|
* namespace is still locked until the current transaction commits, and
|
|
|
|
* its pg_namespace row is not visible yet. However it does not matter:
|
|
|
|
* this flag makes the namespace as being in use, so no objects created on
|
|
|
|
* it would be removed concurrently.
|
Make autovacuum more aggressive to remove orphaned temp tables
Commit dafa084, added in 10, made the removal of temporary orphaned
tables more aggressive. This commit makes an extra step into the
aggressiveness by adding a flag in each backend's MyProc which tracks
down any temporary namespace currently in use. The flag is set when the
namespace gets created and can be reset if the temporary namespace has
been created in a transaction or sub-transaction which is aborted. The
flag value assignment is assumed to be atomic, so this can be done in a
lock-less fashion like other flags already present in PGPROC like
databaseId or backendId, still the fact that the temporary namespace and
table created are still locked until the transaction creating those
commits acts as a barrier for other backends.
This new flag gets used by autovacuum to discard more aggressively
orphaned tables by additionally checking for the database a backend is
connected to as well as its temporary namespace in-use, removing
orphaned temporary relations even if a backend reuses the same slot as
one which created temporary relations in a past session.
The base idea of this patch comes from Robert Haas, has been written in
its first version by Tsunakawa Takayuki, then heavily reviewed by me.
Author: Tsunakawa Takayuki
Reviewed-by: Michael Paquier, Kyotaro Horiguchi, Andres Freund
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F8A4DC6@G01JPEXMBYT05
Backpatch: 11-, as PGPROC gains a new flag and we don't want silent ABI
breakages on already released versions.
2018-08-13 11:49:04 +02:00
|
|
|
*/
|
|
|
|
MyProc->tempNamespaceId = namespaceId;
|
|
|
|
|
2004-07-28 16:23:31 +02:00
|
|
|
/* It should not be done already. */
|
2022-10-28 09:19:06 +02:00
|
|
|
Assert(myTempNamespaceSubID == InvalidSubTransactionId);
|
2004-09-16 18:58:44 +02:00
|
|
|
myTempNamespaceSubID = GetCurrentSubTransactionId();
|
2002-05-17 22:53:33 +02:00
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
baseSearchPathValid = false; /* need to rebuild list */
|
2002-05-17 22:53:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* End-of-transaction cleanup for namespaces.
|
|
|
|
*/
|
|
|
|
void
|
Create an infrastructure for parallel computation in PostgreSQL.
This does four basic things. First, it provides convenience routines
to coordinate the startup and shutdown of parallel workers. Second,
it synchronizes various pieces of state (e.g. GUCs, combo CID
mappings, transaction snapshot) from the parallel group leader to the
worker processes. Third, it prohibits various operations that would
result in unsafe changes to that state while parallelism is active.
Finally, it propagates events that would result in an ErrorResponse,
NoticeResponse, or NotifyResponse message being sent to the client
from the parallel workers back to the master, from which they can then
be sent on to the client.
Robert Haas, Amit Kapila, Noah Misch, Rushabh Lathia, Jeevan Chalke.
Suggestions and review from Andres Freund, Heikki Linnakangas, Noah
Misch, Simon Riggs, Euler Taveira, and Jim Nasby.
2015-04-30 21:02:14 +02:00
|
|
|
AtEOXact_Namespace(bool isCommit, bool parallel)
|
2002-05-17 22:53:33 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If we abort the transaction in which a temp namespace was selected,
|
|
|
|
* we'll have to do any creation or cleanout work over again. So, just
|
|
|
|
* forget the namespace entirely until next time. On the other hand, if
|
|
|
|
* we commit then register an exit callback to clean out the temp tables
|
|
|
|
* at backend shutdown. (We only want to register the callback once per
|
|
|
|
* session, so this is a good place to do it.)
|
|
|
|
*/
|
Create an infrastructure for parallel computation in PostgreSQL.
This does four basic things. First, it provides convenience routines
to coordinate the startup and shutdown of parallel workers. Second,
it synchronizes various pieces of state (e.g. GUCs, combo CID
mappings, transaction snapshot) from the parallel group leader to the
worker processes. Third, it prohibits various operations that would
result in unsafe changes to that state while parallelism is active.
Finally, it propagates events that would result in an ErrorResponse,
NoticeResponse, or NotifyResponse message being sent to the client
from the parallel workers back to the master, from which they can then
be sent on to the client.
Robert Haas, Amit Kapila, Noah Misch, Rushabh Lathia, Jeevan Chalke.
Suggestions and review from Andres Freund, Heikki Linnakangas, Noah
Misch, Simon Riggs, Euler Taveira, and Jim Nasby.
2015-04-30 21:02:14 +02:00
|
|
|
if (myTempNamespaceSubID != InvalidSubTransactionId && !parallel)
|
2002-05-17 22:53:33 +02:00
|
|
|
{
|
|
|
|
if (isCommit)
|
2013-12-18 18:57:20 +01:00
|
|
|
before_shmem_exit(RemoveTempRelationsCallback, 0);
|
2002-05-17 22:53:33 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
myTempNamespace = InvalidOid;
|
2007-07-26 00:16:18 +02:00
|
|
|
myTempToastNamespace = InvalidOid;
|
2007-03-23 20:53:52 +01:00
|
|
|
baseSearchPathValid = false; /* need to rebuild list */
|
Make autovacuum more aggressive to remove orphaned temp tables
Commit dafa084, added in 10, made the removal of temporary orphaned
tables more aggressive. This commit makes an extra step into the
aggressiveness by adding a flag in each backend's MyProc which tracks
down any temporary namespace currently in use. The flag is set when the
namespace gets created and can be reset if the temporary namespace has
been created in a transaction or sub-transaction which is aborted. The
flag value assignment is assumed to be atomic, so this can be done in a
lock-less fashion like other flags already present in PGPROC like
databaseId or backendId, still the fact that the temporary namespace and
table created are still locked until the transaction creating those
commits acts as a barrier for other backends.
This new flag gets used by autovacuum to discard more aggressively
orphaned tables by additionally checking for the database a backend is
connected to as well as its temporary namespace in-use, removing
orphaned temporary relations even if a backend reuses the same slot as
one which created temporary relations in a past session.
The base idea of this patch comes from Robert Haas, has been written in
its first version by Tsunakawa Takayuki, then heavily reviewed by me.
Author: Tsunakawa Takayuki
Reviewed-by: Michael Paquier, Kyotaro Horiguchi, Andres Freund
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F8A4DC6@G01JPEXMBYT05
Backpatch: 11-, as PGPROC gains a new flag and we don't want silent ABI
breakages on already released versions.
2018-08-13 11:49:04 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Reset the temporary namespace flag in MyProc. We assume that
|
2018-08-21 01:32:18 +02:00
|
|
|
* this operation is atomic.
|
|
|
|
*
|
|
|
|
* Because this transaction is aborting, the pg_namespace row is
|
|
|
|
* not visible to anyone else anyway, but that doesn't matter:
|
|
|
|
* it's not a problem if objects contained in this namespace are
|
|
|
|
* removed concurrently.
|
Make autovacuum more aggressive to remove orphaned temp tables
Commit dafa084, added in 10, made the removal of temporary orphaned
tables more aggressive. This commit makes an extra step into the
aggressiveness by adding a flag in each backend's MyProc which tracks
down any temporary namespace currently in use. The flag is set when the
namespace gets created and can be reset if the temporary namespace has
been created in a transaction or sub-transaction which is aborted. The
flag value assignment is assumed to be atomic, so this can be done in a
lock-less fashion like other flags already present in PGPROC like
databaseId or backendId, still the fact that the temporary namespace and
table created are still locked until the transaction creating those
commits acts as a barrier for other backends.
This new flag gets used by autovacuum to discard more aggressively
orphaned tables by additionally checking for the database a backend is
connected to as well as its temporary namespace in-use, removing
orphaned temporary relations even if a backend reuses the same slot as
one which created temporary relations in a past session.
The base idea of this patch comes from Robert Haas, has been written in
its first version by Tsunakawa Takayuki, then heavily reviewed by me.
Author: Tsunakawa Takayuki
Reviewed-by: Michael Paquier, Kyotaro Horiguchi, Andres Freund
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F8A4DC6@G01JPEXMBYT05
Backpatch: 11-, as PGPROC gains a new flag and we don't want silent ABI
breakages on already released versions.
2018-08-13 11:49:04 +02:00
|
|
|
*/
|
|
|
|
MyProc->tempNamespaceId = InvalidOid;
|
2002-05-17 22:53:33 +02:00
|
|
|
}
|
2004-09-16 18:58:44 +02:00
|
|
|
myTempNamespaceSubID = InvalidSubTransactionId;
|
2002-05-17 22:53:33 +02:00
|
|
|
}
|
2002-09-04 22:31:48 +02:00
|
|
|
|
2002-05-17 22:53:33 +02:00
|
|
|
/*
|
2007-03-23 20:53:52 +01:00
|
|
|
* Clean up if someone failed to do PopOverrideSearchPath
|
2002-05-17 22:53:33 +02:00
|
|
|
*/
|
2007-03-23 20:53:52 +01:00
|
|
|
if (overrideStack)
|
2002-05-17 22:53:33 +02:00
|
|
|
{
|
2007-03-23 20:53:52 +01:00
|
|
|
if (isCommit)
|
|
|
|
elog(WARNING, "leaked override search path");
|
|
|
|
while (overrideStack)
|
|
|
|
{
|
|
|
|
OverrideStackEntry *entry;
|
|
|
|
|
|
|
|
entry = (OverrideStackEntry *) linitial(overrideStack);
|
|
|
|
overrideStack = list_delete_first(overrideStack);
|
|
|
|
list_free(entry->searchPath);
|
|
|
|
pfree(entry);
|
|
|
|
}
|
|
|
|
/* If not baseSearchPathValid, this is useless but harmless */
|
|
|
|
activeSearchPath = baseSearchPath;
|
|
|
|
activeCreationNamespace = baseCreationNamespace;
|
2007-04-20 04:37:38 +02:00
|
|
|
activeTempCreationPending = baseTempCreationPending;
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
/* Always bump generation --- see note in recomputeNamespacePath */
|
|
|
|
activePathGeneration++;
|
2002-05-17 22:53:33 +02:00
|
|
|
}
|
2002-03-31 08:26:32 +02:00
|
|
|
}
|
|
|
|
|
2004-07-28 16:23:31 +02:00
|
|
|
/*
|
|
|
|
* AtEOSubXact_Namespace
|
|
|
|
*
|
|
|
|
* At subtransaction commit, propagate the temp-namespace-creation
|
2004-09-16 18:58:44 +02:00
|
|
|
* flag to the parent subtransaction.
|
2004-07-28 16:23:31 +02:00
|
|
|
*
|
|
|
|
* At subtransaction abort, forget the flag if we set it up.
|
|
|
|
*/
|
|
|
|
void
|
2004-09-16 18:58:44 +02:00
|
|
|
AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
|
|
|
|
SubTransactionId parentSubid)
|
2004-07-28 16:23:31 +02:00
|
|
|
{
|
2007-03-23 20:53:52 +01:00
|
|
|
OverrideStackEntry *entry;
|
|
|
|
|
2004-09-16 18:58:44 +02:00
|
|
|
if (myTempNamespaceSubID == mySubid)
|
2004-07-28 16:23:31 +02:00
|
|
|
{
|
|
|
|
if (isCommit)
|
2004-09-16 18:58:44 +02:00
|
|
|
myTempNamespaceSubID = parentSubid;
|
2004-07-28 16:23:31 +02:00
|
|
|
else
|
|
|
|
{
|
2004-09-16 18:58:44 +02:00
|
|
|
myTempNamespaceSubID = InvalidSubTransactionId;
|
2004-07-28 16:23:31 +02:00
|
|
|
/* TEMP namespace creation failed, so reset state */
|
|
|
|
myTempNamespace = InvalidOid;
|
2007-07-26 00:16:18 +02:00
|
|
|
myTempToastNamespace = InvalidOid;
|
2007-03-23 20:53:52 +01:00
|
|
|
baseSearchPathValid = false; /* need to rebuild list */
|
Make autovacuum more aggressive to remove orphaned temp tables
Commit dafa084, added in 10, made the removal of temporary orphaned
tables more aggressive. This commit makes an extra step into the
aggressiveness by adding a flag in each backend's MyProc which tracks
down any temporary namespace currently in use. The flag is set when the
namespace gets created and can be reset if the temporary namespace has
been created in a transaction or sub-transaction which is aborted. The
flag value assignment is assumed to be atomic, so this can be done in a
lock-less fashion like other flags already present in PGPROC like
databaseId or backendId, still the fact that the temporary namespace and
table created are still locked until the transaction creating those
commits acts as a barrier for other backends.
This new flag gets used by autovacuum to discard more aggressively
orphaned tables by additionally checking for the database a backend is
connected to as well as its temporary namespace in-use, removing
orphaned temporary relations even if a backend reuses the same slot as
one which created temporary relations in a past session.
The base idea of this patch comes from Robert Haas, has been written in
its first version by Tsunakawa Takayuki, then heavily reviewed by me.
Author: Tsunakawa Takayuki
Reviewed-by: Michael Paquier, Kyotaro Horiguchi, Andres Freund
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F8A4DC6@G01JPEXMBYT05
Backpatch: 11-, as PGPROC gains a new flag and we don't want silent ABI
breakages on already released versions.
2018-08-13 11:49:04 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Reset the temporary namespace flag in MyProc. We assume that
|
2018-08-21 01:32:18 +02:00
|
|
|
* this operation is atomic.
|
|
|
|
*
|
|
|
|
* Because this subtransaction is aborting, the pg_namespace row
|
|
|
|
* is not visible to anyone else anyway, but that doesn't matter:
|
|
|
|
* it's not a problem if objects contained in this namespace are
|
|
|
|
* removed concurrently.
|
Make autovacuum more aggressive to remove orphaned temp tables
Commit dafa084, added in 10, made the removal of temporary orphaned
tables more aggressive. This commit makes an extra step into the
aggressiveness by adding a flag in each backend's MyProc which tracks
down any temporary namespace currently in use. The flag is set when the
namespace gets created and can be reset if the temporary namespace has
been created in a transaction or sub-transaction which is aborted. The
flag value assignment is assumed to be atomic, so this can be done in a
lock-less fashion like other flags already present in PGPROC like
databaseId or backendId, still the fact that the temporary namespace and
table created are still locked until the transaction creating those
commits acts as a barrier for other backends.
This new flag gets used by autovacuum to discard more aggressively
orphaned tables by additionally checking for the database a backend is
connected to as well as its temporary namespace in-use, removing
orphaned temporary relations even if a backend reuses the same slot as
one which created temporary relations in a past session.
The base idea of this patch comes from Robert Haas, has been written in
its first version by Tsunakawa Takayuki, then heavily reviewed by me.
Author: Tsunakawa Takayuki
Reviewed-by: Michael Paquier, Kyotaro Horiguchi, Andres Freund
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F8A4DC6@G01JPEXMBYT05
Backpatch: 11-, as PGPROC gains a new flag and we don't want silent ABI
breakages on already released versions.
2018-08-13 11:49:04 +02:00
|
|
|
*/
|
|
|
|
MyProc->tempNamespaceId = InvalidOid;
|
2004-07-28 16:23:31 +02:00
|
|
|
}
|
|
|
|
}
|
2007-03-23 20:53:52 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Clean up if someone failed to do PopOverrideSearchPath
|
|
|
|
*/
|
|
|
|
while (overrideStack)
|
|
|
|
{
|
|
|
|
entry = (OverrideStackEntry *) linitial(overrideStack);
|
|
|
|
if (entry->nestLevel < GetCurrentTransactionNestLevel())
|
|
|
|
break;
|
|
|
|
if (isCommit)
|
|
|
|
elog(WARNING, "leaked override search path");
|
|
|
|
overrideStack = list_delete_first(overrideStack);
|
|
|
|
list_free(entry->searchPath);
|
|
|
|
pfree(entry);
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
/* Always bump generation --- see note in recomputeNamespacePath */
|
|
|
|
activePathGeneration++;
|
2007-03-23 20:53:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Activate the next level down. */
|
|
|
|
if (overrideStack)
|
|
|
|
{
|
|
|
|
entry = (OverrideStackEntry *) linitial(overrideStack);
|
|
|
|
activeSearchPath = entry->searchPath;
|
|
|
|
activeCreationNamespace = entry->creationNamespace;
|
2007-04-20 04:37:38 +02:00
|
|
|
activeTempCreationPending = false; /* XXX is this OK? */
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* It's probably unnecessary to bump generation here, but this should
|
|
|
|
* not be a performance-critical case, so better to be over-cautious.
|
|
|
|
*/
|
|
|
|
activePathGeneration++;
|
2007-03-23 20:53:52 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If not baseSearchPathValid, this is useless but harmless */
|
|
|
|
activeSearchPath = baseSearchPath;
|
|
|
|
activeCreationNamespace = baseCreationNamespace;
|
2007-04-20 04:37:38 +02:00
|
|
|
activeTempCreationPending = baseTempCreationPending;
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If we popped an override stack entry, then we already bumped the
|
|
|
|
* generation above. If we did not, then the above assignments did
|
|
|
|
* nothing and we need not bump the generation.
|
|
|
|
*/
|
2007-03-23 20:53:52 +01:00
|
|
|
}
|
2004-07-28 16:23:31 +02:00
|
|
|
}
|
|
|
|
|
2002-03-31 08:26:32 +02:00
|
|
|
/*
|
|
|
|
* Remove all relations in the specified temp namespace.
|
|
|
|
*
|
|
|
|
* This is called at backend shutdown (if we made any temp relations).
|
|
|
|
* It is also called when we begin using a pre-existing temp namespace,
|
|
|
|
* in order to clean out any relations that might have been created by
|
|
|
|
* a crashed backend.
|
|
|
|
*/
|
2006-04-25 16:11:59 +02:00
|
|
|
static void
|
2002-03-31 08:26:32 +02:00
|
|
|
RemoveTempRelations(Oid tempNamespaceId)
|
|
|
|
{
|
2002-07-12 20:43:19 +02:00
|
|
|
ObjectAddress object;
|
2002-03-31 08:26:32 +02:00
|
|
|
|
|
|
|
/*
|
2003-02-07 02:33:06 +01:00
|
|
|
* We want to get rid of everything in the target namespace, but not the
|
|
|
|
* namespace itself (deleting it only to recreate it later would be a
|
Delete deleteWhatDependsOn() in favor of more performDeletion() flag bits.
deleteWhatDependsOn() had grown an uncomfortably large number of
assumptions about what it's used for. There are actually only two minor
differences between what it does and what a regular performDeletion() call
can do, so let's invent additional bits in performDeletion's existing flags
argument that specify those behaviors, and get rid of deleteWhatDependsOn()
as such. (We'd probably have done it this way from the start, except that
performDeletion didn't originally have a flags argument, IIRC.)
Also, add a SKIP_EXTENSIONS flag bit that prevents ever recursing to an
extension, and use that when dropping temporary objects at session end.
This provides a more general solution to the problem addressed in a hacky
way in commit 08dd23cec: if an extension script creates temp objects and
forgets to remove them again, the whole extension went away when its
contained temp objects were deleted. The previous solution only covered
temp relations, but this solves it for all object types.
These changes require minor additions in dependency.c to pass the flags
to subroutines that previously didn't get them, but it's still a net
savings of code, and it seems cleaner than before.
Having done this, revert the special-case code added in 08dd23cec that
prevented addition of pg_depend records for temp table extension
membership, because that caused its own oddities: dropping an extension
that had created such a table didn't automatically remove the table,
leading to a failure if the table had another dependency on the extension
(such as use of an extension data type), or to a duplicate-name failure if
you then tried to recreate the extension. But we keep the part that
prevents the pg_temp_nnn schema from becoming an extension member; we never
want that to happen. Add a regression test case covering these behaviors.
Although this fixes some arguable bugs, we've heard few field complaints,
and any such problems are easily worked around by explicitly dropping temp
objects at the end of extension scripts (which seems like good practice
anyway). So I won't risk a back-patch.
Discussion: https://postgr.es/m/e51f4311-f483-4dd0-1ccc-abec3c405110@BlueTreble.com
2016-12-02 20:57:35 +01:00
|
|
|
* waste of cycles). Hence, specify SKIP_ORIGINAL. It's also an INTERNAL
|
|
|
|
* deletion, and we want to not drop any extensions that might happen to
|
|
|
|
* own temp objects.
|
2002-03-31 08:26:32 +02:00
|
|
|
*/
|
2005-04-14 22:03:27 +02:00
|
|
|
object.classId = NamespaceRelationId;
|
2003-02-07 02:33:06 +01:00
|
|
|
object.objectId = tempNamespaceId;
|
|
|
|
object.objectSubId = 0;
|
2002-03-31 08:26:32 +02:00
|
|
|
|
Delete deleteWhatDependsOn() in favor of more performDeletion() flag bits.
deleteWhatDependsOn() had grown an uncomfortably large number of
assumptions about what it's used for. There are actually only two minor
differences between what it does and what a regular performDeletion() call
can do, so let's invent additional bits in performDeletion's existing flags
argument that specify those behaviors, and get rid of deleteWhatDependsOn()
as such. (We'd probably have done it this way from the start, except that
performDeletion didn't originally have a flags argument, IIRC.)
Also, add a SKIP_EXTENSIONS flag bit that prevents ever recursing to an
extension, and use that when dropping temporary objects at session end.
This provides a more general solution to the problem addressed in a hacky
way in commit 08dd23cec: if an extension script creates temp objects and
forgets to remove them again, the whole extension went away when its
contained temp objects were deleted. The previous solution only covered
temp relations, but this solves it for all object types.
These changes require minor additions in dependency.c to pass the flags
to subroutines that previously didn't get them, but it's still a net
savings of code, and it seems cleaner than before.
Having done this, revert the special-case code added in 08dd23cec that
prevented addition of pg_depend records for temp table extension
membership, because that caused its own oddities: dropping an extension
that had created such a table didn't automatically remove the table,
leading to a failure if the table had another dependency on the extension
(such as use of an extension data type), or to a duplicate-name failure if
you then tried to recreate the extension. But we keep the part that
prevents the pg_temp_nnn schema from becoming an extension member; we never
want that to happen. Add a regression test case covering these behaviors.
Although this fixes some arguable bugs, we've heard few field complaints,
and any such problems are easily worked around by explicitly dropping temp
objects at the end of extension scripts (which seems like good practice
anyway). So I won't risk a back-patch.
Discussion: https://postgr.es/m/e51f4311-f483-4dd0-1ccc-abec3c405110@BlueTreble.com
2016-12-02 20:57:35 +01:00
|
|
|
performDeletion(&object, DROP_CASCADE,
|
|
|
|
PERFORM_DELETION_INTERNAL |
|
|
|
|
PERFORM_DELETION_QUIETLY |
|
|
|
|
PERFORM_DELETION_SKIP_ORIGINAL |
|
|
|
|
PERFORM_DELETION_SKIP_EXTENSIONS);
|
2002-03-31 08:26:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Callback to remove temp relations at backend exit.
|
|
|
|
*/
|
|
|
|
static void
|
2003-12-12 19:45:10 +01:00
|
|
|
RemoveTempRelationsCallback(int code, Datum arg)
|
2002-03-31 08:26:32 +02:00
|
|
|
{
|
|
|
|
if (OidIsValid(myTempNamespace)) /* should always be true */
|
|
|
|
{
|
|
|
|
/* Need to ensure we have a usable transaction. */
|
|
|
|
AbortOutOfAnyTransaction();
|
2003-05-14 05:26:03 +02:00
|
|
|
StartTransactionCommand();
|
2022-02-21 17:57:34 +01:00
|
|
|
PushActiveSnapshot(GetTransactionSnapshot());
|
2002-03-31 08:26:32 +02:00
|
|
|
|
|
|
|
RemoveTempRelations(myTempNamespace);
|
|
|
|
|
2022-02-21 17:57:34 +01:00
|
|
|
PopActiveSnapshot();
|
2003-05-14 05:26:03 +02:00
|
|
|
CommitTransactionCommand();
|
2002-03-31 08:26:32 +02:00
|
|
|
}
|
|
|
|
}
|
2002-04-01 05:34:27 +02:00
|
|
|
|
2007-04-20 04:37:38 +02:00
|
|
|
/*
|
|
|
|
* Remove all temp tables from the temporary namespace.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ResetTempTableNamespace(void)
|
|
|
|
{
|
|
|
|
if (OidIsValid(myTempNamespace))
|
|
|
|
RemoveTempRelations(myTempNamespace);
|
|
|
|
}
|
|
|
|
|
2002-05-02 01:06:41 +02:00
|
|
|
|
2002-04-01 05:34:27 +02:00
|
|
|
/*
|
|
|
|
* Routines for handling the GUC variable 'search_path'.
|
|
|
|
*/
|
|
|
|
|
2012-04-11 17:29:22 +02:00
|
|
|
/* check_hook: validate new search_path value */
|
2011-04-07 06:11:01 +02:00
|
|
|
bool
|
|
|
|
check_search_path(char **newval, void **extra, GucSource source)
|
2002-04-01 05:34:27 +02:00
|
|
|
{
|
|
|
|
char *rawname;
|
|
|
|
List *namelist;
|
|
|
|
|
|
|
|
/* Need a modifiable copy of string */
|
2011-04-07 06:11:01 +02:00
|
|
|
rawname = pstrdup(*newval);
|
2002-04-01 05:34:27 +02:00
|
|
|
|
|
|
|
/* Parse string into list of identifiers */
|
|
|
|
if (!SplitIdentifierString(rawname, ',', &namelist))
|
|
|
|
{
|
|
|
|
/* syntax error in name list */
|
2011-04-07 06:11:01 +02:00
|
|
|
GUC_check_errdetail("List syntax is invalid.");
|
2002-04-01 05:34:27 +02:00
|
|
|
pfree(rawname);
|
2004-05-26 06:41:50 +02:00
|
|
|
list_free(namelist);
|
2011-04-07 06:11:01 +02:00
|
|
|
return false;
|
2002-04-01 05:34:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2012-04-11 17:29:22 +02:00
|
|
|
* We used to try to check that the named schemas exist, but there are
|
|
|
|
* many valid use-cases for having search_path settings that include
|
|
|
|
* schemas that don't exist; and often, we are not inside a transaction
|
|
|
|
* here and so can't consult the system catalogs anyway. So now, the only
|
|
|
|
* requirement is syntactic validity of the identifier list.
|
2002-04-01 05:34:27 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
pfree(rawname);
|
2004-05-26 06:41:50 +02:00
|
|
|
list_free(namelist);
|
2002-04-01 05:34:27 +02:00
|
|
|
|
2012-04-11 17:29:22 +02:00
|
|
|
return true;
|
2011-04-07 06:11:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* assign_hook: do extra actions as needed */
|
|
|
|
void
|
|
|
|
assign_search_path(const char *newval, void *extra)
|
|
|
|
{
|
2002-04-01 05:34:27 +02:00
|
|
|
/*
|
2002-04-30 00:15:07 +02:00
|
|
|
* We mark the path as needing recomputation, but don't do anything until
|
|
|
|
* it's needed. This avoids trying to do database access during GUC
|
2011-04-07 06:11:01 +02:00
|
|
|
* initialization, or outside a transaction.
|
2002-04-01 05:34:27 +02:00
|
|
|
*/
|
2011-04-07 06:11:01 +02:00
|
|
|
baseSearchPathValid = false;
|
2002-04-01 05:34:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* InitializeSearchPath: initialize module during InitPostgres.
|
|
|
|
*
|
|
|
|
* This is called after we are up enough to be able to do catalog lookups.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
InitializeSearchPath(void)
|
|
|
|
{
|
2002-04-16 00:33:21 +02:00
|
|
|
if (IsBootstrapProcessingMode())
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* In bootstrap mode, the search path must be 'pg_catalog' so that
|
|
|
|
* tables are created in the proper namespace; ignore the GUC setting.
|
|
|
|
*/
|
|
|
|
MemoryContext oldcxt;
|
|
|
|
|
|
|
|
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
|
2007-03-23 20:53:52 +01:00
|
|
|
baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
|
2002-04-16 00:33:21 +02:00
|
|
|
MemoryContextSwitchTo(oldcxt);
|
2007-03-23 20:53:52 +01:00
|
|
|
baseCreationNamespace = PG_CATALOG_NAMESPACE;
|
2007-04-20 04:37:38 +02:00
|
|
|
baseTempCreationPending = false;
|
2007-03-23 20:53:52 +01:00
|
|
|
baseSearchPathValid = true;
|
2002-04-30 00:15:07 +02:00
|
|
|
namespaceUser = GetUserId();
|
2007-03-23 20:53:52 +01:00
|
|
|
activeSearchPath = baseSearchPath;
|
|
|
|
activeCreationNamespace = baseCreationNamespace;
|
2007-04-20 04:37:38 +02:00
|
|
|
activeTempCreationPending = baseTempCreationPending;
|
Improve performance of "simple expressions" in PL/pgSQL.
For relatively simple expressions (say, "x + 1" or "x > 0"), plpgsql's
management overhead exceeds the cost of evaluating the expression.
This patch substantially improves that situation, providing roughly
2X speedup for such trivial expressions.
First, add infrastructure in the plancache to allow fast re-validation
of cached plans that contain no table access, and hence need no locks.
Teach plpgsql to use this infrastructure for expressions that it's
already deemed "simple" (which in particular will never contain table
references).
The fast path still requires checking that search_path hasn't changed,
so provide a fast path for OverrideSearchPathMatchesCurrent by
counting changes that have occurred to the active search path in the
current session. This is simplistic but seems enough for now, seeing
that PushOverrideSearchPath is not used in any performance-critical
cases.
Second, manage the refcounts on simple expressions' cached plans using
a transaction-lifespan resource owner, so that we only need to take
and release an expression's refcount once per transaction not once per
expression evaluation. The management of this resource owner exactly
parallels the existing management of plpgsql's simple-expression EState.
Add some regression tests covering this area, in particular verifying
that expression caching doesn't break semantics for search_path changes.
Patch by me, but it owes something to previous work by Amit Langote,
who recognized that getting rid of plancache-related overhead would
be a useful thing to do here. Also thanks to Andres Freund for review.
Discussion: https://postgr.es/m/CAFj8pRDRVfLdAxsWeVLzCAbkLFZhW549K+67tpOc-faC8uH8zw@mail.gmail.com
2020-03-26 23:58:57 +01:00
|
|
|
activePathGeneration++; /* pro forma */
|
2002-04-16 00:33:21 +02:00
|
|
|
}
|
|
|
|
else
|
2002-04-01 05:34:27 +02:00
|
|
|
{
|
2002-04-16 00:33:21 +02:00
|
|
|
/*
|
2002-04-30 00:15:07 +02:00
|
|
|
* In normal mode, arrange for a callback on any syscache invalidation
|
|
|
|
* of pg_namespace rows.
|
2002-04-16 00:33:21 +02:00
|
|
|
*/
|
2002-04-30 00:15:07 +02:00
|
|
|
CacheRegisterSyscacheCallback(NAMESPACEOID,
|
|
|
|
NamespaceCallback,
|
|
|
|
(Datum) 0);
|
2002-05-17 03:19:19 +02:00
|
|
|
/* Force search path to be recomputed on next use */
|
2007-03-23 20:53:52 +01:00
|
|
|
baseSearchPathValid = false;
|
2002-04-01 05:34:27 +02:00
|
|
|
}
|
|
|
|
}
|
2002-04-26 03:24:08 +02:00
|
|
|
|
2002-04-30 00:15:07 +02:00
|
|
|
/*
|
|
|
|
* NamespaceCallback
|
|
|
|
* Syscache inval callback function
|
|
|
|
*/
|
|
|
|
static void
|
2011-08-17 01:27:46 +02:00
|
|
|
NamespaceCallback(Datum arg, int cacheid, uint32 hashvalue)
|
2002-04-30 00:15:07 +02:00
|
|
|
{
|
|
|
|
/* Force search path to be recomputed on next use */
|
2007-03-23 20:53:52 +01:00
|
|
|
baseSearchPathValid = false;
|
2002-04-30 00:15:07 +02:00
|
|
|
}
|
|
|
|
|
2002-04-26 03:24:08 +02:00
|
|
|
/*
|
2004-05-26 06:41:50 +02:00
|
|
|
* Fetch the active search path. The return value is a palloc'ed list
|
|
|
|
* of OIDs; the caller is responsible for freeing this storage as
|
|
|
|
* appropriate.
|
2002-04-26 03:24:08 +02:00
|
|
|
*
|
2002-05-17 22:53:33 +02:00
|
|
|
* The returned list includes the implicitly-prepended namespaces only if
|
|
|
|
* includeImplicit is true.
|
2007-04-20 04:37:38 +02:00
|
|
|
*
|
|
|
|
* Note: calling this may result in a CommandCounterIncrement operation,
|
|
|
|
* if we have to create or clean out the temp namespace.
|
2002-04-26 03:24:08 +02:00
|
|
|
*/
|
|
|
|
List *
|
2002-05-17 22:53:33 +02:00
|
|
|
fetch_search_path(bool includeImplicit)
|
2002-04-26 03:24:08 +02:00
|
|
|
{
|
2002-05-17 22:53:33 +02:00
|
|
|
List *result;
|
|
|
|
|
2002-04-30 00:15:07 +02:00
|
|
|
recomputeNamespacePath();
|
2002-05-17 22:53:33 +02:00
|
|
|
|
2007-04-20 04:37:38 +02:00
|
|
|
/*
|
|
|
|
* If the temp namespace should be first, force it to exist. This is so
|
|
|
|
* that callers can trust the result to reflect the actual default
|
|
|
|
* creation namespace. It's a bit bogus to do this here, since
|
|
|
|
* current_schema() is supposedly a stable function without side-effects,
|
|
|
|
* but the alternatives seem worse.
|
|
|
|
*/
|
|
|
|
if (activeTempCreationPending)
|
|
|
|
{
|
Restrict the use of temporary namespace in two-phase transactions
Attempting to use a temporary table within a two-phase transaction is
forbidden for ages. However, there have been uncovered grounds for
a couple of other object types and commands which work on temporary
objects with two-phase commit. In short, trying to create, lock or drop
an object on a temporary schema should not be authorized within a
two-phase transaction, as it would cause its state to create
dependencies with other sessions, causing all sorts of side effects with
the existing session or other sessions spawned later on trying to use
the same temporary schema name.
Regression tests are added to cover all the grounds found, the original
report mentioned function creation, but monitoring closer there are many
other patterns with LOCK, DROP or CREATE EXTENSION which are involved.
One of the symptoms resulting in combining both is that the session
which used the temporary schema is not able to shut down completely,
waiting for being able to drop the temporary schema, something that it
cannot complete because of the two-phase transaction involved with
temporary objects. In this case the client is able to disconnect but
the session remains alive on the backend-side, potentially blocking
connection backend slots from being used. Other problems reported could
also involve server crashes.
This is back-patched down to v10, which is where 9b013dc has introduced
MyXactFlags, something that this patch relies on.
Reported-by: Alexey Bashtanov
Author: Michael Paquier
Reviewed-by: Masahiko Sawada
Discussion: https://postgr.es/m/5d910e2e-0db8-ec06-dd5f-baec420513c3@imap.cc
Backpatch-through: 10
2019-01-18 01:21:44 +01:00
|
|
|
AccessTempTableNamespace(true);
|
2007-04-20 04:37:38 +02:00
|
|
|
recomputeNamespacePath();
|
|
|
|
}
|
|
|
|
|
2007-03-23 20:53:52 +01:00
|
|
|
result = list_copy(activeSearchPath);
|
2002-05-17 22:53:33 +02:00
|
|
|
if (!includeImplicit)
|
|
|
|
{
|
2007-03-23 20:53:52 +01:00
|
|
|
while (result && linitial_oid(result) != activeCreationNamespace)
|
2004-05-26 06:41:50 +02:00
|
|
|
result = list_delete_first(result);
|
2002-05-17 22:53:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2002-04-26 03:24:08 +02:00
|
|
|
}
|
2002-08-09 18:45:16 +02:00
|
|
|
|
2007-11-28 19:47:56 +01:00
|
|
|
/*
|
|
|
|
* Fetch the active search path into a caller-allocated array of OIDs.
|
|
|
|
* Returns the number of path entries. (If this is more than sarray_len,
|
|
|
|
* then the data didn't fit and is not all stored.)
|
|
|
|
*
|
|
|
|
* The returned list always includes the implicitly-prepended namespaces,
|
|
|
|
* but never includes the temp namespace. (This is suitable for existing
|
|
|
|
* users, which would want to ignore the temp namespace anyway.) This
|
|
|
|
* definition allows us to not worry about initializing the temp namespace.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
fetch_search_path_array(Oid *sarray, int sarray_len)
|
|
|
|
{
|
|
|
|
int count = 0;
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
recomputeNamespacePath();
|
|
|
|
|
|
|
|
foreach(l, activeSearchPath)
|
|
|
|
{
|
|
|
|
Oid namespaceId = lfirst_oid(l);
|
|
|
|
|
|
|
|
if (namespaceId == myTempNamespace)
|
|
|
|
continue; /* do not include temp namespace */
|
|
|
|
|
|
|
|
if (count < sarray_len)
|
|
|
|
sarray[count] = namespaceId;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-08-09 18:45:16 +02:00
|
|
|
/*
|
|
|
|
* Export the FooIsVisible functions as SQL-callable functions.
|
2008-12-15 19:09:41 +01:00
|
|
|
*
|
|
|
|
* Note: as of Postgres 8.4, these will silently return NULL if called on
|
|
|
|
* a nonexistent object OID, rather than failing. This is to avoid race
|
|
|
|
* condition errors when a query that's scanning a catalog using an MVCC
|
|
|
|
* snapshot uses one of these functions. The underlying IsVisible functions
|
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
|
|
|
* always use an up-to-date snapshot and so might see the object as already
|
|
|
|
* gone when it's still visible to the transaction snapshot. (There is no race
|
2008-12-15 19:09:41 +01:00
|
|
|
* condition in the current coding because we don't accept sinval messages
|
|
|
|
* between the SearchSysCacheExists test and the subsequent lookup.)
|
2002-08-09 18:45:16 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
Datum
|
|
|
|
pg_table_is_visible(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid oid = PG_GETARG_OID(0);
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(oid)))
|
2008-12-15 19:09:41 +01:00
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
2002-08-09 18:45:16 +02:00
|
|
|
PG_RETURN_BOOL(RelationIsVisible(oid));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
pg_type_is_visible(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid oid = PG_GETARG_OID(0);
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
if (!SearchSysCacheExists1(TYPEOID, ObjectIdGetDatum(oid)))
|
2008-12-15 19:09:41 +01:00
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
2002-08-09 18:45:16 +02:00
|
|
|
PG_RETURN_BOOL(TypeIsVisible(oid));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
pg_function_is_visible(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid oid = PG_GETARG_OID(0);
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(oid)))
|
2008-12-15 19:09:41 +01:00
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
2002-08-09 18:45:16 +02:00
|
|
|
PG_RETURN_BOOL(FunctionIsVisible(oid));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
pg_operator_is_visible(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid oid = PG_GETARG_OID(0);
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
if (!SearchSysCacheExists1(OPEROID, ObjectIdGetDatum(oid)))
|
2008-12-15 19:09:41 +01:00
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
2002-08-09 18:45:16 +02:00
|
|
|
PG_RETURN_BOOL(OperatorIsVisible(oid));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
pg_opclass_is_visible(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid oid = PG_GETARG_OID(0);
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
if (!SearchSysCacheExists1(CLAOID, ObjectIdGetDatum(oid)))
|
2008-12-15 19:09:41 +01:00
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
2002-08-09 18:45:16 +02:00
|
|
|
PG_RETURN_BOOL(OpclassIsVisible(oid));
|
|
|
|
}
|
2002-12-12 22:02:25 +01:00
|
|
|
|
2011-07-18 05:23:55 +02:00
|
|
|
Datum
|
|
|
|
pg_opfamily_is_visible(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid oid = PG_GETARG_OID(0);
|
|
|
|
|
|
|
|
if (!SearchSysCacheExists1(OPFAMILYOID, ObjectIdGetDatum(oid)))
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(OpfamilyIsVisible(oid));
|
|
|
|
}
|
|
|
|
|
2011-02-08 22:04:18 +01:00
|
|
|
Datum
|
|
|
|
pg_collation_is_visible(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid oid = PG_GETARG_OID(0);
|
|
|
|
|
|
|
|
if (!SearchSysCacheExists1(COLLOID, ObjectIdGetDatum(oid)))
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(CollationIsVisible(oid));
|
|
|
|
}
|
|
|
|
|
2002-12-12 22:02:25 +01:00
|
|
|
Datum
|
|
|
|
pg_conversion_is_visible(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid oid = PG_GETARG_OID(0);
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
if (!SearchSysCacheExists1(CONVOID, ObjectIdGetDatum(oid)))
|
2008-12-15 19:09:41 +01:00
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
2002-12-12 22:02:25 +01:00
|
|
|
PG_RETURN_BOOL(ConversionIsVisible(oid));
|
|
|
|
}
|
2006-09-15 00:05:06 +02:00
|
|
|
|
2017-05-13 06:05:48 +02:00
|
|
|
Datum
|
2017-05-14 16:54:47 +02:00
|
|
|
pg_statistics_obj_is_visible(PG_FUNCTION_ARGS)
|
2017-05-13 06:05:48 +02:00
|
|
|
{
|
|
|
|
Oid oid = PG_GETARG_OID(0);
|
|
|
|
|
|
|
|
if (!SearchSysCacheExists1(STATEXTOID, ObjectIdGetDatum(oid)))
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(StatisticsObjIsVisible(oid));
|
|
|
|
}
|
|
|
|
|
2007-08-21 03:11:32 +02:00
|
|
|
Datum
|
|
|
|
pg_ts_parser_is_visible(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid oid = PG_GETARG_OID(0);
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
if (!SearchSysCacheExists1(TSPARSEROID, ObjectIdGetDatum(oid)))
|
2008-12-15 19:09:41 +01:00
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
2007-08-21 03:11:32 +02:00
|
|
|
PG_RETURN_BOOL(TSParserIsVisible(oid));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
pg_ts_dict_is_visible(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid oid = PG_GETARG_OID(0);
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
if (!SearchSysCacheExists1(TSDICTOID, ObjectIdGetDatum(oid)))
|
2008-12-15 19:09:41 +01:00
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
2007-08-21 03:11:32 +02:00
|
|
|
PG_RETURN_BOOL(TSDictionaryIsVisible(oid));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
pg_ts_template_is_visible(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid oid = PG_GETARG_OID(0);
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
if (!SearchSysCacheExists1(TSTEMPLATEOID, ObjectIdGetDatum(oid)))
|
2008-12-15 19:09:41 +01:00
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
2007-08-21 03:11:32 +02:00
|
|
|
PG_RETURN_BOOL(TSTemplateIsVisible(oid));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
pg_ts_config_is_visible(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid oid = PG_GETARG_OID(0);
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
if (!SearchSysCacheExists1(TSCONFIGOID, ObjectIdGetDatum(oid)))
|
2008-12-15 19:09:41 +01:00
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
2007-08-21 03:11:32 +02:00
|
|
|
PG_RETURN_BOOL(TSConfigIsVisible(oid));
|
|
|
|
}
|
|
|
|
|
2006-09-15 00:05:06 +02:00
|
|
|
Datum
|
|
|
|
pg_my_temp_schema(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
PG_RETURN_OID(myTempNamespace);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
pg_is_other_temp_schema(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid oid = PG_GETARG_OID(0);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(isOtherTempNamespace(oid));
|
|
|
|
}
|