1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* postgres.c
|
1996-07-09 08:22:35 +02:00
|
|
|
* POSTGRES C Backend Interface
|
|
|
|
*
|
2024-01-04 02:49:05 +01:00
|
|
|
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/tcop/postgres.c
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* NOTES
|
|
|
|
* this is the "main" module of the postgres backend and
|
|
|
|
* hence the main module of the "traffic cop".
|
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
1996-11-08 07:02:30 +01:00
|
|
|
|
2000-06-29 09:35:57 +02:00
|
|
|
#include "postgres.h"
|
|
|
|
|
2010-11-06 21:50:18 +01:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <signal.h>
|
1996-11-08 07:02:30 +01:00
|
|
|
#include <unistd.h>
|
2022-08-13 13:35:24 +02:00
|
|
|
#include <sys/resource.h>
|
2022-08-13 13:33:34 +02:00
|
|
|
#include <sys/socket.h>
|
2006-10-08 19:45:50 +02:00
|
|
|
#include <sys/time.h>
|
2006-10-07 21:25:29 +02:00
|
|
|
|
2023-04-03 16:18:38 +02:00
|
|
|
#ifdef USE_VALGRIND
|
|
|
|
#include <valgrind/valgrind.h>
|
|
|
|
#endif
|
|
|
|
|
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"
|
2003-05-05 02:44:56 +02:00
|
|
|
#include "access/printtup.h"
|
2006-07-13 18:49:20 +02:00
|
|
|
#include "access/xact.h"
|
2003-05-05 02:44:56 +02:00
|
|
|
#include "catalog/pg_type.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "commands/async.h"
|
Add support event triggers on authenticated login
This commit introduces trigger on login event, allowing to fire some actions
right on the user connection. This can be useful for logging or connection
check purposes as well as for some personalization of environment. Usage
details are described in the documentation included, but shortly usage is
the same as for other triggers: create function returning event_trigger and
then create event trigger on login event.
In order to prevent the connection time overhead when there are no triggers
the commit introduces pg_database.dathasloginevt flag, which indicates database
has active login triggers. This flag is set by CREATE/ALTER EVENT TRIGGER
command, and unset at connection time when no active triggers found.
Author: Konstantin Knizhnik, Mikhail Gribkov
Discussion: https://postgr.es/m/0d46d29f-4558-3af9-9c85-7774e14a7709%40postgrespro.ru
Reviewed-by: Pavel Stehule, Takayuki Tsunakawa, Greg Nancarrow, Ivan Panchenko
Reviewed-by: Daniel Gustafsson, Teodor Sigaev, Robert Haas, Andres Freund
Reviewed-by: Tom Lane, Andrey Sokolov, Zhihong Yu, Sergey Shinderuk
Reviewed-by: Gregory Stark, Nikita Malakhov, Ted Yu
2023-10-16 02:16:55 +02:00
|
|
|
#include "commands/event_trigger.h"
|
2003-05-05 02:44:56 +02:00
|
|
|
#include "commands/prepare.h"
|
Replace random(), pg_erand48(), etc with a better PRNG API and algorithm.
Standardize on xoroshiro128** as our basic PRNG algorithm, eliminating
a bunch of platform dependencies as well as fundamentally-obsolete PRNG
code. In addition, this API replacement will ease replacing the
algorithm again in future, should that become necessary.
xoroshiro128** is a few percent slower than the drand48 family,
but it can produce full-width 64-bit random values not only 48-bit,
and it should be much more trustworthy. It's likely to be noticeably
faster than the platform's random(), depending on which platform you
are thinking about; and we can have non-global state vectors easily,
unlike with random(). It is not cryptographically strong, but neither
are the functions it replaces.
Fabien Coelho, reviewed by Dean Rasheed, Aleksander Alekseev, and myself
Discussion: https://postgr.es/m/alpine.DEB.2.22.394.2105241211230.165418@pseudo
2021-11-29 03:32:36 +01:00
|
|
|
#include "common/pg_prng.h"
|
2018-03-22 03:28:28 +01:00
|
|
|
#include "jit/jit.h"
|
1998-01-13 05:05:12 +01:00
|
|
|
#include "libpq/libpq.h"
|
1999-04-25 05:19:27 +02:00
|
|
|
#include "libpq/pqformat.h"
|
1998-01-13 05:05:12 +01:00
|
|
|
#include "libpq/pqsignal.h"
|
2019-11-12 04:00:16 +01:00
|
|
|
#include "mb/pg_wchar.h"
|
2019-12-10 21:09:32 +01:00
|
|
|
#include "mb/stringinfo_mb.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "miscadmin.h"
|
1998-01-13 05:05:12 +01:00
|
|
|
#include "nodes/print.h"
|
2019-01-29 21:48:51 +01:00
|
|
|
#include "optimizer/optimizer.h"
|
2000-10-07 02:58:23 +02:00
|
|
|
#include "parser/analyze.h"
|
1997-11-25 23:07:18 +01:00
|
|
|
#include "parser/parser.h"
|
2014-02-15 20:31:30 +01:00
|
|
|
#include "pg_getopt.h"
|
2019-11-12 04:00:16 +01:00
|
|
|
#include "pg_trace.h"
|
|
|
|
#include "pgstat.h"
|
2007-06-29 19:07:39 +02:00
|
|
|
#include "postmaster/autovacuum.h"
|
2019-12-17 19:14:28 +01:00
|
|
|
#include "postmaster/interrupt.h"
|
2009-08-29 21:26:52 +02:00
|
|
|
#include "postmaster/postmaster.h"
|
2017-06-09 00:00:53 +02:00
|
|
|
#include "replication/logicallauncher.h"
|
2017-06-02 20:46:00 +02:00
|
|
|
#include "replication/logicalworker.h"
|
Introduce logical decoding.
This feature, building on previous commits, allows the write-ahead log
stream to be decoded into a series of logical changes; that is,
inserts, updates, and deletes and the transactions which contain them.
It is capable of handling decoding even across changes to the schema
of the effected tables. The output format is controlled by a
so-called "output plugin"; an example is included. To make use of
this in a real replication system, the output plugin will need to be
modified to produce output in the format appropriate to that system,
and to perform filtering.
Currently, information can be extracted from the logical decoding
system only via SQL; future commits will add the ability to stream
changes via walsender.
Andres Freund, with review and other contributions from many other
people, including Álvaro Herrera, Abhijit Menon-Sen, Peter Gheogegan,
Kevin Grittner, Robert Haas, Heikki Linnakangas, Fujii Masao, Abhijit
Menon-Sen, Michael Paquier, Simon Riggs, Craig Ringer, and Steve
Singer.
2014-03-03 22:32:18 +01:00
|
|
|
#include "replication/slot.h"
|
2010-01-15 10:19:10 +01:00
|
|
|
#include "replication/walsender.h"
|
1999-07-16 05:14:30 +02:00
|
|
|
#include "rewrite/rewriteHandler.h"
|
2008-05-12 02:00:54 +02:00
|
|
|
#include "storage/bufmgr.h"
|
2002-05-05 02:03:29 +02:00
|
|
|
#include "storage/ipc.h"
|
2020-12-24 18:58:32 +01:00
|
|
|
#include "storage/pmsignal.h"
|
2002-05-05 02:03:29 +02:00
|
|
|
#include "storage/proc.h"
|
2009-07-31 22:26:23 +02:00
|
|
|
#include "storage/procsignal.h"
|
2004-05-23 05:50:45 +02:00
|
|
|
#include "storage/sinval.h"
|
1998-01-13 05:05:12 +01:00
|
|
|
#include "tcop/fastpath.h"
|
|
|
|
#include "tcop/pquery.h"
|
1999-07-16 05:14:30 +02:00
|
|
|
#include "tcop/tcopprot.h"
|
1998-01-13 05:05:12 +01:00
|
|
|
#include "tcop/utility.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"
|
2024-03-14 12:10:21 +01:00
|
|
|
#include "utils/injection_point.h"
|
2003-05-05 02:44:56 +02:00
|
|
|
#include "utils/lsyscache.h"
|
2000-07-17 05:05:41 +02:00
|
|
|
#include "utils/memutils.h"
|
1998-08-25 23:34:10 +02:00
|
|
|
#include "utils/ps_status.h"
|
2008-03-26 19:48:59 +01:00
|
|
|
#include "utils/snapmgr.h"
|
Introduce timeout handling framework
Management of timeouts was getting a little cumbersome; what we
originally had was more than enough back when we were only concerned
about deadlocks and query cancel; however, when we added timeouts for
standby processes, the code got considerably messier. Since there are
plans to add more complex timeouts, this seems a good time to introduce
a central timeout handling module.
External modules register their timeout handlers during process
initialization, and later enable and disable them as they see fit using
a simple API; timeout.c is in charge of keeping track of which timeouts
are in effect at any time, installing a common SIGALRM signal handler,
and calling setitimer() as appropriate to ensure timely firing of
external handlers.
timeout.c additionally supports pluggable modules to add their own
timeouts, though this capability isn't exercised anywhere yet.
Additionally, as of this commit, walsender processes are aware of
timeouts; we had a preexisting bug there that made those ignore SIGALRM,
thus being subject to unhandled deadlocks, particularly during the
authentication phase. This has already been fixed in back branches in
commit 0bf8eb2a, which see for more details.
Main author: Zoltán Böszörményi
Some review and cleanup by Álvaro Herrera
Extensive reworking by Tom Lane
2012-07-17 00:43:21 +02:00
|
|
|
#include "utils/timeout.h"
|
2011-09-09 19:23:41 +02:00
|
|
|
#include "utils/timestamp.h"
|
1998-08-25 23:34:10 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* ----------------
|
1996-11-14 11:25:54 +01:00
|
|
|
* global variables
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
2009-01-07 20:35:43 +01:00
|
|
|
const char *debug_query_string; /* client-supplied query string */
|
2001-04-14 21:11:45 +02:00
|
|
|
|
2001-09-08 03:10:21 +02:00
|
|
|
/* Note: whereToSendOutput is initialized for the bootstrap/standalone case */
|
2005-11-03 18:11:40 +01:00
|
|
|
CommandDest whereToSendOutput = DestDebug;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2004-02-17 04:54:57 +01:00
|
|
|
/* flag for logging end of session */
|
|
|
|
bool Log_disconnections = false;
|
|
|
|
|
2008-03-10 13:55:13 +01:00
|
|
|
int log_statement = LOGSTMT_NONE;
|
> >>1. change the type of "log_statement" option from boolean to string,
> >>with allowed values of "all, mod, ddl, none" with default "none".
OK, here is a patch that implements #1. Here is sample output:
test=> set client_min_messages = 'log';
SET
test=> set log_statement = 'mod';
SET
test=> select 1;
?column?
----------
1
(1 row)
test=> update test set x=1;
LOG: statement: update test set x=1;
ERROR: relation "test" does not exist
test=> update test set x=1;
LOG: statement: update test set x=1;
ERROR: relation "test" does not exist
test=> copy test from '/tmp/x';
LOG: statement: copy test from '/tmp/x';
ERROR: relation "test" does not exist
test=> copy test to '/tmp/x';
ERROR: relation "test" does not exist
test=> prepare xx as select 1;
PREPARE
test=> prepare xx as update x set y=1;
LOG: statement: prepare xx as update x set y=1;
ERROR: relation "x" does not exist
test=> explain analyze select 1;;
QUERY PLAN
------------------------------------------------------------------------------------
Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.006..0.007 rows=1 loops=1)
Total runtime: 0.046 ms
(2 rows)
test=> explain analyze update test set x=1;
LOG: statement: explain analyze update test set x=1;
ERROR: relation "test" does not exist
test=> explain update test set x=1;
ERROR: relation "test" does not exist
It checks PREPARE and EXECUTE ANALYZE too. The log_statement values are
'none', 'mod', 'ddl', and 'all'. For 'all', it prints before the query
is parsed, and for ddl/mod, it does it right after parsing using the
node tag (or command tag for CREATE/ALTER/DROP), so any non-parse errors
will print after the log line.
2004-04-07 07:05:50 +02:00
|
|
|
|
2004-03-24 23:40:29 +01:00
|
|
|
/* GUC variable for maximum stack depth (measured in kilobytes) */
|
2006-10-07 21:25:29 +02:00
|
|
|
int max_stack_depth = 100;
|
2004-03-24 23:40:29 +01:00
|
|
|
|
2006-01-05 11:07:46 +01:00
|
|
|
/* wait N seconds to allow attach from a debugger */
|
|
|
|
int PostAuthDelay = 0;
|
|
|
|
|
2021-04-02 21:52:30 +02:00
|
|
|
/* Time between checks that the client is still connected. */
|
|
|
|
int client_connection_check_interval = 0;
|
|
|
|
|
2021-03-16 16:16:41 +01:00
|
|
|
/* ----------------
|
|
|
|
* private typedefs etc
|
|
|
|
* ----------------
|
|
|
|
*/
|
2006-01-05 11:07:46 +01:00
|
|
|
|
2021-03-16 16:16:41 +01:00
|
|
|
/* type of argument for bind_param_error_callback */
|
|
|
|
typedef struct BindParamCbData
|
|
|
|
{
|
|
|
|
const char *portalName;
|
|
|
|
int paramno; /* zero-based param number, or -1 initially */
|
|
|
|
const char *paramval; /* textual input string, if available */
|
|
|
|
} BindParamCbData;
|
2004-03-24 23:40:29 +01:00
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/* ----------------
|
|
|
|
* private variables
|
|
|
|
* ----------------
|
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2004-03-24 23:40:29 +01:00
|
|
|
/* max_stack_depth converted to bytes for speed of checking */
|
2006-10-07 21:25:29 +02:00
|
|
|
static long max_stack_depth_bytes = 100 * 1024L;
|
2004-03-24 23:40:29 +01:00
|
|
|
|
2006-02-17 04:29:02 +01:00
|
|
|
/*
|
Do stack-depth checking in all postmaster children.
We used to only initialize the stack base pointer when starting up a regular
backend, not in other processes. In particular, autovacuum workers can run
arbitrary user code, and without stack-depth checking, infinite recursion
in e.g an index expression will bring down the whole cluster.
The comment about PL/Java using set_stack_base() is not yet true. As the
code stands, PL/java still modifies the stack_base_ptr variable directly.
However, it's been discussed in the PL/Java mailing list that it should be
changed to use the function, because PL/Java is currently oblivious to the
register stack used on Itanium. There's another issues with PL/Java, namely
that the stack base pointer it sets is not really the base of the stack, it
could be something close to the bottom of the stack. That's a separate issue
that might need some further changes to this code, but that's a different
story.
Backpatch to all supported releases.
2012-04-08 17:28:12 +02:00
|
|
|
* Stack base pointer -- initialized by PostmasterMain and inherited by
|
2022-02-18 04:45:34 +01:00
|
|
|
* subprocesses (but see also InitPostmasterChild).
|
2006-02-17 04:29:02 +01:00
|
|
|
*/
|
2022-02-18 04:45:34 +01:00
|
|
|
static char *stack_base_ptr = NULL;
|
2004-03-24 23:40:29 +01:00
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* Flag to keep track of whether we have started a transaction.
|
|
|
|
* For extended query protocol this has to be remembered across messages.
|
|
|
|
*/
|
|
|
|
static bool xact_started = false;
|
|
|
|
|
2005-06-02 23:03:25 +02:00
|
|
|
/*
|
|
|
|
* Flag to indicate that we are doing the outer loop's read-from-client,
|
|
|
|
* as opposed to any random read from client that might happen within
|
|
|
|
* commands like COPY FROM STDIN.
|
|
|
|
*/
|
|
|
|
static bool DoingCommandRead = false;
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* Flags to implement skip-till-Sync-after-error behavior for messages of
|
|
|
|
* the extended query protocol.
|
|
|
|
*/
|
|
|
|
static bool doing_extended_query_message = false;
|
|
|
|
static bool ignore_till_sync = false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If an unnamed prepared statement exists, it's stored here.
|
|
|
|
* We keep it separate from the hashtable kept by commands/prepare.c
|
|
|
|
* in order to reduce overhead for short-lived queries.
|
|
|
|
*/
|
2007-03-13 01:33:44 +01:00
|
|
|
static CachedPlanSource *unnamed_stmt_psrc = NULL;
|
2007-11-15 22:14:46 +01:00
|
|
|
|
2009-08-29 21:26:52 +02:00
|
|
|
/* assorted command-line switches */
|
|
|
|
static const char *userDoption = NULL; /* -D switch */
|
|
|
|
static bool EchoQuery = false; /* -E switch */
|
Adjust behavior of single-user -j mode for better initdb error reporting.
Previously, -j caused the entire input file to be read in and executed as
a single command string. That's undesirable, not least because any error
causes the entire file to be regurgitated as the "failing query". Some
experimentation suggests a better rule: end the command string when we see
a semicolon immediately followed by two newlines, ie, an empty line after
a query. This serves nicely to break up the existing examples such as
information_schema.sql and system_views.sql. A limitation is that it's
no longer possible to write such a sequence within a string literal or
multiline comment in a file meant to be read with -j; but there are no
instances of such a problem within the data currently used by initdb.
(If someone does make such a mistake in future, it'll be obvious because
they'll get an unterminated-literal or unterminated-comment syntax error.)
Other than that, there shouldn't be any negative consequences; you're not
forced to end statements that way, it's just a better idea in most cases.
In passing, remove src/include/tcop/tcopdebug.h, which is dead code
because it's not included anywhere, and hasn't been for more than
ten years. One of the debug-support symbols it purported to describe
has been unreferenced for at least the same amount of time, and the
other is removed by this commit on the grounds that it was useless:
forcing -j mode all the time would have broken initdb. The lack of
complaints about that, or about the missing inclusion, shows that
no one has tried to use TCOP_DONTUSENEWLINE in many years.
2015-12-18 01:34:15 +01:00
|
|
|
static bool UseSemiNewlineNewline = false; /* -j switch */
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2011-06-29 08:26:14 +02:00
|
|
|
/* whether or not, and why, we were canceled by conflict with recovery */
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
static volatile sig_atomic_t RecoveryConflictPending = false;
|
|
|
|
static volatile sig_atomic_t RecoveryConflictPendingReasons[NUM_PROCSIGNALS];
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2017-10-12 01:49:31 +02:00
|
|
|
/* reused buffer to pass to SendRowDescriptionMessage() */
|
|
|
|
static MemoryContext row_description_context = NULL;
|
|
|
|
static StringInfoData row_description_buf;
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* ----------------------------------------------------------------
|
1996-11-14 11:25:54 +01:00
|
|
|
* decls for routines only used in this file
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
1999-08-31 06:26:40 +02:00
|
|
|
static int InteractiveBackend(StringInfo inBuf);
|
2007-07-09 03:15:14 +02:00
|
|
|
static int interactive_getc(void);
|
1999-08-31 06:26:40 +02:00
|
|
|
static int SocketBackend(StringInfo inBuf);
|
|
|
|
static int ReadCommand(StringInfo inBuf);
|
2012-10-05 16:13:07 +02:00
|
|
|
static void forbidden_in_wal_sender(char firstchar);
|
2007-02-20 18:32:18 +01:00
|
|
|
static bool check_log_statement(List *stmt_list);
|
2006-09-08 00:52:01 +02:00
|
|
|
static int errdetail_execute(List *raw_parsetree_list);
|
|
|
|
static int errdetail_params(ParamListInfo params);
|
2010-01-16 11:05:59 +01:00
|
|
|
static int errdetail_abort(void);
|
2021-03-16 16:16:41 +01:00
|
|
|
static void bind_param_error_callback(void *arg);
|
2000-10-07 02:58:23 +02:00
|
|
|
static void start_xact_command(void);
|
2003-05-14 05:26:03 +02:00
|
|
|
static void finish_xact_command(void);
|
2005-11-10 01:31:34 +01:00
|
|
|
static bool IsTransactionExitStmt(Node *parsetree);
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
static bool IsTransactionExitStmtList(List *pstmts);
|
|
|
|
static bool IsTransactionStmtList(List *pstmts);
|
2007-03-13 01:33:44 +01:00
|
|
|
static void drop_unnamed_stmt(void);
|
2004-02-17 05:09:26 +01:00
|
|
|
static void log_disconnections(int code, Datum arg);
|
2017-09-19 04:36:44 +02:00
|
|
|
static void enable_statement_timeout(void);
|
|
|
|
static void disable_statement_timeout(void);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
2023-04-03 16:18:38 +02:00
|
|
|
/* ----------------------------------------------------------------
|
|
|
|
* infrastructure for valgrind debugging
|
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#ifdef USE_VALGRIND
|
|
|
|
/* This variable should be set at the top of the main loop. */
|
|
|
|
static unsigned int old_valgrind_error_count;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If Valgrind detected any errors since old_valgrind_error_count was updated,
|
|
|
|
* report the current query as the cause. This should be called at the end
|
|
|
|
* of message processing.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
valgrind_report_error_query(const char *query)
|
|
|
|
{
|
|
|
|
unsigned int valgrind_error_count = VALGRIND_COUNT_ERRORS;
|
|
|
|
|
|
|
|
if (unlikely(valgrind_error_count != old_valgrind_error_count) &&
|
|
|
|
query != NULL)
|
|
|
|
VALGRIND_PRINTF("Valgrind detected %u error(s) during execution of \"%s\"\n",
|
|
|
|
valgrind_error_count - old_valgrind_error_count,
|
|
|
|
query);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* !USE_VALGRIND */
|
|
|
|
#define valgrind_report_error_query(query) ((void) 0)
|
|
|
|
#endif /* USE_VALGRIND */
|
|
|
|
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* ----------------------------------------------------------------
|
1996-11-14 11:25:54 +01:00
|
|
|
* routines to obtain user input
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* ----------------
|
|
|
|
* InteractiveBackend() is called for user interactive connections
|
2003-04-19 02:02:30 +02:00
|
|
|
*
|
|
|
|
* the string entered by the user is placed in its parameter inBuf,
|
|
|
|
* and we act like a Q message was received.
|
1999-07-22 04:40:07 +02:00
|
|
|
*
|
|
|
|
* EOF is returned if end-of-file input is seen; time to shut down.
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
|
1999-07-22 04:40:07 +02:00
|
|
|
static int
|
1999-08-31 06:26:40 +02:00
|
|
|
InteractiveBackend(StringInfo inBuf)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1996-11-14 11:25:54 +01:00
|
|
|
int c; /* character read from getc() */
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
1996-11-14 11:25:54 +01:00
|
|
|
* display a prompt and obtain input from the user
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1999-05-22 04:55:58 +02:00
|
|
|
printf("backend> ");
|
1998-10-02 03:14:14 +02:00
|
|
|
fflush(stdout);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2007-03-03 20:32:55 +01:00
|
|
|
resetStringInfo(inBuf);
|
1999-08-31 06:26:40 +02:00
|
|
|
|
Adjust behavior of single-user -j mode for better initdb error reporting.
Previously, -j caused the entire input file to be read in and executed as
a single command string. That's undesirable, not least because any error
causes the entire file to be regurgitated as the "failing query". Some
experimentation suggests a better rule: end the command string when we see
a semicolon immediately followed by two newlines, ie, an empty line after
a query. This serves nicely to break up the existing examples such as
information_schema.sql and system_views.sql. A limitation is that it's
no longer possible to write such a sequence within a string literal or
multiline comment in a file meant to be read with -j; but there are no
instances of such a problem within the data currently used by initdb.
(If someone does make such a mistake in future, it'll be obvious because
they'll get an unterminated-literal or unterminated-comment syntax error.)
Other than that, there shouldn't be any negative consequences; you're not
forced to end statements that way, it's just a better idea in most cases.
In passing, remove src/include/tcop/tcopdebug.h, which is dead code
because it's not included anywhere, and hasn't been for more than
ten years. One of the debug-support symbols it purported to describe
has been unreferenced for at least the same amount of time, and the
other is removed by this commit on the grounds that it was useless:
forcing -j mode all the time would have broken initdb. The lack of
complaints about that, or about the missing inclusion, shows that
no one has tried to use TCOP_DONTUSENEWLINE in many years.
2015-12-18 01:34:15 +01:00
|
|
|
/*
|
|
|
|
* Read characters until EOF or the appropriate delimiter is seen.
|
|
|
|
*/
|
|
|
|
while ((c = interactive_getc()) != EOF)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
Adjust behavior of single-user -j mode for better initdb error reporting.
Previously, -j caused the entire input file to be read in and executed as
a single command string. That's undesirable, not least because any error
causes the entire file to be regurgitated as the "failing query". Some
experimentation suggests a better rule: end the command string when we see
a semicolon immediately followed by two newlines, ie, an empty line after
a query. This serves nicely to break up the existing examples such as
information_schema.sql and system_views.sql. A limitation is that it's
no longer possible to write such a sequence within a string literal or
multiline comment in a file meant to be read with -j; but there are no
instances of such a problem within the data currently used by initdb.
(If someone does make such a mistake in future, it'll be obvious because
they'll get an unterminated-literal or unterminated-comment syntax error.)
Other than that, there shouldn't be any negative consequences; you're not
forced to end statements that way, it's just a better idea in most cases.
In passing, remove src/include/tcop/tcopdebug.h, which is dead code
because it's not included anywhere, and hasn't been for more than
ten years. One of the debug-support symbols it purported to describe
has been unreferenced for at least the same amount of time, and the
other is removed by this commit on the grounds that it was useless:
forcing -j mode all the time would have broken initdb. The lack of
complaints about that, or about the missing inclusion, shows that
no one has tried to use TCOP_DONTUSENEWLINE in many years.
2015-12-18 01:34:15 +01:00
|
|
|
if (c == '\n')
|
1996-11-14 11:25:54 +01:00
|
|
|
{
|
Adjust behavior of single-user -j mode for better initdb error reporting.
Previously, -j caused the entire input file to be read in and executed as
a single command string. That's undesirable, not least because any error
causes the entire file to be regurgitated as the "failing query". Some
experimentation suggests a better rule: end the command string when we see
a semicolon immediately followed by two newlines, ie, an empty line after
a query. This serves nicely to break up the existing examples such as
information_schema.sql and system_views.sql. A limitation is that it's
no longer possible to write such a sequence within a string literal or
multiline comment in a file meant to be read with -j; but there are no
instances of such a problem within the data currently used by initdb.
(If someone does make such a mistake in future, it'll be obvious because
they'll get an unterminated-literal or unterminated-comment syntax error.)
Other than that, there shouldn't be any negative consequences; you're not
forced to end statements that way, it's just a better idea in most cases.
In passing, remove src/include/tcop/tcopdebug.h, which is dead code
because it's not included anywhere, and hasn't been for more than
ten years. One of the debug-support symbols it purported to describe
has been unreferenced for at least the same amount of time, and the
other is removed by this commit on the grounds that it was useless:
forcing -j mode all the time would have broken initdb. The lack of
complaints about that, or about the missing inclusion, shows that
no one has tried to use TCOP_DONTUSENEWLINE in many years.
2015-12-18 01:34:15 +01:00
|
|
|
if (UseSemiNewlineNewline)
|
1996-11-14 11:25:54 +01:00
|
|
|
{
|
Adjust behavior of single-user -j mode for better initdb error reporting.
Previously, -j caused the entire input file to be read in and executed as
a single command string. That's undesirable, not least because any error
causes the entire file to be regurgitated as the "failing query". Some
experimentation suggests a better rule: end the command string when we see
a semicolon immediately followed by two newlines, ie, an empty line after
a query. This serves nicely to break up the existing examples such as
information_schema.sql and system_views.sql. A limitation is that it's
no longer possible to write such a sequence within a string literal or
multiline comment in a file meant to be read with -j; but there are no
instances of such a problem within the data currently used by initdb.
(If someone does make such a mistake in future, it'll be obvious because
they'll get an unterminated-literal or unterminated-comment syntax error.)
Other than that, there shouldn't be any negative consequences; you're not
forced to end statements that way, it's just a better idea in most cases.
In passing, remove src/include/tcop/tcopdebug.h, which is dead code
because it's not included anywhere, and hasn't been for more than
ten years. One of the debug-support symbols it purported to describe
has been unreferenced for at least the same amount of time, and the
other is removed by this commit on the grounds that it was useless:
forcing -j mode all the time would have broken initdb. The lack of
complaints about that, or about the missing inclusion, shows that
no one has tried to use TCOP_DONTUSENEWLINE in many years.
2015-12-18 01:34:15 +01:00
|
|
|
/*
|
|
|
|
* In -j mode, semicolon followed by two newlines ends the
|
|
|
|
* command; otherwise treat newline as regular character.
|
|
|
|
*/
|
|
|
|
if (inBuf->len > 1 &&
|
|
|
|
inBuf->data[inBuf->len - 1] == '\n' &&
|
|
|
|
inBuf->data[inBuf->len - 2] == ';')
|
|
|
|
{
|
|
|
|
/* might as well drop the second newline */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* In plain mode, newline ends the command unless preceded by
|
|
|
|
* backslash.
|
|
|
|
*/
|
|
|
|
if (inBuf->len > 0 &&
|
|
|
|
inBuf->data[inBuf->len - 1] == '\\')
|
1996-11-14 11:25:54 +01:00
|
|
|
{
|
2007-07-09 03:15:14 +02:00
|
|
|
/* discard backslash from inBuf */
|
|
|
|
inBuf->data[--inBuf->len] = '\0';
|
Adjust behavior of single-user -j mode for better initdb error reporting.
Previously, -j caused the entire input file to be read in and executed as
a single command string. That's undesirable, not least because any error
causes the entire file to be regurgitated as the "failing query". Some
experimentation suggests a better rule: end the command string when we see
a semicolon immediately followed by two newlines, ie, an empty line after
a query. This serves nicely to break up the existing examples such as
information_schema.sql and system_views.sql. A limitation is that it's
no longer possible to write such a sequence within a string literal or
multiline comment in a file meant to be read with -j; but there are no
instances of such a problem within the data currently used by initdb.
(If someone does make such a mistake in future, it'll be obvious because
they'll get an unterminated-literal or unterminated-comment syntax error.)
Other than that, there shouldn't be any negative consequences; you're not
forced to end statements that way, it's just a better idea in most cases.
In passing, remove src/include/tcop/tcopdebug.h, which is dead code
because it's not included anywhere, and hasn't been for more than
ten years. One of the debug-support symbols it purported to describe
has been unreferenced for at least the same amount of time, and the
other is removed by this commit on the grounds that it was useless:
forcing -j mode all the time would have broken initdb. The lack of
complaints about that, or about the missing inclusion, shows that
no one has tried to use TCOP_DONTUSENEWLINE in many years.
2015-12-18 01:34:15 +01:00
|
|
|
/* discard newline too */
|
2007-07-09 03:15:14 +02:00
|
|
|
continue;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-11-14 11:25:54 +01:00
|
|
|
else
|
2007-07-09 03:15:14 +02:00
|
|
|
{
|
Adjust behavior of single-user -j mode for better initdb error reporting.
Previously, -j caused the entire input file to be read in and executed as
a single command string. That's undesirable, not least because any error
causes the entire file to be regurgitated as the "failing query". Some
experimentation suggests a better rule: end the command string when we see
a semicolon immediately followed by two newlines, ie, an empty line after
a query. This serves nicely to break up the existing examples such as
information_schema.sql and system_views.sql. A limitation is that it's
no longer possible to write such a sequence within a string literal or
multiline comment in a file meant to be read with -j; but there are no
instances of such a problem within the data currently used by initdb.
(If someone does make such a mistake in future, it'll be obvious because
they'll get an unterminated-literal or unterminated-comment syntax error.)
Other than that, there shouldn't be any negative consequences; you're not
forced to end statements that way, it's just a better idea in most cases.
In passing, remove src/include/tcop/tcopdebug.h, which is dead code
because it's not included anywhere, and hasn't been for more than
ten years. One of the debug-support symbols it purported to describe
has been unreferenced for at least the same amount of time, and the
other is removed by this commit on the grounds that it was useless:
forcing -j mode all the time would have broken initdb. The lack of
complaints about that, or about the missing inclusion, shows that
no one has tried to use TCOP_DONTUSENEWLINE in many years.
2015-12-18 01:34:15 +01:00
|
|
|
/* keep the newline character, but end the command */
|
2007-07-09 03:15:14 +02:00
|
|
|
appendStringInfoChar(inBuf, '\n');
|
|
|
|
break;
|
|
|
|
}
|
1996-11-14 11:25:54 +01:00
|
|
|
}
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
Adjust behavior of single-user -j mode for better initdb error reporting.
Previously, -j caused the entire input file to be read in and executed as
a single command string. That's undesirable, not least because any error
causes the entire file to be regurgitated as the "failing query". Some
experimentation suggests a better rule: end the command string when we see
a semicolon immediately followed by two newlines, ie, an empty line after
a query. This serves nicely to break up the existing examples such as
information_schema.sql and system_views.sql. A limitation is that it's
no longer possible to write such a sequence within a string literal or
multiline comment in a file meant to be read with -j; but there are no
instances of such a problem within the data currently used by initdb.
(If someone does make such a mistake in future, it'll be obvious because
they'll get an unterminated-literal or unterminated-comment syntax error.)
Other than that, there shouldn't be any negative consequences; you're not
forced to end statements that way, it's just a better idea in most cases.
In passing, remove src/include/tcop/tcopdebug.h, which is dead code
because it's not included anywhere, and hasn't been for more than
ten years. One of the debug-support symbols it purported to describe
has been unreferenced for at least the same amount of time, and the
other is removed by this commit on the grounds that it was useless:
forcing -j mode all the time would have broken initdb. The lack of
complaints about that, or about the missing inclusion, shows that
no one has tried to use TCOP_DONTUSENEWLINE in many years.
2015-12-18 01:34:15 +01:00
|
|
|
/* Not newline, or newline treated as regular character */
|
|
|
|
appendStringInfoChar(inBuf, (char) c);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
Adjust behavior of single-user -j mode for better initdb error reporting.
Previously, -j caused the entire input file to be read in and executed as
a single command string. That's undesirable, not least because any error
causes the entire file to be regurgitated as the "failing query". Some
experimentation suggests a better rule: end the command string when we see
a semicolon immediately followed by two newlines, ie, an empty line after
a query. This serves nicely to break up the existing examples such as
information_schema.sql and system_views.sql. A limitation is that it's
no longer possible to write such a sequence within a string literal or
multiline comment in a file meant to be read with -j; but there are no
instances of such a problem within the data currently used by initdb.
(If someone does make such a mistake in future, it'll be obvious because
they'll get an unterminated-literal or unterminated-comment syntax error.)
Other than that, there shouldn't be any negative consequences; you're not
forced to end statements that way, it's just a better idea in most cases.
In passing, remove src/include/tcop/tcopdebug.h, which is dead code
because it's not included anywhere, and hasn't been for more than
ten years. One of the debug-support symbols it purported to describe
has been unreferenced for at least the same amount of time, and the
other is removed by this commit on the grounds that it was useless:
forcing -j mode all the time would have broken initdb. The lack of
complaints about that, or about the missing inclusion, shows that
no one has tried to use TCOP_DONTUSENEWLINE in many years.
2015-12-18 01:34:15 +01:00
|
|
|
/* No input before EOF signal means time to quit. */
|
|
|
|
if (c == EOF && inBuf->len == 0)
|
2007-07-09 03:15:14 +02:00
|
|
|
return EOF;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* otherwise we have a user query so process it.
|
|
|
|
*/
|
|
|
|
|
2003-04-19 02:02:30 +02:00
|
|
|
/* Add '\0' to make it look the same as message case. */
|
|
|
|
appendStringInfoChar(inBuf, (char) '\0');
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
1996-11-14 11:25:54 +01:00
|
|
|
* if the query echo flag was given, print the query..
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
if (EchoQuery)
|
2002-09-02 01:26:06 +02:00
|
|
|
printf("statement: %s\n", inBuf->data);
|
1998-10-02 03:14:14 +02:00
|
|
|
fflush(stdout);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
return 'Q';
|
|
|
|
}
|
|
|
|
|
2007-07-09 03:15:14 +02:00
|
|
|
/*
|
|
|
|
* interactive_getc -- collect one character from stdin
|
|
|
|
*
|
|
|
|
* Even though we are not reading from a "client" process, we still want to
|
Introduce and use infrastructure for interrupt processing during client reads.
Up to now large swathes of backend code ran inside signal handlers
while reading commands from the client, to allow for speedy reaction to
asynchronous events. Most prominently shared invalidation and NOTIFY
handling. That means that complex code like the starting/stopping of
transactions is run in signal handlers... The required code was
fragile and verbose, and is likely to contain bugs.
That approach also severely limited what could be done while
communicating with the client. As the read might be from within
openssl it wasn't safely possible to trigger an error, e.g. to cancel
a backend in idle-in-transaction state. We did that in some cases,
namely fatal errors, nonetheless.
Now that FE/BE communication in the backend employs non-blocking
sockets and latches to block, we can quite simply interrupt reads from
signal handlers by setting the latch. That allows us to signal an
interrupted read, which is supposed to be retried after returning from
within the ssl library.
As signal handlers now only need to set the latch to guarantee timely
interrupt processing, remove a fair amount of complicated & fragile
code from async.c and sinval.c.
We could now actually start to process some kinds of interrupts, like
sinval ones, more often that before, but that seems better done
separately.
This work will hopefully allow to handle cases like being blocked by
sending data, interrupting idle transactions and similar to be
implemented without too much effort. In addition to allowing getting
rid of ImmediateInterruptOK, that is.
Author: Andres Freund
Reviewed-By: Heikki Linnakangas
2015-02-03 22:25:20 +01:00
|
|
|
* respond to signals, particularly SIGTERM/SIGQUIT.
|
2007-07-09 03:15:14 +02:00
|
|
|
*/
|
|
|
|
static int
|
|
|
|
interactive_getc(void)
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
Introduce and use infrastructure for interrupt processing during client reads.
Up to now large swathes of backend code ran inside signal handlers
while reading commands from the client, to allow for speedy reaction to
asynchronous events. Most prominently shared invalidation and NOTIFY
handling. That means that complex code like the starting/stopping of
transactions is run in signal handlers... The required code was
fragile and verbose, and is likely to contain bugs.
That approach also severely limited what could be done while
communicating with the client. As the read might be from within
openssl it wasn't safely possible to trigger an error, e.g. to cancel
a backend in idle-in-transaction state. We did that in some cases,
namely fatal errors, nonetheless.
Now that FE/BE communication in the backend employs non-blocking
sockets and latches to block, we can quite simply interrupt reads from
signal handlers by setting the latch. That allows us to signal an
interrupted read, which is supposed to be retried after returning from
within the ssl library.
As signal handlers now only need to set the latch to guarantee timely
interrupt processing, remove a fair amount of complicated & fragile
code from async.c and sinval.c.
We could now actually start to process some kinds of interrupts, like
sinval ones, more often that before, but that seems better done
separately.
This work will hopefully allow to handle cases like being blocked by
sending data, interrupting idle transactions and similar to be
implemented without too much effort. In addition to allowing getting
rid of ImmediateInterruptOK, that is.
Author: Andres Freund
Reviewed-By: Heikki Linnakangas
2015-02-03 22:25:20 +01:00
|
|
|
/*
|
|
|
|
* This will not process catchup interrupts or notifications while
|
|
|
|
* reading. But those can't really be relevant for a standalone backend
|
|
|
|
* anyway. To properly handle SIGTERM there's a hack in die() that
|
|
|
|
* directly processes interrupts at this stage...
|
|
|
|
*/
|
|
|
|
CHECK_FOR_INTERRUPTS();
|
|
|
|
|
2007-07-09 03:15:14 +02:00
|
|
|
c = getc(stdin);
|
Introduce and use infrastructure for interrupt processing during client reads.
Up to now large swathes of backend code ran inside signal handlers
while reading commands from the client, to allow for speedy reaction to
asynchronous events. Most prominently shared invalidation and NOTIFY
handling. That means that complex code like the starting/stopping of
transactions is run in signal handlers... The required code was
fragile and verbose, and is likely to contain bugs.
That approach also severely limited what could be done while
communicating with the client. As the read might be from within
openssl it wasn't safely possible to trigger an error, e.g. to cancel
a backend in idle-in-transaction state. We did that in some cases,
namely fatal errors, nonetheless.
Now that FE/BE communication in the backend employs non-blocking
sockets and latches to block, we can quite simply interrupt reads from
signal handlers by setting the latch. That allows us to signal an
interrupted read, which is supposed to be retried after returning from
within the ssl library.
As signal handlers now only need to set the latch to guarantee timely
interrupt processing, remove a fair amount of complicated & fragile
code from async.c and sinval.c.
We could now actually start to process some kinds of interrupts, like
sinval ones, more often that before, but that seems better done
separately.
This work will hopefully allow to handle cases like being blocked by
sending data, interrupting idle transactions and similar to be
implemented without too much effort. In addition to allowing getting
rid of ImmediateInterruptOK, that is.
Author: Andres Freund
Reviewed-By: Heikki Linnakangas
2015-02-03 22:25:20 +01:00
|
|
|
|
Server-side fix for delayed NOTIFY and SIGTERM processing.
Commit 4f85fde8e introduced some code that was meant to ensure that we'd
process cancel, die, sinval catchup, and notify interrupts while waiting
for client input. But there was a flaw: it supposed that the process
latch would be set upon arrival at secure_read() if any such interrupt
was pending. In reality, we might well have cleared the process latch
at some earlier point while those flags remained set -- particularly
notifyInterruptPending, which can't be handled as long as we're within
a transaction.
To fix the NOTIFY case, also attempt to process signals (except
ProcDiePending) before trying to read.
Also, if we see that ProcDiePending is set before we read, forcibly set the
process latch to ensure that we will handle that signal promptly if no data
is available. I also made it set the process latch on the way out, in case
there is similar logic elsewhere. (It remains true that we won't service
ProcDiePending here unless we need to wait for input.)
The code for handling ProcDiePending during a write needs those changes,
too.
Also be a little more careful about when to reset whereToSendOutput,
and improve related comments.
Back-patch to 9.5 where this code was added. I'm not entirely convinced
that older branches don't have similar issues, but the complaint at hand
is just about the >= 9.5 code.
Jeff Janes and Tom Lane
Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
2018-10-20 03:39:21 +02:00
|
|
|
ProcessClientReadInterrupt(false);
|
Introduce and use infrastructure for interrupt processing during client reads.
Up to now large swathes of backend code ran inside signal handlers
while reading commands from the client, to allow for speedy reaction to
asynchronous events. Most prominently shared invalidation and NOTIFY
handling. That means that complex code like the starting/stopping of
transactions is run in signal handlers... The required code was
fragile and verbose, and is likely to contain bugs.
That approach also severely limited what could be done while
communicating with the client. As the read might be from within
openssl it wasn't safely possible to trigger an error, e.g. to cancel
a backend in idle-in-transaction state. We did that in some cases,
namely fatal errors, nonetheless.
Now that FE/BE communication in the backend employs non-blocking
sockets and latches to block, we can quite simply interrupt reads from
signal handlers by setting the latch. That allows us to signal an
interrupted read, which is supposed to be retried after returning from
within the ssl library.
As signal handlers now only need to set the latch to guarantee timely
interrupt processing, remove a fair amount of complicated & fragile
code from async.c and sinval.c.
We could now actually start to process some kinds of interrupts, like
sinval ones, more often that before, but that seems better done
separately.
This work will hopefully allow to handle cases like being blocked by
sending data, interrupting idle transactions and similar to be
implemented without too much effort. In addition to allowing getting
rid of ImmediateInterruptOK, that is.
Author: Andres Freund
Reviewed-By: Heikki Linnakangas
2015-02-03 22:25:20 +01:00
|
|
|
|
2007-07-09 03:15:14 +02:00
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* ----------------
|
1996-11-14 11:25:54 +01:00
|
|
|
* SocketBackend() Is called for frontend-backend connections
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2003-04-19 02:02:30 +02:00
|
|
|
* Returns the message type code, and loads message body data into inBuf.
|
1999-07-22 04:40:07 +02:00
|
|
|
*
|
|
|
|
* EOF is returned if the connection is lost.
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
1999-07-22 04:40:07 +02:00
|
|
|
static int
|
1999-08-31 06:26:40 +02:00
|
|
|
SocketBackend(StringInfo inBuf)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2001-12-04 20:40:17 +01:00
|
|
|
int qtype;
|
Add heuristic incoming-message-size limits in the server.
We had a report of confusing server behavior caused by a client bug
that sent junk to the server: the server thought the junk was a
very long message length and waited patiently for data that would
never come. We can reduce the risk of that by being less trusting
about message lengths.
For a long time, libpq has had a heuristic rule that it wouldn't
believe large message size words, except for a small number of
message types that are expected to be (potentially) long. This
provides some defense against loss of message-boundary sync and
other corrupted-data cases. The server does something similar,
except that up to now it only limited the lengths of messages
received during the connection authentication phase. Let's
do the same as in libpq and put restrictions on the allowed
length of all messages, while distinguishing between message
types that are expected to be long and those that aren't.
I used a limit of 10000 bytes for non-long messages. (libpq's
corresponding limit is 30000 bytes, but given the asymmetry of
the FE/BE protocol, there's no good reason why the numbers should
be the same.) Experimentation suggests that this is at least a
factor of 10, maybe a factor of 100, more than we really need;
but plenty of daylight seems desirable to avoid false positives.
In any case we can adjust the limit based on beta-test results.
For long messages, set a limit of MaxAllocSize - 1, which is the
most that we can absorb into the StringInfo buffer that the message
is collected in. This just serves to make sure that a bogus message
size is reported as such, rather than as a confusing gripe about
not being able to enlarge a string buffer.
While at it, make sure that non-mainline code paths (such as
COPY FROM STDIN) are as paranoid as SocketBackend is, and validate
the message type code before believing the message length.
This provides an additional guard against getting stuck on corrupted
input.
Discussion: https://postgr.es/m/2003757.1619373089@sss.pgh.pa.us
2021-04-28 21:50:42 +02:00
|
|
|
int maxmsglen;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2003-04-19 02:02:30 +02:00
|
|
|
* Get message type code from the frontend.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
HOLD_CANCEL_INTERRUPTS();
|
|
|
|
pq_startmsgread();
|
2001-12-04 20:40:17 +01:00
|
|
|
qtype = pq_getbyte();
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2003-04-19 02:02:30 +02:00
|
|
|
if (qtype == EOF) /* frontend disconnected */
|
|
|
|
{
|
2012-05-07 18:39:37 +02:00
|
|
|
if (IsTransactionState())
|
|
|
|
ereport(COMMERROR,
|
|
|
|
(errcode(ERRCODE_CONNECTION_FAILURE),
|
|
|
|
errmsg("unexpected EOF on client connection with an open transaction")));
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Can't send DEBUG log messages to client at this point. Since
|
|
|
|
* we're disconnecting right away, we don't need to restore
|
|
|
|
* whereToSendOutput.
|
|
|
|
*/
|
|
|
|
whereToSendOutput = DestNone;
|
|
|
|
ereport(DEBUG1,
|
|
|
|
(errcode(ERRCODE_CONNECTION_DOES_NOT_EXIST),
|
2021-02-17 11:24:46 +01:00
|
|
|
errmsg_internal("unexpected EOF on client connection")));
|
2012-05-07 18:39:37 +02:00
|
|
|
}
|
2003-04-19 02:02:30 +02:00
|
|
|
return qtype;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Validate message type code before trying to read body; if we have lost
|
|
|
|
* sync, better to say "command unknown" than to run out of memory because
|
Add heuristic incoming-message-size limits in the server.
We had a report of confusing server behavior caused by a client bug
that sent junk to the server: the server thought the junk was a
very long message length and waited patiently for data that would
never come. We can reduce the risk of that by being less trusting
about message lengths.
For a long time, libpq has had a heuristic rule that it wouldn't
believe large message size words, except for a small number of
message types that are expected to be (potentially) long. This
provides some defense against loss of message-boundary sync and
other corrupted-data cases. The server does something similar,
except that up to now it only limited the lengths of messages
received during the connection authentication phase. Let's
do the same as in libpq and put restrictions on the allowed
length of all messages, while distinguishing between message
types that are expected to be long and those that aren't.
I used a limit of 10000 bytes for non-long messages. (libpq's
corresponding limit is 30000 bytes, but given the asymmetry of
the FE/BE protocol, there's no good reason why the numbers should
be the same.) Experimentation suggests that this is at least a
factor of 10, maybe a factor of 100, more than we really need;
but plenty of daylight seems desirable to avoid false positives.
In any case we can adjust the limit based on beta-test results.
For long messages, set a limit of MaxAllocSize - 1, which is the
most that we can absorb into the StringInfo buffer that the message
is collected in. This just serves to make sure that a bogus message
size is reported as such, rather than as a confusing gripe about
not being able to enlarge a string buffer.
While at it, make sure that non-mainline code paths (such as
COPY FROM STDIN) are as paranoid as SocketBackend is, and validate
the message type code before believing the message length.
This provides an additional guard against getting stuck on corrupted
input.
Discussion: https://postgr.es/m/2003757.1619373089@sss.pgh.pa.us
2021-04-28 21:50:42 +02:00
|
|
|
* we used garbage as a length word. We can also select a type-dependent
|
|
|
|
* limit on what a sane length word could be. (The limit could be chosen
|
|
|
|
* more granularly, but it's not clear it's worth fussing over.)
|
2003-05-05 02:44:56 +02:00
|
|
|
*
|
|
|
|
* This also gives us a place to set the doing_extended_query_message flag
|
|
|
|
* as soon as possible.
|
2003-04-19 02:02:30 +02:00
|
|
|
*/
|
1999-04-25 05:19:27 +02:00
|
|
|
switch (qtype)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_Query:
|
Add heuristic incoming-message-size limits in the server.
We had a report of confusing server behavior caused by a client bug
that sent junk to the server: the server thought the junk was a
very long message length and waited patiently for data that would
never come. We can reduce the risk of that by being less trusting
about message lengths.
For a long time, libpq has had a heuristic rule that it wouldn't
believe large message size words, except for a small number of
message types that are expected to be (potentially) long. This
provides some defense against loss of message-boundary sync and
other corrupted-data cases. The server does something similar,
except that up to now it only limited the lengths of messages
received during the connection authentication phase. Let's
do the same as in libpq and put restrictions on the allowed
length of all messages, while distinguishing between message
types that are expected to be long and those that aren't.
I used a limit of 10000 bytes for non-long messages. (libpq's
corresponding limit is 30000 bytes, but given the asymmetry of
the FE/BE protocol, there's no good reason why the numbers should
be the same.) Experimentation suggests that this is at least a
factor of 10, maybe a factor of 100, more than we really need;
but plenty of daylight seems desirable to avoid false positives.
In any case we can adjust the limit based on beta-test results.
For long messages, set a limit of MaxAllocSize - 1, which is the
most that we can absorb into the StringInfo buffer that the message
is collected in. This just serves to make sure that a bogus message
size is reported as such, rather than as a confusing gripe about
not being able to enlarge a string buffer.
While at it, make sure that non-mainline code paths (such as
COPY FROM STDIN) are as paranoid as SocketBackend is, and validate
the message type code before believing the message length.
This provides an additional guard against getting stuck on corrupted
input.
Discussion: https://postgr.es/m/2003757.1619373089@sss.pgh.pa.us
2021-04-28 21:50:42 +02:00
|
|
|
maxmsglen = PQ_LARGE_MESSAGE_LIMIT;
|
2003-05-05 02:44:56 +02:00
|
|
|
doing_extended_query_message = false;
|
2001-12-04 20:40:17 +01:00
|
|
|
break;
|
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_FunctionCall:
|
Add heuristic incoming-message-size limits in the server.
We had a report of confusing server behavior caused by a client bug
that sent junk to the server: the server thought the junk was a
very long message length and waited patiently for data that would
never come. We can reduce the risk of that by being less trusting
about message lengths.
For a long time, libpq has had a heuristic rule that it wouldn't
believe large message size words, except for a small number of
message types that are expected to be (potentially) long. This
provides some defense against loss of message-boundary sync and
other corrupted-data cases. The server does something similar,
except that up to now it only limited the lengths of messages
received during the connection authentication phase. Let's
do the same as in libpq and put restrictions on the allowed
length of all messages, while distinguishing between message
types that are expected to be long and those that aren't.
I used a limit of 10000 bytes for non-long messages. (libpq's
corresponding limit is 30000 bytes, but given the asymmetry of
the FE/BE protocol, there's no good reason why the numbers should
be the same.) Experimentation suggests that this is at least a
factor of 10, maybe a factor of 100, more than we really need;
but plenty of daylight seems desirable to avoid false positives.
In any case we can adjust the limit based on beta-test results.
For long messages, set a limit of MaxAllocSize - 1, which is the
most that we can absorb into the StringInfo buffer that the message
is collected in. This just serves to make sure that a bogus message
size is reported as such, rather than as a confusing gripe about
not being able to enlarge a string buffer.
While at it, make sure that non-mainline code paths (such as
COPY FROM STDIN) are as paranoid as SocketBackend is, and validate
the message type code before believing the message length.
This provides an additional guard against getting stuck on corrupted
input.
Discussion: https://postgr.es/m/2003757.1619373089@sss.pgh.pa.us
2021-04-28 21:50:42 +02:00
|
|
|
maxmsglen = PQ_LARGE_MESSAGE_LIMIT;
|
2003-05-05 02:44:56 +02:00
|
|
|
doing_extended_query_message = false;
|
1996-11-14 11:25:54 +01:00
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_Terminate:
|
Add heuristic incoming-message-size limits in the server.
We had a report of confusing server behavior caused by a client bug
that sent junk to the server: the server thought the junk was a
very long message length and waited patiently for data that would
never come. We can reduce the risk of that by being less trusting
about message lengths.
For a long time, libpq has had a heuristic rule that it wouldn't
believe large message size words, except for a small number of
message types that are expected to be (potentially) long. This
provides some defense against loss of message-boundary sync and
other corrupted-data cases. The server does something similar,
except that up to now it only limited the lengths of messages
received during the connection authentication phase. Let's
do the same as in libpq and put restrictions on the allowed
length of all messages, while distinguishing between message
types that are expected to be long and those that aren't.
I used a limit of 10000 bytes for non-long messages. (libpq's
corresponding limit is 30000 bytes, but given the asymmetry of
the FE/BE protocol, there's no good reason why the numbers should
be the same.) Experimentation suggests that this is at least a
factor of 10, maybe a factor of 100, more than we really need;
but plenty of daylight seems desirable to avoid false positives.
In any case we can adjust the limit based on beta-test results.
For long messages, set a limit of MaxAllocSize - 1, which is the
most that we can absorb into the StringInfo buffer that the message
is collected in. This just serves to make sure that a bogus message
size is reported as such, rather than as a confusing gripe about
not being able to enlarge a string buffer.
While at it, make sure that non-mainline code paths (such as
COPY FROM STDIN) are as paranoid as SocketBackend is, and validate
the message type code before believing the message length.
This provides an additional guard against getting stuck on corrupted
input.
Discussion: https://postgr.es/m/2003757.1619373089@sss.pgh.pa.us
2021-04-28 21:50:42 +02:00
|
|
|
maxmsglen = PQ_SMALL_MESSAGE_LIMIT;
|
2003-05-05 02:44:56 +02:00
|
|
|
doing_extended_query_message = false;
|
2003-05-14 20:40:37 +02:00
|
|
|
ignore_till_sync = false;
|
2003-05-05 02:44:56 +02:00
|
|
|
break;
|
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_Bind:
|
|
|
|
case PqMsg_Parse:
|
Add heuristic incoming-message-size limits in the server.
We had a report of confusing server behavior caused by a client bug
that sent junk to the server: the server thought the junk was a
very long message length and waited patiently for data that would
never come. We can reduce the risk of that by being less trusting
about message lengths.
For a long time, libpq has had a heuristic rule that it wouldn't
believe large message size words, except for a small number of
message types that are expected to be (potentially) long. This
provides some defense against loss of message-boundary sync and
other corrupted-data cases. The server does something similar,
except that up to now it only limited the lengths of messages
received during the connection authentication phase. Let's
do the same as in libpq and put restrictions on the allowed
length of all messages, while distinguishing between message
types that are expected to be long and those that aren't.
I used a limit of 10000 bytes for non-long messages. (libpq's
corresponding limit is 30000 bytes, but given the asymmetry of
the FE/BE protocol, there's no good reason why the numbers should
be the same.) Experimentation suggests that this is at least a
factor of 10, maybe a factor of 100, more than we really need;
but plenty of daylight seems desirable to avoid false positives.
In any case we can adjust the limit based on beta-test results.
For long messages, set a limit of MaxAllocSize - 1, which is the
most that we can absorb into the StringInfo buffer that the message
is collected in. This just serves to make sure that a bogus message
size is reported as such, rather than as a confusing gripe about
not being able to enlarge a string buffer.
While at it, make sure that non-mainline code paths (such as
COPY FROM STDIN) are as paranoid as SocketBackend is, and validate
the message type code before believing the message length.
This provides an additional guard against getting stuck on corrupted
input.
Discussion: https://postgr.es/m/2003757.1619373089@sss.pgh.pa.us
2021-04-28 21:50:42 +02:00
|
|
|
maxmsglen = PQ_LARGE_MESSAGE_LIMIT;
|
|
|
|
doing_extended_query_message = true;
|
|
|
|
break;
|
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_Close:
|
|
|
|
case PqMsg_Describe:
|
|
|
|
case PqMsg_Execute:
|
|
|
|
case PqMsg_Flush:
|
Add heuristic incoming-message-size limits in the server.
We had a report of confusing server behavior caused by a client bug
that sent junk to the server: the server thought the junk was a
very long message length and waited patiently for data that would
never come. We can reduce the risk of that by being less trusting
about message lengths.
For a long time, libpq has had a heuristic rule that it wouldn't
believe large message size words, except for a small number of
message types that are expected to be (potentially) long. This
provides some defense against loss of message-boundary sync and
other corrupted-data cases. The server does something similar,
except that up to now it only limited the lengths of messages
received during the connection authentication phase. Let's
do the same as in libpq and put restrictions on the allowed
length of all messages, while distinguishing between message
types that are expected to be long and those that aren't.
I used a limit of 10000 bytes for non-long messages. (libpq's
corresponding limit is 30000 bytes, but given the asymmetry of
the FE/BE protocol, there's no good reason why the numbers should
be the same.) Experimentation suggests that this is at least a
factor of 10, maybe a factor of 100, more than we really need;
but plenty of daylight seems desirable to avoid false positives.
In any case we can adjust the limit based on beta-test results.
For long messages, set a limit of MaxAllocSize - 1, which is the
most that we can absorb into the StringInfo buffer that the message
is collected in. This just serves to make sure that a bogus message
size is reported as such, rather than as a confusing gripe about
not being able to enlarge a string buffer.
While at it, make sure that non-mainline code paths (such as
COPY FROM STDIN) are as paranoid as SocketBackend is, and validate
the message type code before believing the message length.
This provides an additional guard against getting stuck on corrupted
input.
Discussion: https://postgr.es/m/2003757.1619373089@sss.pgh.pa.us
2021-04-28 21:50:42 +02:00
|
|
|
maxmsglen = PQ_SMALL_MESSAGE_LIMIT;
|
2003-05-05 02:44:56 +02:00
|
|
|
doing_extended_query_message = true;
|
|
|
|
break;
|
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_Sync:
|
Add heuristic incoming-message-size limits in the server.
We had a report of confusing server behavior caused by a client bug
that sent junk to the server: the server thought the junk was a
very long message length and waited patiently for data that would
never come. We can reduce the risk of that by being less trusting
about message lengths.
For a long time, libpq has had a heuristic rule that it wouldn't
believe large message size words, except for a small number of
message types that are expected to be (potentially) long. This
provides some defense against loss of message-boundary sync and
other corrupted-data cases. The server does something similar,
except that up to now it only limited the lengths of messages
received during the connection authentication phase. Let's
do the same as in libpq and put restrictions on the allowed
length of all messages, while distinguishing between message
types that are expected to be long and those that aren't.
I used a limit of 10000 bytes for non-long messages. (libpq's
corresponding limit is 30000 bytes, but given the asymmetry of
the FE/BE protocol, there's no good reason why the numbers should
be the same.) Experimentation suggests that this is at least a
factor of 10, maybe a factor of 100, more than we really need;
but plenty of daylight seems desirable to avoid false positives.
In any case we can adjust the limit based on beta-test results.
For long messages, set a limit of MaxAllocSize - 1, which is the
most that we can absorb into the StringInfo buffer that the message
is collected in. This just serves to make sure that a bogus message
size is reported as such, rather than as a confusing gripe about
not being able to enlarge a string buffer.
While at it, make sure that non-mainline code paths (such as
COPY FROM STDIN) are as paranoid as SocketBackend is, and validate
the message type code before believing the message length.
This provides an additional guard against getting stuck on corrupted
input.
Discussion: https://postgr.es/m/2003757.1619373089@sss.pgh.pa.us
2021-04-28 21:50:42 +02:00
|
|
|
maxmsglen = PQ_SMALL_MESSAGE_LIMIT;
|
2003-05-05 02:44:56 +02:00
|
|
|
/* stop any active skip-till-Sync */
|
|
|
|
ignore_till_sync = false;
|
|
|
|
/* mark not-extended, so that a new error doesn't begin skip */
|
|
|
|
doing_extended_query_message = false;
|
1996-07-09 08:22:35 +02:00
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_CopyData:
|
Add heuristic incoming-message-size limits in the server.
We had a report of confusing server behavior caused by a client bug
that sent junk to the server: the server thought the junk was a
very long message length and waited patiently for data that would
never come. We can reduce the risk of that by being less trusting
about message lengths.
For a long time, libpq has had a heuristic rule that it wouldn't
believe large message size words, except for a small number of
message types that are expected to be (potentially) long. This
provides some defense against loss of message-boundary sync and
other corrupted-data cases. The server does something similar,
except that up to now it only limited the lengths of messages
received during the connection authentication phase. Let's
do the same as in libpq and put restrictions on the allowed
length of all messages, while distinguishing between message
types that are expected to be long and those that aren't.
I used a limit of 10000 bytes for non-long messages. (libpq's
corresponding limit is 30000 bytes, but given the asymmetry of
the FE/BE protocol, there's no good reason why the numbers should
be the same.) Experimentation suggests that this is at least a
factor of 10, maybe a factor of 100, more than we really need;
but plenty of daylight seems desirable to avoid false positives.
In any case we can adjust the limit based on beta-test results.
For long messages, set a limit of MaxAllocSize - 1, which is the
most that we can absorb into the StringInfo buffer that the message
is collected in. This just serves to make sure that a bogus message
size is reported as such, rather than as a confusing gripe about
not being able to enlarge a string buffer.
While at it, make sure that non-mainline code paths (such as
COPY FROM STDIN) are as paranoid as SocketBackend is, and validate
the message type code before believing the message length.
This provides an additional guard against getting stuck on corrupted
input.
Discussion: https://postgr.es/m/2003757.1619373089@sss.pgh.pa.us
2021-04-28 21:50:42 +02:00
|
|
|
maxmsglen = PQ_LARGE_MESSAGE_LIMIT;
|
|
|
|
doing_extended_query_message = false;
|
|
|
|
break;
|
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_CopyDone:
|
|
|
|
case PqMsg_CopyFail:
|
Add heuristic incoming-message-size limits in the server.
We had a report of confusing server behavior caused by a client bug
that sent junk to the server: the server thought the junk was a
very long message length and waited patiently for data that would
never come. We can reduce the risk of that by being less trusting
about message lengths.
For a long time, libpq has had a heuristic rule that it wouldn't
believe large message size words, except for a small number of
message types that are expected to be (potentially) long. This
provides some defense against loss of message-boundary sync and
other corrupted-data cases. The server does something similar,
except that up to now it only limited the lengths of messages
received during the connection authentication phase. Let's
do the same as in libpq and put restrictions on the allowed
length of all messages, while distinguishing between message
types that are expected to be long and those that aren't.
I used a limit of 10000 bytes for non-long messages. (libpq's
corresponding limit is 30000 bytes, but given the asymmetry of
the FE/BE protocol, there's no good reason why the numbers should
be the same.) Experimentation suggests that this is at least a
factor of 10, maybe a factor of 100, more than we really need;
but plenty of daylight seems desirable to avoid false positives.
In any case we can adjust the limit based on beta-test results.
For long messages, set a limit of MaxAllocSize - 1, which is the
most that we can absorb into the StringInfo buffer that the message
is collected in. This just serves to make sure that a bogus message
size is reported as such, rather than as a confusing gripe about
not being able to enlarge a string buffer.
While at it, make sure that non-mainline code paths (such as
COPY FROM STDIN) are as paranoid as SocketBackend is, and validate
the message type code before believing the message length.
This provides an additional guard against getting stuck on corrupted
input.
Discussion: https://postgr.es/m/2003757.1619373089@sss.pgh.pa.us
2021-04-28 21:50:42 +02:00
|
|
|
maxmsglen = PQ_SMALL_MESSAGE_LIMIT;
|
2003-05-05 02:44:56 +02:00
|
|
|
doing_extended_query_message = false;
|
1996-11-14 11:25:54 +01:00
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2003-04-19 02:02:30 +02:00
|
|
|
default:
|
2003-08-04 02:43:34 +02:00
|
|
|
|
1996-11-14 11:25:54 +01:00
|
|
|
/*
|
2003-04-19 02:02:30 +02:00
|
|
|
* Otherwise we got garbage from the frontend. We treat this as
|
|
|
|
* fatal because we have probably lost message boundary sync, and
|
|
|
|
* there's no good way to recover.
|
1996-11-14 11:25:54 +01:00
|
|
|
*/
|
2003-07-22 21:00:12 +02:00
|
|
|
ereport(FATAL,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("invalid frontend message type %d", qtype)));
|
Add heuristic incoming-message-size limits in the server.
We had a report of confusing server behavior caused by a client bug
that sent junk to the server: the server thought the junk was a
very long message length and waited patiently for data that would
never come. We can reduce the risk of that by being less trusting
about message lengths.
For a long time, libpq has had a heuristic rule that it wouldn't
believe large message size words, except for a small number of
message types that are expected to be (potentially) long. This
provides some defense against loss of message-boundary sync and
other corrupted-data cases. The server does something similar,
except that up to now it only limited the lengths of messages
received during the connection authentication phase. Let's
do the same as in libpq and put restrictions on the allowed
length of all messages, while distinguishing between message
types that are expected to be long and those that aren't.
I used a limit of 10000 bytes for non-long messages. (libpq's
corresponding limit is 30000 bytes, but given the asymmetry of
the FE/BE protocol, there's no good reason why the numbers should
be the same.) Experimentation suggests that this is at least a
factor of 10, maybe a factor of 100, more than we really need;
but plenty of daylight seems desirable to avoid false positives.
In any case we can adjust the limit based on beta-test results.
For long messages, set a limit of MaxAllocSize - 1, which is the
most that we can absorb into the StringInfo buffer that the message
is collected in. This just serves to make sure that a bogus message
size is reported as such, rather than as a confusing gripe about
not being able to enlarge a string buffer.
While at it, make sure that non-mainline code paths (such as
COPY FROM STDIN) are as paranoid as SocketBackend is, and validate
the message type code before believing the message length.
This provides an additional guard against getting stuck on corrupted
input.
Discussion: https://postgr.es/m/2003757.1619373089@sss.pgh.pa.us
2021-04-28 21:50:42 +02:00
|
|
|
maxmsglen = 0; /* keep compiler quiet */
|
1996-11-14 11:25:54 +01:00
|
|
|
break;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
2001-12-04 20:40:17 +01:00
|
|
|
|
2003-04-19 02:02:30 +02:00
|
|
|
/*
|
|
|
|
* In protocol version 3, all frontend messages have a length word next
|
|
|
|
* after the type code; we can read the message contents independently of
|
|
|
|
* the type.
|
|
|
|
*/
|
Add heuristic incoming-message-size limits in the server.
We had a report of confusing server behavior caused by a client bug
that sent junk to the server: the server thought the junk was a
very long message length and waited patiently for data that would
never come. We can reduce the risk of that by being less trusting
about message lengths.
For a long time, libpq has had a heuristic rule that it wouldn't
believe large message size words, except for a small number of
message types that are expected to be (potentially) long. This
provides some defense against loss of message-boundary sync and
other corrupted-data cases. The server does something similar,
except that up to now it only limited the lengths of messages
received during the connection authentication phase. Let's
do the same as in libpq and put restrictions on the allowed
length of all messages, while distinguishing between message
types that are expected to be long and those that aren't.
I used a limit of 10000 bytes for non-long messages. (libpq's
corresponding limit is 30000 bytes, but given the asymmetry of
the FE/BE protocol, there's no good reason why the numbers should
be the same.) Experimentation suggests that this is at least a
factor of 10, maybe a factor of 100, more than we really need;
but plenty of daylight seems desirable to avoid false positives.
In any case we can adjust the limit based on beta-test results.
For long messages, set a limit of MaxAllocSize - 1, which is the
most that we can absorb into the StringInfo buffer that the message
is collected in. This just serves to make sure that a bogus message
size is reported as such, rather than as a confusing gripe about
not being able to enlarge a string buffer.
While at it, make sure that non-mainline code paths (such as
COPY FROM STDIN) are as paranoid as SocketBackend is, and validate
the message type code before believing the message length.
This provides an additional guard against getting stuck on corrupted
input.
Discussion: https://postgr.es/m/2003757.1619373089@sss.pgh.pa.us
2021-04-28 21:50:42 +02:00
|
|
|
if (pq_getmessage(inBuf, maxmsglen))
|
2021-03-04 09:45:55 +01:00
|
|
|
return EOF; /* suitable message already logged */
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
RESUME_CANCEL_INTERRUPTS();
|
2003-04-19 02:02:30 +02:00
|
|
|
|
2001-12-04 20:40:17 +01:00
|
|
|
return qtype;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------
|
1996-11-14 11:25:54 +01:00
|
|
|
* ReadCommand reads a command from either the frontend or
|
2003-05-02 22:54:36 +02:00
|
|
|
* standard input, places it in inBuf, and returns the
|
|
|
|
* message type code (first byte of the message).
|
|
|
|
* EOF is returned if end of file.
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------
|
|
|
|
*/
|
1999-07-22 04:40:07 +02:00
|
|
|
static int
|
1999-08-31 06:26:40 +02:00
|
|
|
ReadCommand(StringInfo inBuf)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1999-08-31 06:26:40 +02:00
|
|
|
int result;
|
|
|
|
|
2005-11-03 18:11:40 +01:00
|
|
|
if (whereToSendOutput == DestRemote)
|
1999-08-31 06:26:40 +02:00
|
|
|
result = SocketBackend(inBuf);
|
1996-07-09 08:22:35 +02:00
|
|
|
else
|
1999-08-31 06:26:40 +02:00
|
|
|
result = InteractiveBackend(inBuf);
|
|
|
|
return result;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2005-06-02 23:03:25 +02:00
|
|
|
/*
|
Introduce and use infrastructure for interrupt processing during client reads.
Up to now large swathes of backend code ran inside signal handlers
while reading commands from the client, to allow for speedy reaction to
asynchronous events. Most prominently shared invalidation and NOTIFY
handling. That means that complex code like the starting/stopping of
transactions is run in signal handlers... The required code was
fragile and verbose, and is likely to contain bugs.
That approach also severely limited what could be done while
communicating with the client. As the read might be from within
openssl it wasn't safely possible to trigger an error, e.g. to cancel
a backend in idle-in-transaction state. We did that in some cases,
namely fatal errors, nonetheless.
Now that FE/BE communication in the backend employs non-blocking
sockets and latches to block, we can quite simply interrupt reads from
signal handlers by setting the latch. That allows us to signal an
interrupted read, which is supposed to be retried after returning from
within the ssl library.
As signal handlers now only need to set the latch to guarantee timely
interrupt processing, remove a fair amount of complicated & fragile
code from async.c and sinval.c.
We could now actually start to process some kinds of interrupts, like
sinval ones, more often that before, but that seems better done
separately.
This work will hopefully allow to handle cases like being blocked by
sending data, interrupting idle transactions and similar to be
implemented without too much effort. In addition to allowing getting
rid of ImmediateInterruptOK, that is.
Author: Andres Freund
Reviewed-By: Heikki Linnakangas
2015-02-03 22:25:20 +01:00
|
|
|
* ProcessClientReadInterrupt() - Process interrupts specific to client reads
|
2005-06-02 23:03:25 +02:00
|
|
|
*
|
Server-side fix for delayed NOTIFY and SIGTERM processing.
Commit 4f85fde8e introduced some code that was meant to ensure that we'd
process cancel, die, sinval catchup, and notify interrupts while waiting
for client input. But there was a flaw: it supposed that the process
latch would be set upon arrival at secure_read() if any such interrupt
was pending. In reality, we might well have cleared the process latch
at some earlier point while those flags remained set -- particularly
notifyInterruptPending, which can't be handled as long as we're within
a transaction.
To fix the NOTIFY case, also attempt to process signals (except
ProcDiePending) before trying to read.
Also, if we see that ProcDiePending is set before we read, forcibly set the
process latch to ensure that we will handle that signal promptly if no data
is available. I also made it set the process latch on the way out, in case
there is similar logic elsewhere. (It remains true that we won't service
ProcDiePending here unless we need to wait for input.)
The code for handling ProcDiePending during a write needs those changes,
too.
Also be a little more careful about when to reset whereToSendOutput,
and improve related comments.
Back-patch to 9.5 where this code was added. I'm not entirely convinced
that older branches don't have similar issues, but the complaint at hand
is just about the >= 9.5 code.
Jeff Janes and Tom Lane
Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
2018-10-20 03:39:21 +02:00
|
|
|
* This is called just before and after low-level reads.
|
|
|
|
* 'blocked' is true if no data was available to read and we plan to retry,
|
|
|
|
* false if about to read or done reading.
|
2013-11-24 19:09:38 +01:00
|
|
|
*
|
Introduce and use infrastructure for interrupt processing during client reads.
Up to now large swathes of backend code ran inside signal handlers
while reading commands from the client, to allow for speedy reaction to
asynchronous events. Most prominently shared invalidation and NOTIFY
handling. That means that complex code like the starting/stopping of
transactions is run in signal handlers... The required code was
fragile and verbose, and is likely to contain bugs.
That approach also severely limited what could be done while
communicating with the client. As the read might be from within
openssl it wasn't safely possible to trigger an error, e.g. to cancel
a backend in idle-in-transaction state. We did that in some cases,
namely fatal errors, nonetheless.
Now that FE/BE communication in the backend employs non-blocking
sockets and latches to block, we can quite simply interrupt reads from
signal handlers by setting the latch. That allows us to signal an
interrupted read, which is supposed to be retried after returning from
within the ssl library.
As signal handlers now only need to set the latch to guarantee timely
interrupt processing, remove a fair amount of complicated & fragile
code from async.c and sinval.c.
We could now actually start to process some kinds of interrupts, like
sinval ones, more often that before, but that seems better done
separately.
This work will hopefully allow to handle cases like being blocked by
sending data, interrupting idle transactions and similar to be
implemented without too much effort. In addition to allowing getting
rid of ImmediateInterruptOK, that is.
Author: Andres Freund
Reviewed-By: Heikki Linnakangas
2015-02-03 22:25:20 +01:00
|
|
|
* Must preserve errno!
|
2005-06-02 23:03:25 +02:00
|
|
|
*/
|
|
|
|
void
|
2015-02-03 22:45:45 +01:00
|
|
|
ProcessClientReadInterrupt(bool blocked)
|
2005-06-02 23:03:25 +02:00
|
|
|
{
|
Introduce and use infrastructure for interrupt processing during client reads.
Up to now large swathes of backend code ran inside signal handlers
while reading commands from the client, to allow for speedy reaction to
asynchronous events. Most prominently shared invalidation and NOTIFY
handling. That means that complex code like the starting/stopping of
transactions is run in signal handlers... The required code was
fragile and verbose, and is likely to contain bugs.
That approach also severely limited what could be done while
communicating with the client. As the read might be from within
openssl it wasn't safely possible to trigger an error, e.g. to cancel
a backend in idle-in-transaction state. We did that in some cases,
namely fatal errors, nonetheless.
Now that FE/BE communication in the backend employs non-blocking
sockets and latches to block, we can quite simply interrupt reads from
signal handlers by setting the latch. That allows us to signal an
interrupted read, which is supposed to be retried after returning from
within the ssl library.
As signal handlers now only need to set the latch to guarantee timely
interrupt processing, remove a fair amount of complicated & fragile
code from async.c and sinval.c.
We could now actually start to process some kinds of interrupts, like
sinval ones, more often that before, but that seems better done
separately.
This work will hopefully allow to handle cases like being blocked by
sending data, interrupting idle transactions and similar to be
implemented without too much effort. In addition to allowing getting
rid of ImmediateInterruptOK, that is.
Author: Andres Freund
Reviewed-By: Heikki Linnakangas
2015-02-03 22:25:20 +01:00
|
|
|
int save_errno = errno;
|
|
|
|
|
2005-06-02 23:03:25 +02:00
|
|
|
if (DoingCommandRead)
|
|
|
|
{
|
Server-side fix for delayed NOTIFY and SIGTERM processing.
Commit 4f85fde8e introduced some code that was meant to ensure that we'd
process cancel, die, sinval catchup, and notify interrupts while waiting
for client input. But there was a flaw: it supposed that the process
latch would be set upon arrival at secure_read() if any such interrupt
was pending. In reality, we might well have cleared the process latch
at some earlier point while those flags remained set -- particularly
notifyInterruptPending, which can't be handled as long as we're within
a transaction.
To fix the NOTIFY case, also attempt to process signals (except
ProcDiePending) before trying to read.
Also, if we see that ProcDiePending is set before we read, forcibly set the
process latch to ensure that we will handle that signal promptly if no data
is available. I also made it set the process latch on the way out, in case
there is similar logic elsewhere. (It remains true that we won't service
ProcDiePending here unless we need to wait for input.)
The code for handling ProcDiePending during a write needs those changes,
too.
Also be a little more careful about when to reset whereToSendOutput,
and improve related comments.
Back-patch to 9.5 where this code was added. I'm not entirely convinced
that older branches don't have similar issues, but the complaint at hand
is just about the >= 9.5 code.
Jeff Janes and Tom Lane
Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
2018-10-20 03:39:21 +02:00
|
|
|
/* Check for general interrupts that arrived before/while reading */
|
Introduce and use infrastructure for interrupt processing during client reads.
Up to now large swathes of backend code ran inside signal handlers
while reading commands from the client, to allow for speedy reaction to
asynchronous events. Most prominently shared invalidation and NOTIFY
handling. That means that complex code like the starting/stopping of
transactions is run in signal handlers... The required code was
fragile and verbose, and is likely to contain bugs.
That approach also severely limited what could be done while
communicating with the client. As the read might be from within
openssl it wasn't safely possible to trigger an error, e.g. to cancel
a backend in idle-in-transaction state. We did that in some cases,
namely fatal errors, nonetheless.
Now that FE/BE communication in the backend employs non-blocking
sockets and latches to block, we can quite simply interrupt reads from
signal handlers by setting the latch. That allows us to signal an
interrupted read, which is supposed to be retried after returning from
within the ssl library.
As signal handlers now only need to set the latch to guarantee timely
interrupt processing, remove a fair amount of complicated & fragile
code from async.c and sinval.c.
We could now actually start to process some kinds of interrupts, like
sinval ones, more often that before, but that seems better done
separately.
This work will hopefully allow to handle cases like being blocked by
sending data, interrupting idle transactions and similar to be
implemented without too much effort. In addition to allowing getting
rid of ImmediateInterruptOK, that is.
Author: Andres Freund
Reviewed-By: Heikki Linnakangas
2015-02-03 22:25:20 +01:00
|
|
|
CHECK_FOR_INTERRUPTS();
|
2005-06-02 23:03:25 +02:00
|
|
|
|
Server-side fix for delayed NOTIFY and SIGTERM processing.
Commit 4f85fde8e introduced some code that was meant to ensure that we'd
process cancel, die, sinval catchup, and notify interrupts while waiting
for client input. But there was a flaw: it supposed that the process
latch would be set upon arrival at secure_read() if any such interrupt
was pending. In reality, we might well have cleared the process latch
at some earlier point while those flags remained set -- particularly
notifyInterruptPending, which can't be handled as long as we're within
a transaction.
To fix the NOTIFY case, also attempt to process signals (except
ProcDiePending) before trying to read.
Also, if we see that ProcDiePending is set before we read, forcibly set the
process latch to ensure that we will handle that signal promptly if no data
is available. I also made it set the process latch on the way out, in case
there is similar logic elsewhere. (It remains true that we won't service
ProcDiePending here unless we need to wait for input.)
The code for handling ProcDiePending during a write needs those changes,
too.
Also be a little more careful about when to reset whereToSendOutput,
and improve related comments.
Back-patch to 9.5 where this code was added. I'm not entirely convinced
that older branches don't have similar issues, but the complaint at hand
is just about the >= 9.5 code.
Jeff Janes and Tom Lane
Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
2018-10-20 03:39:21 +02:00
|
|
|
/* Process sinval catchup interrupts, if any */
|
Introduce and use infrastructure for interrupt processing during client reads.
Up to now large swathes of backend code ran inside signal handlers
while reading commands from the client, to allow for speedy reaction to
asynchronous events. Most prominently shared invalidation and NOTIFY
handling. That means that complex code like the starting/stopping of
transactions is run in signal handlers... The required code was
fragile and verbose, and is likely to contain bugs.
That approach also severely limited what could be done while
communicating with the client. As the read might be from within
openssl it wasn't safely possible to trigger an error, e.g. to cancel
a backend in idle-in-transaction state. We did that in some cases,
namely fatal errors, nonetheless.
Now that FE/BE communication in the backend employs non-blocking
sockets and latches to block, we can quite simply interrupt reads from
signal handlers by setting the latch. That allows us to signal an
interrupted read, which is supposed to be retried after returning from
within the ssl library.
As signal handlers now only need to set the latch to guarantee timely
interrupt processing, remove a fair amount of complicated & fragile
code from async.c and sinval.c.
We could now actually start to process some kinds of interrupts, like
sinval ones, more often that before, but that seems better done
separately.
This work will hopefully allow to handle cases like being blocked by
sending data, interrupting idle transactions and similar to be
implemented without too much effort. In addition to allowing getting
rid of ImmediateInterruptOK, that is.
Author: Andres Freund
Reviewed-By: Heikki Linnakangas
2015-02-03 22:25:20 +01:00
|
|
|
if (catchupInterruptPending)
|
|
|
|
ProcessCatchupInterrupt();
|
2013-11-24 19:09:38 +01:00
|
|
|
|
Server-side fix for delayed NOTIFY and SIGTERM processing.
Commit 4f85fde8e introduced some code that was meant to ensure that we'd
process cancel, die, sinval catchup, and notify interrupts while waiting
for client input. But there was a flaw: it supposed that the process
latch would be set upon arrival at secure_read() if any such interrupt
was pending. In reality, we might well have cleared the process latch
at some earlier point while those flags remained set -- particularly
notifyInterruptPending, which can't be handled as long as we're within
a transaction.
To fix the NOTIFY case, also attempt to process signals (except
ProcDiePending) before trying to read.
Also, if we see that ProcDiePending is set before we read, forcibly set the
process latch to ensure that we will handle that signal promptly if no data
is available. I also made it set the process latch on the way out, in case
there is similar logic elsewhere. (It remains true that we won't service
ProcDiePending here unless we need to wait for input.)
The code for handling ProcDiePending during a write needs those changes,
too.
Also be a little more careful about when to reset whereToSendOutput,
and improve related comments.
Back-patch to 9.5 where this code was added. I'm not entirely convinced
that older branches don't have similar issues, but the complaint at hand
is just about the >= 9.5 code.
Jeff Janes and Tom Lane
Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
2018-10-20 03:39:21 +02:00
|
|
|
/* Process notify interrupts, if any */
|
Introduce and use infrastructure for interrupt processing during client reads.
Up to now large swathes of backend code ran inside signal handlers
while reading commands from the client, to allow for speedy reaction to
asynchronous events. Most prominently shared invalidation and NOTIFY
handling. That means that complex code like the starting/stopping of
transactions is run in signal handlers... The required code was
fragile and verbose, and is likely to contain bugs.
That approach also severely limited what could be done while
communicating with the client. As the read might be from within
openssl it wasn't safely possible to trigger an error, e.g. to cancel
a backend in idle-in-transaction state. We did that in some cases,
namely fatal errors, nonetheless.
Now that FE/BE communication in the backend employs non-blocking
sockets and latches to block, we can quite simply interrupt reads from
signal handlers by setting the latch. That allows us to signal an
interrupted read, which is supposed to be retried after returning from
within the ssl library.
As signal handlers now only need to set the latch to guarantee timely
interrupt processing, remove a fair amount of complicated & fragile
code from async.c and sinval.c.
We could now actually start to process some kinds of interrupts, like
sinval ones, more often that before, but that seems better done
separately.
This work will hopefully allow to handle cases like being blocked by
sending data, interrupting idle transactions and similar to be
implemented without too much effort. In addition to allowing getting
rid of ImmediateInterruptOK, that is.
Author: Andres Freund
Reviewed-By: Heikki Linnakangas
2015-02-03 22:25:20 +01:00
|
|
|
if (notifyInterruptPending)
|
Send NOTIFY signals during CommitTransaction.
Formerly, we sent signals for outgoing NOTIFY messages within
ProcessCompletedNotifies, which was also responsible for sending
relevant ones of those messages to our connected client. It therefore
had to run during the main-loop processing that occurs just before
going idle. This arrangement had two big disadvantages:
* Now that procedures allow intra-command COMMITs, it would be
useful to send NOTIFYs to other sessions immediately at COMMIT
(though, for reasons of wire-protocol stability, we still shouldn't
forward them to our client until end of command).
* Background processes such as replication workers would not send
NOTIFYs at all, since they never execute the client communication
loop. We've had requests to allow triggers running in replication
workers to send NOTIFYs, so that's a problem.
To fix these things, move transmission of outgoing NOTIFY signals
into AtCommit_Notify, where it will happen during CommitTransaction.
Also move the possible call of asyncQueueAdvanceTail there, to
ensure we don't bloat the async SLRU if a background worker sends
many NOTIFYs with no one listening.
We can also drop the call of asyncQueueReadAllNotifications,
allowing ProcessCompletedNotifies to go away entirely. That's
because commit 790026972 added a call of ProcessNotifyInterrupt
adjacent to PostgresMain's call of ProcessCompletedNotifies,
and that does its own call of asyncQueueReadAllNotifications,
meaning that we were uselessly doing two such calls (inside two
separate transactions) whenever inbound notify signals coincided
with an outbound notify. We need only set notifyInterruptPending
to ensure that ProcessNotifyInterrupt runs, and we're done.
The existing documentation suggests that custom background workers
should call ProcessCompletedNotifies if they want to send NOTIFY
messages. To avoid an ABI break in the back branches, reduce it
to an empty routine rather than removing it entirely. Removal
will occur in v15.
Although the problems mentioned above have existed for awhile,
I don't feel comfortable back-patching this any further than v13.
There was quite a bit of churn in adjacent code between 12 and 13.
At minimum we'd have to also backpatch 51004c717, and a good deal
of other adjustment would also be needed, so the benefit-to-risk
ratio doesn't look attractive.
Per bug #15293 from Michael Powers (and similar gripes from others).
Artur Zakirov and Tom Lane
Discussion: https://postgr.es/m/153243441449.1404.2274116228506175596@wrigleys.postgresql.org
2021-09-14 23:18:25 +02:00
|
|
|
ProcessNotifyInterrupt(true);
|
2005-06-02 23:03:25 +02:00
|
|
|
}
|
Server-side fix for delayed NOTIFY and SIGTERM processing.
Commit 4f85fde8e introduced some code that was meant to ensure that we'd
process cancel, die, sinval catchup, and notify interrupts while waiting
for client input. But there was a flaw: it supposed that the process
latch would be set upon arrival at secure_read() if any such interrupt
was pending. In reality, we might well have cleared the process latch
at some earlier point while those flags remained set -- particularly
notifyInterruptPending, which can't be handled as long as we're within
a transaction.
To fix the NOTIFY case, also attempt to process signals (except
ProcDiePending) before trying to read.
Also, if we see that ProcDiePending is set before we read, forcibly set the
process latch to ensure that we will handle that signal promptly if no data
is available. I also made it set the process latch on the way out, in case
there is similar logic elsewhere. (It remains true that we won't service
ProcDiePending here unless we need to wait for input.)
The code for handling ProcDiePending during a write needs those changes,
too.
Also be a little more careful about when to reset whereToSendOutput,
and improve related comments.
Back-patch to 9.5 where this code was added. I'm not entirely convinced
that older branches don't have similar issues, but the complaint at hand
is just about the >= 9.5 code.
Jeff Janes and Tom Lane
Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
2018-10-20 03:39:21 +02:00
|
|
|
else if (ProcDiePending)
|
2015-02-03 22:45:45 +01:00
|
|
|
{
|
|
|
|
/*
|
Server-side fix for delayed NOTIFY and SIGTERM processing.
Commit 4f85fde8e introduced some code that was meant to ensure that we'd
process cancel, die, sinval catchup, and notify interrupts while waiting
for client input. But there was a flaw: it supposed that the process
latch would be set upon arrival at secure_read() if any such interrupt
was pending. In reality, we might well have cleared the process latch
at some earlier point while those flags remained set -- particularly
notifyInterruptPending, which can't be handled as long as we're within
a transaction.
To fix the NOTIFY case, also attempt to process signals (except
ProcDiePending) before trying to read.
Also, if we see that ProcDiePending is set before we read, forcibly set the
process latch to ensure that we will handle that signal promptly if no data
is available. I also made it set the process latch on the way out, in case
there is similar logic elsewhere. (It remains true that we won't service
ProcDiePending here unless we need to wait for input.)
The code for handling ProcDiePending during a write needs those changes,
too.
Also be a little more careful about when to reset whereToSendOutput,
and improve related comments.
Back-patch to 9.5 where this code was added. I'm not entirely convinced
that older branches don't have similar issues, but the complaint at hand
is just about the >= 9.5 code.
Jeff Janes and Tom Lane
Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
2018-10-20 03:39:21 +02:00
|
|
|
* We're dying. If there is no data available to read, then it's safe
|
|
|
|
* (and sane) to handle that now. If we haven't tried to read yet,
|
|
|
|
* make sure the process latch is set, so that if there is no data
|
|
|
|
* then we'll come back here and die. If we're done reading, also
|
|
|
|
* make sure the process latch is set, as we might've undesirably
|
|
|
|
* cleared it while reading.
|
2015-02-03 22:45:45 +01:00
|
|
|
*/
|
Server-side fix for delayed NOTIFY and SIGTERM processing.
Commit 4f85fde8e introduced some code that was meant to ensure that we'd
process cancel, die, sinval catchup, and notify interrupts while waiting
for client input. But there was a flaw: it supposed that the process
latch would be set upon arrival at secure_read() if any such interrupt
was pending. In reality, we might well have cleared the process latch
at some earlier point while those flags remained set -- particularly
notifyInterruptPending, which can't be handled as long as we're within
a transaction.
To fix the NOTIFY case, also attempt to process signals (except
ProcDiePending) before trying to read.
Also, if we see that ProcDiePending is set before we read, forcibly set the
process latch to ensure that we will handle that signal promptly if no data
is available. I also made it set the process latch on the way out, in case
there is similar logic elsewhere. (It remains true that we won't service
ProcDiePending here unless we need to wait for input.)
The code for handling ProcDiePending during a write needs those changes,
too.
Also be a little more careful about when to reset whereToSendOutput,
and improve related comments.
Back-patch to 9.5 where this code was added. I'm not entirely convinced
that older branches don't have similar issues, but the complaint at hand
is just about the >= 9.5 code.
Jeff Janes and Tom Lane
Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
2018-10-20 03:39:21 +02:00
|
|
|
if (blocked)
|
|
|
|
CHECK_FOR_INTERRUPTS();
|
|
|
|
else
|
|
|
|
SetLatch(MyLatch);
|
2015-02-03 22:45:45 +01:00
|
|
|
}
|
Introduce and use infrastructure for interrupt processing during client reads.
Up to now large swathes of backend code ran inside signal handlers
while reading commands from the client, to allow for speedy reaction to
asynchronous events. Most prominently shared invalidation and NOTIFY
handling. That means that complex code like the starting/stopping of
transactions is run in signal handlers... The required code was
fragile and verbose, and is likely to contain bugs.
That approach also severely limited what could be done while
communicating with the client. As the read might be from within
openssl it wasn't safely possible to trigger an error, e.g. to cancel
a backend in idle-in-transaction state. We did that in some cases,
namely fatal errors, nonetheless.
Now that FE/BE communication in the backend employs non-blocking
sockets and latches to block, we can quite simply interrupt reads from
signal handlers by setting the latch. That allows us to signal an
interrupted read, which is supposed to be retried after returning from
within the ssl library.
As signal handlers now only need to set the latch to guarantee timely
interrupt processing, remove a fair amount of complicated & fragile
code from async.c and sinval.c.
We could now actually start to process some kinds of interrupts, like
sinval ones, more often that before, but that seems better done
separately.
This work will hopefully allow to handle cases like being blocked by
sending data, interrupting idle transactions and similar to be
implemented without too much effort. In addition to allowing getting
rid of ImmediateInterruptOK, that is.
Author: Andres Freund
Reviewed-By: Heikki Linnakangas
2015-02-03 22:25:20 +01:00
|
|
|
|
|
|
|
errno = save_errno;
|
2005-06-02 23:03:25 +02:00
|
|
|
}
|
|
|
|
|
2015-02-03 22:45:45 +01:00
|
|
|
/*
|
|
|
|
* ProcessClientWriteInterrupt() - Process interrupts specific to client writes
|
|
|
|
*
|
Server-side fix for delayed NOTIFY and SIGTERM processing.
Commit 4f85fde8e introduced some code that was meant to ensure that we'd
process cancel, die, sinval catchup, and notify interrupts while waiting
for client input. But there was a flaw: it supposed that the process
latch would be set upon arrival at secure_read() if any such interrupt
was pending. In reality, we might well have cleared the process latch
at some earlier point while those flags remained set -- particularly
notifyInterruptPending, which can't be handled as long as we're within
a transaction.
To fix the NOTIFY case, also attempt to process signals (except
ProcDiePending) before trying to read.
Also, if we see that ProcDiePending is set before we read, forcibly set the
process latch to ensure that we will handle that signal promptly if no data
is available. I also made it set the process latch on the way out, in case
there is similar logic elsewhere. (It remains true that we won't service
ProcDiePending here unless we need to wait for input.)
The code for handling ProcDiePending during a write needs those changes,
too.
Also be a little more careful about when to reset whereToSendOutput,
and improve related comments.
Back-patch to 9.5 where this code was added. I'm not entirely convinced
that older branches don't have similar issues, but the complaint at hand
is just about the >= 9.5 code.
Jeff Janes and Tom Lane
Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
2018-10-20 03:39:21 +02:00
|
|
|
* This is called just before and after low-level writes.
|
|
|
|
* 'blocked' is true if no data could be written and we plan to retry,
|
|
|
|
* false if about to write or done writing.
|
2015-02-03 22:45:45 +01:00
|
|
|
*
|
|
|
|
* Must preserve errno!
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ProcessClientWriteInterrupt(bool blocked)
|
|
|
|
{
|
|
|
|
int save_errno = errno;
|
|
|
|
|
Server-side fix for delayed NOTIFY and SIGTERM processing.
Commit 4f85fde8e introduced some code that was meant to ensure that we'd
process cancel, die, sinval catchup, and notify interrupts while waiting
for client input. But there was a flaw: it supposed that the process
latch would be set upon arrival at secure_read() if any such interrupt
was pending. In reality, we might well have cleared the process latch
at some earlier point while those flags remained set -- particularly
notifyInterruptPending, which can't be handled as long as we're within
a transaction.
To fix the NOTIFY case, also attempt to process signals (except
ProcDiePending) before trying to read.
Also, if we see that ProcDiePending is set before we read, forcibly set the
process latch to ensure that we will handle that signal promptly if no data
is available. I also made it set the process latch on the way out, in case
there is similar logic elsewhere. (It remains true that we won't service
ProcDiePending here unless we need to wait for input.)
The code for handling ProcDiePending during a write needs those changes,
too.
Also be a little more careful about when to reset whereToSendOutput,
and improve related comments.
Back-patch to 9.5 where this code was added. I'm not entirely convinced
that older branches don't have similar issues, but the complaint at hand
is just about the >= 9.5 code.
Jeff Janes and Tom Lane
Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
2018-10-20 03:39:21 +02:00
|
|
|
if (ProcDiePending)
|
2015-02-03 22:45:45 +01:00
|
|
|
{
|
|
|
|
/*
|
Server-side fix for delayed NOTIFY and SIGTERM processing.
Commit 4f85fde8e introduced some code that was meant to ensure that we'd
process cancel, die, sinval catchup, and notify interrupts while waiting
for client input. But there was a flaw: it supposed that the process
latch would be set upon arrival at secure_read() if any such interrupt
was pending. In reality, we might well have cleared the process latch
at some earlier point while those flags remained set -- particularly
notifyInterruptPending, which can't be handled as long as we're within
a transaction.
To fix the NOTIFY case, also attempt to process signals (except
ProcDiePending) before trying to read.
Also, if we see that ProcDiePending is set before we read, forcibly set the
process latch to ensure that we will handle that signal promptly if no data
is available. I also made it set the process latch on the way out, in case
there is similar logic elsewhere. (It remains true that we won't service
ProcDiePending here unless we need to wait for input.)
The code for handling ProcDiePending during a write needs those changes,
too.
Also be a little more careful about when to reset whereToSendOutput,
and improve related comments.
Back-patch to 9.5 where this code was added. I'm not entirely convinced
that older branches don't have similar issues, but the complaint at hand
is just about the >= 9.5 code.
Jeff Janes and Tom Lane
Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
2018-10-20 03:39:21 +02:00
|
|
|
* We're dying. If it's not possible to write, then we should handle
|
|
|
|
* that immediately, else a stuck client could indefinitely delay our
|
|
|
|
* response to the signal. If we haven't tried to write yet, make
|
|
|
|
* sure the process latch is set, so that if the write would block
|
|
|
|
* then we'll come back here and die. If we're done writing, also
|
|
|
|
* make sure the process latch is set, as we might've undesirably
|
|
|
|
* cleared it while writing.
|
2015-02-03 22:45:45 +01:00
|
|
|
*/
|
Server-side fix for delayed NOTIFY and SIGTERM processing.
Commit 4f85fde8e introduced some code that was meant to ensure that we'd
process cancel, die, sinval catchup, and notify interrupts while waiting
for client input. But there was a flaw: it supposed that the process
latch would be set upon arrival at secure_read() if any such interrupt
was pending. In reality, we might well have cleared the process latch
at some earlier point while those flags remained set -- particularly
notifyInterruptPending, which can't be handled as long as we're within
a transaction.
To fix the NOTIFY case, also attempt to process signals (except
ProcDiePending) before trying to read.
Also, if we see that ProcDiePending is set before we read, forcibly set the
process latch to ensure that we will handle that signal promptly if no data
is available. I also made it set the process latch on the way out, in case
there is similar logic elsewhere. (It remains true that we won't service
ProcDiePending here unless we need to wait for input.)
The code for handling ProcDiePending during a write needs those changes,
too.
Also be a little more careful about when to reset whereToSendOutput,
and improve related comments.
Back-patch to 9.5 where this code was added. I'm not entirely convinced
that older branches don't have similar issues, but the complaint at hand
is just about the >= 9.5 code.
Jeff Janes and Tom Lane
Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
2018-10-20 03:39:21 +02:00
|
|
|
if (blocked)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Don't mess with whereToSendOutput if ProcessInterrupts wouldn't
|
2021-05-14 18:54:26 +02:00
|
|
|
* service ProcDiePending.
|
Server-side fix for delayed NOTIFY and SIGTERM processing.
Commit 4f85fde8e introduced some code that was meant to ensure that we'd
process cancel, die, sinval catchup, and notify interrupts while waiting
for client input. But there was a flaw: it supposed that the process
latch would be set upon arrival at secure_read() if any such interrupt
was pending. In reality, we might well have cleared the process latch
at some earlier point while those flags remained set -- particularly
notifyInterruptPending, which can't be handled as long as we're within
a transaction.
To fix the NOTIFY case, also attempt to process signals (except
ProcDiePending) before trying to read.
Also, if we see that ProcDiePending is set before we read, forcibly set the
process latch to ensure that we will handle that signal promptly if no data
is available. I also made it set the process latch on the way out, in case
there is similar logic elsewhere. (It remains true that we won't service
ProcDiePending here unless we need to wait for input.)
The code for handling ProcDiePending during a write needs those changes,
too.
Also be a little more careful about when to reset whereToSendOutput,
and improve related comments.
Back-patch to 9.5 where this code was added. I'm not entirely convinced
that older branches don't have similar issues, but the complaint at hand
is just about the >= 9.5 code.
Jeff Janes and Tom Lane
Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
2018-10-20 03:39:21 +02:00
|
|
|
*/
|
|
|
|
if (InterruptHoldoffCount == 0 && CritSectionCount == 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We don't want to send the client the error message, as a)
|
|
|
|
* that would possibly block again, and b) it would likely
|
|
|
|
* lead to loss of protocol sync because we may have already
|
|
|
|
* sent a partial protocol message.
|
|
|
|
*/
|
|
|
|
if (whereToSendOutput == DestRemote)
|
|
|
|
whereToSendOutput = DestNone;
|
2015-02-03 22:45:45 +01:00
|
|
|
|
Server-side fix for delayed NOTIFY and SIGTERM processing.
Commit 4f85fde8e introduced some code that was meant to ensure that we'd
process cancel, die, sinval catchup, and notify interrupts while waiting
for client input. But there was a flaw: it supposed that the process
latch would be set upon arrival at secure_read() if any such interrupt
was pending. In reality, we might well have cleared the process latch
at some earlier point while those flags remained set -- particularly
notifyInterruptPending, which can't be handled as long as we're within
a transaction.
To fix the NOTIFY case, also attempt to process signals (except
ProcDiePending) before trying to read.
Also, if we see that ProcDiePending is set before we read, forcibly set the
process latch to ensure that we will handle that signal promptly if no data
is available. I also made it set the process latch on the way out, in case
there is similar logic elsewhere. (It remains true that we won't service
ProcDiePending here unless we need to wait for input.)
The code for handling ProcDiePending during a write needs those changes,
too.
Also be a little more careful about when to reset whereToSendOutput,
and improve related comments.
Back-patch to 9.5 where this code was added. I'm not entirely convinced
that older branches don't have similar issues, but the complaint at hand
is just about the >= 9.5 code.
Jeff Janes and Tom Lane
Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
2018-10-20 03:39:21 +02:00
|
|
|
CHECK_FOR_INTERRUPTS();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
SetLatch(MyLatch);
|
2015-02-03 22:45:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
errno = save_errno;
|
|
|
|
}
|
2000-04-04 23:44:40 +02:00
|
|
|
|
2000-10-07 02:58:23 +02:00
|
|
|
/*
|
|
|
|
* Do raw parsing (only).
|
|
|
|
*
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
* A list of parsetrees (RawStmt nodes) is returned, since there might be
|
|
|
|
* multiple commands in the given string.
|
2000-10-07 02:58:23 +02:00
|
|
|
*
|
|
|
|
* NOTE: for interactive queries, it is important to keep this routine
|
|
|
|
* separate from the analysis & rewrite stages. Analysis and rewriting
|
|
|
|
* cannot be done in an aborted transaction, since they require access to
|
|
|
|
* database tables. So, we rely on the raw parser to determine whether
|
|
|
|
* we've seen a COMMIT or ABORT command; when we are in abort state, other
|
|
|
|
* commands are not processed any further than the raw parse stage.
|
|
|
|
*/
|
2002-10-15 01:49:20 +02:00
|
|
|
List *
|
2003-04-30 00:13:11 +02:00
|
|
|
pg_parse_query(const char *query_string)
|
2000-10-07 02:58:23 +02:00
|
|
|
{
|
2004-05-26 06:41:50 +02:00
|
|
|
List *raw_parsetree_list;
|
1999-05-10 01:31:47 +02:00
|
|
|
|
2008-08-01 15:16:09 +02:00
|
|
|
TRACE_POSTGRESQL_QUERY_PARSE_START(query_string);
|
|
|
|
|
2002-11-15 01:47:22 +01:00
|
|
|
if (log_parser_stats)
|
2000-10-07 02:58:23 +02:00
|
|
|
ResetUsage();
|
|
|
|
|
2021-01-04 17:03:22 +01:00
|
|
|
raw_parsetree_list = raw_parser(query_string, RAW_PARSE_DEFAULT);
|
2000-10-07 02:58:23 +02:00
|
|
|
|
2005-05-24 06:18:04 +02:00
|
|
|
if (log_parser_stats)
|
|
|
|
ShowUsage("PARSER STATISTICS");
|
|
|
|
|
2007-02-17 20:33:32 +01:00
|
|
|
#ifdef COPY_PARSE_PLAN_TREES
|
|
|
|
/* Optional debugging check: pass raw parsetrees through copyObject() */
|
|
|
|
{
|
2017-03-09 21:18:59 +01:00
|
|
|
List *new_list = copyObject(raw_parsetree_list);
|
2007-02-17 20:33:32 +01:00
|
|
|
|
|
|
|
/* This checks both copyObject() and the equal() routines... */
|
|
|
|
if (!equal(new_list, raw_parsetree_list))
|
|
|
|
elog(WARNING, "copyObject() failed to produce an equal raw parse tree");
|
|
|
|
else
|
|
|
|
raw_parsetree_list = new_list;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
Add a debugging option to stress-test outfuncs.c and readfuncs.c.
In the normal course of operation, query trees will be serialized only if
they are stored as views or rules; and plan trees will be serialized only
if they get passed to parallel-query workers. This leaves an awful lot of
opportunity for bugs/oversights to not get detected, as indeed we've just
been reminded of the hard way.
To improve matters, this patch adds a new compile option
WRITE_READ_PARSE_PLAN_TREES, which is modeled on the longstanding option
COPY_PARSE_PLAN_TREES; but instead of passing all parse and plan trees
through copyObject, it passes them through nodeToString + stringToNode.
Enabling this option in a buildfarm animal or two will catch problems
at least for cases that are exercised by the regression tests.
A small problem with this idea is that readfuncs.c historically has
discarded location fields, on the reasonable grounds that parse
locations in a retrieved view are not relevant to the current query.
But doing that in WRITE_READ_PARSE_PLAN_TREES breaks pg_stat_statements,
and it could cause problems for future improvements that might try to
report error locations at runtime. To fix that, provide a variant
behavior in readfuncs.c that makes it restore location fields when
told to.
In passing, const-ify the string arguments of stringToNode and its
subsidiary functions, just because it annoyed me that they weren't
const already.
Discussion: https://postgr.es/m/17114.1537138992@sss.pgh.pa.us
2018-09-18 23:11:54 +02:00
|
|
|
/*
|
2022-09-26 16:32:16 +02:00
|
|
|
* Optional debugging check: pass raw parsetrees through
|
|
|
|
* outfuncs/readfuncs
|
Add a debugging option to stress-test outfuncs.c and readfuncs.c.
In the normal course of operation, query trees will be serialized only if
they are stored as views or rules; and plan trees will be serialized only
if they get passed to parallel-query workers. This leaves an awful lot of
opportunity for bugs/oversights to not get detected, as indeed we've just
been reminded of the hard way.
To improve matters, this patch adds a new compile option
WRITE_READ_PARSE_PLAN_TREES, which is modeled on the longstanding option
COPY_PARSE_PLAN_TREES; but instead of passing all parse and plan trees
through copyObject, it passes them through nodeToString + stringToNode.
Enabling this option in a buildfarm animal or two will catch problems
at least for cases that are exercised by the regression tests.
A small problem with this idea is that readfuncs.c historically has
discarded location fields, on the reasonable grounds that parse
locations in a retrieved view are not relevant to the current query.
But doing that in WRITE_READ_PARSE_PLAN_TREES breaks pg_stat_statements,
and it could cause problems for future improvements that might try to
report error locations at runtime. To fix that, provide a variant
behavior in readfuncs.c that makes it restore location fields when
told to.
In passing, const-ify the string arguments of stringToNode and its
subsidiary functions, just because it annoyed me that they weren't
const already.
Discussion: https://postgr.es/m/17114.1537138992@sss.pgh.pa.us
2018-09-18 23:11:54 +02:00
|
|
|
*/
|
2022-09-26 16:32:16 +02:00
|
|
|
#ifdef WRITE_READ_PARSE_PLAN_TREES
|
|
|
|
{
|
2024-03-22 09:13:35 +01:00
|
|
|
char *str = nodeToStringWithLocations(raw_parsetree_list);
|
2022-09-26 16:32:16 +02:00
|
|
|
List *new_list = stringToNodeWithLocations(str);
|
|
|
|
|
|
|
|
pfree(str);
|
|
|
|
/* This checks both outfuncs/readfuncs and the equal() routines... */
|
|
|
|
if (!equal(new_list, raw_parsetree_list))
|
|
|
|
elog(WARNING, "outfuncs/readfuncs failed to produce an equal raw parse tree");
|
|
|
|
else
|
|
|
|
raw_parsetree_list = new_list;
|
|
|
|
}
|
|
|
|
#endif
|
Add a debugging option to stress-test outfuncs.c and readfuncs.c.
In the normal course of operation, query trees will be serialized only if
they are stored as views or rules; and plan trees will be serialized only
if they get passed to parallel-query workers. This leaves an awful lot of
opportunity for bugs/oversights to not get detected, as indeed we've just
been reminded of the hard way.
To improve matters, this patch adds a new compile option
WRITE_READ_PARSE_PLAN_TREES, which is modeled on the longstanding option
COPY_PARSE_PLAN_TREES; but instead of passing all parse and plan trees
through copyObject, it passes them through nodeToString + stringToNode.
Enabling this option in a buildfarm animal or two will catch problems
at least for cases that are exercised by the regression tests.
A small problem with this idea is that readfuncs.c historically has
discarded location fields, on the reasonable grounds that parse
locations in a retrieved view are not relevant to the current query.
But doing that in WRITE_READ_PARSE_PLAN_TREES breaks pg_stat_statements,
and it could cause problems for future improvements that might try to
report error locations at runtime. To fix that, provide a variant
behavior in readfuncs.c that makes it restore location fields when
told to.
In passing, const-ify the string arguments of stringToNode and its
subsidiary functions, just because it annoyed me that they weren't
const already.
Discussion: https://postgr.es/m/17114.1537138992@sss.pgh.pa.us
2018-09-18 23:11:54 +02:00
|
|
|
|
2008-08-01 15:16:09 +02:00
|
|
|
TRACE_POSTGRESQL_QUERY_PARSE_DONE(query_string);
|
|
|
|
|
2005-05-24 06:18:04 +02:00
|
|
|
return raw_parsetree_list;
|
|
|
|
}
|
|
|
|
|
2000-10-07 02:58:23 +02:00
|
|
|
/*
|
2003-04-30 00:13:11 +02:00
|
|
|
* Given a raw parsetree (gram.y output), and optionally information about
|
|
|
|
* types of parameter symbols ($n), perform parse analysis and rule rewriting.
|
2000-10-07 02:58:23 +02:00
|
|
|
*
|
|
|
|
* A list of Query nodes is returned, since either the analyzer or the
|
|
|
|
* rewriter might expand one query to several.
|
|
|
|
*
|
|
|
|
* NOTE: for reasons mentioned above, this must be separate from raw parsing.
|
|
|
|
*/
|
2002-10-15 01:49:20 +02:00
|
|
|
List *
|
2022-03-04 14:49:37 +01:00
|
|
|
pg_analyze_and_rewrite_fixedparams(RawStmt *parsetree,
|
|
|
|
const char *query_string,
|
|
|
|
const Oid *paramTypes,
|
|
|
|
int numParams,
|
|
|
|
QueryEnvironment *queryEnv)
|
2000-10-07 02:58:23 +02:00
|
|
|
{
|
2007-06-24 00:12:52 +02:00
|
|
|
Query *query;
|
2000-10-07 02:58:23 +02:00
|
|
|
List *querytree_list;
|
|
|
|
|
2008-08-01 15:16:09 +02:00
|
|
|
TRACE_POSTGRESQL_QUERY_REWRITE_START(query_string);
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2000-10-07 02:58:23 +02:00
|
|
|
* (1) Perform parse analysis.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2002-11-15 01:47:22 +01:00
|
|
|
if (log_parser_stats)
|
1996-11-14 11:25:54 +01:00
|
|
|
ResetUsage();
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2022-03-04 14:49:37 +01:00
|
|
|
query = parse_analyze_fixedparams(parsetree, query_string, paramTypes, numParams,
|
2017-04-01 06:17:18 +02:00
|
|
|
queryEnv);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2002-11-15 01:47:22 +01:00
|
|
|
if (log_parser_stats)
|
2001-11-11 00:51:14 +01:00
|
|
|
ShowUsage("PARSE ANALYSIS STATISTICS");
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2000-10-07 02:58:23 +02:00
|
|
|
* (2) Rewrite the queries, as necessary
|
2003-05-05 02:44:56 +02:00
|
|
|
*/
|
2007-06-24 00:12:52 +02:00
|
|
|
querytree_list = pg_rewrite_query(query);
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2008-08-01 15:16:09 +02:00
|
|
|
TRACE_POSTGRESQL_QUERY_REWRITE_DONE(query_string);
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
return querytree_list;
|
|
|
|
}
|
|
|
|
|
2022-03-04 14:49:37 +01:00
|
|
|
/*
|
|
|
|
* Do parse analysis and rewriting. This is the same as
|
|
|
|
* pg_analyze_and_rewrite_fixedparams except that it's okay to deduce
|
|
|
|
* information about $n symbol datatypes from context.
|
|
|
|
*/
|
|
|
|
List *
|
|
|
|
pg_analyze_and_rewrite_varparams(RawStmt *parsetree,
|
|
|
|
const char *query_string,
|
|
|
|
Oid **paramTypes,
|
|
|
|
int *numParams,
|
|
|
|
QueryEnvironment *queryEnv)
|
|
|
|
{
|
|
|
|
Query *query;
|
|
|
|
List *querytree_list;
|
|
|
|
|
|
|
|
TRACE_POSTGRESQL_QUERY_REWRITE_START(query_string);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* (1) Perform parse analysis.
|
|
|
|
*/
|
|
|
|
if (log_parser_stats)
|
|
|
|
ResetUsage();
|
|
|
|
|
|
|
|
query = parse_analyze_varparams(parsetree, query_string, paramTypes, numParams,
|
|
|
|
queryEnv);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check all parameter types got determined.
|
|
|
|
*/
|
|
|
|
for (int i = 0; i < *numParams; i++)
|
|
|
|
{
|
|
|
|
Oid ptype = (*paramTypes)[i];
|
|
|
|
|
|
|
|
if (ptype == InvalidOid || ptype == UNKNOWNOID)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INDETERMINATE_DATATYPE),
|
|
|
|
errmsg("could not determine data type of parameter $%d",
|
|
|
|
i + 1)));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (log_parser_stats)
|
|
|
|
ShowUsage("PARSE ANALYSIS STATISTICS");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* (2) Rewrite the queries, as necessary
|
|
|
|
*/
|
|
|
|
querytree_list = pg_rewrite_query(query);
|
|
|
|
|
|
|
|
TRACE_POSTGRESQL_QUERY_REWRITE_DONE(query_string);
|
|
|
|
|
|
|
|
return querytree_list;
|
|
|
|
}
|
|
|
|
|
2009-11-04 23:26:08 +01:00
|
|
|
/*
|
2022-03-04 14:49:37 +01:00
|
|
|
* Do parse analysis and rewriting. This is the same as
|
|
|
|
* pg_analyze_and_rewrite_fixedparams except that, instead of a fixed list of
|
|
|
|
* parameter datatypes, a parser callback is supplied that can do
|
|
|
|
* external-parameter resolution and possibly other things.
|
2009-11-04 23:26:08 +01:00
|
|
|
*/
|
|
|
|
List *
|
2022-03-04 14:49:37 +01:00
|
|
|
pg_analyze_and_rewrite_withcb(RawStmt *parsetree,
|
2009-11-04 23:26:08 +01:00
|
|
|
const char *query_string,
|
|
|
|
ParserSetupHook parserSetup,
|
2017-04-01 06:17:18 +02:00
|
|
|
void *parserSetupArg,
|
|
|
|
QueryEnvironment *queryEnv)
|
2009-11-04 23:26:08 +01:00
|
|
|
{
|
|
|
|
Query *query;
|
|
|
|
List *querytree_list;
|
|
|
|
|
|
|
|
TRACE_POSTGRESQL_QUERY_REWRITE_START(query_string);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* (1) Perform parse analysis.
|
|
|
|
*/
|
|
|
|
if (log_parser_stats)
|
|
|
|
ResetUsage();
|
|
|
|
|
2022-03-09 10:56:44 +01:00
|
|
|
query = parse_analyze_withcb(parsetree, query_string, parserSetup, parserSetupArg,
|
|
|
|
queryEnv);
|
Make use of in-core query id added by commit 5fd9dfa5f5
Use the in-core query id computation for pg_stat_activity,
log_line_prefix, and EXPLAIN VERBOSE.
Similar to other fields in pg_stat_activity, only the queryid from the
top level statements are exposed, and if the backends status isn't
active then the queryid from the last executed statements is displayed.
Add a %Q placeholder to include the queryid in log_line_prefix, which
will also only expose top level statements.
For EXPLAIN VERBOSE, if a query identifier has been computed, either by
enabling compute_query_id or using a third-party module, display it.
Bump catalog version.
Discussion: https://postgr.es/m/20210407125726.tkvjdbw76hxnpwfi@nol
Author: Julien Rouhaud
Reviewed-by: Alvaro Herrera, Nitin Jadhav, Zhihong Yu
2021-04-07 20:03:56 +02:00
|
|
|
|
2009-11-04 23:26:08 +01:00
|
|
|
if (log_parser_stats)
|
|
|
|
ShowUsage("PARSE ANALYSIS STATISTICS");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* (2) Rewrite the queries, as necessary
|
|
|
|
*/
|
|
|
|
querytree_list = pg_rewrite_query(query);
|
|
|
|
|
|
|
|
TRACE_POSTGRESQL_QUERY_REWRITE_DONE(query_string);
|
|
|
|
|
|
|
|
return querytree_list;
|
|
|
|
}
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
2007-06-24 00:12:52 +02:00
|
|
|
* Perform rewriting of a query produced by parse analysis.
|
2005-06-04 01:05:30 +02:00
|
|
|
*
|
2007-06-24 00:12:52 +02:00
|
|
|
* Note: query must just have come from the parser, because we do not do
|
|
|
|
* AcquireRewriteLocks() on it.
|
2003-05-05 02:44:56 +02:00
|
|
|
*/
|
2021-04-07 21:30:08 +02:00
|
|
|
List *
|
2007-06-24 00:12:52 +02:00
|
|
|
pg_rewrite_query(Query *query)
|
2003-05-05 02:44:56 +02:00
|
|
|
{
|
2007-06-24 00:12:52 +02:00
|
|
|
List *querytree_list;
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2007-06-24 00:12:52 +02:00
|
|
|
if (Debug_print_parse)
|
2008-08-19 20:30:04 +02:00
|
|
|
elog_node_display(LOG, "parse tree", query,
|
2007-06-24 00:12:52 +02:00
|
|
|
Debug_pretty_print);
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2008-08-19 20:30:04 +02:00
|
|
|
if (log_parser_stats)
|
|
|
|
ResetUsage();
|
|
|
|
|
2007-06-24 00:12:52 +02:00
|
|
|
if (query->commandType == CMD_UTILITY)
|
|
|
|
{
|
|
|
|
/* don't rewrite utilities, just dump 'em into result list */
|
|
|
|
querytree_list = list_make1(query);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* rewrite regular queries */
|
|
|
|
querytree_list = QueryRewrite(query);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2002-11-15 01:47:22 +01:00
|
|
|
if (log_parser_stats)
|
2001-11-11 00:51:14 +01:00
|
|
|
ShowUsage("REWRITER STATISTICS");
|
2000-10-07 02:58:23 +02:00
|
|
|
|
2000-06-29 09:35:57 +02:00
|
|
|
#ifdef COPY_PARSE_PLAN_TREES
|
Add a debugging option to stress-test outfuncs.c and readfuncs.c.
In the normal course of operation, query trees will be serialized only if
they are stored as views or rules; and plan trees will be serialized only
if they get passed to parallel-query workers. This leaves an awful lot of
opportunity for bugs/oversights to not get detected, as indeed we've just
been reminded of the hard way.
To improve matters, this patch adds a new compile option
WRITE_READ_PARSE_PLAN_TREES, which is modeled on the longstanding option
COPY_PARSE_PLAN_TREES; but instead of passing all parse and plan trees
through copyObject, it passes them through nodeToString + stringToNode.
Enabling this option in a buildfarm animal or two will catch problems
at least for cases that are exercised by the regression tests.
A small problem with this idea is that readfuncs.c historically has
discarded location fields, on the reasonable grounds that parse
locations in a retrieved view are not relevant to the current query.
But doing that in WRITE_READ_PARSE_PLAN_TREES breaks pg_stat_statements,
and it could cause problems for future improvements that might try to
report error locations at runtime. To fix that, provide a variant
behavior in readfuncs.c that makes it restore location fields when
told to.
In passing, const-ify the string arguments of stringToNode and its
subsidiary functions, just because it annoyed me that they weren't
const already.
Discussion: https://postgr.es/m/17114.1537138992@sss.pgh.pa.us
2018-09-18 23:11:54 +02:00
|
|
|
/* Optional debugging check: pass querytree through copyObject() */
|
2007-06-24 00:12:52 +02:00
|
|
|
{
|
|
|
|
List *new_list;
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2017-03-09 21:18:59 +01:00
|
|
|
new_list = copyObject(querytree_list);
|
2007-06-24 00:12:52 +02:00
|
|
|
/* This checks both copyObject() and the equal() routines... */
|
|
|
|
if (!equal(new_list, querytree_list))
|
2022-09-26 16:32:16 +02:00
|
|
|
elog(WARNING, "copyObject() failed to produce an equal rewritten parse tree");
|
2007-06-24 00:12:52 +02:00
|
|
|
else
|
|
|
|
querytree_list = new_list;
|
|
|
|
}
|
2000-06-29 09:35:57 +02:00
|
|
|
#endif
|
|
|
|
|
Add a debugging option to stress-test outfuncs.c and readfuncs.c.
In the normal course of operation, query trees will be serialized only if
they are stored as views or rules; and plan trees will be serialized only
if they get passed to parallel-query workers. This leaves an awful lot of
opportunity for bugs/oversights to not get detected, as indeed we've just
been reminded of the hard way.
To improve matters, this patch adds a new compile option
WRITE_READ_PARSE_PLAN_TREES, which is modeled on the longstanding option
COPY_PARSE_PLAN_TREES; but instead of passing all parse and plan trees
through copyObject, it passes them through nodeToString + stringToNode.
Enabling this option in a buildfarm animal or two will catch problems
at least for cases that are exercised by the regression tests.
A small problem with this idea is that readfuncs.c historically has
discarded location fields, on the reasonable grounds that parse
locations in a retrieved view are not relevant to the current query.
But doing that in WRITE_READ_PARSE_PLAN_TREES breaks pg_stat_statements,
and it could cause problems for future improvements that might try to
report error locations at runtime. To fix that, provide a variant
behavior in readfuncs.c that makes it restore location fields when
told to.
In passing, const-ify the string arguments of stringToNode and its
subsidiary functions, just because it annoyed me that they weren't
const already.
Discussion: https://postgr.es/m/17114.1537138992@sss.pgh.pa.us
2018-09-18 23:11:54 +02:00
|
|
|
#ifdef WRITE_READ_PARSE_PLAN_TREES
|
|
|
|
/* Optional debugging check: pass querytree through outfuncs/readfuncs */
|
|
|
|
{
|
|
|
|
List *new_list = NIL;
|
|
|
|
ListCell *lc;
|
|
|
|
|
|
|
|
foreach(lc, querytree_list)
|
|
|
|
{
|
2022-10-12 06:42:30 +02:00
|
|
|
Query *curr_query = lfirst_node(Query, lc);
|
2024-03-22 09:13:35 +01:00
|
|
|
char *str = nodeToStringWithLocations(curr_query);
|
2022-09-26 16:32:16 +02:00
|
|
|
Query *new_query = stringToNodeWithLocations(str);
|
Add a debugging option to stress-test outfuncs.c and readfuncs.c.
In the normal course of operation, query trees will be serialized only if
they are stored as views or rules; and plan trees will be serialized only
if they get passed to parallel-query workers. This leaves an awful lot of
opportunity for bugs/oversights to not get detected, as indeed we've just
been reminded of the hard way.
To improve matters, this patch adds a new compile option
WRITE_READ_PARSE_PLAN_TREES, which is modeled on the longstanding option
COPY_PARSE_PLAN_TREES; but instead of passing all parse and plan trees
through copyObject, it passes them through nodeToString + stringToNode.
Enabling this option in a buildfarm animal or two will catch problems
at least for cases that are exercised by the regression tests.
A small problem with this idea is that readfuncs.c historically has
discarded location fields, on the reasonable grounds that parse
locations in a retrieved view are not relevant to the current query.
But doing that in WRITE_READ_PARSE_PLAN_TREES breaks pg_stat_statements,
and it could cause problems for future improvements that might try to
report error locations at runtime. To fix that, provide a variant
behavior in readfuncs.c that makes it restore location fields when
told to.
In passing, const-ify the string arguments of stringToNode and its
subsidiary functions, just because it annoyed me that they weren't
const already.
Discussion: https://postgr.es/m/17114.1537138992@sss.pgh.pa.us
2018-09-18 23:11:54 +02:00
|
|
|
|
2022-09-26 16:32:16 +02:00
|
|
|
/*
|
|
|
|
* queryId is not saved in stored rules, but we must preserve it
|
|
|
|
* here to avoid breaking pg_stat_statements.
|
|
|
|
*/
|
2022-10-12 06:42:30 +02:00
|
|
|
new_query->queryId = curr_query->queryId;
|
Add a debugging option to stress-test outfuncs.c and readfuncs.c.
In the normal course of operation, query trees will be serialized only if
they are stored as views or rules; and plan trees will be serialized only
if they get passed to parallel-query workers. This leaves an awful lot of
opportunity for bugs/oversights to not get detected, as indeed we've just
been reminded of the hard way.
To improve matters, this patch adds a new compile option
WRITE_READ_PARSE_PLAN_TREES, which is modeled on the longstanding option
COPY_PARSE_PLAN_TREES; but instead of passing all parse and plan trees
through copyObject, it passes them through nodeToString + stringToNode.
Enabling this option in a buildfarm animal or two will catch problems
at least for cases that are exercised by the regression tests.
A small problem with this idea is that readfuncs.c historically has
discarded location fields, on the reasonable grounds that parse
locations in a retrieved view are not relevant to the current query.
But doing that in WRITE_READ_PARSE_PLAN_TREES breaks pg_stat_statements,
and it could cause problems for future improvements that might try to
report error locations at runtime. To fix that, provide a variant
behavior in readfuncs.c that makes it restore location fields when
told to.
In passing, const-ify the string arguments of stringToNode and its
subsidiary functions, just because it annoyed me that they weren't
const already.
Discussion: https://postgr.es/m/17114.1537138992@sss.pgh.pa.us
2018-09-18 23:11:54 +02:00
|
|
|
|
2022-09-26 16:32:16 +02:00
|
|
|
new_list = lappend(new_list, new_query);
|
|
|
|
pfree(str);
|
Add a debugging option to stress-test outfuncs.c and readfuncs.c.
In the normal course of operation, query trees will be serialized only if
they are stored as views or rules; and plan trees will be serialized only
if they get passed to parallel-query workers. This leaves an awful lot of
opportunity for bugs/oversights to not get detected, as indeed we've just
been reminded of the hard way.
To improve matters, this patch adds a new compile option
WRITE_READ_PARSE_PLAN_TREES, which is modeled on the longstanding option
COPY_PARSE_PLAN_TREES; but instead of passing all parse and plan trees
through copyObject, it passes them through nodeToString + stringToNode.
Enabling this option in a buildfarm animal or two will catch problems
at least for cases that are exercised by the regression tests.
A small problem with this idea is that readfuncs.c historically has
discarded location fields, on the reasonable grounds that parse
locations in a retrieved view are not relevant to the current query.
But doing that in WRITE_READ_PARSE_PLAN_TREES breaks pg_stat_statements,
and it could cause problems for future improvements that might try to
report error locations at runtime. To fix that, provide a variant
behavior in readfuncs.c that makes it restore location fields when
told to.
In passing, const-ify the string arguments of stringToNode and its
subsidiary functions, just because it annoyed me that they weren't
const already.
Discussion: https://postgr.es/m/17114.1537138992@sss.pgh.pa.us
2018-09-18 23:11:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This checks both outfuncs/readfuncs and the equal() routines... */
|
|
|
|
if (!equal(new_list, querytree_list))
|
2022-09-26 16:32:16 +02:00
|
|
|
elog(WARNING, "outfuncs/readfuncs failed to produce an equal rewritten parse tree");
|
Add a debugging option to stress-test outfuncs.c and readfuncs.c.
In the normal course of operation, query trees will be serialized only if
they are stored as views or rules; and plan trees will be serialized only
if they get passed to parallel-query workers. This leaves an awful lot of
opportunity for bugs/oversights to not get detected, as indeed we've just
been reminded of the hard way.
To improve matters, this patch adds a new compile option
WRITE_READ_PARSE_PLAN_TREES, which is modeled on the longstanding option
COPY_PARSE_PLAN_TREES; but instead of passing all parse and plan trees
through copyObject, it passes them through nodeToString + stringToNode.
Enabling this option in a buildfarm animal or two will catch problems
at least for cases that are exercised by the regression tests.
A small problem with this idea is that readfuncs.c historically has
discarded location fields, on the reasonable grounds that parse
locations in a retrieved view are not relevant to the current query.
But doing that in WRITE_READ_PARSE_PLAN_TREES breaks pg_stat_statements,
and it could cause problems for future improvements that might try to
report error locations at runtime. To fix that, provide a variant
behavior in readfuncs.c that makes it restore location fields when
told to.
In passing, const-ify the string arguments of stringToNode and its
subsidiary functions, just because it annoyed me that they weren't
const already.
Discussion: https://postgr.es/m/17114.1537138992@sss.pgh.pa.us
2018-09-18 23:11:54 +02:00
|
|
|
else
|
|
|
|
querytree_list = new_list;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2000-05-31 02:28:42 +02:00
|
|
|
if (Debug_print_rewritten)
|
2008-08-19 20:30:04 +02:00
|
|
|
elog_node_display(LOG, "rewritten parse tree", querytree_list,
|
2002-03-24 05:31:09 +01:00
|
|
|
Debug_pretty_print);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-04-04 23:44:40 +02:00
|
|
|
return querytree_list;
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
|
2007-04-16 03:14:58 +02:00
|
|
|
/*
|
|
|
|
* Generate a plan for a single already-rewritten query.
|
|
|
|
* This is a thin wrapper around planner() and takes the same parameters.
|
|
|
|
*/
|
2007-02-20 18:32:18 +01:00
|
|
|
PlannedStmt *
|
2020-03-30 06:51:05 +02:00
|
|
|
pg_plan_query(Query *querytree, const char *query_string, int cursorOptions,
|
|
|
|
ParamListInfo boundParams)
|
2000-04-04 23:44:40 +02:00
|
|
|
{
|
2007-02-20 18:32:18 +01:00
|
|
|
PlannedStmt *plan;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-04-04 23:44:40 +02:00
|
|
|
/* Utility commands have no plans. */
|
|
|
|
if (querytree->commandType == CMD_UTILITY)
|
|
|
|
return NULL;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2008-12-13 03:00:20 +01:00
|
|
|
/* Planner must have a snapshot in case it calls user-defined functions. */
|
|
|
|
Assert(ActiveSnapshotSet());
|
|
|
|
|
2008-08-01 15:16:09 +02:00
|
|
|
TRACE_POSTGRESQL_QUERY_PLAN_START();
|
|
|
|
|
2002-11-15 01:47:22 +01:00
|
|
|
if (log_planner_stats)
|
2000-04-04 23:44:40 +02:00
|
|
|
ResetUsage();
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2002-09-20 05:45:08 +02:00
|
|
|
/* call the optimizer */
|
2020-03-30 06:51:05 +02:00
|
|
|
plan = planner(querytree, query_string, cursorOptions, boundParams);
|
1997-12-11 18:36:58 +01:00
|
|
|
|
2002-11-15 01:47:22 +01:00
|
|
|
if (log_planner_stats)
|
2001-11-11 00:51:14 +01:00
|
|
|
ShowUsage("PLANNER STATISTICS");
|
1997-12-11 18:36:58 +01:00
|
|
|
|
2000-06-29 09:35:57 +02:00
|
|
|
#ifdef COPY_PARSE_PLAN_TREES
|
Add a debugging option to stress-test outfuncs.c and readfuncs.c.
In the normal course of operation, query trees will be serialized only if
they are stored as views or rules; and plan trees will be serialized only
if they get passed to parallel-query workers. This leaves an awful lot of
opportunity for bugs/oversights to not get detected, as indeed we've just
been reminded of the hard way.
To improve matters, this patch adds a new compile option
WRITE_READ_PARSE_PLAN_TREES, which is modeled on the longstanding option
COPY_PARSE_PLAN_TREES; but instead of passing all parse and plan trees
through copyObject, it passes them through nodeToString + stringToNode.
Enabling this option in a buildfarm animal or two will catch problems
at least for cases that are exercised by the regression tests.
A small problem with this idea is that readfuncs.c historically has
discarded location fields, on the reasonable grounds that parse
locations in a retrieved view are not relevant to the current query.
But doing that in WRITE_READ_PARSE_PLAN_TREES breaks pg_stat_statements,
and it could cause problems for future improvements that might try to
report error locations at runtime. To fix that, provide a variant
behavior in readfuncs.c that makes it restore location fields when
told to.
In passing, const-ify the string arguments of stringToNode and its
subsidiary functions, just because it annoyed me that they weren't
const already.
Discussion: https://postgr.es/m/17114.1537138992@sss.pgh.pa.us
2018-09-18 23:11:54 +02:00
|
|
|
/* Optional debugging check: pass plan tree through copyObject() */
|
2000-06-29 09:35:57 +02:00
|
|
|
{
|
2017-03-09 21:18:59 +01:00
|
|
|
PlannedStmt *new_plan = copyObject(plan);
|
2000-06-29 09:35:57 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* equal() currently does not have routines to compare Plan nodes, so
|
|
|
|
* don't try to test equality here. Perhaps fix someday?
|
|
|
|
*/
|
|
|
|
#ifdef NOT_USED
|
|
|
|
/* This checks both copyObject() and the equal() routines... */
|
|
|
|
if (!equal(new_plan, plan))
|
2003-10-02 08:34:04 +02:00
|
|
|
elog(WARNING, "copyObject() failed to produce an equal plan tree");
|
2000-06-29 09:35:57 +02:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
plan = new_plan;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
Add a debugging option to stress-test outfuncs.c and readfuncs.c.
In the normal course of operation, query trees will be serialized only if
they are stored as views or rules; and plan trees will be serialized only
if they get passed to parallel-query workers. This leaves an awful lot of
opportunity for bugs/oversights to not get detected, as indeed we've just
been reminded of the hard way.
To improve matters, this patch adds a new compile option
WRITE_READ_PARSE_PLAN_TREES, which is modeled on the longstanding option
COPY_PARSE_PLAN_TREES; but instead of passing all parse and plan trees
through copyObject, it passes them through nodeToString + stringToNode.
Enabling this option in a buildfarm animal or two will catch problems
at least for cases that are exercised by the regression tests.
A small problem with this idea is that readfuncs.c historically has
discarded location fields, on the reasonable grounds that parse
locations in a retrieved view are not relevant to the current query.
But doing that in WRITE_READ_PARSE_PLAN_TREES breaks pg_stat_statements,
and it could cause problems for future improvements that might try to
report error locations at runtime. To fix that, provide a variant
behavior in readfuncs.c that makes it restore location fields when
told to.
In passing, const-ify the string arguments of stringToNode and its
subsidiary functions, just because it annoyed me that they weren't
const already.
Discussion: https://postgr.es/m/17114.1537138992@sss.pgh.pa.us
2018-09-18 23:11:54 +02:00
|
|
|
#ifdef WRITE_READ_PARSE_PLAN_TREES
|
|
|
|
/* Optional debugging check: pass plan tree through outfuncs/readfuncs */
|
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
PlannedStmt *new_plan;
|
|
|
|
|
2024-03-22 09:13:35 +01:00
|
|
|
str = nodeToStringWithLocations(plan);
|
Add a debugging option to stress-test outfuncs.c and readfuncs.c.
In the normal course of operation, query trees will be serialized only if
they are stored as views or rules; and plan trees will be serialized only
if they get passed to parallel-query workers. This leaves an awful lot of
opportunity for bugs/oversights to not get detected, as indeed we've just
been reminded of the hard way.
To improve matters, this patch adds a new compile option
WRITE_READ_PARSE_PLAN_TREES, which is modeled on the longstanding option
COPY_PARSE_PLAN_TREES; but instead of passing all parse and plan trees
through copyObject, it passes them through nodeToString + stringToNode.
Enabling this option in a buildfarm animal or two will catch problems
at least for cases that are exercised by the regression tests.
A small problem with this idea is that readfuncs.c historically has
discarded location fields, on the reasonable grounds that parse
locations in a retrieved view are not relevant to the current query.
But doing that in WRITE_READ_PARSE_PLAN_TREES breaks pg_stat_statements,
and it could cause problems for future improvements that might try to
report error locations at runtime. To fix that, provide a variant
behavior in readfuncs.c that makes it restore location fields when
told to.
In passing, const-ify the string arguments of stringToNode and its
subsidiary functions, just because it annoyed me that they weren't
const already.
Discussion: https://postgr.es/m/17114.1537138992@sss.pgh.pa.us
2018-09-18 23:11:54 +02:00
|
|
|
new_plan = stringToNodeWithLocations(str);
|
|
|
|
pfree(str);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* equal() currently does not have routines to compare Plan nodes, so
|
|
|
|
* don't try to test equality here. Perhaps fix someday?
|
|
|
|
*/
|
|
|
|
#ifdef NOT_USED
|
|
|
|
/* This checks both outfuncs/readfuncs and the equal() routines... */
|
|
|
|
if (!equal(new_plan, plan))
|
|
|
|
elog(WARNING, "outfuncs/readfuncs failed to produce an equal plan tree");
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
plan = new_plan;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2000-04-04 23:44:40 +02:00
|
|
|
/*
|
|
|
|
* Print plan if debugging.
|
|
|
|
*/
|
2000-05-31 02:28:42 +02:00
|
|
|
if (Debug_print_plan)
|
2008-08-19 20:30:04 +02:00
|
|
|
elog_node_display(LOG, "plan", plan, Debug_pretty_print);
|
1998-08-24 03:38:11 +02:00
|
|
|
|
2008-08-01 15:16:09 +02:00
|
|
|
TRACE_POSTGRESQL_QUERY_PLAN_DONE();
|
|
|
|
|
2000-04-04 23:44:40 +02:00
|
|
|
return plan;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2003-05-02 22:54:36 +02:00
|
|
|
/*
|
|
|
|
* Generate plans for a list of already-rewritten queries.
|
2000-06-28 05:33:33 +02:00
|
|
|
*
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
* For normal optimizable statements, invoke the planner. For utility
|
|
|
|
* statements, just make a wrapper PlannedStmt node.
|
|
|
|
*
|
|
|
|
* The result is a list of PlannedStmt nodes.
|
2003-05-02 22:54:36 +02:00
|
|
|
*/
|
|
|
|
List *
|
2020-03-30 06:51:05 +02:00
|
|
|
pg_plan_queries(List *querytrees, const char *query_string, int cursorOptions,
|
|
|
|
ParamListInfo boundParams)
|
2003-05-02 22:54:36 +02:00
|
|
|
{
|
2008-05-12 22:02:02 +02:00
|
|
|
List *stmt_list = NIL;
|
|
|
|
ListCell *query_list;
|
2003-05-02 22:54:36 +02:00
|
|
|
|
2008-05-12 22:02:02 +02:00
|
|
|
foreach(query_list, querytrees)
|
2003-05-02 22:54:36 +02:00
|
|
|
{
|
Improve castNode notation by introducing list-extraction-specific variants.
This extends the castNode() notation introduced by commit 5bcab1114 to
provide, in one step, extraction of a list cell's pointer and coercion to
a concrete node type. For example, "lfirst_node(Foo, lc)" is the same
as "castNode(Foo, lfirst(lc))". Almost half of the uses of castNode
that have appeared so far include a list extraction call, so this is
pretty widely useful, and it saves a few more keystrokes compared to the
old way.
As with the previous patch, back-patch the addition of these macros to
pg_list.h, so that the notation will be available when back-patching.
Patch by me, after an idea of Andrew Gierth's.
Discussion: https://postgr.es/m/14197.1491841216@sss.pgh.pa.us
2017-04-10 19:51:29 +02:00
|
|
|
Query *query = lfirst_node(Query, query_list);
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
PlannedStmt *stmt;
|
2003-05-02 22:54:36 +02:00
|
|
|
|
2008-05-12 22:02:02 +02:00
|
|
|
if (query->commandType == CMD_UTILITY)
|
2003-05-02 22:54:36 +02:00
|
|
|
{
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
/* Utility commands require no planning. */
|
|
|
|
stmt = makeNode(PlannedStmt);
|
|
|
|
stmt->commandType = CMD_UTILITY;
|
|
|
|
stmt->canSetTag = query->canSetTag;
|
|
|
|
stmt->utilityStmt = query->utilityStmt;
|
|
|
|
stmt->stmt_location = query->stmt_location;
|
|
|
|
stmt->stmt_len = query->stmt_len;
|
Make use of in-core query id added by commit 5fd9dfa5f5
Use the in-core query id computation for pg_stat_activity,
log_line_prefix, and EXPLAIN VERBOSE.
Similar to other fields in pg_stat_activity, only the queryid from the
top level statements are exposed, and if the backends status isn't
active then the queryid from the last executed statements is displayed.
Add a %Q placeholder to include the queryid in log_line_prefix, which
will also only expose top level statements.
For EXPLAIN VERBOSE, if a query identifier has been computed, either by
enabling compute_query_id or using a third-party module, display it.
Bump catalog version.
Discussion: https://postgr.es/m/20210407125726.tkvjdbw76hxnpwfi@nol
Author: Julien Rouhaud
Reviewed-by: Alvaro Herrera, Nitin Jadhav, Zhihong Yu
2021-04-07 20:03:56 +02:00
|
|
|
stmt->queryId = query->queryId;
|
2008-05-12 22:02:02 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-30 06:51:05 +02:00
|
|
|
stmt = pg_plan_query(query, query_string, cursorOptions,
|
|
|
|
boundParams);
|
2003-05-02 22:54:36 +02:00
|
|
|
}
|
|
|
|
|
2008-05-12 22:02:02 +02:00
|
|
|
stmt_list = lappend(stmt_list, stmt);
|
2008-03-13 00:58:27 +01:00
|
|
|
}
|
2008-05-12 22:02:02 +02:00
|
|
|
|
2007-02-20 18:32:18 +01:00
|
|
|
return stmt_list;
|
2003-05-02 22:54:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2003-05-05 02:44:56 +02:00
|
|
|
* exec_simple_query
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2003-05-02 22:54:36 +02:00
|
|
|
* Execute a "simple Query" protocol message.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2003-04-30 00:13:11 +02:00
|
|
|
static void
|
2003-05-05 02:44:56 +02:00
|
|
|
exec_simple_query(const char *query_string)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2003-05-06 22:26:28 +02:00
|
|
|
CommandDest dest = whereToSendOutput;
|
2000-06-28 05:33:33 +02:00
|
|
|
MemoryContext oldcontext;
|
2004-05-26 06:41:50 +02:00
|
|
|
List *parsetree_list;
|
|
|
|
ListCell *parsetree_item;
|
2003-05-02 22:54:36 +02:00
|
|
|
bool save_log_statement_stats = log_statement_stats;
|
2005-05-24 06:18:04 +02:00
|
|
|
bool was_logged = false;
|
Fix handling of savepoint commands within multi-statement Query strings.
Issuing a savepoint-related command in a Query message that contains
multiple SQL statements led to a FATAL exit with a complaint about
"unexpected state STARTED". This is a shortcoming of commit 4f896dac1,
which attempted to prevent such misbehaviors in multi-statement strings;
its quick hack of marking the individual statements as "not top-level"
does the wrong thing in this case, and isn't a very accurate description
of the situation anyway.
To fix, let's introduce into xact.c an explicit model of what happens for
multi-statement Query strings. This is an "implicit transaction block
in progress" state, which for many purposes works like the normal
TBLOCK_INPROGRESS state --- in particular, IsTransactionBlock returns true,
causing the desired result that PreventTransactionChain will throw error.
But in case of error abort it works like TBLOCK_STARTED, allowing the
transaction to be cancelled without need for an explicit ROLLBACK command.
Commit 4f896dac1 is reverted in toto, so that we go back to treating the
individual statements as "top level". We could have left it as-is, but
this allows sharpening the error message for PreventTransactionChain
calls inside functions.
Except for getting a normal error instead of a FATAL exit for savepoint
commands, this patch should result in no user-visible behavioral change
(other than that one error message rewording). There are some things
we might want to do in the line of changing the appearance or wording of
error and warning messages around this behavior, which would be much
simpler to do now that it's an explicitly modeled state. But I haven't
done them here.
Although this fixes a long-standing bug, no backpatch. The consequences
of the bug don't seem severe enough to justify the risk that this commit
itself creates some new issue.
Patch by me, but it owes something to previous investigation by
Takayuki Tsunakawa, who also reported the bug in the first place.
Also thanks to Michael Paquier for reviewing.
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F6BE40D@G01JPEXMBYT05
2017-09-07 15:49:55 +02:00
|
|
|
bool use_implicit_block;
|
2006-09-08 00:52:01 +02:00
|
|
|
char msec_str[32];
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2003-05-02 22:54:36 +02:00
|
|
|
/*
|
|
|
|
* Report query to various monitoring facilities.
|
|
|
|
*/
|
2003-04-27 22:09:44 +02:00
|
|
|
debug_query_string = query_string;
|
2001-04-14 21:11:45 +02:00
|
|
|
|
2012-01-19 14:19:20 +01:00
|
|
|
pgstat_report_activity(STATE_RUNNING, query_string);
|
2003-05-02 22:54:36 +02:00
|
|
|
|
2008-08-01 15:16:09 +02:00
|
|
|
TRACE_POSTGRESQL_QUERY_START(query_string);
|
|
|
|
|
2002-09-02 01:26:06 +02:00
|
|
|
/*
|
2006-06-21 00:52:00 +02:00
|
|
|
* We use save_log_statement_stats so ShowUsage doesn't report incorrect
|
|
|
|
* results because ResetUsage wasn't called.
|
2002-09-02 01:26:06 +02:00
|
|
|
*/
|
2003-05-02 22:54:36 +02:00
|
|
|
if (save_log_statement_stats)
|
|
|
|
ResetUsage();
|
|
|
|
|
2000-07-04 08:11:54 +02:00
|
|
|
/*
|
2000-10-07 02:58:23 +02:00
|
|
|
* Start up a transaction command. All queries generated by the
|
|
|
|
* query_string will be in this same command block, *unless* we find a
|
|
|
|
* BEGIN/COMMIT/ABORT statement; we have to force a new xact command after
|
|
|
|
* one of those, else bad things will happen in xact.c. (Note that this
|
2003-05-02 22:54:36 +02:00
|
|
|
* will normally change current memory context.)
|
2000-10-07 02:58:23 +02:00
|
|
|
*/
|
2006-06-21 00:52:00 +02:00
|
|
|
start_xact_command();
|
2003-05-05 02:44:56 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Zap any pre-existing unnamed statement. (While not strictly necessary,
|
|
|
|
* it seems best to define simple-Query mode as if it used the unnamed
|
|
|
|
* statement and portal; this ensures we recover any storage used by prior
|
|
|
|
* unnamed operations.)
|
|
|
|
*/
|
2007-03-13 01:33:44 +01:00
|
|
|
drop_unnamed_stmt();
|
2000-10-07 02:58:23 +02:00
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
/*
|
|
|
|
* Switch to appropriate context for constructing parsetrees.
|
|
|
|
*/
|
2003-05-02 22:54:36 +02:00
|
|
|
oldcontext = MemoryContextSwitchTo(MessageContext);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-05-13 09:29:22 +02:00
|
|
|
/*
|
2000-10-07 02:58:23 +02:00
|
|
|
* Do basic parsing of the query or queries (this should be safe even if
|
|
|
|
* we are in aborted transaction state!)
|
1999-05-13 09:29:22 +02:00
|
|
|
*/
|
2003-04-30 00:13:11 +02:00
|
|
|
parsetree_list = pg_parse_query(query_string);
|
2000-04-04 23:44:40 +02:00
|
|
|
|
2006-06-21 00:52:00 +02:00
|
|
|
/* Log immediately if dictated by log_statement */
|
2007-02-20 18:32:18 +01:00
|
|
|
if (check_log_statement(parsetree_list))
|
2006-09-08 00:52:01 +02:00
|
|
|
{
|
|
|
|
ereport(LOG,
|
|
|
|
(errmsg("statement: %s", query_string),
|
2007-03-03 00:37:23 +01:00
|
|
|
errhidestmt(true),
|
2006-09-08 00:52:01 +02:00
|
|
|
errdetail_execute(parsetree_list)));
|
|
|
|
was_logged = true;
|
|
|
|
}
|
2005-05-24 06:18:04 +02:00
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
/*
|
2003-05-02 22:54:36 +02:00
|
|
|
* Switch back to transaction context to enter the loop.
|
2000-06-28 05:33:33 +02:00
|
|
|
*/
|
|
|
|
MemoryContextSwitchTo(oldcontext);
|
|
|
|
|
2007-03-22 20:55:04 +01:00
|
|
|
/*
|
Fix handling of savepoint commands within multi-statement Query strings.
Issuing a savepoint-related command in a Query message that contains
multiple SQL statements led to a FATAL exit with a complaint about
"unexpected state STARTED". This is a shortcoming of commit 4f896dac1,
which attempted to prevent such misbehaviors in multi-statement strings;
its quick hack of marking the individual statements as "not top-level"
does the wrong thing in this case, and isn't a very accurate description
of the situation anyway.
To fix, let's introduce into xact.c an explicit model of what happens for
multi-statement Query strings. This is an "implicit transaction block
in progress" state, which for many purposes works like the normal
TBLOCK_INPROGRESS state --- in particular, IsTransactionBlock returns true,
causing the desired result that PreventTransactionChain will throw error.
But in case of error abort it works like TBLOCK_STARTED, allowing the
transaction to be cancelled without need for an explicit ROLLBACK command.
Commit 4f896dac1 is reverted in toto, so that we go back to treating the
individual statements as "top level". We could have left it as-is, but
this allows sharpening the error message for PreventTransactionChain
calls inside functions.
Except for getting a normal error instead of a FATAL exit for savepoint
commands, this patch should result in no user-visible behavioral change
(other than that one error message rewording). There are some things
we might want to do in the line of changing the appearance or wording of
error and warning messages around this behavior, which would be much
simpler to do now that it's an explicitly modeled state. But I haven't
done them here.
Although this fixes a long-standing bug, no backpatch. The consequences
of the bug don't seem severe enough to justify the risk that this commit
itself creates some new issue.
Patch by me, but it owes something to previous investigation by
Takayuki Tsunakawa, who also reported the bug in the first place.
Also thanks to Michael Paquier for reviewing.
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F6BE40D@G01JPEXMBYT05
2017-09-07 15:49:55 +02:00
|
|
|
* For historical reasons, if multiple SQL statements are given in a
|
|
|
|
* single "simple Query" message, we execute them as a single transaction,
|
|
|
|
* unless explicit transaction control commands are included to make
|
|
|
|
* portions of the list be separate transactions. To represent this
|
|
|
|
* behavior properly in the transaction machinery, we use an "implicit"
|
|
|
|
* transaction block.
|
2007-03-22 20:55:04 +01:00
|
|
|
*/
|
Fix handling of savepoint commands within multi-statement Query strings.
Issuing a savepoint-related command in a Query message that contains
multiple SQL statements led to a FATAL exit with a complaint about
"unexpected state STARTED". This is a shortcoming of commit 4f896dac1,
which attempted to prevent such misbehaviors in multi-statement strings;
its quick hack of marking the individual statements as "not top-level"
does the wrong thing in this case, and isn't a very accurate description
of the situation anyway.
To fix, let's introduce into xact.c an explicit model of what happens for
multi-statement Query strings. This is an "implicit transaction block
in progress" state, which for many purposes works like the normal
TBLOCK_INPROGRESS state --- in particular, IsTransactionBlock returns true,
causing the desired result that PreventTransactionChain will throw error.
But in case of error abort it works like TBLOCK_STARTED, allowing the
transaction to be cancelled without need for an explicit ROLLBACK command.
Commit 4f896dac1 is reverted in toto, so that we go back to treating the
individual statements as "top level". We could have left it as-is, but
this allows sharpening the error message for PreventTransactionChain
calls inside functions.
Except for getting a normal error instead of a FATAL exit for savepoint
commands, this patch should result in no user-visible behavioral change
(other than that one error message rewording). There are some things
we might want to do in the line of changing the appearance or wording of
error and warning messages around this behavior, which would be much
simpler to do now that it's an explicitly modeled state. But I haven't
done them here.
Although this fixes a long-standing bug, no backpatch. The consequences
of the bug don't seem severe enough to justify the risk that this commit
itself creates some new issue.
Patch by me, but it owes something to previous investigation by
Takayuki Tsunakawa, who also reported the bug in the first place.
Also thanks to Michael Paquier for reviewing.
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F6BE40D@G01JPEXMBYT05
2017-09-07 15:49:55 +02:00
|
|
|
use_implicit_block = (list_length(parsetree_list) > 1);
|
2007-03-22 20:55:04 +01:00
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
/*
|
2003-05-02 22:54:36 +02:00
|
|
|
* Run through the raw parsetree(s) and process each one.
|
2000-06-28 05:33:33 +02:00
|
|
|
*/
|
2000-10-07 02:58:23 +02:00
|
|
|
foreach(parsetree_item, parsetree_list)
|
2000-06-28 05:33:33 +02:00
|
|
|
{
|
Improve castNode notation by introducing list-extraction-specific variants.
This extends the castNode() notation introduced by commit 5bcab1114 to
provide, in one step, extraction of a list cell's pointer and coercion to
a concrete node type. For example, "lfirst_node(Foo, lc)" is the same
as "castNode(Foo, lfirst(lc))". Almost half of the uses of castNode
that have appeared so far include a list extraction call, so this is
pretty widely useful, and it saves a few more keystrokes compared to the
old way.
As with the previous patch, back-patch the addition of these macros to
pg_list.h, so that the notation will be available when back-patching.
Patch by me, after an idea of Andrew Gierth's.
Discussion: https://postgr.es/m/14197.1491841216@sss.pgh.pa.us
2017-04-10 19:51:29 +02:00
|
|
|
RawStmt *parsetree = lfirst_node(RawStmt, parsetree_item);
|
2008-12-13 03:00:20 +01:00
|
|
|
bool snapshot_set = false;
|
2020-03-02 22:19:51 +01:00
|
|
|
CommandTag commandTag;
|
|
|
|
QueryCompletion qc;
|
Reduce memory consumption for multi-statement query strings.
Previously, exec_simple_query always ran parse analysis, rewrite, and
planning in MessageContext, allowing all the data generated thereby
to persist until the end of processing of the whole query string.
That's fine for single-command strings, but if a client sends many
commands in a single simple-Query message, this strategy could result
in annoying memory bloat, as complained of by Andreas Seltenreich.
To fix, create a child context to do this work in, and reclaim it
after each command. But we only do so for parsetrees that are not
last in their query string. That avoids adding any memory management
overhead for the typical case of a single-command string. Memory
allocated for the last parsetree would be freed immediately after
finishing the command string anyway.
Similarly, adjust extension.c's execute_sql_string() to reclaim memory
after each command. In that usage, multi-command strings are the norm,
so it's a bit surprising that no one has yet complained of bloat ---
especially since the bloat extended to whatever data ProcessUtility
execution might leak.
Amit Langote, reviewed by Julien Rouhaud
Discussion: https://postgr.es/m/87ftp6l2qr.fsf@credativ.de
2019-07-10 20:32:28 +02:00
|
|
|
MemoryContext per_parsetree_context = NULL;
|
2000-10-07 02:58:23 +02:00
|
|
|
List *querytree_list,
|
2003-05-02 22:54:36 +02:00
|
|
|
*plantree_list;
|
|
|
|
Portal portal;
|
2003-05-08 20:16:37 +02:00
|
|
|
DestReceiver *receiver;
|
|
|
|
int16 format;
|
2023-02-20 04:18:27 +01:00
|
|
|
const char *cmdtagname;
|
|
|
|
size_t cmdtaglen;
|
2000-04-04 23:44:40 +02:00
|
|
|
|
2021-04-20 18:22:26 +02:00
|
|
|
pgstat_report_query_id(0, true);
|
Make use of in-core query id added by commit 5fd9dfa5f5
Use the in-core query id computation for pg_stat_activity,
log_line_prefix, and EXPLAIN VERBOSE.
Similar to other fields in pg_stat_activity, only the queryid from the
top level statements are exposed, and if the backends status isn't
active then the queryid from the last executed statements is displayed.
Add a %Q placeholder to include the queryid in log_line_prefix, which
will also only expose top level statements.
For EXPLAIN VERBOSE, if a query identifier has been computed, either by
enabling compute_query_id or using a third-party module, display it.
Bump catalog version.
Discussion: https://postgr.es/m/20210407125726.tkvjdbw76hxnpwfi@nol
Author: Julien Rouhaud
Reviewed-by: Alvaro Herrera, Nitin Jadhav, Zhihong Yu
2021-04-07 20:03:56 +02:00
|
|
|
|
2002-02-27 20:36:13 +01:00
|
|
|
/*
|
2003-05-02 22:54:36 +02:00
|
|
|
* Get the command name for use in status display (it also becomes the
|
|
|
|
* default completion tag, down inside PortalRun). Set ps_status and
|
|
|
|
* do any special start-of-SQL-command processing needed by the
|
|
|
|
* destination.
|
2002-02-27 20:36:13 +01:00
|
|
|
*/
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
commandTag = CreateCommandTag(parsetree->stmt);
|
2023-02-20 04:18:27 +01:00
|
|
|
cmdtagname = GetCommandTagNameAndLen(commandTag, &cmdtaglen);
|
2002-02-27 20:36:13 +01:00
|
|
|
|
2023-02-20 04:18:27 +01:00
|
|
|
set_ps_display_with_len(cmdtagname, cmdtaglen);
|
2002-02-27 20:36:13 +01:00
|
|
|
|
2003-05-06 22:26:28 +02:00
|
|
|
BeginCommand(commandTag, dest);
|
2002-02-27 20:36:13 +01:00
|
|
|
|
2000-10-07 02:58:23 +02:00
|
|
|
/*
|
2003-05-02 22:54:36 +02:00
|
|
|
* If we are in an aborted transaction, reject all commands except
|
2000-10-07 02:58:23 +02:00
|
|
|
* COMMIT/ABORT. It is important that this test occur before we try
|
|
|
|
* to do parse analysis, rewrite, or planning, since all those phases
|
|
|
|
* try to do database accesses, which may fail in abort state. (It
|
|
|
|
* might be safe to allow some additional utility commands in this
|
|
|
|
* state, but not many...)
|
|
|
|
*/
|
2005-11-10 01:31:34 +01:00
|
|
|
if (IsAbortedTransactionBlockState() &&
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
!IsTransactionExitStmt(parsetree->stmt))
|
2005-11-10 01:31:34 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
|
|
|
|
errmsg("current transaction is aborted, "
|
2010-01-16 11:05:59 +01:00
|
|
|
"commands ignored until end of transaction block"),
|
|
|
|
errdetail_abort()));
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-10-07 02:58:23 +02:00
|
|
|
/* Make sure we are in a transaction command */
|
2003-05-05 02:44:56 +02:00
|
|
|
start_xact_command();
|
2000-04-04 23:44:40 +02:00
|
|
|
|
Fix handling of savepoint commands within multi-statement Query strings.
Issuing a savepoint-related command in a Query message that contains
multiple SQL statements led to a FATAL exit with a complaint about
"unexpected state STARTED". This is a shortcoming of commit 4f896dac1,
which attempted to prevent such misbehaviors in multi-statement strings;
its quick hack of marking the individual statements as "not top-level"
does the wrong thing in this case, and isn't a very accurate description
of the situation anyway.
To fix, let's introduce into xact.c an explicit model of what happens for
multi-statement Query strings. This is an "implicit transaction block
in progress" state, which for many purposes works like the normal
TBLOCK_INPROGRESS state --- in particular, IsTransactionBlock returns true,
causing the desired result that PreventTransactionChain will throw error.
But in case of error abort it works like TBLOCK_STARTED, allowing the
transaction to be cancelled without need for an explicit ROLLBACK command.
Commit 4f896dac1 is reverted in toto, so that we go back to treating the
individual statements as "top level". We could have left it as-is, but
this allows sharpening the error message for PreventTransactionChain
calls inside functions.
Except for getting a normal error instead of a FATAL exit for savepoint
commands, this patch should result in no user-visible behavioral change
(other than that one error message rewording). There are some things
we might want to do in the line of changing the appearance or wording of
error and warning messages around this behavior, which would be much
simpler to do now that it's an explicitly modeled state. But I haven't
done them here.
Although this fixes a long-standing bug, no backpatch. The consequences
of the bug don't seem severe enough to justify the risk that this commit
itself creates some new issue.
Patch by me, but it owes something to previous investigation by
Takayuki Tsunakawa, who also reported the bug in the first place.
Also thanks to Michael Paquier for reviewing.
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F6BE40D@G01JPEXMBYT05
2017-09-07 15:49:55 +02:00
|
|
|
/*
|
|
|
|
* If using an implicit transaction block, and we're not already in a
|
|
|
|
* transaction block, start an implicit block to force this statement
|
|
|
|
* to be grouped together with any following ones. (We must do this
|
|
|
|
* each time through the loop; otherwise, a COMMIT/ROLLBACK in the
|
|
|
|
* list would cause later statements to not be grouped.)
|
|
|
|
*/
|
|
|
|
if (use_implicit_block)
|
|
|
|
BeginImplicitTransactionBlock();
|
|
|
|
|
2000-10-07 02:58:23 +02:00
|
|
|
/* If we got a cancel signal in parsing or prior command, quit */
|
2001-01-14 06:08:17 +01:00
|
|
|
CHECK_FOR_INTERRUPTS();
|
2000-10-07 02:58:23 +02:00
|
|
|
|
2008-12-13 03:00:20 +01:00
|
|
|
/*
|
|
|
|
* Set up a snapshot if parse analysis/planning will need one.
|
|
|
|
*/
|
|
|
|
if (analyze_requires_snapshot(parsetree))
|
|
|
|
{
|
|
|
|
PushActiveSnapshot(GetTransactionSnapshot());
|
|
|
|
snapshot_set = true;
|
|
|
|
}
|
|
|
|
|
2000-10-07 02:58:23 +02:00
|
|
|
/*
|
2003-05-02 22:54:36 +02:00
|
|
|
* OK to analyze, rewrite, and plan this query.
|
2002-02-27 20:36:13 +01:00
|
|
|
*
|
Reduce memory consumption for multi-statement query strings.
Previously, exec_simple_query always ran parse analysis, rewrite, and
planning in MessageContext, allowing all the data generated thereby
to persist until the end of processing of the whole query string.
That's fine for single-command strings, but if a client sends many
commands in a single simple-Query message, this strategy could result
in annoying memory bloat, as complained of by Andreas Seltenreich.
To fix, create a child context to do this work in, and reclaim it
after each command. But we only do so for parsetrees that are not
last in their query string. That avoids adding any memory management
overhead for the typical case of a single-command string. Memory
allocated for the last parsetree would be freed immediately after
finishing the command string anyway.
Similarly, adjust extension.c's execute_sql_string() to reclaim memory
after each command. In that usage, multi-command strings are the norm,
so it's a bit surprising that no one has yet complained of bloat ---
especially since the bloat extended to whatever data ProcessUtility
execution might leak.
Amit Langote, reviewed by Julien Rouhaud
Discussion: https://postgr.es/m/87ftp6l2qr.fsf@credativ.de
2019-07-10 20:32:28 +02:00
|
|
|
* Switch to appropriate context for constructing query and plan trees
|
|
|
|
* (these can't be in the transaction context, as that will get reset
|
|
|
|
* when the command is COMMIT/ROLLBACK). If we have multiple
|
|
|
|
* parsetrees, we use a separate context for each one, so that we can
|
|
|
|
* free that memory before moving on to the next one. But for the
|
|
|
|
* last (or only) parsetree, just use MessageContext, which will be
|
|
|
|
* reset shortly after completion anyway. In event of an error, the
|
|
|
|
* per_parsetree_context will be deleted when MessageContext is reset.
|
2000-10-07 02:58:23 +02:00
|
|
|
*/
|
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
|
|
|
if (lnext(parsetree_list, parsetree_item) != NULL)
|
Reduce memory consumption for multi-statement query strings.
Previously, exec_simple_query always ran parse analysis, rewrite, and
planning in MessageContext, allowing all the data generated thereby
to persist until the end of processing of the whole query string.
That's fine for single-command strings, but if a client sends many
commands in a single simple-Query message, this strategy could result
in annoying memory bloat, as complained of by Andreas Seltenreich.
To fix, create a child context to do this work in, and reclaim it
after each command. But we only do so for parsetrees that are not
last in their query string. That avoids adding any memory management
overhead for the typical case of a single-command string. Memory
allocated for the last parsetree would be freed immediately after
finishing the command string anyway.
Similarly, adjust extension.c's execute_sql_string() to reclaim memory
after each command. In that usage, multi-command strings are the norm,
so it's a bit surprising that no one has yet complained of bloat ---
especially since the bloat extended to whatever data ProcessUtility
execution might leak.
Amit Langote, reviewed by Julien Rouhaud
Discussion: https://postgr.es/m/87ftp6l2qr.fsf@credativ.de
2019-07-10 20:32:28 +02:00
|
|
|
{
|
|
|
|
per_parsetree_context =
|
|
|
|
AllocSetContextCreate(MessageContext,
|
|
|
|
"per-parsetree message context",
|
|
|
|
ALLOCSET_DEFAULT_SIZES);
|
|
|
|
oldcontext = MemoryContextSwitchTo(per_parsetree_context);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
oldcontext = MemoryContextSwitchTo(MessageContext);
|
2000-04-04 23:44:40 +02:00
|
|
|
|
2022-03-04 14:49:37 +01:00
|
|
|
querytree_list = pg_analyze_and_rewrite_fixedparams(parsetree, query_string,
|
2017-04-01 06:17:18 +02:00
|
|
|
NULL, 0, NULL);
|
1998-12-16 12:53:55 +01:00
|
|
|
|
2020-03-30 06:51:05 +02:00
|
|
|
plantree_list = pg_plan_queries(querytree_list, query_string,
|
2015-09-16 21:38:47 +02:00
|
|
|
CURSOR_OPT_PARALLEL_OK, NULL);
|
2008-12-13 03:00:20 +01:00
|
|
|
|
2020-02-28 17:13:54 +01:00
|
|
|
/*
|
|
|
|
* Done with the snapshot used for parsing/planning.
|
|
|
|
*
|
|
|
|
* While it looks promising to reuse the same snapshot for query
|
|
|
|
* execution (at least for simple protocol), unfortunately it causes
|
|
|
|
* execution to use a snapshot that has been acquired before locking
|
|
|
|
* any of the tables mentioned in the query. This creates user-
|
|
|
|
* visible anomalies, so refrain. Refer to
|
|
|
|
* https://postgr.es/m/flat/5075D8DF.6050500@fuzzy.cz for details.
|
|
|
|
*/
|
2012-11-26 21:55:43 +01:00
|
|
|
if (snapshot_set)
|
|
|
|
PopActiveSnapshot();
|
|
|
|
|
2003-05-02 22:54:36 +02:00
|
|
|
/* If we got a cancel signal in analysis or planning, quit */
|
|
|
|
CHECK_FOR_INTERRUPTS();
|
|
|
|
|
2000-10-07 02:58:23 +02:00
|
|
|
/*
|
2003-05-02 22:54:36 +02:00
|
|
|
* Create unnamed portal to run the query or queries in. If there
|
|
|
|
* already is one, silently drop it.
|
2000-10-07 02:58:23 +02:00
|
|
|
*/
|
2003-05-02 22:54:36 +02:00
|
|
|
portal = CreatePortal("", true, true);
|
2006-01-18 07:49:30 +01:00
|
|
|
/* Don't display the portal in pg_cursors */
|
|
|
|
portal->visible = false;
|
2000-10-07 02:58:23 +02:00
|
|
|
|
2008-04-02 20:31:50 +02:00
|
|
|
/*
|
|
|
|
* We don't have to copy anything into the portal, because everything
|
Reduce memory consumption for multi-statement query strings.
Previously, exec_simple_query always ran parse analysis, rewrite, and
planning in MessageContext, allowing all the data generated thereby
to persist until the end of processing of the whole query string.
That's fine for single-command strings, but if a client sends many
commands in a single simple-Query message, this strategy could result
in annoying memory bloat, as complained of by Andreas Seltenreich.
To fix, create a child context to do this work in, and reclaim it
after each command. But we only do so for parsetrees that are not
last in their query string. That avoids adding any memory management
overhead for the typical case of a single-command string. Memory
allocated for the last parsetree would be freed immediately after
finishing the command string anyway.
Similarly, adjust extension.c's execute_sql_string() to reclaim memory
after each command. In that usage, multi-command strings are the norm,
so it's a bit surprising that no one has yet complained of bloat ---
especially since the bloat extended to whatever data ProcessUtility
execution might leak.
Amit Langote, reviewed by Julien Rouhaud
Discussion: https://postgr.es/m/87ftp6l2qr.fsf@credativ.de
2019-07-10 20:32:28 +02:00
|
|
|
* we are passing here is in MessageContext or the
|
|
|
|
* per_parsetree_context, and so will outlive the portal anyway.
|
2008-04-02 20:31:50 +02:00
|
|
|
*/
|
2003-05-02 22:54:36 +02:00
|
|
|
PortalDefineQuery(portal,
|
2006-08-08 03:23:15 +02:00
|
|
|
NULL,
|
2003-05-02 22:54:36 +02:00
|
|
|
query_string,
|
|
|
|
commandTag,
|
|
|
|
plantree_list,
|
2007-03-13 01:33:44 +01:00
|
|
|
NULL);
|
2000-10-07 02:58:23 +02:00
|
|
|
|
2003-05-02 22:54:36 +02:00
|
|
|
/*
|
2012-11-26 21:55:43 +01:00
|
|
|
* Start the portal. No parameters here.
|
2003-05-02 22:54:36 +02:00
|
|
|
*/
|
2012-11-26 21:55:43 +01:00
|
|
|
PortalStart(portal, NULL, 0, InvalidSnapshot);
|
2000-10-07 02:58:23 +02:00
|
|
|
|
2003-05-08 20:16:37 +02:00
|
|
|
/*
|
|
|
|
* Select the appropriate output format: text unless we are doing a
|
|
|
|
* FETCH from a binary cursor. (Pretty grotty to have to do this here
|
|
|
|
* --- but it avoids grottiness in other places. Ah, the joys of
|
|
|
|
* backward compatibility...)
|
|
|
|
*/
|
|
|
|
format = 0; /* TEXT is default */
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
if (IsA(parsetree->stmt, FetchStmt))
|
2003-05-08 20:16:37 +02:00
|
|
|
{
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
FetchStmt *stmt = (FetchStmt *) parsetree->stmt;
|
2003-05-08 20:16:37 +02:00
|
|
|
|
|
|
|
if (!stmt->ismove)
|
|
|
|
{
|
|
|
|
Portal fportal = GetPortalByName(stmt->portalname);
|
|
|
|
|
|
|
|
if (PortalIsValid(fportal) &&
|
|
|
|
(fportal->cursorOptions & CURSOR_OPT_BINARY))
|
|
|
|
format = 1; /* BINARY */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PortalSetResultFormat(portal, 1, &format);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now we can create the destination receiver object.
|
|
|
|
*/
|
2008-11-30 21:51:25 +01:00
|
|
|
receiver = CreateDestReceiver(dest);
|
|
|
|
if (dest == DestRemote)
|
|
|
|
SetRemoteDestReceiverParams(receiver, portal);
|
2003-05-08 20:16:37 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Switch back to transaction context for execution.
|
|
|
|
*/
|
|
|
|
MemoryContextSwitchTo(oldcontext);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Run the portal to completion, and then drop it (and the receiver).
|
|
|
|
*/
|
2003-05-05 02:44:56 +02:00
|
|
|
(void) PortalRun(portal,
|
|
|
|
FETCH_ALL,
|
Fix handling of savepoint commands within multi-statement Query strings.
Issuing a savepoint-related command in a Query message that contains
multiple SQL statements led to a FATAL exit with a complaint about
"unexpected state STARTED". This is a shortcoming of commit 4f896dac1,
which attempted to prevent such misbehaviors in multi-statement strings;
its quick hack of marking the individual statements as "not top-level"
does the wrong thing in this case, and isn't a very accurate description
of the situation anyway.
To fix, let's introduce into xact.c an explicit model of what happens for
multi-statement Query strings. This is an "implicit transaction block
in progress" state, which for many purposes works like the normal
TBLOCK_INPROGRESS state --- in particular, IsTransactionBlock returns true,
causing the desired result that PreventTransactionChain will throw error.
But in case of error abort it works like TBLOCK_STARTED, allowing the
transaction to be cancelled without need for an explicit ROLLBACK command.
Commit 4f896dac1 is reverted in toto, so that we go back to treating the
individual statements as "top level". We could have left it as-is, but
this allows sharpening the error message for PreventTransactionChain
calls inside functions.
Except for getting a normal error instead of a FATAL exit for savepoint
commands, this patch should result in no user-visible behavioral change
(other than that one error message rewording). There are some things
we might want to do in the line of changing the appearance or wording of
error and warning messages around this behavior, which would be much
simpler to do now that it's an explicitly modeled state. But I haven't
done them here.
Although this fixes a long-standing bug, no backpatch. The consequences
of the bug don't seem severe enough to justify the risk that this commit
itself creates some new issue.
Patch by me, but it owes something to previous investigation by
Takayuki Tsunakawa, who also reported the bug in the first place.
Also thanks to Michael Paquier for reviewing.
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F6BE40D@G01JPEXMBYT05
2017-09-07 15:49:55 +02:00
|
|
|
true, /* always top level */
|
2017-03-23 18:05:48 +01:00
|
|
|
true,
|
2003-05-06 22:26:28 +02:00
|
|
|
receiver,
|
|
|
|
receiver,
|
2020-03-02 22:19:51 +01:00
|
|
|
&qc);
|
2000-10-07 02:58:23 +02:00
|
|
|
|
2017-09-07 18:06:23 +02:00
|
|
|
receiver->rDestroy(receiver);
|
2003-05-08 20:16:37 +02:00
|
|
|
|
2003-05-02 22:54:36 +02:00
|
|
|
PortalDrop(portal, false);
|
2002-02-26 23:47:12 +01:00
|
|
|
|
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
|
|
|
if (lnext(parsetree_list, parsetree_item) == NULL)
|
2002-02-28 00:16:07 +01:00
|
|
|
{
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* If this is the last parsetree of the query string, close down
|
|
|
|
* transaction statement before reporting command-complete. This
|
|
|
|
* is so that any end-of-transaction errors are reported before
|
|
|
|
* the command-complete message is issued, to avoid confusing
|
|
|
|
* clients who will expect either a command-complete message or an
|
Fix handling of savepoint commands within multi-statement Query strings.
Issuing a savepoint-related command in a Query message that contains
multiple SQL statements led to a FATAL exit with a complaint about
"unexpected state STARTED". This is a shortcoming of commit 4f896dac1,
which attempted to prevent such misbehaviors in multi-statement strings;
its quick hack of marking the individual statements as "not top-level"
does the wrong thing in this case, and isn't a very accurate description
of the situation anyway.
To fix, let's introduce into xact.c an explicit model of what happens for
multi-statement Query strings. This is an "implicit transaction block
in progress" state, which for many purposes works like the normal
TBLOCK_INPROGRESS state --- in particular, IsTransactionBlock returns true,
causing the desired result that PreventTransactionChain will throw error.
But in case of error abort it works like TBLOCK_STARTED, allowing the
transaction to be cancelled without need for an explicit ROLLBACK command.
Commit 4f896dac1 is reverted in toto, so that we go back to treating the
individual statements as "top level". We could have left it as-is, but
this allows sharpening the error message for PreventTransactionChain
calls inside functions.
Except for getting a normal error instead of a FATAL exit for savepoint
commands, this patch should result in no user-visible behavioral change
(other than that one error message rewording). There are some things
we might want to do in the line of changing the appearance or wording of
error and warning messages around this behavior, which would be much
simpler to do now that it's an explicitly modeled state. But I haven't
done them here.
Although this fixes a long-standing bug, no backpatch. The consequences
of the bug don't seem severe enough to justify the risk that this commit
itself creates some new issue.
Patch by me, but it owes something to previous investigation by
Takayuki Tsunakawa, who also reported the bug in the first place.
Also thanks to Michael Paquier for reviewing.
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F6BE40D@G01JPEXMBYT05
2017-09-07 15:49:55 +02:00
|
|
|
* error, not one and then the other. Also, if we're using an
|
|
|
|
* implicit transaction block, we must close that out first.
|
|
|
|
*/
|
|
|
|
if (use_implicit_block)
|
|
|
|
EndImplicitTransactionBlock();
|
|
|
|
finish_xact_command();
|
|
|
|
}
|
|
|
|
else if (IsA(parsetree->stmt, TransactionStmt))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If this was a transaction control statement, commit it. We will
|
|
|
|
* start a new xact command for the next command.
|
2003-05-05 02:44:56 +02:00
|
|
|
*/
|
2003-05-14 05:26:03 +02:00
|
|
|
finish_xact_command();
|
2002-02-28 00:16:07 +01:00
|
|
|
}
|
2003-05-02 22:54:36 +02:00
|
|
|
else
|
2002-10-15 00:14:35 +02:00
|
|
|
{
|
Force immediate commit after CREATE DATABASE etc in extended protocol.
We have a few commands that "can't run in a transaction block",
meaning that if they complete their processing but then we fail
to COMMIT, we'll be left with inconsistent on-disk state.
However, the existing defenses for this are only watertight for
simple query protocol. In extended protocol, we didn't commit
until receiving a Sync message. Since the client is allowed to
issue another command instead of Sync, we're in trouble if that
command fails or is an explicit ROLLBACK. In any case, sitting
in an inconsistent state while waiting for a client message
that might not come seems pretty risky.
This case wasn't reachable via libpq before we introduced pipeline
mode, but it's always been an intended aspect of extended query
protocol, and likely there are other clients that could reach it
before.
To fix, set a flag in PreventInTransactionBlock that tells
exec_execute_message to force an immediate commit. This seems
to be the approach that does least damage to existing working
cases while still preventing the undesirable outcomes.
While here, add some documentation to protocol.sgml that explicitly
says how to use pipelining. That's latent in the existing docs if
you know what to look for, but it's better to spell it out; and it
provides a place to document this new behavior.
Per bug #17434 from Yugo Nagata. It's been wrong for ages,
so back-patch to all supported branches.
Discussion: https://postgr.es/m/17434-d9f7a064ce2a88a3@postgresql.org
2022-07-26 19:07:03 +02:00
|
|
|
/*
|
|
|
|
* We had better not see XACT_FLAGS_NEEDIMMEDIATECOMMIT set if
|
|
|
|
* we're not calling finish_xact_command(). (The implicit
|
|
|
|
* transaction block should have prevented it from getting set.)
|
|
|
|
*/
|
|
|
|
Assert(!(MyXactFlags & XACT_FLAGS_NEEDIMMEDIATECOMMIT));
|
|
|
|
|
2003-05-02 22:54:36 +02:00
|
|
|
/*
|
|
|
|
* We need a CommandCounterIncrement after every query, except
|
|
|
|
* those that start or end a transaction block.
|
|
|
|
*/
|
|
|
|
CommandCounterIncrement();
|
Reset statement_timeout between queries of a multi-query string.
Historically, we started the timer (if StatementTimeout > 0) at the
beginning of a simple-Query message and usually let it run until the
end, so that the timeout limit applied to the entire query string,
and intra-string changes of the statement_timeout GUC had no effect.
But, confusingly, a COMMIT within the string would reset the state
and allow a fresh timeout cycle to start with the current setting.
Commit f8e5f156b changed the behavior of statement_timeout for extended
query protocol, and as an apparently-unintended side effect, a change in
the statement_timeout GUC during a multi-statement simple-Query message
might have an effect immediately --- but only if it was going from
"disabled" to "enabled".
This is all pretty confusing, not to mention completely undocumented.
Let's change things so that the timeout is always reset between queries
of a multi-query string, whether they're transaction control commands
or not. Thus the active timeout setting is applied to each query in
the string, separately. This costs a few more cycles if statement_timeout
is active, but it provides much more intuitive behavior, especially if one
changes statement_timeout in one of the queries of the string.
Also, add something to the documentation to explain all this.
Per bug #16035 from Raj Mohite. Although this is a bug fix, I'm hesitant
to back-patch it; conceivably somebody has worked out the old behavior
and is depending on it. (But note that this change should make the
behavior less restrictive in most cases, since the timeout will now
be applied to shorter segments of code.)
Discussion: https://postgr.es/m/16035-456e6e69ebfd4374@postgresql.org
2019-10-25 17:15:50 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Disable statement timeout between queries of a multi-query
|
|
|
|
* string, so that the timeout applies separately to each query.
|
|
|
|
* (Our next loop iteration will start a fresh timeout.)
|
|
|
|
*/
|
|
|
|
disable_statement_timeout();
|
2002-10-15 00:14:35 +02:00
|
|
|
}
|
2002-02-26 23:47:12 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Tell client that we're done with this query. Note we emit exactly
|
|
|
|
* one EndCommand report for each raw parsetree, thus one for each SQL
|
|
|
|
* command the client sent, regardless of rewriting. (But a command
|
2002-02-28 00:16:07 +01:00
|
|
|
* aborted by error will not send an EndCommand report at all.)
|
2002-02-26 23:47:12 +01:00
|
|
|
*/
|
2020-03-02 22:19:51 +01:00
|
|
|
EndCommand(&qc, dest, false);
|
Reduce memory consumption for multi-statement query strings.
Previously, exec_simple_query always ran parse analysis, rewrite, and
planning in MessageContext, allowing all the data generated thereby
to persist until the end of processing of the whole query string.
That's fine for single-command strings, but if a client sends many
commands in a single simple-Query message, this strategy could result
in annoying memory bloat, as complained of by Andreas Seltenreich.
To fix, create a child context to do this work in, and reclaim it
after each command. But we only do so for parsetrees that are not
last in their query string. That avoids adding any memory management
overhead for the typical case of a single-command string. Memory
allocated for the last parsetree would be freed immediately after
finishing the command string anyway.
Similarly, adjust extension.c's execute_sql_string() to reclaim memory
after each command. In that usage, multi-command strings are the norm,
so it's a bit surprising that no one has yet complained of bloat ---
especially since the bloat extended to whatever data ProcessUtility
execution might leak.
Amit Langote, reviewed by Julien Rouhaud
Discussion: https://postgr.es/m/87ftp6l2qr.fsf@credativ.de
2019-07-10 20:32:28 +02:00
|
|
|
|
|
|
|
/* Now we may drop the per-parsetree context, if one was created. */
|
|
|
|
if (per_parsetree_context)
|
|
|
|
MemoryContextDelete(per_parsetree_context);
|
2000-10-07 02:58:23 +02:00
|
|
|
} /* end loop over parsetrees */
|
|
|
|
|
2003-05-14 05:26:03 +02:00
|
|
|
/*
|
Fix handling of savepoint commands within multi-statement Query strings.
Issuing a savepoint-related command in a Query message that contains
multiple SQL statements led to a FATAL exit with a complaint about
"unexpected state STARTED". This is a shortcoming of commit 4f896dac1,
which attempted to prevent such misbehaviors in multi-statement strings;
its quick hack of marking the individual statements as "not top-level"
does the wrong thing in this case, and isn't a very accurate description
of the situation anyway.
To fix, let's introduce into xact.c an explicit model of what happens for
multi-statement Query strings. This is an "implicit transaction block
in progress" state, which for many purposes works like the normal
TBLOCK_INPROGRESS state --- in particular, IsTransactionBlock returns true,
causing the desired result that PreventTransactionChain will throw error.
But in case of error abort it works like TBLOCK_STARTED, allowing the
transaction to be cancelled without need for an explicit ROLLBACK command.
Commit 4f896dac1 is reverted in toto, so that we go back to treating the
individual statements as "top level". We could have left it as-is, but
this allows sharpening the error message for PreventTransactionChain
calls inside functions.
Except for getting a normal error instead of a FATAL exit for savepoint
commands, this patch should result in no user-visible behavioral change
(other than that one error message rewording). There are some things
we might want to do in the line of changing the appearance or wording of
error and warning messages around this behavior, which would be much
simpler to do now that it's an explicitly modeled state. But I haven't
done them here.
Although this fixes a long-standing bug, no backpatch. The consequences
of the bug don't seem severe enough to justify the risk that this commit
itself creates some new issue.
Patch by me, but it owes something to previous investigation by
Takayuki Tsunakawa, who also reported the bug in the first place.
Also thanks to Michael Paquier for reviewing.
Discussion: https://postgr.es/m/0A3221C70F24FB45833433255569204D1F6BE40D@G01JPEXMBYT05
2017-09-07 15:49:55 +02:00
|
|
|
* Close down transaction statement, if one is open. (This will only do
|
|
|
|
* something if the parsetree list was empty; otherwise the last loop
|
|
|
|
* iteration already did it.)
|
2003-05-14 05:26:03 +02:00
|
|
|
*/
|
2006-06-21 00:52:00 +02:00
|
|
|
finish_xact_command();
|
2003-05-14 05:26:03 +02:00
|
|
|
|
2003-05-02 22:54:36 +02:00
|
|
|
/*
|
|
|
|
* If there were no parsetrees, return EmptyQueryResponse message.
|
|
|
|
*/
|
2003-03-22 05:23:34 +01:00
|
|
|
if (!parsetree_list)
|
2003-05-06 22:26:28 +02:00
|
|
|
NullCommand(dest);
|
|
|
|
|
2003-05-02 22:54:36 +02:00
|
|
|
/*
|
2006-06-21 00:52:00 +02:00
|
|
|
* Emit duration logging if appropriate.
|
2003-05-02 22:54:36 +02:00
|
|
|
*/
|
2006-09-08 17:55:53 +02:00
|
|
|
switch (check_log_duration(msec_str, was_logged))
|
2002-09-02 01:26:06 +02:00
|
|
|
{
|
2006-09-08 17:55:53 +02:00
|
|
|
case 1:
|
2006-09-08 00:52:01 +02:00
|
|
|
ereport(LOG,
|
2007-03-03 00:37:23 +01:00
|
|
|
(errmsg("duration: %s ms", msec_str),
|
|
|
|
errhidestmt(true)));
|
2006-09-08 17:55:53 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2006-09-08 00:52:01 +02:00
|
|
|
ereport(LOG,
|
|
|
|
(errmsg("duration: %s ms statement: %s",
|
|
|
|
msec_str, query_string),
|
2007-03-03 00:37:23 +01:00
|
|
|
errhidestmt(true),
|
2006-09-08 00:52:01 +02:00
|
|
|
errdetail_execute(parsetree_list)));
|
2006-09-08 17:55:53 +02:00
|
|
|
break;
|
2002-09-02 01:26:06 +02:00
|
|
|
}
|
2002-09-02 07:25:37 +02:00
|
|
|
|
2003-05-02 22:54:36 +02:00
|
|
|
if (save_log_statement_stats)
|
|
|
|
ShowUsage("QUERY STATISTICS");
|
|
|
|
|
2008-08-01 15:16:09 +02:00
|
|
|
TRACE_POSTGRESQL_QUERY_DONE(query_string);
|
|
|
|
|
2002-09-02 07:25:37 +02:00
|
|
|
debug_query_string = NULL;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* exec_parse_message
|
|
|
|
*
|
|
|
|
* Execute a "Parse" protocol message.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
exec_parse_message(const char *query_string, /* string to execute */
|
|
|
|
const char *stmt_name, /* name for prepared stmt */
|
|
|
|
Oid *paramTypes, /* parameter types */
|
|
|
|
int numParams) /* number of parameters */
|
|
|
|
{
|
2011-09-16 06:42:53 +02:00
|
|
|
MemoryContext unnamed_stmt_context = NULL;
|
2003-05-05 02:44:56 +02:00
|
|
|
MemoryContext oldcontext;
|
|
|
|
List *parsetree_list;
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
RawStmt *raw_parse_tree;
|
2011-09-16 06:42:53 +02:00
|
|
|
List *querytree_list;
|
|
|
|
CachedPlanSource *psrc;
|
2003-05-05 02:44:56 +02:00
|
|
|
bool is_named;
|
|
|
|
bool save_log_statement_stats = log_statement_stats;
|
2006-09-08 00:52:01 +02:00
|
|
|
char msec_str[32];
|
2003-05-05 02:44:56 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Report query to various monitoring facilities.
|
|
|
|
*/
|
|
|
|
debug_query_string = query_string;
|
|
|
|
|
2012-01-19 14:19:20 +01:00
|
|
|
pgstat_report_activity(STATE_RUNNING, query_string);
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2020-03-11 16:36:40 +01:00
|
|
|
set_ps_display("PARSE");
|
2003-05-05 02:44:56 +02:00
|
|
|
|
|
|
|
if (save_log_statement_stats)
|
|
|
|
ResetUsage();
|
|
|
|
|
2006-09-08 00:52:01 +02:00
|
|
|
ereport(DEBUG2,
|
2021-02-17 11:24:46 +01:00
|
|
|
(errmsg_internal("parse %s: %s",
|
2006-09-08 00:52:01 +02:00
|
|
|
*stmt_name ? stmt_name : "<unnamed>",
|
|
|
|
query_string)));
|
2005-05-24 06:18:04 +02:00
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* Start up a transaction command so we can run parse analysis etc. (Note
|
|
|
|
* that this will normally change current memory context.) Nothing happens
|
2017-09-19 04:36:44 +02:00
|
|
|
* if we are already in one. This also arms the statement timeout if
|
|
|
|
* necessary.
|
2003-05-05 02:44:56 +02:00
|
|
|
*/
|
2006-06-21 00:52:00 +02:00
|
|
|
start_xact_command();
|
2003-05-05 02:44:56 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Switch to appropriate context for constructing parsetrees.
|
|
|
|
*
|
|
|
|
* We have two strategies depending on whether the prepared statement is
|
|
|
|
* named or not. For a named prepared statement, we do parsing in
|
|
|
|
* MessageContext and copy the finished trees into the prepared
|
2007-03-13 01:33:44 +01:00
|
|
|
* statement's plancache entry; then the reset of MessageContext releases
|
2011-09-16 06:42:53 +02:00
|
|
|
* temporary space used by parsing and rewriting. For an unnamed prepared
|
2003-05-05 02:44:56 +02:00
|
|
|
* statement, we assume the statement isn't going to hang around long, so
|
|
|
|
* getting rid of temp space quickly is probably not worth the costs of
|
2011-09-16 06:42:53 +02:00
|
|
|
* copying parse trees. So in this case, we create the plancache entry's
|
|
|
|
* query_context here, and do all the parsing work therein.
|
2003-05-05 02:44:56 +02:00
|
|
|
*/
|
|
|
|
is_named = (stmt_name[0] != '\0');
|
|
|
|
if (is_named)
|
|
|
|
{
|
|
|
|
/* Named prepared statement --- parse in MessageContext */
|
|
|
|
oldcontext = MemoryContextSwitchTo(MessageContext);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Unnamed prepared statement --- release any prior unnamed stmt */
|
2007-03-13 01:33:44 +01:00
|
|
|
drop_unnamed_stmt();
|
2011-09-16 06:42:53 +02:00
|
|
|
/* Create context for parsing */
|
2003-05-05 02:44:56 +02:00
|
|
|
unnamed_stmt_context =
|
2011-09-16 06:42:53 +02:00
|
|
|
AllocSetContextCreate(MessageContext,
|
2003-05-05 02:44:56 +02:00
|
|
|
"unnamed prepared statement",
|
Add macros to make AllocSetContextCreate() calls simpler and safer.
I found that half a dozen (nearly 5%) of our AllocSetContextCreate calls
had typos in the context-sizing parameters. While none of these led to
especially significant problems, they did create minor inefficiencies,
and it's now clear that expecting people to copy-and-paste those calls
accurately is not a great idea. Let's reduce the risk of future errors
by introducing single macros that encapsulate the common use-cases.
Three such macros are enough to cover all but two special-purpose contexts;
those two calls can be left as-is, I think.
While this patch doesn't in itself improve matters for third-party
extensions, it doesn't break anything for them either, and they can
gradually adopt the simplified notation over time.
In passing, change TopMemoryContext to use the default allocation
parameters. Formerly it could only be extended 8K at a time. That was
probably reasonable when this code was written; but nowadays we create
many more contexts than we did then, so that it's not unusual to have a
couple hundred K in TopMemoryContext, even without considering various
dubious code that sticks other things there. There seems no good reason
not to let it use growing blocks like most other contexts.
Back-patch to 9.6, mostly because that's still close enough to HEAD that
it's easy to do so, and keeping the branches in sync can be expected to
avoid some future back-patching pain. The bugs fixed by these changes
don't seem to be significant enough to justify fixing them further back.
Discussion: <21072.1472321324@sss.pgh.pa.us>
2016-08-27 23:50:38 +02:00
|
|
|
ALLOCSET_DEFAULT_SIZES);
|
2003-05-05 02:44:56 +02:00
|
|
|
oldcontext = MemoryContextSwitchTo(unnamed_stmt_context);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do basic parsing of the query or queries (this should be safe even if
|
|
|
|
* we are in aborted transaction state!)
|
|
|
|
*/
|
|
|
|
parsetree_list = pg_parse_query(query_string);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We only allow a single user statement in a prepared statement. This is
|
|
|
|
* mainly to keep the protocol simple --- otherwise we'd need to worry
|
|
|
|
* about multiple result tupdescs and things like that.
|
|
|
|
*/
|
2004-05-26 06:41:50 +02:00
|
|
|
if (list_length(parsetree_list) > 1)
|
2003-07-22 21:00:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("cannot insert multiple commands into a prepared statement")));
|
2003-05-05 02:44:56 +02:00
|
|
|
|
|
|
|
if (parsetree_list != NIL)
|
|
|
|
{
|
2008-12-13 03:00:20 +01:00
|
|
|
bool snapshot_set = false;
|
2003-05-05 02:44:56 +02:00
|
|
|
|
Improve castNode notation by introducing list-extraction-specific variants.
This extends the castNode() notation introduced by commit 5bcab1114 to
provide, in one step, extraction of a list cell's pointer and coercion to
a concrete node type. For example, "lfirst_node(Foo, lc)" is the same
as "castNode(Foo, lfirst(lc))". Almost half of the uses of castNode
that have appeared so far include a list extraction call, so this is
pretty widely useful, and it saves a few more keystrokes compared to the
old way.
As with the previous patch, back-patch the addition of these macros to
pg_list.h, so that the notation will be available when back-patching.
Patch by me, after an idea of Andrew Gierth's.
Discussion: https://postgr.es/m/14197.1491841216@sss.pgh.pa.us
2017-04-10 19:51:29 +02:00
|
|
|
raw_parse_tree = linitial_node(RawStmt, parsetree_list);
|
2007-03-13 01:33:44 +01:00
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* If we are in an aborted transaction, reject all commands except
|
|
|
|
* COMMIT/ROLLBACK. It is important that this test occur before we
|
|
|
|
* try to do parse analysis, rewrite, or planning, since all those
|
|
|
|
* phases try to do database accesses, which may fail in abort state.
|
|
|
|
* (It might be safe to allow some additional utility commands in this
|
|
|
|
* state, but not many...)
|
|
|
|
*/
|
2005-11-10 01:31:34 +01:00
|
|
|
if (IsAbortedTransactionBlockState() &&
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
!IsTransactionExitStmt(raw_parse_tree->stmt))
|
2005-11-10 01:31:34 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
|
|
|
|
errmsg("current transaction is aborted, "
|
2010-01-16 11:05:59 +01:00
|
|
|
"commands ignored until end of transaction block"),
|
|
|
|
errdetail_abort()));
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2008-12-13 03:00:20 +01:00
|
|
|
/*
|
2011-09-16 06:42:53 +02:00
|
|
|
* Create the CachedPlanSource before we do parse analysis, since it
|
|
|
|
* needs to see the unmodified raw parse tree.
|
|
|
|
*/
|
2020-03-02 22:19:51 +01:00
|
|
|
psrc = CreateCachedPlan(raw_parse_tree, query_string,
|
|
|
|
CreateCommandTag(raw_parse_tree->stmt));
|
2011-09-16 06:42:53 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up a snapshot if parse analysis will need one.
|
2008-12-13 03:00:20 +01:00
|
|
|
*/
|
|
|
|
if (analyze_requires_snapshot(raw_parse_tree))
|
|
|
|
{
|
|
|
|
PushActiveSnapshot(GetTransactionSnapshot());
|
|
|
|
snapshot_set = true;
|
|
|
|
}
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
2011-09-16 06:42:53 +02:00
|
|
|
* Analyze and rewrite the query. Note that the originally specified
|
|
|
|
* parameter set is not required to be complete, so we have to use
|
2022-03-04 14:49:37 +01:00
|
|
|
* pg_analyze_and_rewrite_varparams().
|
2003-05-05 02:44:56 +02:00
|
|
|
*/
|
2022-03-04 14:49:37 +01:00
|
|
|
querytree_list = pg_analyze_and_rewrite_varparams(raw_parse_tree,
|
|
|
|
query_string,
|
|
|
|
¶mTypes,
|
|
|
|
&numParams,
|
|
|
|
NULL);
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2011-09-16 06:42:53 +02:00
|
|
|
/* Done with the snapshot used for parsing */
|
2008-12-13 03:00:20 +01:00
|
|
|
if (snapshot_set)
|
|
|
|
PopActiveSnapshot();
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Empty input string. This is legal. */
|
2007-03-13 01:33:44 +01:00
|
|
|
raw_parse_tree = NULL;
|
2020-03-02 22:19:51 +01:00
|
|
|
psrc = CreateCachedPlan(raw_parse_tree, query_string,
|
|
|
|
CMDTAG_UNKNOWN);
|
2011-09-16 06:42:53 +02:00
|
|
|
querytree_list = NIL;
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-09-16 06:42:53 +02:00
|
|
|
* CachedPlanSource must be a direct child of MessageContext before we
|
|
|
|
* reparent unnamed_stmt_context under it, else we have a disconnected
|
|
|
|
* circular subgraph. Klugy, but less so than flipping contexts even more
|
|
|
|
* above.
|
2003-05-05 02:44:56 +02:00
|
|
|
*/
|
2011-09-16 06:42:53 +02:00
|
|
|
if (unnamed_stmt_context)
|
|
|
|
MemoryContextSetParent(psrc->context, MessageContext);
|
|
|
|
|
|
|
|
/* Finish filling in the CachedPlanSource */
|
|
|
|
CompleteCachedPlan(psrc,
|
|
|
|
querytree_list,
|
|
|
|
unnamed_stmt_context,
|
|
|
|
paramTypes,
|
|
|
|
numParams,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
2016-02-25 08:32:18 +01:00
|
|
|
CURSOR_OPT_PARALLEL_OK, /* allow parallel mode */
|
2011-09-16 06:42:53 +02:00
|
|
|
true); /* fixed result */
|
|
|
|
|
|
|
|
/* If we got a cancel signal during analysis, quit */
|
|
|
|
CHECK_FOR_INTERRUPTS();
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
if (is_named)
|
|
|
|
{
|
2011-09-16 06:42:53 +02:00
|
|
|
/*
|
|
|
|
* Store the query as a prepared statement.
|
|
|
|
*/
|
|
|
|
StorePreparedStatement(stmt_name, psrc, false);
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-03-29 21:10:10 +02:00
|
|
|
/*
|
2011-09-16 06:42:53 +02:00
|
|
|
* We just save the CachedPlanSource into unnamed_stmt_psrc.
|
2007-03-29 21:10:10 +02:00
|
|
|
*/
|
2011-09-16 06:42:53 +02:00
|
|
|
SaveCachedPlan(psrc);
|
|
|
|
unnamed_stmt_psrc = psrc;
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
MemoryContextSwitchTo(oldcontext);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We do NOT close the open transaction command here; that only happens
|
|
|
|
* when the client sends Sync. Instead, do CommandCounterIncrement just
|
|
|
|
* in case something happened during parse/plan.
|
|
|
|
*/
|
|
|
|
CommandCounterIncrement();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send ParseComplete.
|
|
|
|
*/
|
2005-11-03 18:11:40 +01:00
|
|
|
if (whereToSendOutput == DestRemote)
|
2023-08-23 04:16:12 +02:00
|
|
|
pq_putemptymessage(PqMsg_ParseComplete);
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2006-09-08 00:52:01 +02:00
|
|
|
/*
|
|
|
|
* Emit duration logging if appropriate.
|
|
|
|
*/
|
2006-09-08 17:55:53 +02:00
|
|
|
switch (check_log_duration(msec_str, false))
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
ereport(LOG,
|
2007-03-03 00:37:23 +01:00
|
|
|
(errmsg("duration: %s ms", msec_str),
|
|
|
|
errhidestmt(true)));
|
2006-09-08 17:55:53 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ereport(LOG,
|
|
|
|
(errmsg("duration: %s ms parse %s: %s",
|
|
|
|
msec_str,
|
|
|
|
*stmt_name ? stmt_name : "<unnamed>",
|
2007-03-03 00:37:23 +01:00
|
|
|
query_string),
|
|
|
|
errhidestmt(true)));
|
2006-09-08 17:55:53 +02:00
|
|
|
break;
|
|
|
|
}
|
2006-09-08 00:52:01 +02:00
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
if (save_log_statement_stats)
|
|
|
|
ShowUsage("PARSE MESSAGE STATISTICS");
|
|
|
|
|
|
|
|
debug_query_string = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* exec_bind_message
|
|
|
|
*
|
|
|
|
* Process a "Bind" message to create a portal from a prepared statement
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
exec_bind_message(StringInfo input_message)
|
|
|
|
{
|
|
|
|
const char *portal_name;
|
|
|
|
const char *stmt_name;
|
2003-05-08 20:16:37 +02:00
|
|
|
int numPFormats;
|
|
|
|
int16 *pformats = NULL;
|
2003-05-05 02:44:56 +02:00
|
|
|
int numParams;
|
2003-05-08 20:16:37 +02:00
|
|
|
int numRFormats;
|
|
|
|
int16 *rformats = NULL;
|
2007-03-13 01:33:44 +01:00
|
|
|
CachedPlanSource *psrc;
|
|
|
|
CachedPlan *cplan;
|
2003-05-05 02:44:56 +02:00
|
|
|
Portal portal;
|
2008-04-02 20:31:50 +02:00
|
|
|
char *query_string;
|
|
|
|
char *saved_stmt_name;
|
2003-05-05 02:44:56 +02:00
|
|
|
ParamListInfo params;
|
2008-04-02 20:31:50 +02:00
|
|
|
MemoryContext oldContext;
|
2006-09-08 00:52:01 +02:00
|
|
|
bool save_log_statement_stats = log_statement_stats;
|
2008-12-13 03:00:20 +01:00
|
|
|
bool snapshot_set = false;
|
2006-09-08 00:52:01 +02:00
|
|
|
char msec_str[32];
|
2019-12-11 22:03:35 +01:00
|
|
|
ParamsErrorCbData params_data;
|
|
|
|
ErrorContextCallback params_errcxt;
|
2006-09-08 00:52:01 +02:00
|
|
|
|
|
|
|
/* Get the fixed part of the message */
|
|
|
|
portal_name = pq_getmsgstring(input_message);
|
|
|
|
stmt_name = pq_getmsgstring(input_message);
|
|
|
|
|
|
|
|
ereport(DEBUG2,
|
2021-02-17 11:24:46 +01:00
|
|
|
(errmsg_internal("bind %s to %s",
|
2006-09-08 00:52:01 +02:00
|
|
|
*portal_name ? portal_name : "<unnamed>",
|
|
|
|
*stmt_name ? stmt_name : "<unnamed>")));
|
|
|
|
|
|
|
|
/* Find prepared statement */
|
|
|
|
if (stmt_name[0] != '\0')
|
2007-03-13 01:33:44 +01:00
|
|
|
{
|
|
|
|
PreparedStatement *pstmt;
|
|
|
|
|
2006-09-08 00:52:01 +02:00
|
|
|
pstmt = FetchPreparedStatement(stmt_name, true);
|
2007-03-13 01:33:44 +01:00
|
|
|
psrc = pstmt->plansource;
|
|
|
|
}
|
2006-09-08 00:52:01 +02:00
|
|
|
else
|
|
|
|
{
|
2011-09-16 06:42:53 +02:00
|
|
|
/* special-case the unnamed statement */
|
2007-03-13 01:33:44 +01:00
|
|
|
psrc = unnamed_stmt_psrc;
|
|
|
|
if (!psrc)
|
2006-09-08 00:52:01 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_PSTATEMENT),
|
|
|
|
errmsg("unnamed prepared statement does not exist")));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report query to various monitoring facilities.
|
|
|
|
*/
|
Adjust things so that the query_string of a cached plan and the sourceText of
a portal are never NULL, but reliably provide the source text of the query.
It turns out that there was only one place that was really taking a short-cut,
which was the 'EXECUTE' utility statement. That doesn't seem like a
sufficiently critical performance hotspot to justify not offering a guarantee
of validity of the portal source text. Fix it to copy the source text over
from the cached plan. Add Asserts in the places that set up cached plans and
portals to reject null source strings, and simplify a bunch of places that
formerly needed to guard against nulls.
There may be a few places that cons up statements for execution without
having any source text at all; I found one such in ConvertTriggerToFK().
It seems sufficient to inject a phony source string in such a case,
for instance
ProcessUtility((Node *) atstmt,
"(generated ALTER TABLE ADD FOREIGN KEY command)",
NULL, false, None_Receiver, NULL);
We should take a second look at the usage of debug_query_string,
particularly the recently added current_query() SQL function.
ITAGAKI Takahiro and Tom Lane
2008-07-18 22:26:06 +02:00
|
|
|
debug_query_string = psrc->query_string;
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2012-01-19 14:19:20 +01:00
|
|
|
pgstat_report_activity(STATE_RUNNING, psrc->query_string);
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2020-03-11 16:36:40 +01:00
|
|
|
set_ps_display("BIND");
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2006-09-08 00:52:01 +02:00
|
|
|
if (save_log_statement_stats)
|
|
|
|
ResetUsage();
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* Start up a transaction command so we can call functions etc. (Note that
|
|
|
|
* this will normally change current memory context.) Nothing happens if
|
2017-09-19 04:36:44 +02:00
|
|
|
* we are already in one. This also arms the statement timeout if
|
|
|
|
* necessary.
|
2003-05-05 02:44:56 +02:00
|
|
|
*/
|
2006-06-21 00:52:00 +02:00
|
|
|
start_xact_command();
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2003-05-08 20:16:37 +02:00
|
|
|
/* Switch back to message context */
|
|
|
|
MemoryContextSwitchTo(MessageContext);
|
|
|
|
|
|
|
|
/* Get the parameter format codes */
|
|
|
|
numPFormats = pq_getmsgint(input_message, 2);
|
|
|
|
if (numPFormats > 0)
|
|
|
|
{
|
2022-09-12 08:31:56 +02:00
|
|
|
pformats = palloc_array(int16, numPFormats);
|
2018-08-24 03:36:07 +02:00
|
|
|
for (int i = 0; i < numPFormats; i++)
|
2003-05-08 20:16:37 +02:00
|
|
|
pformats[i] = pq_getmsgint(input_message, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the parameter value count */
|
|
|
|
numParams = pq_getmsgint(input_message, 2);
|
|
|
|
|
|
|
|
if (numPFormats > 1 && numPFormats != numParams)
|
2003-07-22 21:00:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("bind message has %d parameter formats but %d parameters",
|
|
|
|
numPFormats, numParams)));
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2007-03-13 01:33:44 +01:00
|
|
|
if (numParams != psrc->num_params)
|
2003-07-22 21:00:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("bind message supplies %d parameters, but prepared statement \"%s\" requires %d",
|
2007-03-13 01:33:44 +01:00
|
|
|
numParams, stmt_name, psrc->num_params)));
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2005-11-10 01:31:34 +01:00
|
|
|
/*
|
|
|
|
* If we are in aborted transaction state, the only portals we can
|
|
|
|
* actually run are those containing COMMIT or ROLLBACK commands. We
|
|
|
|
* disallow binding anything else to avoid problems with infrastructure
|
|
|
|
* that expects to run inside a valid transaction. We also disallow
|
|
|
|
* binding any parameters, since we can't risk calling user-defined I/O
|
|
|
|
* functions.
|
|
|
|
*/
|
|
|
|
if (IsAbortedTransactionBlockState() &&
|
2017-01-20 01:52:13 +01:00
|
|
|
(!(psrc->raw_parse_tree &&
|
|
|
|
IsTransactionExitStmt(psrc->raw_parse_tree->stmt)) ||
|
2005-11-10 01:31:34 +01:00
|
|
|
numParams != 0))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
|
|
|
|
errmsg("current transaction is aborted, "
|
2010-01-16 11:05:59 +01:00
|
|
|
"commands ignored until end of transaction block"),
|
|
|
|
errdetail_abort()));
|
2005-11-10 01:31:34 +01:00
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* Create the portal. Allow silent replacement of an existing portal only
|
|
|
|
* if the unnamed portal is specified.
|
|
|
|
*/
|
|
|
|
if (portal_name[0] == '\0')
|
|
|
|
portal = CreatePortal(portal_name, true, true);
|
|
|
|
else
|
|
|
|
portal = CreatePortal(portal_name, false, false);
|
|
|
|
|
2008-04-02 20:31:50 +02:00
|
|
|
/*
|
|
|
|
* Prepare to copy stuff into the portal's memory context. We do all this
|
|
|
|
* copying first, because it could possibly fail (out-of-memory) and we
|
2011-09-16 06:42:53 +02:00
|
|
|
* don't want a failure to occur between GetCachedPlan and
|
2008-04-02 20:31:50 +02:00
|
|
|
* PortalDefineQuery; that would result in leaking our plancache refcount.
|
|
|
|
*/
|
2017-12-16 23:26:26 +01:00
|
|
|
oldContext = MemoryContextSwitchTo(portal->portalContext);
|
2008-04-02 20:31:50 +02:00
|
|
|
|
Adjust things so that the query_string of a cached plan and the sourceText of
a portal are never NULL, but reliably provide the source text of the query.
It turns out that there was only one place that was really taking a short-cut,
which was the 'EXECUTE' utility statement. That doesn't seem like a
sufficiently critical performance hotspot to justify not offering a guarantee
of validity of the portal source text. Fix it to copy the source text over
from the cached plan. Add Asserts in the places that set up cached plans and
portals to reject null source strings, and simplify a bunch of places that
formerly needed to guard against nulls.
There may be a few places that cons up statements for execution without
having any source text at all; I found one such in ConvertTriggerToFK().
It seems sufficient to inject a phony source string in such a case,
for instance
ProcessUtility((Node *) atstmt,
"(generated ALTER TABLE ADD FOREIGN KEY command)",
NULL, false, None_Receiver, NULL);
We should take a second look at the usage of debug_query_string,
particularly the recently added current_query() SQL function.
ITAGAKI Takahiro and Tom Lane
2008-07-18 22:26:06 +02:00
|
|
|
/* Copy the plan's query string into the portal */
|
|
|
|
query_string = pstrdup(psrc->query_string);
|
2008-04-02 20:31:50 +02:00
|
|
|
|
|
|
|
/* Likewise make a copy of the statement name, unless it's unnamed */
|
|
|
|
if (stmt_name[0])
|
|
|
|
saved_stmt_name = pstrdup(stmt_name);
|
|
|
|
else
|
|
|
|
saved_stmt_name = NULL;
|
|
|
|
|
2008-12-13 03:00:20 +01:00
|
|
|
/*
|
|
|
|
* Set a snapshot if we have parameters to fetch (since the input
|
|
|
|
* functions might need it) or the query isn't a utility command (and
|
2011-09-16 06:42:53 +02:00
|
|
|
* hence could require redoing parse analysis and planning). We keep the
|
|
|
|
* snapshot active till we're done, so that plancache.c doesn't have to
|
|
|
|
* take new ones.
|
2008-12-13 03:00:20 +01:00
|
|
|
*/
|
2014-11-12 21:58:37 +01:00
|
|
|
if (numParams > 0 ||
|
|
|
|
(psrc->raw_parse_tree &&
|
|
|
|
analyze_requires_snapshot(psrc->raw_parse_tree)))
|
2008-12-13 03:00:20 +01:00
|
|
|
{
|
|
|
|
PushActiveSnapshot(GetTransactionSnapshot());
|
|
|
|
snapshot_set = true;
|
|
|
|
}
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* Fetch parameters, if any, and store in the portal's memory context.
|
|
|
|
*/
|
|
|
|
if (numParams > 0)
|
|
|
|
{
|
2020-04-02 21:04:51 +02:00
|
|
|
char **knownTextValues = NULL; /* allocate on first use */
|
2021-03-16 16:16:41 +01:00
|
|
|
BindParamCbData one_param_data;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up an error callback so that if there's an error in this phase,
|
|
|
|
* we can report the specific parameter causing the problem.
|
|
|
|
*/
|
|
|
|
one_param_data.portalName = portal->name;
|
|
|
|
one_param_data.paramno = -1;
|
|
|
|
one_param_data.paramval = NULL;
|
|
|
|
params_errcxt.previous = error_context_stack;
|
|
|
|
params_errcxt.callback = bind_param_error_callback;
|
|
|
|
params_errcxt.arg = (void *) &one_param_data;
|
|
|
|
error_context_stack = ¶ms_errcxt;
|
2019-12-11 22:03:35 +01:00
|
|
|
|
2019-03-14 13:30:09 +01:00
|
|
|
params = makeParamList(numParams);
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2018-08-24 03:36:07 +02:00
|
|
|
for (int paramno = 0; paramno < numParams; paramno++)
|
2003-05-05 02:44:56 +02:00
|
|
|
{
|
2007-03-13 01:33:44 +01:00
|
|
|
Oid ptype = psrc->param_types[paramno];
|
2003-05-08 20:16:37 +02:00
|
|
|
int32 plength;
|
2006-09-06 22:40:48 +02:00
|
|
|
Datum pval;
|
2003-05-05 02:44:56 +02:00
|
|
|
bool isNull;
|
2006-04-04 21:35:37 +02:00
|
|
|
StringInfoData pbuf;
|
|
|
|
char csave;
|
|
|
|
int16 pformat;
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2021-03-16 16:16:41 +01:00
|
|
|
one_param_data.paramno = paramno;
|
|
|
|
one_param_data.paramval = NULL;
|
|
|
|
|
2003-05-08 20:16:37 +02:00
|
|
|
plength = pq_getmsgint(input_message, 4);
|
|
|
|
isNull = (plength == -1);
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
if (!isNull)
|
|
|
|
{
|
2023-10-26 05:31:48 +02:00
|
|
|
char *pvalue;
|
2005-11-10 01:31:34 +01:00
|
|
|
|
|
|
|
/*
|
2023-10-26 05:31:48 +02:00
|
|
|
* Rather than copying data around, we just initialize a
|
2005-11-10 01:31:34 +01:00
|
|
|
* StringInfo pointing to the correct portion of the message
|
2023-10-26 05:31:48 +02:00
|
|
|
* buffer. We assume we can scribble on the message buffer to
|
|
|
|
* add a trailing NUL which is required for the input function
|
|
|
|
* call.
|
2005-11-10 01:31:34 +01:00
|
|
|
*/
|
2023-10-26 05:31:48 +02:00
|
|
|
pvalue = unconstify(char *, pq_getmsgbytes(input_message, plength));
|
|
|
|
csave = pvalue[plength];
|
|
|
|
pvalue[plength] = '\0';
|
|
|
|
initReadOnlyStringInfo(&pbuf, pvalue, plength);
|
2006-04-04 21:35:37 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pbuf.data = NULL; /* keep compiler quiet */
|
|
|
|
csave = 0;
|
|
|
|
}
|
2005-11-10 01:31:34 +01:00
|
|
|
|
2006-04-04 21:35:37 +02:00
|
|
|
if (numPFormats > 1)
|
2006-08-06 04:00:52 +02:00
|
|
|
pformat = pformats[paramno];
|
2006-04-04 21:35:37 +02:00
|
|
|
else if (numPFormats > 0)
|
|
|
|
pformat = pformats[0];
|
|
|
|
else
|
|
|
|
pformat = 0; /* default = text */
|
|
|
|
|
2006-08-08 03:23:15 +02:00
|
|
|
if (pformat == 0) /* text mode */
|
2006-04-04 21:35:37 +02:00
|
|
|
{
|
|
|
|
Oid typinput;
|
|
|
|
Oid typioparam;
|
2006-09-08 00:52:01 +02:00
|
|
|
char *pstring;
|
2005-11-10 01:31:34 +01:00
|
|
|
|
2006-04-04 21:35:37 +02:00
|
|
|
getTypeInputInfo(ptype, &typinput, &typioparam);
|
2005-11-10 01:31:34 +01:00
|
|
|
|
2006-04-04 21:35:37 +02:00
|
|
|
/*
|
|
|
|
* We have to do encoding conversion before calling the
|
|
|
|
* typinput routine.
|
|
|
|
*/
|
|
|
|
if (isNull)
|
|
|
|
pstring = NULL;
|
|
|
|
else
|
2005-11-10 01:31:34 +01:00
|
|
|
pstring = pg_client_to_server(pbuf.data, plength);
|
2006-04-04 21:35:37 +02:00
|
|
|
|
2021-03-16 16:16:41 +01:00
|
|
|
/* Now we can log the input string in case of error */
|
|
|
|
one_param_data.paramval = pstring;
|
|
|
|
|
2006-09-06 22:40:48 +02:00
|
|
|
pval = OidInputFunctionCall(typinput, pstring, typioparam, -1);
|
2006-08-08 03:23:15 +02:00
|
|
|
|
2021-03-16 16:16:41 +01:00
|
|
|
one_param_data.paramval = NULL;
|
|
|
|
|
2019-12-11 22:03:35 +01:00
|
|
|
/*
|
2020-04-02 21:04:51 +02:00
|
|
|
* If we might need to log parameters later, save a copy of
|
|
|
|
* the converted string in MessageContext; then free the
|
|
|
|
* result of encoding conversion, if any was done.
|
2019-12-11 22:03:35 +01:00
|
|
|
*/
|
|
|
|
if (pstring)
|
|
|
|
{
|
2020-04-02 21:04:51 +02:00
|
|
|
if (log_parameter_max_length_on_error != 0)
|
2019-12-11 22:03:35 +01:00
|
|
|
{
|
2020-04-02 21:04:51 +02:00
|
|
|
MemoryContext oldcxt;
|
2019-12-11 22:03:35 +01:00
|
|
|
|
|
|
|
oldcxt = MemoryContextSwitchTo(MessageContext);
|
2020-04-02 21:04:51 +02:00
|
|
|
|
2019-12-11 22:03:35 +01:00
|
|
|
if (knownTextValues == NULL)
|
2022-09-12 08:31:56 +02:00
|
|
|
knownTextValues = palloc0_array(char *, numParams);
|
2020-04-02 21:04:51 +02:00
|
|
|
|
|
|
|
if (log_parameter_max_length_on_error < 0)
|
|
|
|
knownTextValues[paramno] = pstrdup(pstring);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We can trim the saved string, knowing that we
|
|
|
|
* won't print all of it. But we must copy at
|
|
|
|
* least two more full characters than
|
|
|
|
* BuildParamLogString wants to use; otherwise it
|
|
|
|
* might fail to include the trailing ellipsis.
|
|
|
|
*/
|
|
|
|
knownTextValues[paramno] =
|
|
|
|
pnstrdup(pstring,
|
|
|
|
log_parameter_max_length_on_error
|
|
|
|
+ 2 * MAX_MULTIBYTE_CHAR_LEN);
|
|
|
|
}
|
|
|
|
|
2019-12-11 22:03:35 +01:00
|
|
|
MemoryContextSwitchTo(oldcxt);
|
|
|
|
}
|
|
|
|
if (pstring != pbuf.data)
|
|
|
|
pfree(pstring);
|
|
|
|
}
|
2006-04-04 21:35:37 +02:00
|
|
|
}
|
2006-08-08 03:23:15 +02:00
|
|
|
else if (pformat == 1) /* binary mode */
|
2006-04-04 21:35:37 +02:00
|
|
|
{
|
|
|
|
Oid typreceive;
|
|
|
|
Oid typioparam;
|
|
|
|
StringInfo bufptr;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Call the parameter type's binary input converter
|
|
|
|
*/
|
|
|
|
getTypeBinaryInputInfo(ptype, &typreceive, &typioparam);
|
|
|
|
|
|
|
|
if (isNull)
|
|
|
|
bufptr = NULL;
|
2005-11-10 01:31:34 +01:00
|
|
|
else
|
2006-04-04 21:35:37 +02:00
|
|
|
bufptr = &pbuf;
|
|
|
|
|
2006-09-06 22:40:48 +02:00
|
|
|
pval = OidReceiveFunctionCall(typreceive, bufptr, typioparam, -1);
|
2006-04-04 21:35:37 +02:00
|
|
|
|
|
|
|
/* Trouble if it didn't eat the whole buffer */
|
|
|
|
if (!isNull && pbuf.cursor != pbuf.len)
|
2005-11-10 01:31:34 +01:00
|
|
|
ereport(ERROR,
|
2006-04-04 21:35:37 +02:00
|
|
|
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
|
|
|
errmsg("incorrect binary data format in bind parameter %d",
|
2006-08-06 04:00:52 +02:00
|
|
|
paramno + 1)));
|
2006-04-04 21:35:37 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("unsupported format code: %d",
|
|
|
|
pformat)));
|
2006-09-06 22:40:48 +02:00
|
|
|
pval = 0; /* keep compiler quiet */
|
2006-04-04 21:35:37 +02:00
|
|
|
}
|
2005-11-10 01:31:34 +01:00
|
|
|
|
2006-04-04 21:35:37 +02:00
|
|
|
/* Restore message buffer contents */
|
|
|
|
if (!isNull)
|
2005-11-10 01:31:34 +01:00
|
|
|
pbuf.data[plength] = csave;
|
2003-05-08 20:16:37 +02:00
|
|
|
|
2006-09-06 22:40:48 +02:00
|
|
|
params->params[paramno].value = pval;
|
2006-08-06 04:00:52 +02:00
|
|
|
params->params[paramno].isnull = isNull;
|
2006-10-04 02:30:14 +02:00
|
|
|
|
2006-09-06 22:40:48 +02:00
|
|
|
/*
|
2011-09-16 06:42:53 +02:00
|
|
|
* We mark the params as CONST. This ensures that any custom plan
|
|
|
|
* makes full use of the parameter values.
|
2006-09-06 22:40:48 +02:00
|
|
|
*/
|
|
|
|
params->params[paramno].pflags = PARAM_FLAG_CONST;
|
2006-08-06 04:00:52 +02:00
|
|
|
params->params[paramno].ptype = ptype;
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
2019-12-11 22:03:35 +01:00
|
|
|
|
2021-03-16 16:16:41 +01:00
|
|
|
/* Pop the per-parameter error callback */
|
|
|
|
error_context_stack = error_context_stack->previous;
|
|
|
|
|
2019-12-11 22:03:35 +01:00
|
|
|
/*
|
2020-04-02 21:04:51 +02:00
|
|
|
* Once all parameters have been received, prepare for printing them
|
2021-03-16 16:16:41 +01:00
|
|
|
* in future errors, if configured to do so. (This is saved in the
|
|
|
|
* portal, so that they'll appear when the query is executed later.)
|
2019-12-11 22:03:35 +01:00
|
|
|
*/
|
2020-04-02 21:04:51 +02:00
|
|
|
if (log_parameter_max_length_on_error != 0)
|
2019-12-11 22:03:35 +01:00
|
|
|
params->paramValuesStr =
|
2020-04-02 21:04:51 +02:00
|
|
|
BuildParamLogString(params,
|
|
|
|
knownTextValues,
|
|
|
|
log_parameter_max_length_on_error);
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
params = NULL;
|
|
|
|
|
2008-04-02 20:31:50 +02:00
|
|
|
/* Done storing stuff in portal's context */
|
|
|
|
MemoryContextSwitchTo(oldContext);
|
|
|
|
|
2021-03-16 16:16:41 +01:00
|
|
|
/*
|
|
|
|
* Set up another error callback so that all the parameters are logged if
|
|
|
|
* we get an error during the rest of the BIND processing.
|
|
|
|
*/
|
2019-12-11 22:03:35 +01:00
|
|
|
params_data.portalName = portal->name;
|
|
|
|
params_data.params = params;
|
|
|
|
params_errcxt.previous = error_context_stack;
|
|
|
|
params_errcxt.callback = ParamsErrorCallback;
|
|
|
|
params_errcxt.arg = (void *) ¶ms_data;
|
|
|
|
error_context_stack = ¶ms_errcxt;
|
|
|
|
|
2003-05-08 20:16:37 +02:00
|
|
|
/* Get the result format codes */
|
|
|
|
numRFormats = pq_getmsgint(input_message, 2);
|
|
|
|
if (numRFormats > 0)
|
|
|
|
{
|
2022-09-12 08:31:56 +02:00
|
|
|
rformats = palloc_array(int16, numRFormats);
|
2018-08-24 03:36:07 +02:00
|
|
|
for (int i = 0; i < numRFormats; i++)
|
2003-05-08 20:16:37 +02:00
|
|
|
rformats[i] = pq_getmsgint(input_message, 2);
|
|
|
|
}
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
pq_getmsgend(input_message);
|
|
|
|
|
2011-09-16 06:42:53 +02:00
|
|
|
/*
|
|
|
|
* Obtain a plan from the CachedPlanSource. Any cruft from (re)planning
|
|
|
|
* will be generated in MessageContext. The plan refcount will be
|
|
|
|
* assigned to the Portal, so it will be released at portal destruction.
|
|
|
|
*/
|
Improve performance of repeated CALLs within plpgsql procedures.
This patch essentially is cleaning up technical debt left behind
by the original implementation of plpgsql procedures, particularly
commit d92bc83c4. That patch (or more precisely, follow-on patches
fixing its worst bugs) forced us to re-plan CALL and DO statements
each time through, if we're in a non-atomic context. That wasn't
for any fundamental reason, but just because use of a saved plan
requires having a ResourceOwner to hold a reference count for the
plan, and we had no suitable resowner at hand, nor would the
available APIs support using one if we did. While it's not that
expensive to create a "plan" for CALL/DO, the cycles do add up
in repeated executions.
This patch therefore makes the following API changes:
* GetCachedPlan/ReleaseCachedPlan are modified to let the caller
specify which resowner to use to pin the plan, rather than forcing
use of CurrentResourceOwner.
* spi.c gains a "SPI_execute_plan_extended" entry point that lets
callers say which resowner to use to pin the plan. This borrows the
idea of an options struct from the recently added SPI_prepare_extended,
hopefully allowing future options to be added without more API breaks.
This supersedes SPI_execute_plan_with_paramlist (which I've marked
deprecated) as well as SPI_execute_plan_with_receiver (which is new
in v14, so I just took it out altogether).
* I also took the opportunity to remove the crude hack of letting
plpgsql reach into SPI private data structures to mark SPI plans as
"no_snapshot". It's better to treat that as an option of
SPI_prepare_extended.
Now, when running a non-atomic procedure or DO block that contains
any CALL or DO commands, plpgsql creates a ResourceOwner that
will be used to pin the plans of the CALL/DO commands. (In an
atomic context, we just use CurrentResourceOwner, as before.)
Having done this, we can just save CALL/DO plans normally,
whether or not they are used across transaction boundaries.
This seems to be good for something like 2X speedup of a CALL
of a trivial procedure with a few simple argument expressions.
By restricting the creation of an extra ResourceOwner like this,
there's essentially zero penalty in cases that can't benefit.
Pavel Stehule, with some further hacking by me
Discussion: https://postgr.es/m/CAFj8pRCLPdDAETvR7Po7gC5y_ibkn_-bOzbeJb39WHms01194Q@mail.gmail.com
2021-01-26 04:28:29 +01:00
|
|
|
cplan = GetCachedPlan(psrc, params, NULL, NULL);
|
2004-06-11 03:09:22 +02:00
|
|
|
|
|
|
|
/*
|
2009-01-01 18:12:16 +01:00
|
|
|
* Now we can define the portal.
|
|
|
|
*
|
|
|
|
* DO NOT put any code that could possibly throw an error between the
|
2011-09-16 06:42:53 +02:00
|
|
|
* above GetCachedPlan call and here.
|
2004-06-11 03:09:22 +02:00
|
|
|
*/
|
|
|
|
PortalDefineQuery(portal,
|
2008-04-02 20:31:50 +02:00
|
|
|
saved_stmt_name,
|
|
|
|
query_string,
|
2007-03-13 01:33:44 +01:00
|
|
|
psrc->commandTag,
|
2011-09-16 06:42:53 +02:00
|
|
|
cplan->stmt_list,
|
2007-03-13 01:33:44 +01:00
|
|
|
cplan);
|
2004-06-11 03:09:22 +02:00
|
|
|
|
2011-12-21 15:16:55 +01:00
|
|
|
/* Done with the snapshot used for parameter I/O and parsing/planning */
|
|
|
|
if (snapshot_set)
|
|
|
|
PopActiveSnapshot();
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2012-11-26 21:55:43 +01:00
|
|
|
/*
|
|
|
|
* And we're ready to start portal execution.
|
|
|
|
*/
|
|
|
|
PortalStart(portal, params, 0, InvalidSnapshot);
|
|
|
|
|
2003-05-08 20:16:37 +02:00
|
|
|
/*
|
|
|
|
* Apply the result format requests to the portal.
|
|
|
|
*/
|
|
|
|
PortalSetResultFormat(portal, numRFormats, rformats);
|
|
|
|
|
2019-12-11 22:03:35 +01:00
|
|
|
/*
|
|
|
|
* Done binding; remove the parameters error callback. Entries emitted
|
|
|
|
* later determine independently whether to log the parameters or not.
|
|
|
|
*/
|
|
|
|
error_context_stack = error_context_stack->previous;
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* Send BindComplete.
|
|
|
|
*/
|
2005-11-03 18:11:40 +01:00
|
|
|
if (whereToSendOutput == DestRemote)
|
2023-08-23 04:16:12 +02:00
|
|
|
pq_putemptymessage(PqMsg_BindComplete);
|
2006-09-08 00:52:01 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Emit duration logging if appropriate.
|
|
|
|
*/
|
2006-09-08 17:55:53 +02:00
|
|
|
switch (check_log_duration(msec_str, false))
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
ereport(LOG,
|
2007-03-03 00:37:23 +01:00
|
|
|
(errmsg("duration: %s ms", msec_str),
|
|
|
|
errhidestmt(true)));
|
2006-09-08 17:55:53 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ereport(LOG,
|
2006-09-13 23:59:04 +02:00
|
|
|
(errmsg("duration: %s ms bind %s%s%s: %s",
|
2006-09-08 17:55:53 +02:00
|
|
|
msec_str,
|
|
|
|
*stmt_name ? stmt_name : "<unnamed>",
|
2006-09-13 23:59:04 +02:00
|
|
|
*portal_name ? "/" : "",
|
|
|
|
*portal_name ? portal_name : "",
|
Adjust things so that the query_string of a cached plan and the sourceText of
a portal are never NULL, but reliably provide the source text of the query.
It turns out that there was only one place that was really taking a short-cut,
which was the 'EXECUTE' utility statement. That doesn't seem like a
sufficiently critical performance hotspot to justify not offering a guarantee
of validity of the portal source text. Fix it to copy the source text over
from the cached plan. Add Asserts in the places that set up cached plans and
portals to reject null source strings, and simplify a bunch of places that
formerly needed to guard against nulls.
There may be a few places that cons up statements for execution without
having any source text at all; I found one such in ConvertTriggerToFK().
It seems sufficient to inject a phony source string in such a case,
for instance
ProcessUtility((Node *) atstmt,
"(generated ALTER TABLE ADD FOREIGN KEY command)",
NULL, false, None_Receiver, NULL);
We should take a second look at the usage of debug_query_string,
particularly the recently added current_query() SQL function.
ITAGAKI Takahiro and Tom Lane
2008-07-18 22:26:06 +02:00
|
|
|
psrc->query_string),
|
2007-03-03 00:37:23 +01:00
|
|
|
errhidestmt(true),
|
2006-09-08 17:55:53 +02:00
|
|
|
errdetail_params(params)));
|
|
|
|
break;
|
|
|
|
}
|
2006-09-08 00:52:01 +02:00
|
|
|
|
|
|
|
if (save_log_statement_stats)
|
|
|
|
ShowUsage("BIND MESSAGE STATISTICS");
|
|
|
|
|
2023-04-03 16:18:38 +02:00
|
|
|
valgrind_report_error_query(debug_query_string);
|
|
|
|
|
2006-09-08 00:52:01 +02:00
|
|
|
debug_query_string = NULL;
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* exec_execute_message
|
|
|
|
*
|
|
|
|
* Process an "Execute" message for a portal
|
|
|
|
*/
|
|
|
|
static void
|
2006-09-03 05:19:45 +02:00
|
|
|
exec_execute_message(const char *portal_name, long max_rows)
|
2003-05-05 02:44:56 +02:00
|
|
|
{
|
|
|
|
CommandDest dest;
|
2003-05-06 22:26:28 +02:00
|
|
|
DestReceiver *receiver;
|
2003-05-05 02:44:56 +02:00
|
|
|
Portal portal;
|
|
|
|
bool completed;
|
2020-03-02 22:19:51 +01:00
|
|
|
QueryCompletion qc;
|
2006-09-08 00:52:01 +02:00
|
|
|
const char *sourceText;
|
2006-08-14 00:18:08 +02:00
|
|
|
const char *prepStmtName;
|
2006-09-08 00:52:01 +02:00
|
|
|
ParamListInfo portalParams;
|
2005-05-24 06:18:04 +02:00
|
|
|
bool save_log_statement_stats = log_statement_stats;
|
2006-08-14 00:18:08 +02:00
|
|
|
bool is_xact_command;
|
|
|
|
bool execute_is_fetch;
|
2006-09-08 00:52:01 +02:00
|
|
|
bool was_logged = false;
|
|
|
|
char msec_str[32];
|
2019-12-11 22:03:35 +01:00
|
|
|
ParamsErrorCbData params_data;
|
|
|
|
ErrorContextCallback params_errcxt;
|
2023-02-20 04:18:27 +01:00
|
|
|
const char *cmdtagname;
|
|
|
|
size_t cmdtaglen;
|
2003-05-05 02:44:56 +02:00
|
|
|
|
|
|
|
/* Adjust destination to tell printtup.c what to do */
|
|
|
|
dest = whereToSendOutput;
|
2005-11-03 18:11:40 +01:00
|
|
|
if (dest == DestRemote)
|
|
|
|
dest = DestRemoteExecute;
|
2003-05-05 02:44:56 +02:00
|
|
|
|
|
|
|
portal = GetPortalByName(portal_name);
|
|
|
|
if (!PortalIsValid(portal))
|
2003-07-22 21:00:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_CURSOR),
|
|
|
|
errmsg("portal \"%s\" does not exist", portal_name)));
|
2003-05-05 02:44:56 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the original query was a null string, just return
|
|
|
|
* EmptyQueryResponse.
|
|
|
|
*/
|
2020-03-02 22:19:51 +01:00
|
|
|
if (portal->commandTag == CMDTAG_UNKNOWN)
|
2003-05-05 02:44:56 +02:00
|
|
|
{
|
2007-02-20 18:32:18 +01:00
|
|
|
Assert(portal->stmts == NIL);
|
2003-05-05 02:44:56 +02:00
|
|
|
NullCommand(dest);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-08-14 00:18:08 +02:00
|
|
|
/* Does the portal contain a transaction command? */
|
2007-02-20 18:32:18 +01:00
|
|
|
is_xact_command = IsTransactionStmtList(portal->stmts);
|
2006-08-14 00:18:08 +02:00
|
|
|
|
2006-08-29 04:11:30 +02:00
|
|
|
/*
|
2006-09-08 00:52:01 +02:00
|
|
|
* We must copy the sourceText and prepStmtName into MessageContext in
|
Force immediate commit after CREATE DATABASE etc in extended protocol.
We have a few commands that "can't run in a transaction block",
meaning that if they complete their processing but then we fail
to COMMIT, we'll be left with inconsistent on-disk state.
However, the existing defenses for this are only watertight for
simple query protocol. In extended protocol, we didn't commit
until receiving a Sync message. Since the client is allowed to
issue another command instead of Sync, we're in trouble if that
command fails or is an explicit ROLLBACK. In any case, sitting
in an inconsistent state while waiting for a client message
that might not come seems pretty risky.
This case wasn't reachable via libpq before we introduced pipeline
mode, but it's always been an intended aspect of extended query
protocol, and likely there are other clients that could reach it
before.
To fix, set a flag in PreventInTransactionBlock that tells
exec_execute_message to force an immediate commit. This seems
to be the approach that does least damage to existing working
cases while still preventing the undesirable outcomes.
While here, add some documentation to protocol.sgml that explicitly
says how to use pipelining. That's latent in the existing docs if
you know what to look for, but it's better to spell it out; and it
provides a place to document this new behavior.
Per bug #17434 from Yugo Nagata. It's been wrong for ages,
so back-patch to all supported branches.
Discussion: https://postgr.es/m/17434-d9f7a064ce2a88a3@postgresql.org
2022-07-26 19:07:03 +02:00
|
|
|
* case the portal is destroyed during finish_xact_command. We do not
|
|
|
|
* make a copy of the portalParams though, preferring to just not print
|
|
|
|
* them in that case.
|
2006-08-29 04:11:30 +02:00
|
|
|
*/
|
Force immediate commit after CREATE DATABASE etc in extended protocol.
We have a few commands that "can't run in a transaction block",
meaning that if they complete their processing but then we fail
to COMMIT, we'll be left with inconsistent on-disk state.
However, the existing defenses for this are only watertight for
simple query protocol. In extended protocol, we didn't commit
until receiving a Sync message. Since the client is allowed to
issue another command instead of Sync, we're in trouble if that
command fails or is an explicit ROLLBACK. In any case, sitting
in an inconsistent state while waiting for a client message
that might not come seems pretty risky.
This case wasn't reachable via libpq before we introduced pipeline
mode, but it's always been an intended aspect of extended query
protocol, and likely there are other clients that could reach it
before.
To fix, set a flag in PreventInTransactionBlock that tells
exec_execute_message to force an immediate commit. This seems
to be the approach that does least damage to existing working
cases while still preventing the undesirable outcomes.
While here, add some documentation to protocol.sgml that explicitly
says how to use pipelining. That's latent in the existing docs if
you know what to look for, but it's better to spell it out; and it
provides a place to document this new behavior.
Per bug #17434 from Yugo Nagata. It's been wrong for ages,
so back-patch to all supported branches.
Discussion: https://postgr.es/m/17434-d9f7a064ce2a88a3@postgresql.org
2022-07-26 19:07:03 +02:00
|
|
|
sourceText = pstrdup(portal->sourceText);
|
|
|
|
if (portal->prepStmtName)
|
|
|
|
prepStmtName = pstrdup(portal->prepStmtName);
|
2006-08-29 04:11:30 +02:00
|
|
|
else
|
Force immediate commit after CREATE DATABASE etc in extended protocol.
We have a few commands that "can't run in a transaction block",
meaning that if they complete their processing but then we fail
to COMMIT, we'll be left with inconsistent on-disk state.
However, the existing defenses for this are only watertight for
simple query protocol. In extended protocol, we didn't commit
until receiving a Sync message. Since the client is allowed to
issue another command instead of Sync, we're in trouble if that
command fails or is an explicit ROLLBACK. In any case, sitting
in an inconsistent state while waiting for a client message
that might not come seems pretty risky.
This case wasn't reachable via libpq before we introduced pipeline
mode, but it's always been an intended aspect of extended query
protocol, and likely there are other clients that could reach it
before.
To fix, set a flag in PreventInTransactionBlock that tells
exec_execute_message to force an immediate commit. This seems
to be the approach that does least damage to existing working
cases while still preventing the undesirable outcomes.
While here, add some documentation to protocol.sgml that explicitly
says how to use pipelining. That's latent in the existing docs if
you know what to look for, but it's better to spell it out; and it
provides a place to document this new behavior.
Per bug #17434 from Yugo Nagata. It's been wrong for ages,
so back-patch to all supported branches.
Discussion: https://postgr.es/m/17434-d9f7a064ce2a88a3@postgresql.org
2022-07-26 19:07:03 +02:00
|
|
|
prepStmtName = "<unnamed>";
|
|
|
|
portalParams = portal->portalParams;
|
2005-05-24 06:18:04 +02:00
|
|
|
|
2006-10-19 21:52:22 +02:00
|
|
|
/*
|
|
|
|
* Report query to various monitoring facilities.
|
|
|
|
*/
|
Adjust things so that the query_string of a cached plan and the sourceText of
a portal are never NULL, but reliably provide the source text of the query.
It turns out that there was only one place that was really taking a short-cut,
which was the 'EXECUTE' utility statement. That doesn't seem like a
sufficiently critical performance hotspot to justify not offering a guarantee
of validity of the portal source text. Fix it to copy the source text over
from the cached plan. Add Asserts in the places that set up cached plans and
portals to reject null source strings, and simplify a bunch of places that
formerly needed to guard against nulls.
There may be a few places that cons up statements for execution without
having any source text at all; I found one such in ConvertTriggerToFK().
It seems sufficient to inject a phony source string in such a case,
for instance
ProcessUtility((Node *) atstmt,
"(generated ALTER TABLE ADD FOREIGN KEY command)",
NULL, false, None_Receiver, NULL);
We should take a second look at the usage of debug_query_string,
particularly the recently added current_query() SQL function.
ITAGAKI Takahiro and Tom Lane
2008-07-18 22:26:06 +02:00
|
|
|
debug_query_string = sourceText;
|
2006-10-19 21:52:22 +02:00
|
|
|
|
2012-01-19 14:19:20 +01:00
|
|
|
pgstat_report_activity(STATE_RUNNING, sourceText);
|
2006-10-19 21:52:22 +02:00
|
|
|
|
2023-02-20 04:18:27 +01:00
|
|
|
cmdtagname = GetCommandTagNameAndLen(portal->commandTag, &cmdtaglen);
|
|
|
|
|
|
|
|
set_ps_display_with_len(cmdtagname, cmdtaglen);
|
2006-10-19 21:52:22 +02:00
|
|
|
|
|
|
|
if (save_log_statement_stats)
|
|
|
|
ResetUsage();
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
BeginCommand(portal->commandTag, dest);
|
|
|
|
|
2003-05-08 20:16:37 +02:00
|
|
|
/*
|
|
|
|
* Create dest receiver in MessageContext (we don't want it in transaction
|
|
|
|
* context, because that may get deleted if portal contains VACUUM).
|
|
|
|
*/
|
2008-11-30 21:51:25 +01:00
|
|
|
receiver = CreateDestReceiver(dest);
|
|
|
|
if (dest == DestRemoteExecute)
|
|
|
|
SetRemoteDestReceiverParams(receiver, portal);
|
2003-05-08 20:16:37 +02:00
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* Ensure we are in a transaction command (this should normally be the
|
|
|
|
* case already due to prior BIND).
|
|
|
|
*/
|
2006-06-21 00:52:00 +02:00
|
|
|
start_xact_command();
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2006-10-19 21:52:22 +02:00
|
|
|
/*
|
|
|
|
* If we re-issue an Execute protocol request against an existing portal,
|
|
|
|
* then we are only fetching more rows rather than completely re-executing
|
|
|
|
* the query from the start. atStart is never reset for a v3 portal, so we
|
|
|
|
* are safe to use this check.
|
|
|
|
*/
|
|
|
|
execute_is_fetch = !portal->atStart;
|
|
|
|
|
2006-09-08 00:52:01 +02:00
|
|
|
/* Log immediately if dictated by log_statement */
|
2007-02-20 18:32:18 +01:00
|
|
|
if (check_log_statement(portal->stmts))
|
2006-09-08 00:52:01 +02:00
|
|
|
{
|
|
|
|
ereport(LOG,
|
Adjust things so that the query_string of a cached plan and the sourceText of
a portal are never NULL, but reliably provide the source text of the query.
It turns out that there was only one place that was really taking a short-cut,
which was the 'EXECUTE' utility statement. That doesn't seem like a
sufficiently critical performance hotspot to justify not offering a guarantee
of validity of the portal source text. Fix it to copy the source text over
from the cached plan. Add Asserts in the places that set up cached plans and
portals to reject null source strings, and simplify a bunch of places that
formerly needed to guard against nulls.
There may be a few places that cons up statements for execution without
having any source text at all; I found one such in ConvertTriggerToFK().
It seems sufficient to inject a phony source string in such a case,
for instance
ProcessUtility((Node *) atstmt,
"(generated ALTER TABLE ADD FOREIGN KEY command)",
NULL, false, None_Receiver, NULL);
We should take a second look at the usage of debug_query_string,
particularly the recently added current_query() SQL function.
ITAGAKI Takahiro and Tom Lane
2008-07-18 22:26:06 +02:00
|
|
|
(errmsg("%s %s%s%s: %s",
|
2006-09-08 00:52:01 +02:00
|
|
|
execute_is_fetch ?
|
2006-09-13 23:59:04 +02:00
|
|
|
_("execute fetch from") :
|
|
|
|
_("execute"),
|
2006-09-08 00:52:01 +02:00
|
|
|
prepStmtName,
|
|
|
|
*portal_name ? "/" : "",
|
|
|
|
*portal_name ? portal_name : "",
|
Adjust things so that the query_string of a cached plan and the sourceText of
a portal are never NULL, but reliably provide the source text of the query.
It turns out that there was only one place that was really taking a short-cut,
which was the 'EXECUTE' utility statement. That doesn't seem like a
sufficiently critical performance hotspot to justify not offering a guarantee
of validity of the portal source text. Fix it to copy the source text over
from the cached plan. Add Asserts in the places that set up cached plans and
portals to reject null source strings, and simplify a bunch of places that
formerly needed to guard against nulls.
There may be a few places that cons up statements for execution without
having any source text at all; I found one such in ConvertTriggerToFK().
It seems sufficient to inject a phony source string in such a case,
for instance
ProcessUtility((Node *) atstmt,
"(generated ALTER TABLE ADD FOREIGN KEY command)",
NULL, false, None_Receiver, NULL);
We should take a second look at the usage of debug_query_string,
particularly the recently added current_query() SQL function.
ITAGAKI Takahiro and Tom Lane
2008-07-18 22:26:06 +02:00
|
|
|
sourceText),
|
2007-03-03 00:37:23 +01:00
|
|
|
errhidestmt(true),
|
2006-09-08 00:52:01 +02:00
|
|
|
errdetail_params(portalParams)));
|
|
|
|
was_logged = true;
|
|
|
|
}
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* If we are in aborted transaction state, the only portals we can
|
|
|
|
* actually run are those containing COMMIT or ROLLBACK commands.
|
|
|
|
*/
|
2005-11-10 01:31:34 +01:00
|
|
|
if (IsAbortedTransactionBlockState() &&
|
2007-02-20 18:32:18 +01:00
|
|
|
!IsTransactionExitStmtList(portal->stmts))
|
2005-11-10 01:31:34 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
|
|
|
|
errmsg("current transaction is aborted, "
|
2010-01-16 11:05:59 +01:00
|
|
|
"commands ignored until end of transaction block"),
|
|
|
|
errdetail_abort()));
|
2003-05-05 02:44:56 +02:00
|
|
|
|
|
|
|
/* Check for cancel signal before we start execution */
|
|
|
|
CHECK_FOR_INTERRUPTS();
|
|
|
|
|
|
|
|
/*
|
2019-12-11 22:03:35 +01:00
|
|
|
* Okay to run the portal. Set the error callback so that parameters are
|
|
|
|
* logged. The parameters must have been saved during the bind phase.
|
2003-05-05 02:44:56 +02:00
|
|
|
*/
|
2019-12-11 22:03:35 +01:00
|
|
|
params_data.portalName = portal->name;
|
|
|
|
params_data.params = portalParams;
|
|
|
|
params_errcxt.previous = error_context_stack;
|
|
|
|
params_errcxt.callback = ParamsErrorCallback;
|
|
|
|
params_errcxt.arg = (void *) ¶ms_data;
|
|
|
|
error_context_stack = ¶ms_errcxt;
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
if (max_rows <= 0)
|
|
|
|
max_rows = FETCH_ALL;
|
|
|
|
|
|
|
|
completed = PortalRun(portal,
|
|
|
|
max_rows,
|
2007-03-22 20:55:04 +01:00
|
|
|
true, /* always top level */
|
2017-03-23 18:05:48 +01:00
|
|
|
!execute_is_fetch && max_rows == FETCH_ALL,
|
2003-05-06 22:26:28 +02:00
|
|
|
receiver,
|
|
|
|
receiver,
|
2020-03-02 22:19:51 +01:00
|
|
|
&qc);
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2017-09-07 18:06:23 +02:00
|
|
|
receiver->rDestroy(receiver);
|
2003-05-06 22:26:28 +02:00
|
|
|
|
2019-12-11 22:03:35 +01:00
|
|
|
/* Done executing; remove the params error callback */
|
|
|
|
error_context_stack = error_context_stack->previous;
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
if (completed)
|
|
|
|
{
|
Force immediate commit after CREATE DATABASE etc in extended protocol.
We have a few commands that "can't run in a transaction block",
meaning that if they complete their processing but then we fail
to COMMIT, we'll be left with inconsistent on-disk state.
However, the existing defenses for this are only watertight for
simple query protocol. In extended protocol, we didn't commit
until receiving a Sync message. Since the client is allowed to
issue another command instead of Sync, we're in trouble if that
command fails or is an explicit ROLLBACK. In any case, sitting
in an inconsistent state while waiting for a client message
that might not come seems pretty risky.
This case wasn't reachable via libpq before we introduced pipeline
mode, but it's always been an intended aspect of extended query
protocol, and likely there are other clients that could reach it
before.
To fix, set a flag in PreventInTransactionBlock that tells
exec_execute_message to force an immediate commit. This seems
to be the approach that does least damage to existing working
cases while still preventing the undesirable outcomes.
While here, add some documentation to protocol.sgml that explicitly
says how to use pipelining. That's latent in the existing docs if
you know what to look for, but it's better to spell it out; and it
provides a place to document this new behavior.
Per bug #17434 from Yugo Nagata. It's been wrong for ages,
so back-patch to all supported branches.
Discussion: https://postgr.es/m/17434-d9f7a064ce2a88a3@postgresql.org
2022-07-26 19:07:03 +02:00
|
|
|
if (is_xact_command || (MyXactFlags & XACT_FLAGS_NEEDIMMEDIATECOMMIT))
|
2003-05-05 02:44:56 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If this was a transaction control statement, commit it. We
|
|
|
|
* will start a new xact command for the next command (if any).
|
Force immediate commit after CREATE DATABASE etc in extended protocol.
We have a few commands that "can't run in a transaction block",
meaning that if they complete their processing but then we fail
to COMMIT, we'll be left with inconsistent on-disk state.
However, the existing defenses for this are only watertight for
simple query protocol. In extended protocol, we didn't commit
until receiving a Sync message. Since the client is allowed to
issue another command instead of Sync, we're in trouble if that
command fails or is an explicit ROLLBACK. In any case, sitting
in an inconsistent state while waiting for a client message
that might not come seems pretty risky.
This case wasn't reachable via libpq before we introduced pipeline
mode, but it's always been an intended aspect of extended query
protocol, and likely there are other clients that could reach it
before.
To fix, set a flag in PreventInTransactionBlock that tells
exec_execute_message to force an immediate commit. This seems
to be the approach that does least damage to existing working
cases while still preventing the undesirable outcomes.
While here, add some documentation to protocol.sgml that explicitly
says how to use pipelining. That's latent in the existing docs if
you know what to look for, but it's better to spell it out; and it
provides a place to document this new behavior.
Per bug #17434 from Yugo Nagata. It's been wrong for ages,
so back-patch to all supported branches.
Discussion: https://postgr.es/m/17434-d9f7a064ce2a88a3@postgresql.org
2022-07-26 19:07:03 +02:00
|
|
|
* Likewise if the statement required immediate commit. Without
|
|
|
|
* this provision, we wouldn't force commit until Sync is
|
|
|
|
* received, which creates a hazard if the client tries to
|
|
|
|
* pipeline immediate-commit statements.
|
2003-05-05 02:44:56 +02:00
|
|
|
*/
|
2003-05-14 05:26:03 +02:00
|
|
|
finish_xact_command();
|
Force immediate commit after CREATE DATABASE etc in extended protocol.
We have a few commands that "can't run in a transaction block",
meaning that if they complete their processing but then we fail
to COMMIT, we'll be left with inconsistent on-disk state.
However, the existing defenses for this are only watertight for
simple query protocol. In extended protocol, we didn't commit
until receiving a Sync message. Since the client is allowed to
issue another command instead of Sync, we're in trouble if that
command fails or is an explicit ROLLBACK. In any case, sitting
in an inconsistent state while waiting for a client message
that might not come seems pretty risky.
This case wasn't reachable via libpq before we introduced pipeline
mode, but it's always been an intended aspect of extended query
protocol, and likely there are other clients that could reach it
before.
To fix, set a flag in PreventInTransactionBlock that tells
exec_execute_message to force an immediate commit. This seems
to be the approach that does least damage to existing working
cases while still preventing the undesirable outcomes.
While here, add some documentation to protocol.sgml that explicitly
says how to use pipelining. That's latent in the existing docs if
you know what to look for, but it's better to spell it out; and it
provides a place to document this new behavior.
Per bug #17434 from Yugo Nagata. It's been wrong for ages,
so back-patch to all supported branches.
Discussion: https://postgr.es/m/17434-d9f7a064ce2a88a3@postgresql.org
2022-07-26 19:07:03 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* These commands typically don't have any parameters, and even if
|
|
|
|
* one did we couldn't print them now because the storage went
|
|
|
|
* away during finish_xact_command. So pretend there were none.
|
|
|
|
*/
|
|
|
|
portalParams = NULL;
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We need a CommandCounterIncrement after every query, except
|
|
|
|
* those that start or end a transaction block.
|
|
|
|
*/
|
|
|
|
CommandCounterIncrement();
|
2017-09-19 04:36:44 +02:00
|
|
|
|
Rethink handling of [Prevent|Is]InTransactionBlock in pipeline mode.
Commits f92944137 et al. made IsInTransactionBlock() set the
XACT_FLAGS_NEEDIMMEDIATECOMMIT flag before returning "false",
on the grounds that that kept its API promises equivalent to those of
PreventInTransactionBlock(). This turns out to be a bad idea though,
because it allows an ANALYZE in a pipelined series of commands to
cause an immediate commit, which is unexpected.
Furthermore, if we return "false" then we have another issue,
which is that ANALYZE will decide it's allowed to do internal
commit-and-start-transaction sequences, thus possibly unexpectedly
committing the effects of previous commands in the pipeline.
To fix the latter situation, invent another transaction state flag
XACT_FLAGS_PIPELINING, which explicitly records the fact that we
have executed some extended-protocol command and not yet seen a
commit for it. Then, require that flag to not be set before allowing
InTransactionBlock() to return "false".
Having done that, we can remove its setting of NEEDIMMEDIATECOMMIT
without fear of causing problems. This means that the API guarantees
of IsInTransactionBlock now diverge from PreventInTransactionBlock,
which is mildly annoying, but it seems OK given the very limited usage
of IsInTransactionBlock. (In any case, a caller preferring the old
behavior could always set NEEDIMMEDIATECOMMIT for itself.)
For consistency also require XACT_FLAGS_PIPELINING to not be set
in PreventInTransactionBlock. This too is meant to prevent commands
such as CREATE DATABASE from silently committing previous commands
in a pipeline.
Per report from Peter Eisentraut. As before, back-patch to all
supported branches (which sadly no longer includes v10).
Discussion: https://postgr.es/m/65a899dd-aebc-f667-1d0a-abb89ff3abf8@enterprisedb.com
2022-12-13 20:23:58 +01:00
|
|
|
/*
|
|
|
|
* Set XACT_FLAGS_PIPELINING whenever we complete an Execute
|
|
|
|
* message without immediately committing the transaction.
|
|
|
|
*/
|
|
|
|
MyXactFlags |= XACT_FLAGS_PIPELINING;
|
|
|
|
|
Reset statement_timeout between queries of a multi-query string.
Historically, we started the timer (if StatementTimeout > 0) at the
beginning of a simple-Query message and usually let it run until the
end, so that the timeout limit applied to the entire query string,
and intra-string changes of the statement_timeout GUC had no effect.
But, confusingly, a COMMIT within the string would reset the state
and allow a fresh timeout cycle to start with the current setting.
Commit f8e5f156b changed the behavior of statement_timeout for extended
query protocol, and as an apparently-unintended side effect, a change in
the statement_timeout GUC during a multi-statement simple-Query message
might have an effect immediately --- but only if it was going from
"disabled" to "enabled".
This is all pretty confusing, not to mention completely undocumented.
Let's change things so that the timeout is always reset between queries
of a multi-query string, whether they're transaction control commands
or not. Thus the active timeout setting is applied to each query in
the string, separately. This costs a few more cycles if statement_timeout
is active, but it provides much more intuitive behavior, especially if one
changes statement_timeout in one of the queries of the string.
Also, add something to the documentation to explain all this.
Per bug #16035 from Raj Mohite. Although this is a bug fix, I'm hesitant
to back-patch it; conceivably somebody has worked out the old behavior
and is depending on it. (But note that this change should make the
behavior less restrictive in most cases, since the timeout will now
be applied to shorter segments of code.)
Discussion: https://postgr.es/m/16035-456e6e69ebfd4374@postgresql.org
2019-10-25 17:15:50 +02:00
|
|
|
/*
|
|
|
|
* Disable statement timeout whenever we complete an Execute
|
|
|
|
* message. The next protocol message will start a fresh timeout.
|
|
|
|
*/
|
2017-09-19 04:36:44 +02:00
|
|
|
disable_statement_timeout();
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Send appropriate CommandComplete to client */
|
2020-03-02 22:19:51 +01:00
|
|
|
EndCommand(&qc, dest, false);
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Portal run not complete, so send PortalSuspended */
|
2005-11-03 18:11:40 +01:00
|
|
|
if (whereToSendOutput == DestRemote)
|
2023-08-23 04:16:12 +02:00
|
|
|
pq_putemptymessage(PqMsg_PortalSuspended);
|
Rethink handling of [Prevent|Is]InTransactionBlock in pipeline mode.
Commits f92944137 et al. made IsInTransactionBlock() set the
XACT_FLAGS_NEEDIMMEDIATECOMMIT flag before returning "false",
on the grounds that that kept its API promises equivalent to those of
PreventInTransactionBlock(). This turns out to be a bad idea though,
because it allows an ANALYZE in a pipelined series of commands to
cause an immediate commit, which is unexpected.
Furthermore, if we return "false" then we have another issue,
which is that ANALYZE will decide it's allowed to do internal
commit-and-start-transaction sequences, thus possibly unexpectedly
committing the effects of previous commands in the pipeline.
To fix the latter situation, invent another transaction state flag
XACT_FLAGS_PIPELINING, which explicitly records the fact that we
have executed some extended-protocol command and not yet seen a
commit for it. Then, require that flag to not be set before allowing
InTransactionBlock() to return "false".
Having done that, we can remove its setting of NEEDIMMEDIATECOMMIT
without fear of causing problems. This means that the API guarantees
of IsInTransactionBlock now diverge from PreventInTransactionBlock,
which is mildly annoying, but it seems OK given the very limited usage
of IsInTransactionBlock. (In any case, a caller preferring the old
behavior could always set NEEDIMMEDIATECOMMIT for itself.)
For consistency also require XACT_FLAGS_PIPELINING to not be set
in PreventInTransactionBlock. This too is meant to prevent commands
such as CREATE DATABASE from silently committing previous commands
in a pipeline.
Per report from Peter Eisentraut. As before, back-patch to all
supported branches (which sadly no longer includes v10).
Discussion: https://postgr.es/m/65a899dd-aebc-f667-1d0a-abb89ff3abf8@enterprisedb.com
2022-12-13 20:23:58 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set XACT_FLAGS_PIPELINING whenever we suspend an Execute message,
|
|
|
|
* too.
|
|
|
|
*/
|
|
|
|
MyXactFlags |= XACT_FLAGS_PIPELINING;
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
|
2005-05-24 06:18:04 +02:00
|
|
|
/*
|
2006-06-21 00:52:00 +02:00
|
|
|
* Emit duration logging if appropriate.
|
2005-05-24 06:18:04 +02:00
|
|
|
*/
|
2006-09-08 17:55:53 +02:00
|
|
|
switch (check_log_duration(msec_str, was_logged))
|
2006-09-08 00:52:01 +02:00
|
|
|
{
|
2006-09-08 17:55:53 +02:00
|
|
|
case 1:
|
2006-09-08 00:52:01 +02:00
|
|
|
ereport(LOG,
|
2007-03-03 00:37:23 +01:00
|
|
|
(errmsg("duration: %s ms", msec_str),
|
|
|
|
errhidestmt(true)));
|
2006-09-08 17:55:53 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2006-09-08 00:52:01 +02:00
|
|
|
ereport(LOG,
|
Adjust things so that the query_string of a cached plan and the sourceText of
a portal are never NULL, but reliably provide the source text of the query.
It turns out that there was only one place that was really taking a short-cut,
which was the 'EXECUTE' utility statement. That doesn't seem like a
sufficiently critical performance hotspot to justify not offering a guarantee
of validity of the portal source text. Fix it to copy the source text over
from the cached plan. Add Asserts in the places that set up cached plans and
portals to reject null source strings, and simplify a bunch of places that
formerly needed to guard against nulls.
There may be a few places that cons up statements for execution without
having any source text at all; I found one such in ConvertTriggerToFK().
It seems sufficient to inject a phony source string in such a case,
for instance
ProcessUtility((Node *) atstmt,
"(generated ALTER TABLE ADD FOREIGN KEY command)",
NULL, false, None_Receiver, NULL);
We should take a second look at the usage of debug_query_string,
particularly the recently added current_query() SQL function.
ITAGAKI Takahiro and Tom Lane
2008-07-18 22:26:06 +02:00
|
|
|
(errmsg("duration: %s ms %s %s%s%s: %s",
|
2006-09-08 00:52:01 +02:00
|
|
|
msec_str,
|
|
|
|
execute_is_fetch ?
|
|
|
|
_("execute fetch from") :
|
|
|
|
_("execute"),
|
|
|
|
prepStmtName,
|
|
|
|
*portal_name ? "/" : "",
|
|
|
|
*portal_name ? portal_name : "",
|
Adjust things so that the query_string of a cached plan and the sourceText of
a portal are never NULL, but reliably provide the source text of the query.
It turns out that there was only one place that was really taking a short-cut,
which was the 'EXECUTE' utility statement. That doesn't seem like a
sufficiently critical performance hotspot to justify not offering a guarantee
of validity of the portal source text. Fix it to copy the source text over
from the cached plan. Add Asserts in the places that set up cached plans and
portals to reject null source strings, and simplify a bunch of places that
formerly needed to guard against nulls.
There may be a few places that cons up statements for execution without
having any source text at all; I found one such in ConvertTriggerToFK().
It seems sufficient to inject a phony source string in such a case,
for instance
ProcessUtility((Node *) atstmt,
"(generated ALTER TABLE ADD FOREIGN KEY command)",
NULL, false, None_Receiver, NULL);
We should take a second look at the usage of debug_query_string,
particularly the recently added current_query() SQL function.
ITAGAKI Takahiro and Tom Lane
2008-07-18 22:26:06 +02:00
|
|
|
sourceText),
|
2007-03-03 00:37:23 +01:00
|
|
|
errhidestmt(true),
|
2006-09-08 00:52:01 +02:00
|
|
|
errdetail_params(portalParams)));
|
2006-09-08 17:55:53 +02:00
|
|
|
break;
|
2006-09-08 00:52:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (save_log_statement_stats)
|
|
|
|
ShowUsage("EXECUTE MESSAGE STATISTICS");
|
|
|
|
|
2023-04-03 16:18:38 +02:00
|
|
|
valgrind_report_error_query(debug_query_string);
|
|
|
|
|
2006-09-08 00:52:01 +02:00
|
|
|
debug_query_string = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2007-02-20 18:32:18 +01:00
|
|
|
* check_log_statement
|
2006-09-08 00:52:01 +02:00
|
|
|
* Determine whether command should be logged because of log_statement
|
|
|
|
*
|
2014-07-07 12:39:42 +02:00
|
|
|
* stmt_list can be either raw grammar output or a list of planned
|
2007-02-20 18:32:18 +01:00
|
|
|
* statements
|
2006-09-08 00:52:01 +02:00
|
|
|
*/
|
|
|
|
static bool
|
2007-02-20 18:32:18 +01:00
|
|
|
check_log_statement(List *stmt_list)
|
2006-09-08 00:52:01 +02:00
|
|
|
{
|
2007-02-20 18:32:18 +01:00
|
|
|
ListCell *stmt_item;
|
2006-09-08 00:52:01 +02:00
|
|
|
|
|
|
|
if (log_statement == LOGSTMT_NONE)
|
|
|
|
return false;
|
|
|
|
if (log_statement == LOGSTMT_ALL)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
/* Else we have to inspect the statement(s) to see whether to log */
|
2007-02-20 18:32:18 +01:00
|
|
|
foreach(stmt_item, stmt_list)
|
2006-09-08 00:52:01 +02:00
|
|
|
{
|
2007-02-20 18:32:18 +01:00
|
|
|
Node *stmt = (Node *) lfirst(stmt_item);
|
2006-09-08 00:52:01 +02:00
|
|
|
|
2007-02-20 18:32:18 +01:00
|
|
|
if (GetCommandLogLevel(stmt) <= log_statement)
|
2006-09-08 00:52:01 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* check_log_duration
|
2019-08-04 20:29:00 +02:00
|
|
|
* Determine whether current command's duration should be logged
|
2019-04-03 23:43:59 +02:00
|
|
|
* We also check if this statement in this transaction must be logged
|
|
|
|
* (regardless of its duration).
|
2006-09-08 00:52:01 +02:00
|
|
|
*
|
2006-09-08 17:55:53 +02:00
|
|
|
* Returns:
|
|
|
|
* 0 if no logging is needed
|
|
|
|
* 1 if just the duration should be logged
|
|
|
|
* 2 if duration and query details should be logged
|
|
|
|
*
|
2006-09-08 00:52:01 +02:00
|
|
|
* If logging is needed, the duration in msec is formatted into msec_str[],
|
|
|
|
* which must be a 32-byte buffer.
|
2006-09-08 17:55:53 +02:00
|
|
|
*
|
2017-08-16 06:22:32 +02:00
|
|
|
* was_logged should be true if caller already logged query details (this
|
2006-09-08 17:55:53 +02:00
|
|
|
* essentially prevents 2 from being returned).
|
2006-09-08 00:52:01 +02:00
|
|
|
*/
|
2006-09-08 17:55:53 +02:00
|
|
|
int
|
|
|
|
check_log_duration(char *msec_str, bool was_logged)
|
2006-09-08 00:52:01 +02:00
|
|
|
{
|
2019-11-04 01:57:45 +01:00
|
|
|
if (log_duration || log_min_duration_sample >= 0 ||
|
|
|
|
log_min_duration_statement >= 0 || xact_is_sampled)
|
2005-05-24 06:18:04 +02:00
|
|
|
{
|
2006-06-21 00:52:00 +02:00
|
|
|
long secs;
|
|
|
|
int usecs;
|
|
|
|
int msecs;
|
2019-11-04 01:57:45 +01:00
|
|
|
bool exceeded_duration;
|
|
|
|
bool exceeded_sample_duration;
|
|
|
|
bool in_sample = false;
|
2005-05-24 06:18:04 +02:00
|
|
|
|
2006-06-21 00:52:00 +02:00
|
|
|
TimestampDifference(GetCurrentStatementStartTimestamp(),
|
|
|
|
GetCurrentTimestamp(),
|
|
|
|
&secs, &usecs);
|
|
|
|
msecs = usecs / 1000;
|
2005-05-24 06:18:04 +02:00
|
|
|
|
|
|
|
/*
|
2019-11-04 01:57:45 +01:00
|
|
|
* This odd-looking test for log_min_duration_* being exceeded is
|
|
|
|
* designed to avoid integer overflow with very long durations: don't
|
|
|
|
* compute secs * 1000 until we've verified it will fit in int.
|
2005-05-24 06:18:04 +02:00
|
|
|
*/
|
2019-11-04 01:57:45 +01:00
|
|
|
exceeded_duration = (log_min_duration_statement == 0 ||
|
|
|
|
(log_min_duration_statement > 0 &&
|
|
|
|
(secs > log_min_duration_statement / 1000 ||
|
|
|
|
secs * 1000 + msecs >= log_min_duration_statement)));
|
2006-09-08 17:55:53 +02:00
|
|
|
|
2019-11-04 01:57:45 +01:00
|
|
|
exceeded_sample_duration = (log_min_duration_sample == 0 ||
|
|
|
|
(log_min_duration_sample > 0 &&
|
|
|
|
(secs > log_min_duration_sample / 1000 ||
|
|
|
|
secs * 1000 + msecs >= log_min_duration_sample)));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do not log if log_statement_sample_rate = 0. Log a sample if
|
Replace random(), pg_erand48(), etc with a better PRNG API and algorithm.
Standardize on xoroshiro128** as our basic PRNG algorithm, eliminating
a bunch of platform dependencies as well as fundamentally-obsolete PRNG
code. In addition, this API replacement will ease replacing the
algorithm again in future, should that become necessary.
xoroshiro128** is a few percent slower than the drand48 family,
but it can produce full-width 64-bit random values not only 48-bit,
and it should be much more trustworthy. It's likely to be noticeably
faster than the platform's random(), depending on which platform you
are thinking about; and we can have non-global state vectors easily,
unlike with random(). It is not cryptographically strong, but neither
are the functions it replaces.
Fabien Coelho, reviewed by Dean Rasheed, Aleksander Alekseev, and myself
Discussion: https://postgr.es/m/alpine.DEB.2.22.394.2105241211230.165418@pseudo
2021-11-29 03:32:36 +01:00
|
|
|
* log_statement_sample_rate <= 1 and avoid unnecessary PRNG call if
|
|
|
|
* log_statement_sample_rate = 1.
|
2019-11-04 01:57:45 +01:00
|
|
|
*/
|
|
|
|
if (exceeded_sample_duration)
|
|
|
|
in_sample = log_statement_sample_rate != 0 &&
|
|
|
|
(log_statement_sample_rate == 1 ||
|
Replace random(), pg_erand48(), etc with a better PRNG API and algorithm.
Standardize on xoroshiro128** as our basic PRNG algorithm, eliminating
a bunch of platform dependencies as well as fundamentally-obsolete PRNG
code. In addition, this API replacement will ease replacing the
algorithm again in future, should that become necessary.
xoroshiro128** is a few percent slower than the drand48 family,
but it can produce full-width 64-bit random values not only 48-bit,
and it should be much more trustworthy. It's likely to be noticeably
faster than the platform's random(), depending on which platform you
are thinking about; and we can have non-global state vectors easily,
unlike with random(). It is not cryptographically strong, but neither
are the functions it replaces.
Fabien Coelho, reviewed by Dean Rasheed, Aleksander Alekseev, and myself
Discussion: https://postgr.es/m/alpine.DEB.2.22.394.2105241211230.165418@pseudo
2021-11-29 03:32:36 +01:00
|
|
|
pg_prng_double(&pg_global_prng_state) <= log_statement_sample_rate);
|
2019-11-04 01:57:45 +01:00
|
|
|
|
|
|
|
if (exceeded_duration || in_sample || log_duration || xact_is_sampled)
|
2006-06-21 00:52:00 +02:00
|
|
|
{
|
2006-09-08 00:52:01 +02:00
|
|
|
snprintf(msec_str, 32, "%ld.%03d",
|
|
|
|
secs * 1000 + msecs, usecs % 1000);
|
2019-11-04 01:57:45 +01:00
|
|
|
if ((exceeded_duration || in_sample || xact_is_sampled) && !was_logged)
|
2006-09-08 17:55:53 +02:00
|
|
|
return 2;
|
|
|
|
else
|
|
|
|
return 1;
|
2006-06-21 00:52:00 +02:00
|
|
|
}
|
2005-05-24 06:18:04 +02:00
|
|
|
}
|
|
|
|
|
2006-09-08 17:55:53 +02:00
|
|
|
return 0;
|
2006-09-08 00:52:01 +02:00
|
|
|
}
|
2005-05-24 06:18:04 +02:00
|
|
|
|
2006-09-08 00:52:01 +02:00
|
|
|
/*
|
|
|
|
* errdetail_execute
|
|
|
|
*
|
|
|
|
* Add an errdetail() line showing the query referenced by an EXECUTE, if any.
|
|
|
|
* The argument is the raw parsetree list.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
errdetail_execute(List *raw_parsetree_list)
|
|
|
|
{
|
|
|
|
ListCell *parsetree_item;
|
|
|
|
|
|
|
|
foreach(parsetree_item, raw_parsetree_list)
|
|
|
|
{
|
Improve castNode notation by introducing list-extraction-specific variants.
This extends the castNode() notation introduced by commit 5bcab1114 to
provide, in one step, extraction of a list cell's pointer and coercion to
a concrete node type. For example, "lfirst_node(Foo, lc)" is the same
as "castNode(Foo, lfirst(lc))". Almost half of the uses of castNode
that have appeared so far include a list extraction call, so this is
pretty widely useful, and it saves a few more keystrokes compared to the
old way.
As with the previous patch, back-patch the addition of these macros to
pg_list.h, so that the notation will be available when back-patching.
Patch by me, after an idea of Andrew Gierth's.
Discussion: https://postgr.es/m/14197.1491841216@sss.pgh.pa.us
2017-04-10 19:51:29 +02:00
|
|
|
RawStmt *parsetree = lfirst_node(RawStmt, parsetree_item);
|
2006-09-08 00:52:01 +02:00
|
|
|
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
if (IsA(parsetree->stmt, ExecuteStmt))
|
2006-09-08 00:52:01 +02:00
|
|
|
{
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
ExecuteStmt *stmt = (ExecuteStmt *) parsetree->stmt;
|
2006-09-08 00:52:01 +02:00
|
|
|
PreparedStatement *pstmt;
|
|
|
|
|
|
|
|
pstmt = FetchPreparedStatement(stmt->name, false);
|
Adjust things so that the query_string of a cached plan and the sourceText of
a portal are never NULL, but reliably provide the source text of the query.
It turns out that there was only one place that was really taking a short-cut,
which was the 'EXECUTE' utility statement. That doesn't seem like a
sufficiently critical performance hotspot to justify not offering a guarantee
of validity of the portal source text. Fix it to copy the source text over
from the cached plan. Add Asserts in the places that set up cached plans and
portals to reject null source strings, and simplify a bunch of places that
formerly needed to guard against nulls.
There may be a few places that cons up statements for execution without
having any source text at all; I found one such in ConvertTriggerToFK().
It seems sufficient to inject a phony source string in such a case,
for instance
ProcessUtility((Node *) atstmt,
"(generated ALTER TABLE ADD FOREIGN KEY command)",
NULL, false, None_Receiver, NULL);
We should take a second look at the usage of debug_query_string,
particularly the recently added current_query() SQL function.
ITAGAKI Takahiro and Tom Lane
2008-07-18 22:26:06 +02:00
|
|
|
if (pstmt)
|
2006-09-08 00:52:01 +02:00
|
|
|
{
|
2007-03-13 01:33:44 +01:00
|
|
|
errdetail("prepare: %s", pstmt->plansource->query_string);
|
2006-09-08 00:52:01 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* errdetail_params
|
|
|
|
*
|
|
|
|
* Add an errdetail() line showing bind-parameter data, if available.
|
2020-04-02 21:04:51 +02:00
|
|
|
* Note that this is only used for statement logging, so it is controlled
|
|
|
|
* by log_parameter_max_length not log_parameter_max_length_on_error.
|
2006-09-08 00:52:01 +02:00
|
|
|
*/
|
|
|
|
static int
|
|
|
|
errdetail_params(ParamListInfo params)
|
|
|
|
{
|
2020-04-02 21:04:51 +02:00
|
|
|
if (params && params->numParams > 0 && log_parameter_max_length != 0)
|
2006-09-08 00:52:01 +02:00
|
|
|
{
|
2020-04-02 21:04:51 +02:00
|
|
|
char *str;
|
2006-09-08 00:52:01 +02:00
|
|
|
|
2020-04-02 21:04:51 +02:00
|
|
|
str = BuildParamLogString(params, NULL, log_parameter_max_length);
|
2019-12-11 22:03:35 +01:00
|
|
|
if (str && str[0] != '\0')
|
2024-01-18 09:35:12 +01:00
|
|
|
errdetail("Parameters: %s", str);
|
2006-09-08 00:52:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
|
2010-01-16 11:05:59 +01:00
|
|
|
/*
|
|
|
|
* errdetail_abort
|
|
|
|
*
|
|
|
|
* Add an errdetail() line showing abort reason, if any.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
errdetail_abort(void)
|
|
|
|
{
|
|
|
|
if (MyProc->recoveryConflictPending)
|
2024-01-18 09:35:12 +01:00
|
|
|
errdetail("Abort reason: recovery conflict");
|
2010-01-16 11:05:59 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-01-23 18:04:05 +01:00
|
|
|
/*
|
|
|
|
* errdetail_recovery_conflict
|
|
|
|
*
|
|
|
|
* Add an errdetail() line showing conflict source.
|
|
|
|
*/
|
|
|
|
static int
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
errdetail_recovery_conflict(ProcSignalReason reason)
|
2010-01-23 18:04:05 +01:00
|
|
|
{
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
switch (reason)
|
2010-01-23 18:04:05 +01:00
|
|
|
{
|
|
|
|
case PROCSIG_RECOVERY_CONFLICT_BUFFERPIN:
|
|
|
|
errdetail("User was holding shared buffer pin for too long.");
|
|
|
|
break;
|
|
|
|
case PROCSIG_RECOVERY_CONFLICT_LOCK:
|
|
|
|
errdetail("User was holding a relation lock for too long.");
|
|
|
|
break;
|
|
|
|
case PROCSIG_RECOVERY_CONFLICT_TABLESPACE:
|
2010-03-21 01:17:59 +01:00
|
|
|
errdetail("User was or might have been using tablespace that must be dropped.");
|
2010-01-23 18:04:05 +01:00
|
|
|
break;
|
|
|
|
case PROCSIG_RECOVERY_CONFLICT_SNAPSHOT:
|
|
|
|
errdetail("User query might have needed to see row versions that must be removed.");
|
|
|
|
break;
|
2023-04-08 08:11:28 +02:00
|
|
|
case PROCSIG_RECOVERY_CONFLICT_LOGICALSLOT:
|
2023-07-10 10:46:54 +02:00
|
|
|
errdetail("User was using a logical replication slot that must be invalidated.");
|
2023-04-08 08:11:28 +02:00
|
|
|
break;
|
2010-02-13 02:32:20 +01:00
|
|
|
case PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK:
|
|
|
|
errdetail("User transaction caused buffer deadlock with recovery.");
|
|
|
|
break;
|
2010-01-23 18:04:05 +01:00
|
|
|
case PROCSIG_RECOVERY_CONFLICT_DATABASE:
|
|
|
|
errdetail("User was connected to a database that must be dropped.");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
/* no errdetail */
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-03-16 16:16:41 +01:00
|
|
|
/*
|
|
|
|
* bind_param_error_callback
|
|
|
|
*
|
|
|
|
* Error context callback used while parsing parameters in a Bind message
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
bind_param_error_callback(void *arg)
|
|
|
|
{
|
|
|
|
BindParamCbData *data = (BindParamCbData *) arg;
|
|
|
|
StringInfoData buf;
|
|
|
|
char *quotedval;
|
|
|
|
|
|
|
|
if (data->paramno < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* If we have a textual value, quote it, and trim if necessary */
|
|
|
|
if (data->paramval)
|
|
|
|
{
|
|
|
|
initStringInfo(&buf);
|
|
|
|
appendStringInfoStringQuoted(&buf, data->paramval,
|
|
|
|
log_parameter_max_length_on_error);
|
|
|
|
quotedval = buf.data;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
quotedval = NULL;
|
|
|
|
|
|
|
|
if (data->portalName && data->portalName[0] != '\0')
|
|
|
|
{
|
|
|
|
if (quotedval)
|
|
|
|
errcontext("portal \"%s\" parameter $%d = %s",
|
|
|
|
data->portalName, data->paramno + 1, quotedval);
|
|
|
|
else
|
|
|
|
errcontext("portal \"%s\" parameter $%d",
|
|
|
|
data->portalName, data->paramno + 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (quotedval)
|
|
|
|
errcontext("unnamed portal parameter $%d = %s",
|
|
|
|
data->paramno + 1, quotedval);
|
|
|
|
else
|
|
|
|
errcontext("unnamed portal parameter $%d",
|
|
|
|
data->paramno + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (quotedval)
|
|
|
|
pfree(quotedval);
|
|
|
|
}
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* exec_describe_statement_message
|
|
|
|
*
|
|
|
|
* Process a "Describe" message for a prepared statement
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
exec_describe_statement_message(const char *stmt_name)
|
|
|
|
{
|
2007-03-13 01:33:44 +01:00
|
|
|
CachedPlanSource *psrc;
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2005-12-14 18:06:28 +01:00
|
|
|
/*
|
|
|
|
* Start up a transaction command. (Note that this will normally change
|
|
|
|
* current memory context.) Nothing happens if we are already in one.
|
|
|
|
*/
|
2006-06-21 00:52:00 +02:00
|
|
|
start_xact_command();
|
2005-12-14 18:06:28 +01:00
|
|
|
|
|
|
|
/* Switch back to message context */
|
|
|
|
MemoryContextSwitchTo(MessageContext);
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/* Find prepared statement */
|
|
|
|
if (stmt_name[0] != '\0')
|
2007-03-13 01:33:44 +01:00
|
|
|
{
|
|
|
|
PreparedStatement *pstmt;
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
pstmt = FetchPreparedStatement(stmt_name, true);
|
2007-03-13 01:33:44 +01:00
|
|
|
psrc = pstmt->plansource;
|
|
|
|
}
|
2003-05-05 02:44:56 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* special-case the unnamed statement */
|
2007-03-13 01:33:44 +01:00
|
|
|
psrc = unnamed_stmt_psrc;
|
|
|
|
if (!psrc)
|
2003-07-22 21:00:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_PSTATEMENT),
|
|
|
|
errmsg("unnamed prepared statement does not exist")));
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
|
2007-03-13 01:33:44 +01:00
|
|
|
/* Prepared statements shouldn't have changeable result descs */
|
|
|
|
Assert(psrc->fixed_result);
|
|
|
|
|
2005-12-14 18:06:28 +01:00
|
|
|
/*
|
2007-03-13 01:33:44 +01:00
|
|
|
* If we are in aborted transaction state, we can't run
|
2011-09-16 06:42:53 +02:00
|
|
|
* SendRowDescriptionMessage(), because that needs catalog accesses.
|
2007-03-13 01:33:44 +01:00
|
|
|
* Hence, refuse to Describe statements that return data. (We shouldn't
|
|
|
|
* just refuse all Describes, since that might break the ability of some
|
|
|
|
* clients to issue COMMIT or ROLLBACK commands, if they use code that
|
|
|
|
* blindly Describes whatever it does.) We can Describe parameters
|
|
|
|
* without doing anything dangerous, so we don't restrict that.
|
2005-12-14 18:06:28 +01:00
|
|
|
*/
|
|
|
|
if (IsAbortedTransactionBlockState() &&
|
2007-03-13 01:33:44 +01:00
|
|
|
psrc->resultDesc)
|
2005-12-14 18:06:28 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
|
|
|
|
errmsg("current transaction is aborted, "
|
2010-01-16 11:05:59 +01:00
|
|
|
"commands ignored until end of transaction block"),
|
|
|
|
errdetail_abort()));
|
2005-12-14 18:06:28 +01:00
|
|
|
|
2005-11-03 18:11:40 +01:00
|
|
|
if (whereToSendOutput != DestRemote)
|
2003-05-05 02:44:56 +02:00
|
|
|
return; /* can't actually do anything... */
|
|
|
|
|
2003-05-06 23:51:42 +02:00
|
|
|
/*
|
|
|
|
* First describe the parameters...
|
|
|
|
*/
|
2017-10-12 01:49:31 +02:00
|
|
|
pq_beginmessage_reuse(&row_description_buf, 't'); /* parameter description
|
|
|
|
* message type */
|
2017-10-12 06:00:46 +02:00
|
|
|
pq_sendint16(&row_description_buf, psrc->num_params);
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2018-08-24 03:36:07 +02:00
|
|
|
for (int i = 0; i < psrc->num_params; i++)
|
2003-05-05 02:44:56 +02:00
|
|
|
{
|
2007-03-13 01:33:44 +01:00
|
|
|
Oid ptype = psrc->param_types[i];
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2017-10-12 06:00:46 +02:00
|
|
|
pq_sendint32(&row_description_buf, (int) ptype);
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
2017-10-12 01:49:31 +02:00
|
|
|
pq_endmessage_reuse(&row_description_buf);
|
2003-05-06 23:51:42 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Next send RowDescription or NoData to describe the result...
|
|
|
|
*/
|
2007-03-13 01:33:44 +01:00
|
|
|
if (psrc->resultDesc)
|
|
|
|
{
|
|
|
|
List *tlist;
|
|
|
|
|
2011-09-16 06:42:53 +02:00
|
|
|
/* Get the plan's primary targetlist */
|
2017-04-01 06:17:18 +02:00
|
|
|
tlist = CachedPlanGetTargetList(psrc, NULL);
|
2007-03-13 01:33:44 +01:00
|
|
|
|
2017-10-12 01:49:31 +02:00
|
|
|
SendRowDescriptionMessage(&row_description_buf,
|
|
|
|
psrc->resultDesc,
|
|
|
|
tlist,
|
|
|
|
NULL);
|
2007-03-13 01:33:44 +01:00
|
|
|
}
|
2003-05-06 23:51:42 +02:00
|
|
|
else
|
2023-08-23 04:16:12 +02:00
|
|
|
pq_putemptymessage(PqMsg_NoData);
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* exec_describe_portal_message
|
|
|
|
*
|
|
|
|
* Process a "Describe" message for a portal
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
exec_describe_portal_message(const char *portal_name)
|
|
|
|
{
|
|
|
|
Portal portal;
|
|
|
|
|
2005-12-14 18:06:28 +01:00
|
|
|
/*
|
|
|
|
* Start up a transaction command. (Note that this will normally change
|
|
|
|
* current memory context.) Nothing happens if we are already in one.
|
|
|
|
*/
|
2006-06-21 00:52:00 +02:00
|
|
|
start_xact_command();
|
2005-12-14 18:06:28 +01:00
|
|
|
|
|
|
|
/* Switch back to message context */
|
|
|
|
MemoryContextSwitchTo(MessageContext);
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
portal = GetPortalByName(portal_name);
|
|
|
|
if (!PortalIsValid(portal))
|
2003-07-22 21:00:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_CURSOR),
|
|
|
|
errmsg("portal \"%s\" does not exist", portal_name)));
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2005-12-14 18:06:28 +01:00
|
|
|
/*
|
|
|
|
* If we are in aborted transaction state, we can't run
|
|
|
|
* SendRowDescriptionMessage(), because that needs catalog accesses.
|
|
|
|
* Hence, refuse to Describe portals that return data. (We shouldn't just
|
|
|
|
* refuse all Describes, since that might break the ability of some
|
|
|
|
* clients to issue COMMIT or ROLLBACK commands, if they use code that
|
|
|
|
* blindly Describes whatever it does.)
|
|
|
|
*/
|
|
|
|
if (IsAbortedTransactionBlockState() &&
|
|
|
|
portal->tupDesc)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
|
|
|
|
errmsg("current transaction is aborted, "
|
2010-01-16 11:05:59 +01:00
|
|
|
"commands ignored until end of transaction block"),
|
|
|
|
errdetail_abort()));
|
2005-12-14 18:06:28 +01:00
|
|
|
|
2005-11-03 18:11:40 +01:00
|
|
|
if (whereToSendOutput != DestRemote)
|
2003-05-05 02:44:56 +02:00
|
|
|
return; /* can't actually do anything... */
|
|
|
|
|
|
|
|
if (portal->tupDesc)
|
2017-10-12 01:49:31 +02:00
|
|
|
SendRowDescriptionMessage(&row_description_buf,
|
|
|
|
portal->tupDesc,
|
2005-06-22 19:45:46 +02:00
|
|
|
FetchPortalTargetList(portal),
|
2003-05-08 20:16:37 +02:00
|
|
|
portal->formats);
|
2003-05-05 02:44:56 +02:00
|
|
|
else
|
2023-08-23 04:16:12 +02:00
|
|
|
pq_putemptymessage(PqMsg_NoData);
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-10-07 02:58:23 +02:00
|
|
|
/*
|
2006-06-21 00:52:00 +02:00
|
|
|
* Convenience routines for starting/committing a single command.
|
2000-10-07 02:58:23 +02:00
|
|
|
*/
|
|
|
|
static void
|
2006-06-21 00:52:00 +02:00
|
|
|
start_xact_command(void)
|
2000-10-07 02:58:23 +02:00
|
|
|
{
|
2006-06-21 00:52:00 +02:00
|
|
|
if (!xact_started)
|
2003-05-05 02:44:56 +02:00
|
|
|
{
|
2006-06-21 00:52:00 +02:00
|
|
|
StartTransactionCommand();
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2006-04-25 02:25:22 +02:00
|
|
|
xact_started = true;
|
|
|
|
}
|
2017-09-19 04:36:44 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Start statement timeout if necessary. Note that this'll intentionally
|
|
|
|
* not reset the clock on an already started timeout, to avoid the timing
|
|
|
|
* overhead when start_xact_command() is invoked repeatedly, without an
|
|
|
|
* interceding finish_xact_command() (e.g. parse/bind/execute). If that's
|
|
|
|
* not desired, the timeout has to be disabled explicitly.
|
|
|
|
*/
|
|
|
|
enable_statement_timeout();
|
2021-04-02 21:52:30 +02:00
|
|
|
|
|
|
|
/* Start timeout for checking if the client has gone away if necessary. */
|
|
|
|
if (client_connection_check_interval > 0 &&
|
|
|
|
IsUnderPostmaster &&
|
|
|
|
MyProcPort &&
|
|
|
|
!get_timeout_active(CLIENT_CONNECTION_CHECK_TIMEOUT))
|
|
|
|
enable_timeout_after(CLIENT_CONNECTION_CHECK_TIMEOUT,
|
|
|
|
client_connection_check_interval);
|
2006-04-25 02:25:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
finish_xact_command(void)
|
|
|
|
{
|
2017-09-19 04:36:44 +02:00
|
|
|
/* cancel active statement timeout after each command */
|
|
|
|
disable_statement_timeout();
|
|
|
|
|
2006-04-25 02:25:22 +02:00
|
|
|
if (xact_started)
|
|
|
|
{
|
2003-05-14 05:26:03 +02:00
|
|
|
CommitTransactionCommand();
|
2000-10-07 06:00:41 +02:00
|
|
|
|
2003-09-14 02:03:32 +02:00
|
|
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
|
|
/* Check all memory contexts that weren't freed during commit */
|
|
|
|
/* (those that were, were checked before being deleted) */
|
|
|
|
MemoryContextCheck(TopMemoryContext);
|
|
|
|
#endif
|
|
|
|
|
2000-10-07 02:58:23 +02:00
|
|
|
#ifdef SHOW_MEMORY_STATS
|
2003-08-13 18:16:23 +02:00
|
|
|
/* Print mem stats after each commit for leak tracking */
|
2006-12-08 03:15:07 +01:00
|
|
|
MemoryContextStats(TopMemoryContext);
|
2000-10-07 02:58:23 +02:00
|
|
|
#endif
|
2003-05-05 02:44:56 +02:00
|
|
|
|
|
|
|
xact_started = false;
|
|
|
|
}
|
2000-10-07 02:58:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-10 01:31:34 +01:00
|
|
|
/*
|
|
|
|
* Convenience routines for checking whether a statement is one of the
|
|
|
|
* ones that we allow in transaction-aborted state.
|
|
|
|
*/
|
|
|
|
|
2007-02-20 18:32:18 +01:00
|
|
|
/* Test a bare parsetree */
|
2005-11-10 01:31:34 +01:00
|
|
|
static bool
|
|
|
|
IsTransactionExitStmt(Node *parsetree)
|
|
|
|
{
|
|
|
|
if (parsetree && IsA(parsetree, TransactionStmt))
|
|
|
|
{
|
|
|
|
TransactionStmt *stmt = (TransactionStmt *) parsetree;
|
|
|
|
|
|
|
|
if (stmt->kind == TRANS_STMT_COMMIT ||
|
|
|
|
stmt->kind == TRANS_STMT_PREPARE ||
|
|
|
|
stmt->kind == TRANS_STMT_ROLLBACK ||
|
|
|
|
stmt->kind == TRANS_STMT_ROLLBACK_TO)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
/* Test a list that contains PlannedStmt nodes */
|
2005-11-10 01:31:34 +01:00
|
|
|
static bool
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
IsTransactionExitStmtList(List *pstmts)
|
2005-11-10 01:31:34 +01:00
|
|
|
{
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
if (list_length(pstmts) == 1)
|
2005-11-10 01:31:34 +01:00
|
|
|
{
|
Improve castNode notation by introducing list-extraction-specific variants.
This extends the castNode() notation introduced by commit 5bcab1114 to
provide, in one step, extraction of a list cell's pointer and coercion to
a concrete node type. For example, "lfirst_node(Foo, lc)" is the same
as "castNode(Foo, lfirst(lc))". Almost half of the uses of castNode
that have appeared so far include a list extraction call, so this is
pretty widely useful, and it saves a few more keystrokes compared to the
old way.
As with the previous patch, back-patch the addition of these macros to
pg_list.h, so that the notation will be available when back-patching.
Patch by me, after an idea of Andrew Gierth's.
Discussion: https://postgr.es/m/14197.1491841216@sss.pgh.pa.us
2017-04-10 19:51:29 +02:00
|
|
|
PlannedStmt *pstmt = linitial_node(PlannedStmt, pstmts);
|
2005-11-10 01:31:34 +01:00
|
|
|
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
if (pstmt->commandType == CMD_UTILITY &&
|
|
|
|
IsTransactionExitStmt(pstmt->utilityStmt))
|
2005-11-10 01:31:34 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
/* Test a list that contains PlannedStmt nodes */
|
2005-11-10 01:31:34 +01:00
|
|
|
static bool
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
IsTransactionStmtList(List *pstmts)
|
2005-11-10 01:31:34 +01:00
|
|
|
{
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
if (list_length(pstmts) == 1)
|
2005-11-10 01:31:34 +01:00
|
|
|
{
|
Improve castNode notation by introducing list-extraction-specific variants.
This extends the castNode() notation introduced by commit 5bcab1114 to
provide, in one step, extraction of a list cell's pointer and coercion to
a concrete node type. For example, "lfirst_node(Foo, lc)" is the same
as "castNode(Foo, lfirst(lc))". Almost half of the uses of castNode
that have appeared so far include a list extraction call, so this is
pretty widely useful, and it saves a few more keystrokes compared to the
old way.
As with the previous patch, back-patch the addition of these macros to
pg_list.h, so that the notation will be available when back-patching.
Patch by me, after an idea of Andrew Gierth's.
Discussion: https://postgr.es/m/14197.1491841216@sss.pgh.pa.us
2017-04-10 19:51:29 +02:00
|
|
|
PlannedStmt *pstmt = linitial_node(PlannedStmt, pstmts);
|
2005-11-10 01:31:34 +01:00
|
|
|
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
if (pstmt->commandType == CMD_UTILITY &&
|
|
|
|
IsA(pstmt->utilityStmt, TransactionStmt))
|
2005-11-10 01:31:34 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-03-13 01:33:44 +01:00
|
|
|
/* Release any existing unnamed prepared statement */
|
|
|
|
static void
|
|
|
|
drop_unnamed_stmt(void)
|
|
|
|
{
|
2011-09-16 06:42:53 +02:00
|
|
|
/* paranoia to avoid a dangling pointer in case of error */
|
2007-03-13 01:33:44 +01:00
|
|
|
if (unnamed_stmt_psrc)
|
2011-09-16 06:42:53 +02:00
|
|
|
{
|
|
|
|
CachedPlanSource *psrc = unnamed_stmt_psrc;
|
2007-11-15 22:14:46 +01:00
|
|
|
|
2011-09-16 06:42:53 +02:00
|
|
|
unnamed_stmt_psrc = NULL;
|
|
|
|
DropCachedPlan(psrc);
|
|
|
|
}
|
2007-03-13 01:33:44 +01:00
|
|
|
}
|
|
|
|
|
2005-11-10 01:31:34 +01:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* --------------------------------
|
1996-11-14 11:25:54 +01:00
|
|
|
* signal handler routines used in PostgresMain()
|
1996-07-09 08:22:35 +02:00
|
|
|
* --------------------------------
|
|
|
|
*/
|
|
|
|
|
2001-01-14 06:08:17 +01:00
|
|
|
/*
|
2020-06-07 15:06:51 +02:00
|
|
|
* quickdie() occurs when signaled SIGQUIT by the postmaster.
|
2001-01-14 06:08:17 +01:00
|
|
|
*
|
2020-12-24 18:58:32 +01:00
|
|
|
* Either some backend has bought the farm, or we've been told to shut down
|
|
|
|
* "immediately"; so we need to stop what we're doing and exit.
|
2001-01-14 06:08:17 +01:00
|
|
|
*/
|
XLOG (and related) changes:
* Store two past checkpoint locations, not just one, in pg_control.
On startup, we fall back to the older checkpoint if the newer one
is unreadable. Also, a physical copy of the newest checkpoint record
is kept in pg_control for possible use in disaster recovery (ie,
complete loss of pg_xlog). Also add a version number for pg_control
itself. Remove archdir from pg_control; it ought to be a GUC
parameter, not a special case (not that it's implemented yet anyway).
* Suppress successive checkpoint records when nothing has been entered
in the WAL log since the last one. This is not so much to avoid I/O
as to make it actually useful to keep track of the last two
checkpoints. If the things are right next to each other then there's
not a lot of redundancy gained...
* Change CRC scheme to a true 64-bit CRC, not a pair of 32-bit CRCs
on alternate bytes. Polynomial borrowed from ECMA DLT1 standard.
* Fix XLOG record length handling so that it will work at BLCKSZ = 32k.
* Change XID allocation to work more like OID allocation. (This is of
dubious necessity, but I think it's a good idea anyway.)
* Fix a number of minor bugs, such as off-by-one logic for XLOG file
wraparound at the 4 gig mark.
* Add documentation and clean up some coding infelicities; move file
format declarations out to include files where planned contrib
utilities can get at them.
* Checkpoint will now occur every CHECKPOINT_SEGMENTS log segments or
every CHECKPOINT_TIMEOUT seconds, whichever comes first. It is also
possible to force a checkpoint by sending SIGUSR1 to the postmaster
(undocumented feature...)
* Defend against kill -9 postmaster by storing shmem block's key and ID
in postmaster.pid lockfile, and checking at startup to ensure that no
processes are still connected to old shmem block (if it still exists).
* Switch backends to accept SIGQUIT rather than SIGUSR1 for emergency
stop, for symmetry with postmaster and xlog utilities. Clean up signal
handling in bootstrap.c so that xlog utilities launched by postmaster
will react to signals better.
* Standalone bootstrap now grabs lockfile in target directory, as added
insurance against running it in parallel with live postmaster.
2001-03-13 02:17:06 +01:00
|
|
|
void
|
2000-08-29 11:36:51 +02:00
|
|
|
quickdie(SIGNAL_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2009-12-17 00:05:00 +01:00
|
|
|
sigaddset(&BlockSig, SIGQUIT); /* prevent nested calls */
|
2023-02-02 22:34:56 +01:00
|
|
|
sigprocmask(SIG_SETMASK, &BlockSig, NULL);
|
2003-08-04 02:43:34 +02:00
|
|
|
|
2013-09-12 02:10:15 +02:00
|
|
|
/*
|
|
|
|
* Prevent interrupts while exiting; though we just blocked signals that
|
|
|
|
* would queue new interrupts, one may have been pending. We don't want a
|
|
|
|
* quickdie() downgraded to a mere query cancel.
|
|
|
|
*/
|
|
|
|
HOLD_INTERRUPTS();
|
|
|
|
|
2009-08-29 21:26:52 +02:00
|
|
|
/*
|
|
|
|
* If we're aborting out of client auth, don't risk trying to send
|
|
|
|
* anything to the client; we will likely violate the protocol, not to
|
|
|
|
* mention that we may have interrupted the guts of OpenSSL or some
|
|
|
|
* authentication library.
|
|
|
|
*/
|
|
|
|
if (ClientAuthInProgress && whereToSendOutput == DestRemote)
|
|
|
|
whereToSendOutput = DestNone;
|
|
|
|
|
2003-07-22 21:00:12 +02:00
|
|
|
/*
|
2018-08-08 18:08:10 +02:00
|
|
|
* Notify the client before exiting, to give a clue on what happened.
|
|
|
|
*
|
|
|
|
* It's dubious to call ereport() from a signal handler. It is certainly
|
|
|
|
* not async-signal safe. But it seems better to try, than to disconnect
|
|
|
|
* abruptly and leave the client wondering what happened. It's remotely
|
|
|
|
* possible that we crash or hang while trying to send the message, but
|
|
|
|
* receiving a SIGQUIT is a sign that something has already gone badly
|
|
|
|
* wrong, so there's not much to lose. Assuming the postmaster is still
|
|
|
|
* running, it will SIGKILL us soon if we get stuck for some reason.
|
|
|
|
*
|
2020-12-30 00:02:38 +01:00
|
|
|
* One thing we can do to make this a tad safer is to clear the error
|
|
|
|
* context stack, so that context callbacks are not called. That's a lot
|
|
|
|
* less code that could be reached here, and the context info is unlikely
|
|
|
|
* to be very relevant to a SIGQUIT report anyway.
|
|
|
|
*/
|
|
|
|
error_context_stack = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* When responding to a postmaster-issued signal, we send the message only
|
|
|
|
* to the client; sending to the server log just creates log spam, plus
|
|
|
|
* it's more code that we need to hope will work in a signal handler.
|
|
|
|
*
|
2020-12-24 18:58:32 +01:00
|
|
|
* Ideally these should be ereport(FATAL), but then we'd not get control
|
|
|
|
* back to force the correct type of process exit.
|
|
|
|
*/
|
|
|
|
switch (GetQuitSignalReason())
|
|
|
|
{
|
|
|
|
case PMQUIT_NOT_SENT:
|
|
|
|
/* Hmm, SIGQUIT arrived out of the blue */
|
|
|
|
ereport(WARNING,
|
|
|
|
(errcode(ERRCODE_ADMIN_SHUTDOWN),
|
|
|
|
errmsg("terminating connection because of unexpected SIGQUIT signal")));
|
|
|
|
break;
|
|
|
|
case PMQUIT_FOR_CRASH:
|
|
|
|
/* A crash-and-restart cycle is in progress */
|
2020-12-30 00:02:38 +01:00
|
|
|
ereport(WARNING_CLIENT_ONLY,
|
2020-12-24 18:58:32 +01:00
|
|
|
(errcode(ERRCODE_CRASH_SHUTDOWN),
|
|
|
|
errmsg("terminating connection because of crash of another server process"),
|
|
|
|
errdetail("The postmaster has commanded this server process to roll back"
|
|
|
|
" the current transaction and exit, because another"
|
|
|
|
" server process exited abnormally and possibly corrupted"
|
|
|
|
" shared memory."),
|
|
|
|
errhint("In a moment you should be able to reconnect to the"
|
|
|
|
" database and repeat your command.")));
|
|
|
|
break;
|
|
|
|
case PMQUIT_FOR_STOP:
|
|
|
|
/* Immediate-mode stop */
|
2020-12-30 00:02:38 +01:00
|
|
|
ereport(WARNING_CLIENT_ONLY,
|
2020-12-24 18:58:32 +01:00
|
|
|
(errcode(ERRCODE_ADMIN_SHUTDOWN),
|
|
|
|
errmsg("terminating connection due to immediate shutdown command")));
|
|
|
|
break;
|
|
|
|
}
|
2003-08-04 02:43:34 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2018-08-08 18:08:10 +02:00
|
|
|
* We DO NOT want to run proc_exit() or atexit() callbacks -- we're here
|
|
|
|
* because shared memory may be corrupted, so we don't want to try to
|
|
|
|
* clean up our transaction. Just nail the windows shut and get out of
|
|
|
|
* town. The callbacks wouldn't be safe to run from a signal handler,
|
|
|
|
* anyway.
|
|
|
|
*
|
|
|
|
* Note we do _exit(2) not _exit(0). This is to force the postmaster into
|
|
|
|
* a system reset cycle if someone sends a manual SIGQUIT to a random
|
2001-01-14 06:08:17 +01:00
|
|
|
* backend. This is necessary precisely because we don't clean up our
|
2009-05-15 17:56:39 +02:00
|
|
|
* shared memory state. (The "dead man switch" mechanism in pmsignal.c
|
|
|
|
* should ensure the postmaster sees this as a crash, too, but no harm in
|
|
|
|
* being doubly sure.)
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2018-08-08 18:08:10 +02:00
|
|
|
_exit(2);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1999-10-06 23:58:18 +02:00
|
|
|
/*
|
2001-01-14 06:08:17 +01:00
|
|
|
* Shutdown signal from postmaster: abort transaction and exit
|
|
|
|
* at soonest convenient time
|
1999-10-06 23:58:18 +02:00
|
|
|
*/
|
1996-07-09 08:22:35 +02:00
|
|
|
void
|
2000-08-29 11:36:51 +02:00
|
|
|
die(SIGNAL_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2001-01-07 05:17:29 +01:00
|
|
|
/* Don't joggle the elbow of proc_exit */
|
2001-01-14 06:08:17 +01:00
|
|
|
if (!proc_exit_inprogress)
|
1999-10-06 23:58:18 +02:00
|
|
|
{
|
2001-01-14 06:08:17 +01:00
|
|
|
InterruptPending = true;
|
2000-12-18 01:44:50 +01:00
|
|
|
ProcDiePending = true;
|
1999-10-06 23:58:18 +02:00
|
|
|
}
|
2001-01-14 06:08:17 +01:00
|
|
|
|
2022-04-06 22:56:06 +02:00
|
|
|
/* for the cumulative stats system */
|
2021-01-17 13:34:09 +01:00
|
|
|
pgStatSessionEndCause = DISCONNECT_KILLED;
|
|
|
|
|
2011-08-10 18:20:30 +02:00
|
|
|
/* If we're still here, waken anything waiting on the process latch */
|
2015-01-14 18:45:22 +01:00
|
|
|
SetLatch(MyLatch);
|
2011-08-10 18:20:30 +02:00
|
|
|
|
Introduce and use infrastructure for interrupt processing during client reads.
Up to now large swathes of backend code ran inside signal handlers
while reading commands from the client, to allow for speedy reaction to
asynchronous events. Most prominently shared invalidation and NOTIFY
handling. That means that complex code like the starting/stopping of
transactions is run in signal handlers... The required code was
fragile and verbose, and is likely to contain bugs.
That approach also severely limited what could be done while
communicating with the client. As the read might be from within
openssl it wasn't safely possible to trigger an error, e.g. to cancel
a backend in idle-in-transaction state. We did that in some cases,
namely fatal errors, nonetheless.
Now that FE/BE communication in the backend employs non-blocking
sockets and latches to block, we can quite simply interrupt reads from
signal handlers by setting the latch. That allows us to signal an
interrupted read, which is supposed to be retried after returning from
within the ssl library.
As signal handlers now only need to set the latch to guarantee timely
interrupt processing, remove a fair amount of complicated & fragile
code from async.c and sinval.c.
We could now actually start to process some kinds of interrupts, like
sinval ones, more often that before, but that seems better done
separately.
This work will hopefully allow to handle cases like being blocked by
sending data, interrupting idle transactions and similar to be
implemented without too much effort. In addition to allowing getting
rid of ImmediateInterruptOK, that is.
Author: Andres Freund
Reviewed-By: Heikki Linnakangas
2015-02-03 22:25:20 +01:00
|
|
|
/*
|
|
|
|
* If we're in single user mode, we want to quit immediately - we can't
|
|
|
|
* rely on latches as they wouldn't work when stdin/stdout is a file.
|
|
|
|
* Rather ugly, but it's unlikely to be worthwhile to invest much more
|
|
|
|
* effort just for the benefit of single user mode.
|
|
|
|
*/
|
|
|
|
if (DoingCommandRead && whereToSendOutput != DestRemote)
|
|
|
|
ProcessInterrupts();
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2001-01-07 05:17:29 +01:00
|
|
|
/*
|
2001-01-14 06:08:17 +01:00
|
|
|
* Query-cancel signal from postmaster: abort current transaction
|
|
|
|
* at soonest convenient time
|
2001-01-07 05:17:29 +01:00
|
|
|
*/
|
2005-07-14 07:13:45 +02:00
|
|
|
void
|
2002-07-13 03:02:14 +02:00
|
|
|
StatementCancelHandler(SIGNAL_ARGS)
|
1998-05-19 20:05:58 +02:00
|
|
|
{
|
2001-01-07 05:17:29 +01:00
|
|
|
/*
|
2004-07-31 02:45:57 +02:00
|
|
|
* Don't joggle the elbow of proc_exit
|
2001-01-07 05:17:29 +01:00
|
|
|
*/
|
2004-07-31 02:45:57 +02:00
|
|
|
if (!proc_exit_inprogress)
|
2001-01-07 05:17:29 +01:00
|
|
|
{
|
2001-01-14 06:08:17 +01:00
|
|
|
InterruptPending = true;
|
|
|
|
QueryCancelPending = true;
|
2001-01-07 05:17:29 +01:00
|
|
|
}
|
|
|
|
|
2011-08-10 18:20:30 +02:00
|
|
|
/* If we're still here, waken anything waiting on the process latch */
|
2015-01-14 18:45:22 +01:00
|
|
|
SetLatch(MyLatch);
|
1998-05-19 20:05:58 +02:00
|
|
|
}
|
|
|
|
|
2001-01-07 05:17:29 +01:00
|
|
|
/* signal handler for floating point exception */
|
2005-08-11 23:11:50 +02:00
|
|
|
void
|
2001-01-07 05:17:29 +01:00
|
|
|
FloatExceptionHandler(SIGNAL_ARGS)
|
|
|
|
{
|
2011-08-10 18:20:30 +02:00
|
|
|
/* We're not returning, so no need to save errno */
|
2003-07-22 21:00:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
|
|
|
|
errmsg("floating-point exception"),
|
|
|
|
errdetail("An invalid floating-point operation was signaled. "
|
|
|
|
"This probably means an out-of-range result or an "
|
|
|
|
"invalid operation, such as division by zero.")));
|
2001-01-07 05:17:29 +01:00
|
|
|
}
|
|
|
|
|
2010-01-16 11:05:59 +01:00
|
|
|
/*
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
* Tell the next CHECK_FOR_INTERRUPTS() to check for a particular type of
|
|
|
|
* recovery conflict. Runs in a SIGUSR1 handler.
|
2010-01-16 11:05:59 +01:00
|
|
|
*/
|
|
|
|
void
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
HandleRecoveryConflictInterrupt(ProcSignalReason reason)
|
2010-01-16 11:05:59 +01:00
|
|
|
{
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
RecoveryConflictPendingReasons[reason] = true;
|
|
|
|
RecoveryConflictPending = true;
|
|
|
|
InterruptPending = true;
|
|
|
|
/* latch will be set by procsignal_sigusr1_handler */
|
|
|
|
}
|
2010-01-16 11:05:59 +01:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
/*
|
|
|
|
* Check one individual conflict reason.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ProcessRecoveryConflictInterrupt(ProcSignalReason reason)
|
|
|
|
{
|
|
|
|
switch (reason)
|
2010-01-16 11:05:59 +01:00
|
|
|
{
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
case PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK:
|
2010-02-13 02:32:20 +01:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
/*
|
|
|
|
* If we aren't waiting for a lock we can never deadlock.
|
|
|
|
*/
|
|
|
|
if (!IsWaitingForLock())
|
|
|
|
return;
|
2010-02-26 03:01:40 +01:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
/* Intentional fall through to check wait for pin */
|
|
|
|
/* FALLTHROUGH */
|
2010-02-13 02:32:20 +01:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
case PROCSIG_RECOVERY_CONFLICT_BUFFERPIN:
|
2010-01-23 17:37:12 +01:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
/*
|
|
|
|
* If PROCSIG_RECOVERY_CONFLICT_BUFFERPIN is requested but we
|
|
|
|
* aren't blocking the Startup process there is nothing more to
|
|
|
|
* do.
|
|
|
|
*
|
|
|
|
* When PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK is requested,
|
|
|
|
* if we're waiting for locks and the startup process is not
|
|
|
|
* waiting for buffer pin (i.e., also waiting for locks), we set
|
|
|
|
* the flag so that ProcSleep() will check for deadlocks.
|
|
|
|
*/
|
|
|
|
if (!HoldingBufferPinThatDelaysRecovery())
|
|
|
|
{
|
|
|
|
if (reason == PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK &&
|
|
|
|
GetStartupBufferPinWaitBufId() < 0)
|
|
|
|
CheckDeadLockAlert();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MyProc->recoveryConflictPending = true;
|
|
|
|
|
|
|
|
/* Intentional fall through to error handling */
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
|
|
|
|
case PROCSIG_RECOVERY_CONFLICT_LOCK:
|
|
|
|
case PROCSIG_RECOVERY_CONFLICT_TABLESPACE:
|
|
|
|
case PROCSIG_RECOVERY_CONFLICT_SNAPSHOT:
|
2010-02-26 03:01:40 +01:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
/*
|
|
|
|
* If we aren't in a transaction any longer then ignore.
|
|
|
|
*/
|
|
|
|
if (!IsTransactionOrTransactionBlock())
|
|
|
|
return;
|
2010-01-23 17:37:12 +01:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
/* FALLTHROUGH */
|
2010-01-23 17:37:12 +01:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
case PROCSIG_RECOVERY_CONFLICT_LOGICALSLOT:
|
2010-01-16 11:05:59 +01:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
/*
|
|
|
|
* If we're not in a subtransaction then we are OK to throw an
|
|
|
|
* ERROR to resolve the conflict. Otherwise drop through to the
|
|
|
|
* FATAL case.
|
|
|
|
*
|
|
|
|
* PROCSIG_RECOVERY_CONFLICT_LOGICALSLOT is a special case that
|
|
|
|
* always throws an ERROR (ie never promotes to FATAL), though it
|
|
|
|
* still has to respect QueryCancelHoldoffCount, so it shares this
|
|
|
|
* code path. Logical decoding slots are only acquired while
|
|
|
|
* performing logical decoding. During logical decoding no user
|
|
|
|
* controlled code is run. During [sub]transaction abort, the
|
|
|
|
* slot is released. Therefore user controlled code cannot
|
|
|
|
* intercept an error before the replication slot is released.
|
|
|
|
*
|
|
|
|
* XXX other times that we can throw just an ERROR *may* be
|
|
|
|
* PROCSIG_RECOVERY_CONFLICT_LOCK if no locks are held in parent
|
|
|
|
* transactions
|
|
|
|
*
|
|
|
|
* PROCSIG_RECOVERY_CONFLICT_SNAPSHOT if no snapshots are held by
|
|
|
|
* parent transactions and the transaction is not
|
|
|
|
* transaction-snapshot mode
|
|
|
|
*
|
|
|
|
* PROCSIG_RECOVERY_CONFLICT_TABLESPACE if no temp files or
|
|
|
|
* cursors open in parent transactions
|
|
|
|
*/
|
|
|
|
if (reason == PROCSIG_RECOVERY_CONFLICT_LOGICALSLOT ||
|
|
|
|
!IsSubTransaction())
|
|
|
|
{
|
2010-02-26 03:01:40 +01:00
|
|
|
/*
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
* If we already aborted then we no longer need to cancel. We
|
|
|
|
* do this here since we do not wish to ignore aborted
|
|
|
|
* subtransactions, which must cause FATAL, currently.
|
2010-02-26 03:01:40 +01:00
|
|
|
*/
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
if (IsAbortedTransactionBlockState())
|
2010-02-26 03:01:40 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
* If a recovery conflict happens while we are waiting for
|
|
|
|
* input from the client, the client is presumably just
|
|
|
|
* sitting idle in a transaction, preventing recovery from
|
|
|
|
* making progress. We'll drop through to the FATAL case
|
|
|
|
* below to dislodge it, in that case.
|
2010-02-26 03:01:40 +01:00
|
|
|
*/
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
if (!DoingCommandRead)
|
2010-02-26 03:01:40 +01:00
|
|
|
{
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
/* Avoid losing sync in the FE/BE protocol. */
|
|
|
|
if (QueryCancelHoldoffCount != 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Re-arm and defer this interrupt until later. See
|
|
|
|
* similar code in ProcessInterrupts().
|
|
|
|
*/
|
|
|
|
RecoveryConflictPendingReasons[reason] = true;
|
|
|
|
RecoveryConflictPending = true;
|
|
|
|
InterruptPending = true;
|
2010-01-16 11:05:59 +01:00
|
|
|
return;
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
}
|
2010-01-16 11:05:59 +01:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
/*
|
|
|
|
* We are cleared to throw an ERROR. Either it's the
|
|
|
|
* logical slot case, or we have a top-level transaction
|
|
|
|
* that we can abort and a conflict that isn't inherently
|
|
|
|
* non-retryable.
|
|
|
|
*/
|
|
|
|
LockErrorCleanup();
|
|
|
|
pgstat_report_recovery_conflict(reason);
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
|
|
|
|
errmsg("canceling statement due to conflict with recovery"),
|
|
|
|
errdetail_recovery_conflict(reason)));
|
2010-01-16 11:05:59 +01:00
|
|
|
break;
|
2010-02-26 03:01:40 +01:00
|
|
|
}
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
}
|
2010-02-26 03:01:40 +01:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
/* Intentional fall through to session cancel */
|
|
|
|
/* FALLTHROUGH */
|
2023-04-08 08:11:28 +02:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
case PROCSIG_RECOVERY_CONFLICT_DATABASE:
|
2010-01-16 11:05:59 +01:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
/*
|
|
|
|
* Retrying is not possible because the database is dropped, or we
|
|
|
|
* decided above that we couldn't resolve the conflict with an
|
|
|
|
* ERROR and fell through. Terminate the session.
|
|
|
|
*/
|
|
|
|
pgstat_report_recovery_conflict(reason);
|
|
|
|
ereport(FATAL,
|
|
|
|
(errcode(reason == PROCSIG_RECOVERY_CONFLICT_DATABASE ?
|
|
|
|
ERRCODE_DATABASE_DROPPED :
|
|
|
|
ERRCODE_T_R_SERIALIZATION_FAILURE),
|
|
|
|
errmsg("terminating connection due to conflict with recovery"),
|
|
|
|
errdetail_recovery_conflict(reason),
|
|
|
|
errhint("In a moment you should be able to reconnect to the"
|
|
|
|
" database and repeat your command.")));
|
|
|
|
break;
|
2010-02-13 02:32:20 +01:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
default:
|
|
|
|
elog(FATAL, "unrecognized conflict mode: %d", (int) reason);
|
2010-01-16 11:05:59 +01:00
|
|
|
}
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
}
|
2010-01-16 11:05:59 +01:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
/*
|
|
|
|
* Check each possible recovery conflict reason.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ProcessRecoveryConflictInterrupts(void)
|
|
|
|
{
|
2014-06-03 14:02:54 +02:00
|
|
|
/*
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
* We don't need to worry about joggling the elbow of proc_exit, because
|
|
|
|
* proc_exit_prepare() holds interrupts, so ProcessInterrupts() won't call
|
|
|
|
* us.
|
2014-06-03 14:02:54 +02:00
|
|
|
*/
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
Assert(!proc_exit_inprogress);
|
|
|
|
Assert(InterruptHoldoffCount == 0);
|
|
|
|
Assert(RecoveryConflictPending);
|
2014-06-03 14:02:54 +02:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
RecoveryConflictPending = false;
|
|
|
|
|
|
|
|
for (ProcSignalReason reason = PROCSIG_RECOVERY_CONFLICT_FIRST;
|
|
|
|
reason <= PROCSIG_RECOVERY_CONFLICT_LAST;
|
|
|
|
reason++)
|
|
|
|
{
|
|
|
|
if (RecoveryConflictPendingReasons[reason])
|
|
|
|
{
|
|
|
|
RecoveryConflictPendingReasons[reason] = false;
|
|
|
|
ProcessRecoveryConflictInterrupt(reason);
|
|
|
|
}
|
|
|
|
}
|
2010-01-16 11:05:59 +01:00
|
|
|
}
|
1998-05-19 20:05:58 +02:00
|
|
|
|
2001-01-14 06:08:17 +01:00
|
|
|
/*
|
|
|
|
* ProcessInterrupts: out-of-line portion of CHECK_FOR_INTERRUPTS() macro
|
|
|
|
*
|
|
|
|
* If an interrupt condition is pending, and it's safe to service it,
|
|
|
|
* then clear the flag and accept the interrupt. Called only when
|
|
|
|
* InterruptPending is true.
|
2021-05-14 18:54:26 +02:00
|
|
|
*
|
|
|
|
* Note: if INTERRUPTS_CAN_BE_PROCESSED() is true, then ProcessInterrupts
|
|
|
|
* is guaranteed to clear the InterruptPending flag before returning.
|
|
|
|
* (This is not the same as guaranteeing that it's still clear when we
|
|
|
|
* return; another interrupt could have arrived. But we promise that
|
|
|
|
* any pre-existing one will have been serviced.)
|
2001-01-14 06:08:17 +01:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
ProcessInterrupts(void)
|
|
|
|
{
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
/* OK to accept any interrupts now? */
|
2001-01-19 23:08:47 +01:00
|
|
|
if (InterruptHoldoffCount != 0 || CritSectionCount != 0)
|
2001-01-14 06:08:17 +01:00
|
|
|
return;
|
|
|
|
InterruptPending = false;
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
|
2001-01-14 06:08:17 +01:00
|
|
|
if (ProcDiePending)
|
|
|
|
{
|
|
|
|
ProcDiePending = false;
|
|
|
|
QueryCancelPending = false; /* ProcDie trumps QueryCancel */
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
LockErrorCleanup();
|
2009-08-29 21:26:52 +02:00
|
|
|
/* As in quickdie, don't risk sending to client during auth */
|
|
|
|
if (ClientAuthInProgress && whereToSendOutput == DestRemote)
|
|
|
|
whereToSendOutput = DestNone;
|
2015-02-03 22:54:48 +01:00
|
|
|
if (ClientAuthInProgress)
|
|
|
|
ereport(FATAL,
|
|
|
|
(errcode(ERRCODE_QUERY_CANCELED),
|
|
|
|
errmsg("canceling authentication due to timeout")));
|
2024-03-04 09:25:12 +01:00
|
|
|
else if (AmAutoVacuumWorkerProcess())
|
2007-06-29 19:07:39 +02:00
|
|
|
ereport(FATAL,
|
|
|
|
(errcode(ERRCODE_ADMIN_SHUTDOWN),
|
|
|
|
errmsg("terminating autovacuum process due to administrator command")));
|
2017-06-02 20:46:00 +02:00
|
|
|
else if (IsLogicalWorker())
|
|
|
|
ereport(FATAL,
|
|
|
|
(errcode(ERRCODE_ADMIN_SHUTDOWN),
|
|
|
|
errmsg("terminating logical replication worker due to administrator command")));
|
2017-06-09 00:00:53 +02:00
|
|
|
else if (IsLogicalLauncher())
|
|
|
|
{
|
|
|
|
ereport(DEBUG1,
|
2021-02-17 11:24:46 +01:00
|
|
|
(errmsg_internal("logical replication launcher shutting down")));
|
2017-06-09 00:00:53 +02:00
|
|
|
|
2017-06-21 21:15:29 +02:00
|
|
|
/*
|
|
|
|
* The logical replication launcher can be stopped at any time.
|
|
|
|
* Use exit status 1 so the background worker is restarted.
|
|
|
|
*/
|
|
|
|
proc_exit(1);
|
2017-06-09 00:00:53 +02:00
|
|
|
}
|
2024-03-04 09:25:12 +01:00
|
|
|
else if (AmBackgroundWorkerProcess())
|
2020-11-30 03:05:19 +01:00
|
|
|
ereport(FATAL,
|
|
|
|
(errcode(ERRCODE_ADMIN_SHUTDOWN),
|
|
|
|
errmsg("terminating background worker \"%s\" due to administrator command",
|
|
|
|
MyBgworkerEntry->bgw_type)));
|
2007-06-29 19:07:39 +02:00
|
|
|
else
|
|
|
|
ereport(FATAL,
|
|
|
|
(errcode(ERRCODE_ADMIN_SHUTDOWN),
|
|
|
|
errmsg("terminating connection due to administrator command")));
|
2001-01-14 06:08:17 +01:00
|
|
|
}
|
2021-04-02 21:52:30 +02:00
|
|
|
|
|
|
|
if (CheckClientConnectionPending)
|
|
|
|
{
|
|
|
|
CheckClientConnectionPending = false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for lost connection and re-arm, if still configured, but not
|
|
|
|
* if we've arrived back at DoingCommandRead state. We don't want to
|
|
|
|
* wake up idle sessions, and they already know how to detect lost
|
|
|
|
* connections.
|
|
|
|
*/
|
|
|
|
if (!DoingCommandRead && client_connection_check_interval > 0)
|
|
|
|
{
|
|
|
|
if (!pq_check_connection())
|
|
|
|
ClientConnectionLost = true;
|
|
|
|
else
|
|
|
|
enable_timeout_after(CLIENT_CONNECTION_CHECK_TIMEOUT,
|
|
|
|
client_connection_check_interval);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-09 10:37:21 +01:00
|
|
|
if (ClientConnectionLost)
|
|
|
|
{
|
|
|
|
QueryCancelPending = false; /* lost connection trumps QueryCancel */
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
LockErrorCleanup();
|
2011-12-09 10:37:21 +01:00
|
|
|
/* don't send to client, we already know the connection to be dead. */
|
|
|
|
whereToSendOutput = DestNone;
|
|
|
|
ereport(FATAL,
|
|
|
|
(errcode(ERRCODE_CONNECTION_FAILURE),
|
|
|
|
errmsg("connection to client lost")));
|
|
|
|
}
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
|
2017-10-11 21:03:26 +02:00
|
|
|
/*
|
|
|
|
* Don't allow query cancel interrupts while reading input from the
|
|
|
|
* client, because we might lose sync in the FE/BE protocol. (Die
|
|
|
|
* interrupts are OK, because we won't read any further messages from the
|
|
|
|
* client in that case.)
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
*
|
|
|
|
* See similar logic in ProcessRecoveryConflictInterrupts().
|
2017-10-11 21:03:26 +02:00
|
|
|
*/
|
|
|
|
if (QueryCancelPending && QueryCancelHoldoffCount != 0)
|
2001-01-14 06:08:17 +01:00
|
|
|
{
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
/*
|
2017-10-11 21:03:26 +02:00
|
|
|
* Re-arm InterruptPending so that we process the cancel request as
|
2021-05-14 18:54:26 +02:00
|
|
|
* soon as we're done reading the message. (XXX this is seriously
|
|
|
|
* ugly: it complicates INTERRUPTS_CAN_BE_PROCESSED(), and it means we
|
|
|
|
* can't use that macro directly as the initial test in this function,
|
|
|
|
* meaning that this code also creates opportunities for other bugs to
|
|
|
|
* appear.)
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
*/
|
2017-10-11 21:03:26 +02:00
|
|
|
InterruptPending = true;
|
|
|
|
}
|
|
|
|
else if (QueryCancelPending)
|
|
|
|
{
|
|
|
|
bool lock_timeout_occurred;
|
|
|
|
bool stmt_timeout_occurred;
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
|
2001-01-14 06:08:17 +01:00
|
|
|
QueryCancelPending = false;
|
2013-03-17 04:22:17 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If LOCK_TIMEOUT and STATEMENT_TIMEOUT indicators are both set, we
|
Be more predictable about reporting "lock timeout" vs "statement timeout".
If both timeout indicators are set when we arrive at ProcessInterrupts,
we've historically just reported "lock timeout". However, some buildfarm
members have been observed to fail isolationtester's timeouts test by
reporting "lock timeout" when the statement timeout was expected to fire
first. The cause seems to be that the process is allowed to sleep longer
than expected (probably due to heavy machine load) so that the lock
timeout happens before we reach the point of reporting the error, and
then this arbitrary tiebreak rule does the wrong thing. We can improve
matters by comparing the scheduled timeout times to decide which error
to report.
I had originally proposed greatly reducing the 1-second window between
the two timeouts in the test cases. On reflection that is a bad idea,
at least for the case where the lock timeout is expected to fire first,
because that would assume that it takes negligible time to get from
statement start to the beginning of the lock wait. Thus, this patch
doesn't completely remove the risk of test failures on slow machines.
Empirically, however, the case this handles is the one we are seeing
in the buildfarm. The explanation may be that the other case requires
the scheduler to take the CPU away from a busy process, whereas the
case fixed here only requires the scheduler to not give the CPU back
right away to a process that has been woken from a multi-second sleep
(and, perhaps, has been swapped out meanwhile).
Back-patch to 9.3 where the isolationtester timeouts test was added.
Discussion: <8693.1464314819@sss.pgh.pa.us>
2016-05-27 16:40:20 +02:00
|
|
|
* need to clear both, so always fetch both.
|
2013-03-17 04:22:17 +01:00
|
|
|
*/
|
Be more predictable about reporting "lock timeout" vs "statement timeout".
If both timeout indicators are set when we arrive at ProcessInterrupts,
we've historically just reported "lock timeout". However, some buildfarm
members have been observed to fail isolationtester's timeouts test by
reporting "lock timeout" when the statement timeout was expected to fire
first. The cause seems to be that the process is allowed to sleep longer
than expected (probably due to heavy machine load) so that the lock
timeout happens before we reach the point of reporting the error, and
then this arbitrary tiebreak rule does the wrong thing. We can improve
matters by comparing the scheduled timeout times to decide which error
to report.
I had originally proposed greatly reducing the 1-second window between
the two timeouts in the test cases. On reflection that is a bad idea,
at least for the case where the lock timeout is expected to fire first,
because that would assume that it takes negligible time to get from
statement start to the beginning of the lock wait. Thus, this patch
doesn't completely remove the risk of test failures on slow machines.
Empirically, however, the case this handles is the one we are seeing
in the buildfarm. The explanation may be that the other case requires
the scheduler to take the CPU away from a busy process, whereas the
case fixed here only requires the scheduler to not give the CPU back
right away to a process that has been woken from a multi-second sleep
(and, perhaps, has been swapped out meanwhile).
Back-patch to 9.3 where the isolationtester timeouts test was added.
Discussion: <8693.1464314819@sss.pgh.pa.us>
2016-05-27 16:40:20 +02:00
|
|
|
lock_timeout_occurred = get_timeout_indicator(LOCK_TIMEOUT, true);
|
|
|
|
stmt_timeout_occurred = get_timeout_indicator(STATEMENT_TIMEOUT, true);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If both were set, we want to report whichever timeout completed
|
|
|
|
* earlier; this ensures consistent behavior if the machine is slow
|
|
|
|
* enough that the second timeout triggers before we get here. A tie
|
|
|
|
* is arbitrarily broken in favor of reporting a lock timeout.
|
|
|
|
*/
|
|
|
|
if (lock_timeout_occurred && stmt_timeout_occurred &&
|
|
|
|
get_timeout_finish_time(STATEMENT_TIMEOUT) < get_timeout_finish_time(LOCK_TIMEOUT))
|
|
|
|
lock_timeout_occurred = false; /* report stmt timeout */
|
|
|
|
|
|
|
|
if (lock_timeout_occurred)
|
2013-03-17 04:22:17 +01:00
|
|
|
{
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
LockErrorCleanup();
|
2013-03-17 04:22:17 +01:00
|
|
|
ereport(ERROR,
|
2013-06-29 01:57:25 +02:00
|
|
|
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
|
2013-03-17 04:22:17 +01:00
|
|
|
errmsg("canceling statement due to lock timeout")));
|
|
|
|
}
|
Be more predictable about reporting "lock timeout" vs "statement timeout".
If both timeout indicators are set when we arrive at ProcessInterrupts,
we've historically just reported "lock timeout". However, some buildfarm
members have been observed to fail isolationtester's timeouts test by
reporting "lock timeout" when the statement timeout was expected to fire
first. The cause seems to be that the process is allowed to sleep longer
than expected (probably due to heavy machine load) so that the lock
timeout happens before we reach the point of reporting the error, and
then this arbitrary tiebreak rule does the wrong thing. We can improve
matters by comparing the scheduled timeout times to decide which error
to report.
I had originally proposed greatly reducing the 1-second window between
the two timeouts in the test cases. On reflection that is a bad idea,
at least for the case where the lock timeout is expected to fire first,
because that would assume that it takes negligible time to get from
statement start to the beginning of the lock wait. Thus, this patch
doesn't completely remove the risk of test failures on slow machines.
Empirically, however, the case this handles is the one we are seeing
in the buildfarm. The explanation may be that the other case requires
the scheduler to take the CPU away from a busy process, whereas the
case fixed here only requires the scheduler to not give the CPU back
right away to a process that has been woken from a multi-second sleep
(and, perhaps, has been swapped out meanwhile).
Back-patch to 9.3 where the isolationtester timeouts test was added.
Discussion: <8693.1464314819@sss.pgh.pa.us>
2016-05-27 16:40:20 +02:00
|
|
|
if (stmt_timeout_occurred)
|
2010-01-07 17:29:58 +01:00
|
|
|
{
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
LockErrorCleanup();
|
2005-09-19 19:21:49 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_QUERY_CANCELED),
|
|
|
|
errmsg("canceling statement due to statement timeout")));
|
2010-01-07 17:29:58 +01:00
|
|
|
}
|
2024-03-04 09:25:12 +01:00
|
|
|
if (AmAutoVacuumWorkerProcess())
|
2010-01-07 17:29:58 +01:00
|
|
|
{
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
LockErrorCleanup();
|
2007-12-06 15:32:54 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_QUERY_CANCELED),
|
|
|
|
errmsg("canceling autovacuum task")));
|
2010-01-07 17:29:58 +01:00
|
|
|
}
|
Allow read only connections during recovery, known as Hot Standby.
Enabled by recovery_connections = on (default) and forcing archive recovery using a recovery.conf. Recovery processing now emulates the original transactions as they are replayed, providing full locking and MVCC behaviour for read only queries. Recovery must enter consistent state before connections are allowed, so there is a delay, typically short, before connections succeed. Replay of recovering transactions can conflict and in some cases deadlock with queries during recovery; these result in query cancellation after max_standby_delay seconds have expired. Infrastructure changes have minor effects on normal running, though introduce four new types of WAL record.
New test mode "make standbycheck" allows regression tests of static command behaviour on a standby server while in recovery. Typical and extreme dynamic behaviours have been checked via code inspection and manual testing. Few port specific behaviours have been utilised, though primary testing has been on Linux only so far.
This commit is the basic patch. Additional changes will follow in this release to enhance some aspects of behaviour, notably improved handling of conflicts, deadlock detection and query cancellation. Changes to VACUUM FULL are also required.
Simon Riggs, with significant and lengthy review by Heikki Linnakangas, including streamlined redesign of snapshot creation and two-phase commit.
Important contributions from Florian Pflug, Mark Kirkwood, Merlin Moncure, Greg Stark, Gianni Ciolli, Gabriele Bartolini, Hannu Krosing, Robert Haas, Tatsuo Ishii, Hiroyuki Yamada plus support and feedback from many other community members.
2009-12-19 02:32:45 +01:00
|
|
|
|
2010-01-07 17:29:58 +01:00
|
|
|
/*
|
|
|
|
* If we are reading a command from the client, just ignore the cancel
|
|
|
|
* request --- sending an extra error message won't accomplish
|
|
|
|
* anything. Otherwise, go ahead and throw the error.
|
|
|
|
*/
|
|
|
|
if (!DoingCommandRead)
|
|
|
|
{
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
LockErrorCleanup();
|
2005-09-19 19:21:49 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_QUERY_CANCELED),
|
|
|
|
errmsg("canceling statement due to user request")));
|
Allow read only connections during recovery, known as Hot Standby.
Enabled by recovery_connections = on (default) and forcing archive recovery using a recovery.conf. Recovery processing now emulates the original transactions as they are replayed, providing full locking and MVCC behaviour for read only queries. Recovery must enter consistent state before connections are allowed, so there is a delay, typically short, before connections succeed. Replay of recovering transactions can conflict and in some cases deadlock with queries during recovery; these result in query cancellation after max_standby_delay seconds have expired. Infrastructure changes have minor effects on normal running, though introduce four new types of WAL record.
New test mode "make standbycheck" allows regression tests of static command behaviour on a standby server while in recovery. Typical and extreme dynamic behaviours have been checked via code inspection and manual testing. Few port specific behaviours have been utilised, though primary testing has been on Linux only so far.
This commit is the basic patch. Additional changes will follow in this release to enhance some aspects of behaviour, notably improved handling of conflicts, deadlock detection and query cancellation. Changes to VACUUM FULL are also required.
Simon Riggs, with significant and lengthy review by Heikki Linnakangas, including streamlined redesign of snapshot creation and two-phase commit.
Important contributions from Florian Pflug, Mark Kirkwood, Merlin Moncure, Greg Stark, Gianni Ciolli, Gabriele Bartolini, Hannu Krosing, Robert Haas, Tatsuo Ishii, Hiroyuki Yamada plus support and feedback from many other community members.
2009-12-19 02:32:45 +01:00
|
|
|
}
|
2001-01-14 06:08:17 +01:00
|
|
|
}
|
Introduce and use infrastructure for interrupt processing during client reads.
Up to now large swathes of backend code ran inside signal handlers
while reading commands from the client, to allow for speedy reaction to
asynchronous events. Most prominently shared invalidation and NOTIFY
handling. That means that complex code like the starting/stopping of
transactions is run in signal handlers... The required code was
fragile and verbose, and is likely to contain bugs.
That approach also severely limited what could be done while
communicating with the client. As the read might be from within
openssl it wasn't safely possible to trigger an error, e.g. to cancel
a backend in idle-in-transaction state. We did that in some cases,
namely fatal errors, nonetheless.
Now that FE/BE communication in the backend employs non-blocking
sockets and latches to block, we can quite simply interrupt reads from
signal handlers by setting the latch. That allows us to signal an
interrupted read, which is supposed to be retried after returning from
within the ssl library.
As signal handlers now only need to set the latch to guarantee timely
interrupt processing, remove a fair amount of complicated & fragile
code from async.c and sinval.c.
We could now actually start to process some kinds of interrupts, like
sinval ones, more often that before, but that seems better done
separately.
This work will hopefully allow to handle cases like being blocked by
sending data, interrupting idle transactions and similar to be
implemented without too much effort. In addition to allowing getting
rid of ImmediateInterruptOK, that is.
Author: Andres Freund
Reviewed-By: Heikki Linnakangas
2015-02-03 22:25:20 +01:00
|
|
|
|
Fix recovery conflict SIGUSR1 handling.
We shouldn't be doing non-trivial work in signal handlers in general,
and in this case the handler could reach unsafe code and corrupt state.
It also clobbered its own "reason" code.
Move all recovery conflict decision logic into the next
CHECK_FOR_INTERRUPTS(), and have the signal handler just set flags and
the latch, following the standard pattern. Since there are several
different "reasons", use a separate flag for each.
With this refactoring, the recovery conflict system no longer
piggy-backs on top of the regular query cancelation mechanism, but
instead raises an error directly if it decides that is necessary. It
still needs to respect QueryCancelHoldoffCount, because otherwise the
FEBE protocol might get out of sync (see commit 2b3a8b20c2d).
This fixes one class of intermittent failure in the new
031_recovery_conflict.pl test added by commit 9f8a050f, though the buggy
coding is much older. Failures outside contrived testing seem to be
very rare (or perhaps incorrectly attributed) in the field, based on
lack of reports.
No back-patch for now due to complexity and release schedule. We have
the option to back-patch into 16 later, as 16 has prerequisite commit
bea3d7e.
Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version)
Reviewed-by: Michael Paquier <michael@paquier.xyz> (earlier version)
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version)
Tested-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/CA%2BhUKGK3PGKwcKqzoosamn36YW-fsuTdOPPF1i_rtEO%3DnEYKSg%40mail.gmail.com
Discussion: https://postgr.es/m/CALj2ACVr8au2J_9D88UfRCi0JdWhyQDDxAcSVav0B0irx9nXEg%40mail.gmail.com
2023-09-07 02:38:23 +02:00
|
|
|
if (RecoveryConflictPending)
|
|
|
|
ProcessRecoveryConflictInterrupts();
|
|
|
|
|
2016-03-16 16:30:45 +01:00
|
|
|
if (IdleInTransactionSessionTimeoutPending)
|
|
|
|
{
|
2021-01-07 00:28:42 +01:00
|
|
|
/*
|
|
|
|
* If the GUC has been reset to zero, ignore the signal. This is
|
|
|
|
* important because the GUC update itself won't disable any pending
|
2024-03-15 13:31:25 +01:00
|
|
|
* interrupt. We need to unset the flag before the injection point,
|
|
|
|
* otherwise we could loop in interrupts checking.
|
2021-01-07 00:28:42 +01:00
|
|
|
*/
|
2024-03-15 13:31:25 +01:00
|
|
|
IdleInTransactionSessionTimeoutPending = false;
|
2016-03-16 16:30:45 +01:00
|
|
|
if (IdleInTransactionSessionTimeout > 0)
|
2024-03-14 12:10:21 +01:00
|
|
|
{
|
|
|
|
INJECTION_POINT("idle-in-transaction-session-timeout");
|
2016-03-16 16:30:45 +01:00
|
|
|
ereport(FATAL,
|
|
|
|
(errcode(ERRCODE_IDLE_IN_TRANSACTION_SESSION_TIMEOUT),
|
|
|
|
errmsg("terminating connection due to idle-in-transaction timeout")));
|
2024-03-14 12:10:21 +01:00
|
|
|
}
|
2021-01-07 00:28:42 +01:00
|
|
|
}
|
2016-03-16 16:30:45 +01:00
|
|
|
|
2024-02-15 22:34:11 +01:00
|
|
|
if (TransactionTimeoutPending)
|
|
|
|
{
|
|
|
|
/* As above, ignore the signal if the GUC has been reset to zero. */
|
2024-03-15 13:31:25 +01:00
|
|
|
TransactionTimeoutPending = false;
|
2024-02-15 22:34:11 +01:00
|
|
|
if (TransactionTimeout > 0)
|
2024-03-14 12:10:21 +01:00
|
|
|
{
|
|
|
|
INJECTION_POINT("transaction-timeout");
|
2024-02-15 22:34:11 +01:00
|
|
|
ereport(FATAL,
|
|
|
|
(errcode(ERRCODE_TRANSACTION_TIMEOUT),
|
|
|
|
errmsg("terminating connection due to transaction timeout")));
|
2024-03-14 12:10:21 +01:00
|
|
|
}
|
2024-02-15 22:34:11 +01:00
|
|
|
}
|
|
|
|
|
2021-01-07 00:28:42 +01:00
|
|
|
if (IdleSessionTimeoutPending)
|
|
|
|
{
|
|
|
|
/* As above, ignore the signal if the GUC has been reset to zero. */
|
2024-03-15 13:31:25 +01:00
|
|
|
IdleSessionTimeoutPending = false;
|
2021-01-07 00:28:42 +01:00
|
|
|
if (IdleSessionTimeout > 0)
|
2024-03-14 12:10:21 +01:00
|
|
|
{
|
|
|
|
INJECTION_POINT("idle-session-timeout");
|
2021-01-07 00:28:42 +01:00
|
|
|
ereport(FATAL,
|
|
|
|
(errcode(ERRCODE_IDLE_SESSION_TIMEOUT),
|
|
|
|
errmsg("terminating connection due to idle-session timeout")));
|
2024-03-14 12:10:21 +01:00
|
|
|
}
|
2016-03-16 16:30:45 +01:00
|
|
|
}
|
|
|
|
|
2022-06-17 21:48:34 +02:00
|
|
|
/*
|
|
|
|
* If there are pending stats updates and we currently are truly idle
|
|
|
|
* (matching the conditions in PostgresMain(), report stats now.
|
|
|
|
*/
|
|
|
|
if (IdleStatsUpdateTimeoutPending &&
|
|
|
|
DoingCommandRead && !IsTransactionOrTransactionBlock())
|
2022-04-07 06:29:46 +02:00
|
|
|
{
|
|
|
|
IdleStatsUpdateTimeoutPending = false;
|
|
|
|
pgstat_report_stat(true);
|
|
|
|
}
|
|
|
|
|
2019-12-19 20:56:20 +01:00
|
|
|
if (ProcSignalBarrierPending)
|
|
|
|
ProcessProcSignalBarrier();
|
|
|
|
|
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 (ParallelMessagePending)
|
|
|
|
HandleParallelMessages();
|
Add function to log the memory contexts of specified backend process.
Commit 3e98c0bafb added pg_backend_memory_contexts view to display
the memory contexts of the backend process. However its target process
is limited to the backend that is accessing to the view. So this is
not so convenient when investigating the local memory bloat of other
backend process. To improve this situation, this commit adds
pg_log_backend_memory_contexts() function that requests to log
the memory contexts of the specified backend process.
This information can be also collected by calling
MemoryContextStats(TopMemoryContext) via a debugger. But
this technique cannot be used in some environments because no debugger
is available there. So, pg_log_backend_memory_contexts() allows us to
see the memory contexts of specified backend more easily.
Only superusers are allowed to request to log the memory contexts
because allowing any users to issue this request at an unbounded rate
would cause lots of log messages and which can lead to denial of service.
On receipt of the request, at the next CHECK_FOR_INTERRUPTS(),
the target backend logs its memory contexts at LOG_SERVER_ONLY level,
so that these memory contexts will appear in the server log but not
be sent to the client. It logs one message per memory context.
Because if it buffers all memory contexts into StringInfo to log them
as one message, which may require the buffer to be enlarged very much
and lead to OOM error since there can be a large number of memory
contexts in a backend.
When a backend process is consuming huge memory, logging all its
memory contexts might overrun available disk space. To prevent this,
now this patch limits the number of child contexts to log per parent
to 100. As with MemoryContextStats(), it supposes that practical cases
where the log gets long will typically be huge numbers of siblings
under the same parent context; while the additional debugging value
from seeing details about individual siblings beyond 100 will not be large.
There was another proposed patch to add the function to return
the memory contexts of specified backend as the result sets,
instead of logging them, in the discussion. However that patch is
not included in this commit because it had several issues to address.
Thanks to Tatsuhito Kasahara, Andres Freund, Tom Lane, Tomas Vondra,
Michael Paquier, Kyotaro Horiguchi and Zhihong Yu for the discussion.
Bump catalog version.
Author: Atsushi Torikoshi
Reviewed-by: Kyotaro Horiguchi, Zhihong Yu, Fujii Masao
Discussion: https://postgr.es/m/0271f440ac77f2a4180e0e56ebd944d1@oss.nttdata.com
2021-04-06 06:44:15 +02:00
|
|
|
|
|
|
|
if (LogMemoryContextPending)
|
|
|
|
ProcessLogMemoryContextInterrupt();
|
Perform apply of large transactions by parallel workers.
Currently, for large transactions, the publisher sends the data in
multiple streams (changes divided into chunks depending upon
logical_decoding_work_mem), and then on the subscriber-side, the apply
worker writes the changes into temporary files and once it receives the
commit, it reads from those files and applies the entire transaction. To
improve the performance of such transactions, we can instead allow them to
be applied via parallel workers.
In this approach, we assign a new parallel apply worker (if available) as
soon as the xact's first stream is received and the leader apply worker
will send changes to this new worker via shared memory. The parallel apply
worker will directly apply the change instead of writing it to temporary
files. However, if the leader apply worker times out while attempting to
send a message to the parallel apply worker, it will switch to
"partial serialize" mode - in this mode, the leader serializes all
remaining changes to a file and notifies the parallel apply workers to
read and apply them at the end of the transaction. We use a non-blocking
way to send the messages from the leader apply worker to the parallel
apply to avoid deadlocks. We keep this parallel apply assigned till the
transaction commit is received and also wait for the worker to finish at
commit. This preserves commit ordering and avoid writing to and reading
from files in most cases. We still need to spill if there is no worker
available.
This patch also extends the SUBSCRIPTION 'streaming' parameter so that the
user can control whether to apply the streaming transaction in a parallel
apply worker or spill the change to disk. The user can set the streaming
parameter to 'on/off', or 'parallel'. The parameter value 'parallel' means
the streaming will be applied via a parallel apply worker, if available.
The parameter value 'on' means the streaming transaction will be spilled
to disk. The default value is 'off' (same as current behaviour).
In addition, the patch extends the logical replication STREAM_ABORT
message so that abort_lsn and abort_time can also be sent which can be
used to update the replication origin in parallel apply worker when the
streaming transaction is aborted. Because this message extension is needed
to support parallel streaming, parallel streaming is not supported for
publications on servers < PG16.
Author: Hou Zhijie, Wang wei, Amit Kapila with design inputs from Sawada Masahiko
Reviewed-by: Sawada Masahiko, Peter Smith, Dilip Kumar, Shi yu, Kuroda Hayato, Shveta Mallik
Discussion: https://postgr.es/m/CAA4eK1+wyN6zpaHUkCLorEWNx75MG0xhMwcFhvjqm2KURZEAGw@mail.gmail.com
2023-01-09 02:30:39 +01:00
|
|
|
|
|
|
|
if (ParallelApplyMessagePending)
|
|
|
|
HandleParallelApplyMessages();
|
2001-01-14 06:08:17 +01:00
|
|
|
}
|
|
|
|
|
Do stack-depth checking in all postmaster children.
We used to only initialize the stack base pointer when starting up a regular
backend, not in other processes. In particular, autovacuum workers can run
arbitrary user code, and without stack-depth checking, infinite recursion
in e.g an index expression will bring down the whole cluster.
The comment about PL/Java using set_stack_base() is not yet true. As the
code stands, PL/java still modifies the stack_base_ptr variable directly.
However, it's been discussed in the PL/Java mailing list that it should be
changed to use the function, because PL/Java is currently oblivious to the
register stack used on Itanium. There's another issues with PL/Java, namely
that the stack base pointer it sets is not really the base of the stack, it
could be something close to the bottom of the stack. That's a separate issue
that might need some further changes to this code, but that's a different
story.
Backpatch to all supported releases.
2012-04-08 17:28:12 +02:00
|
|
|
/*
|
|
|
|
* set_stack_base: set up reference point for stack depth checking
|
|
|
|
*
|
|
|
|
* Returns the old reference point, if any.
|
|
|
|
*/
|
|
|
|
pg_stack_base_t
|
|
|
|
set_stack_base(void)
|
|
|
|
{
|
2022-02-18 04:45:34 +01:00
|
|
|
#ifndef HAVE__BUILTIN_FRAME_ADDRESS
|
Do stack-depth checking in all postmaster children.
We used to only initialize the stack base pointer when starting up a regular
backend, not in other processes. In particular, autovacuum workers can run
arbitrary user code, and without stack-depth checking, infinite recursion
in e.g an index expression will bring down the whole cluster.
The comment about PL/Java using set_stack_base() is not yet true. As the
code stands, PL/java still modifies the stack_base_ptr variable directly.
However, it's been discussed in the PL/Java mailing list that it should be
changed to use the function, because PL/Java is currently oblivious to the
register stack used on Itanium. There's another issues with PL/Java, namely
that the stack base pointer it sets is not really the base of the stack, it
could be something close to the bottom of the stack. That's a separate issue
that might need some further changes to this code, but that's a different
story.
Backpatch to all supported releases.
2012-04-08 17:28:12 +02:00
|
|
|
char stack_base;
|
2022-02-18 04:45:34 +01:00
|
|
|
#endif
|
Do stack-depth checking in all postmaster children.
We used to only initialize the stack base pointer when starting up a regular
backend, not in other processes. In particular, autovacuum workers can run
arbitrary user code, and without stack-depth checking, infinite recursion
in e.g an index expression will bring down the whole cluster.
The comment about PL/Java using set_stack_base() is not yet true. As the
code stands, PL/java still modifies the stack_base_ptr variable directly.
However, it's been discussed in the PL/Java mailing list that it should be
changed to use the function, because PL/Java is currently oblivious to the
register stack used on Itanium. There's another issues with PL/Java, namely
that the stack base pointer it sets is not really the base of the stack, it
could be something close to the bottom of the stack. That's a separate issue
that might need some further changes to this code, but that's a different
story.
Backpatch to all supported releases.
2012-04-08 17:28:12 +02:00
|
|
|
pg_stack_base_t old;
|
|
|
|
|
|
|
|
old = stack_base_ptr;
|
|
|
|
|
2022-02-18 04:45:34 +01:00
|
|
|
/*
|
|
|
|
* Set up reference point for stack depth checking. On recent gcc we use
|
|
|
|
* __builtin_frame_address() to avoid a warning about storing a local
|
|
|
|
* variable's address in a long-lived variable.
|
|
|
|
*/
|
|
|
|
#ifdef HAVE__BUILTIN_FRAME_ADDRESS
|
|
|
|
stack_base_ptr = __builtin_frame_address(0);
|
|
|
|
#else
|
Do stack-depth checking in all postmaster children.
We used to only initialize the stack base pointer when starting up a regular
backend, not in other processes. In particular, autovacuum workers can run
arbitrary user code, and without stack-depth checking, infinite recursion
in e.g an index expression will bring down the whole cluster.
The comment about PL/Java using set_stack_base() is not yet true. As the
code stands, PL/java still modifies the stack_base_ptr variable directly.
However, it's been discussed in the PL/Java mailing list that it should be
changed to use the function, because PL/Java is currently oblivious to the
register stack used on Itanium. There's another issues with PL/Java, namely
that the stack base pointer it sets is not really the base of the stack, it
could be something close to the bottom of the stack. That's a separate issue
that might need some further changes to this code, but that's a different
story.
Backpatch to all supported releases.
2012-04-08 17:28:12 +02:00
|
|
|
stack_base_ptr = &stack_base;
|
2022-02-18 04:45:34 +01:00
|
|
|
#endif
|
Do stack-depth checking in all postmaster children.
We used to only initialize the stack base pointer when starting up a regular
backend, not in other processes. In particular, autovacuum workers can run
arbitrary user code, and without stack-depth checking, infinite recursion
in e.g an index expression will bring down the whole cluster.
The comment about PL/Java using set_stack_base() is not yet true. As the
code stands, PL/java still modifies the stack_base_ptr variable directly.
However, it's been discussed in the PL/Java mailing list that it should be
changed to use the function, because PL/Java is currently oblivious to the
register stack used on Itanium. There's another issues with PL/Java, namely
that the stack base pointer it sets is not really the base of the stack, it
could be something close to the bottom of the stack. That's a separate issue
that might need some further changes to this code, but that's a different
story.
Backpatch to all supported releases.
2012-04-08 17:28:12 +02:00
|
|
|
|
|
|
|
return old;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* restore_stack_base: restore reference point for stack depth checking
|
|
|
|
*
|
|
|
|
* This can be used after set_stack_base() to restore the old value. This
|
|
|
|
* is currently only used in PL/Java. When PL/Java calls a backend function
|
|
|
|
* from different thread, the thread's stack is at a different location than
|
|
|
|
* the main thread's stack, so it sets the base pointer before the call, and
|
|
|
|
* restores it afterwards.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
restore_stack_base(pg_stack_base_t base)
|
|
|
|
{
|
|
|
|
stack_base_ptr = base;
|
|
|
|
}
|
|
|
|
|
2004-03-24 23:40:29 +01:00
|
|
|
/*
|
2015-10-02 20:51:58 +02:00
|
|
|
* check_stack_depth/stack_is_too_deep: check for excessively deep recursion
|
2004-03-24 23:40:29 +01:00
|
|
|
*
|
|
|
|
* This should be called someplace in any recursive routine that might possibly
|
|
|
|
* recurse deep enough to overflow the stack. Most Unixen treat stack
|
|
|
|
* overflow as an unrecoverable SIGSEGV, so we want to error out ourselves
|
2006-10-07 21:25:29 +02:00
|
|
|
* before hitting the hardware limit.
|
2015-10-02 20:51:58 +02:00
|
|
|
*
|
|
|
|
* check_stack_depth() just throws an error summarily. stack_is_too_deep()
|
|
|
|
* can be used by code that wants to handle the error condition itself.
|
2004-03-24 23:40:29 +01:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
check_stack_depth(void)
|
2015-10-02 20:51:58 +02:00
|
|
|
{
|
|
|
|
if (stack_is_too_deep())
|
|
|
|
{
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
|
|
|
|
errmsg("stack depth limit exceeded"),
|
2023-11-30 06:11:45 +01:00
|
|
|
errhint("Increase the configuration parameter max_stack_depth (currently %dkB), "
|
2015-10-02 20:51:58 +02:00
|
|
|
"after ensuring the platform's stack depth limit is adequate.",
|
|
|
|
max_stack_depth)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
stack_is_too_deep(void)
|
2004-03-24 23:40:29 +01:00
|
|
|
{
|
|
|
|
char stack_top_loc;
|
2006-10-07 18:43:28 +02:00
|
|
|
long stack_depth;
|
2004-03-24 23:40:29 +01:00
|
|
|
|
|
|
|
/*
|
2012-05-02 09:20:27 +02:00
|
|
|
* Compute distance from reference point to my local variables
|
2004-03-24 23:40:29 +01:00
|
|
|
*/
|
2006-10-07 18:43:28 +02:00
|
|
|
stack_depth = (long) (stack_base_ptr - &stack_top_loc);
|
2004-08-29 07:07:03 +02:00
|
|
|
|
2004-03-24 23:40:29 +01:00
|
|
|
/*
|
|
|
|
* Take abs value, since stacks grow up on some machines, down on others
|
|
|
|
*/
|
|
|
|
if (stack_depth < 0)
|
|
|
|
stack_depth = -stack_depth;
|
2004-08-29 07:07:03 +02:00
|
|
|
|
2004-03-24 23:40:29 +01:00
|
|
|
/*
|
|
|
|
* Trouble?
|
|
|
|
*
|
|
|
|
* The test on stack_base_ptr prevents us from erroring out if called
|
|
|
|
* during process setup or in a non-backend process. Logically it should
|
|
|
|
* be done first, but putting it here avoids wasting cycles during normal
|
|
|
|
* cases.
|
|
|
|
*/
|
|
|
|
if (stack_depth > max_stack_depth_bytes &&
|
|
|
|
stack_base_ptr != NULL)
|
2015-10-02 20:51:58 +02:00
|
|
|
return true;
|
2010-11-07 00:36:29 +01:00
|
|
|
|
2015-10-02 20:51:58 +02:00
|
|
|
return false;
|
2004-03-24 23:40:29 +01:00
|
|
|
}
|
|
|
|
|
2011-04-07 06:11:01 +02:00
|
|
|
/* GUC check hook for max_stack_depth */
|
2004-03-24 23:40:29 +01:00
|
|
|
bool
|
2011-04-07 06:11:01 +02:00
|
|
|
check_max_stack_depth(int *newval, void **extra, GucSource source)
|
2004-03-24 23:40:29 +01:00
|
|
|
{
|
2011-04-07 06:11:01 +02:00
|
|
|
long newval_bytes = *newval * 1024L;
|
2006-10-07 21:25:29 +02:00
|
|
|
long stack_rlimit = get_stack_depth_rlimit();
|
|
|
|
|
|
|
|
if (stack_rlimit > 0 && newval_bytes > stack_rlimit - STACK_DEPTH_SLOP)
|
|
|
|
{
|
2023-11-30 06:11:45 +01:00
|
|
|
GUC_check_errdetail("max_stack_depth must not exceed %ldkB.",
|
2011-04-07 06:11:01 +02:00
|
|
|
(stack_rlimit - STACK_DEPTH_SLOP) / 1024L);
|
|
|
|
GUC_check_errhint("Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent.");
|
2006-10-07 21:25:29 +02:00
|
|
|
return false;
|
|
|
|
}
|
2004-03-24 23:40:29 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-04-07 06:11:01 +02:00
|
|
|
/* GUC assign hook for max_stack_depth */
|
|
|
|
void
|
|
|
|
assign_max_stack_depth(int newval, void *extra)
|
|
|
|
{
|
|
|
|
long newval_bytes = newval * 1024L;
|
|
|
|
|
|
|
|
max_stack_depth_bytes = newval_bytes;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
/*
|
|
|
|
* GUC check_hook for client_connection_check_interval
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
check_client_connection_check_interval(int *newval, void **extra, GucSource source)
|
|
|
|
{
|
|
|
|
if (!WaitEventSetCanReportClosed() && *newval != 0)
|
|
|
|
{
|
|
|
|
GUC_check_errdetail("client_connection_check_interval must be set to 0 on this platform.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* GUC check_hook for log_parser_stats, log_planner_stats, log_executor_stats
|
|
|
|
*
|
|
|
|
* This function and check_log_stats interact to prevent their variables from
|
|
|
|
* being set in a disallowed combination. This is a hack that doesn't really
|
|
|
|
* work right; for example it might fail while applying pg_db_role_setting
|
|
|
|
* values even though the final state would have been acceptable. However,
|
|
|
|
* since these variables are legacy settings with little production usage,
|
|
|
|
* we tolerate that.
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
check_stage_log_stats(bool *newval, void **extra, GucSource source)
|
|
|
|
{
|
|
|
|
if (*newval && log_statement_stats)
|
|
|
|
{
|
|
|
|
GUC_check_errdetail("Cannot enable parameter when \"log_statement_stats\" is true.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* GUC check_hook for log_statement_stats
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
check_log_stats(bool *newval, void **extra, GucSource source)
|
|
|
|
{
|
|
|
|
if (*newval &&
|
|
|
|
(log_parser_stats || log_planner_stats || log_executor_stats))
|
|
|
|
{
|
2023-11-30 06:11:45 +01:00
|
|
|
GUC_check_errdetail("Cannot enable log_statement_stats when "
|
|
|
|
"log_parser_stats, log_planner_stats, "
|
|
|
|
"or log_executor_stats is true.");
|
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
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-02-15 22:34:11 +01:00
|
|
|
/* GUC assign hook for transaction_timeout */
|
|
|
|
void
|
|
|
|
assign_transaction_timeout(int newval, void *extra)
|
|
|
|
{
|
2024-02-16 02:36:38 +01:00
|
|
|
if (IsTransactionState())
|
|
|
|
{
|
|
|
|
/*
|
2024-02-20 10:54:34 +01:00
|
|
|
* If transaction_timeout GUC has changed within the transaction block
|
2024-02-16 02:36:38 +01:00
|
|
|
* enable or disable the timer correspondingly.
|
|
|
|
*/
|
|
|
|
if (newval > 0 && !get_timeout_active(TRANSACTION_TIMEOUT))
|
|
|
|
enable_timeout_after(TRANSACTION_TIMEOUT, newval);
|
|
|
|
else if (newval <= 0 && get_timeout_active(TRANSACTION_TIMEOUT))
|
|
|
|
disable_timeout(TRANSACTION_TIMEOUT, false);
|
|
|
|
}
|
2024-02-15 22:34:11 +01:00
|
|
|
}
|
|
|
|
|
2004-03-24 23:40:29 +01:00
|
|
|
|
2004-11-14 20:35:35 +01:00
|
|
|
/*
|
|
|
|
* set_debug_options --- apply "-d N" command line option
|
|
|
|
*
|
|
|
|
* -d is not quite the same as setting log_min_messages because it enables
|
|
|
|
* other output options.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
set_debug_options(int debug_flag, GucContext context, GucSource source)
|
|
|
|
{
|
|
|
|
if (debug_flag > 0)
|
|
|
|
{
|
|
|
|
char debugstr[64];
|
|
|
|
|
|
|
|
sprintf(debugstr, "debug%d", debug_flag);
|
|
|
|
SetConfigOption("log_min_messages", debugstr, context, source);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
SetConfigOption("log_min_messages", "notice", context, source);
|
|
|
|
|
|
|
|
if (debug_flag >= 1 && context == PGC_POSTMASTER)
|
|
|
|
{
|
|
|
|
SetConfigOption("log_connections", "true", context, source);
|
|
|
|
SetConfigOption("log_disconnections", "true", context, source);
|
|
|
|
}
|
|
|
|
if (debug_flag >= 2)
|
|
|
|
SetConfigOption("log_statement", "all", context, source);
|
|
|
|
if (debug_flag >= 3)
|
|
|
|
SetConfigOption("debug_print_parse", "true", context, source);
|
|
|
|
if (debug_flag >= 4)
|
|
|
|
SetConfigOption("debug_print_plan", "true", context, source);
|
|
|
|
if (debug_flag >= 5)
|
|
|
|
SetConfigOption("debug_print_rewritten", "true", context, source);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-01-05 11:07:46 +01:00
|
|
|
bool
|
|
|
|
set_plan_disabling_options(const char *arg, GucContext context, GucSource source)
|
|
|
|
{
|
2011-10-08 02:13:02 +02:00
|
|
|
const char *tmp = NULL;
|
2006-01-05 11:07:46 +01:00
|
|
|
|
|
|
|
switch (arg[0])
|
|
|
|
{
|
|
|
|
case 's': /* seqscan */
|
|
|
|
tmp = "enable_seqscan";
|
|
|
|
break;
|
|
|
|
case 'i': /* indexscan */
|
|
|
|
tmp = "enable_indexscan";
|
|
|
|
break;
|
2011-10-08 02:13:02 +02:00
|
|
|
case 'o': /* indexonlyscan */
|
|
|
|
tmp = "enable_indexonlyscan";
|
|
|
|
break;
|
2006-01-05 11:07:46 +01:00
|
|
|
case 'b': /* bitmapscan */
|
|
|
|
tmp = "enable_bitmapscan";
|
|
|
|
break;
|
|
|
|
case 't': /* tidscan */
|
|
|
|
tmp = "enable_tidscan";
|
|
|
|
break;
|
|
|
|
case 'n': /* nestloop */
|
|
|
|
tmp = "enable_nestloop";
|
|
|
|
break;
|
|
|
|
case 'm': /* mergejoin */
|
|
|
|
tmp = "enable_mergejoin";
|
|
|
|
break;
|
|
|
|
case 'h': /* hashjoin */
|
|
|
|
tmp = "enable_hashjoin";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (tmp)
|
|
|
|
{
|
|
|
|
SetConfigOption(tmp, "false", context, source);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
get_stats_option_name(const char *arg)
|
|
|
|
{
|
|
|
|
switch (arg[0])
|
|
|
|
{
|
|
|
|
case 'p':
|
|
|
|
if (optarg[1] == 'a') /* "parser" */
|
|
|
|
return "log_parser_stats";
|
|
|
|
else if (optarg[1] == 'l') /* "planner" */
|
|
|
|
return "log_planner_stats";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'e': /* "executor" */
|
|
|
|
return "log_executor_stats";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* ----------------------------------------------------------------
|
2009-08-29 21:26:52 +02:00
|
|
|
* process_postgres_switches
|
2021-09-08 21:19:50 +02:00
|
|
|
* Parse command line arguments for backends
|
1999-05-22 19:47:54 +02:00
|
|
|
*
|
2009-08-29 21:26:52 +02:00
|
|
|
* This is called twice, once for the "secure" options coming from the
|
|
|
|
* postmaster or command line, and once for the "insecure" options coming
|
|
|
|
* from the client's startup packet. The latter have the same syntax but
|
|
|
|
* may be restricted in what they can do.
|
|
|
|
*
|
2009-09-01 02:09:42 +02:00
|
|
|
* argv[0] is ignored in either case (it's assumed to be the program name).
|
2009-08-29 21:26:52 +02:00
|
|
|
*
|
|
|
|
* ctx is PGC_POSTMASTER for secure options, PGC_BACKEND for insecure options
|
2014-09-14 03:01:49 +02:00
|
|
|
* coming from the client, or PGC_SU_BACKEND for insecure options coming from
|
2009-08-29 21:26:52 +02:00
|
|
|
* a superuser client.
|
|
|
|
*
|
2013-04-01 20:00:51 +02:00
|
|
|
* If a database name is present in the command line arguments, it's
|
|
|
|
* returned into *dbname (this is allowed only if *dbname is initially NULL).
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
2013-04-01 20:00:51 +02:00
|
|
|
void
|
|
|
|
process_postgres_switches(int argc, char *argv[], GucContext ctx,
|
|
|
|
const char **dbname)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2009-08-29 21:26:52 +02:00
|
|
|
bool secure = (ctx == PGC_POSTMASTER);
|
1998-08-25 23:34:10 +02:00
|
|
|
int errs = 0;
|
2002-02-23 02:31:37 +01:00
|
|
|
GucSource gucsource;
|
2009-08-29 21:26:52 +02:00
|
|
|
int flag;
|
2004-03-24 23:40:29 +01:00
|
|
|
|
2009-08-29 21:26:52 +02:00
|
|
|
if (secure)
|
2004-05-28 07:13:32 +02:00
|
|
|
{
|
2009-08-29 21:26:52 +02:00
|
|
|
gucsource = PGC_S_ARGV; /* switches came from command line */
|
1999-05-22 19:47:54 +02:00
|
|
|
|
2009-08-29 21:26:52 +02:00
|
|
|
/* Ignore the initial --single argument, if present */
|
|
|
|
if (argc > 1 && strcmp(argv[1], "--single") == 0)
|
|
|
|
{
|
|
|
|
argv++;
|
|
|
|
argc--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2006-06-18 17:38:37 +02:00
|
|
|
{
|
2009-08-29 21:26:52 +02:00
|
|
|
gucsource = PGC_S_CLIENT; /* switches came from client */
|
2006-06-18 17:38:37 +02:00
|
|
|
}
|
|
|
|
|
2012-03-11 00:52:05 +01:00
|
|
|
#ifdef HAVE_INT_OPTERR
|
2012-06-10 21:20:04 +02:00
|
|
|
|
2012-03-11 00:52:05 +01:00
|
|
|
/*
|
|
|
|
* Turn this off because it's either printed to stderr and not the log
|
|
|
|
* where we'd want it, or argv[0] is now "--single", which would make for
|
|
|
|
* a weird error message. We print our own error message below.
|
|
|
|
*/
|
|
|
|
opterr = 0;
|
|
|
|
#endif
|
|
|
|
|
2007-01-04 01:57:51 +01:00
|
|
|
/*
|
|
|
|
* Parse command-line options. CAUTION: keep this in sync with
|
|
|
|
* postmaster/postmaster.c (the option sets should not conflict) and with
|
|
|
|
* the common help() function in main/main.c.
|
|
|
|
*/
|
2022-12-12 14:33:41 +01:00
|
|
|
while ((flag = getopt(argc, argv, "B:bC:c:D:d:EeFf:h:ijk:lN:nOPp:r:S:sTt:v:W:-:")) != -1)
|
2004-11-14 20:35:35 +01:00
|
|
|
{
|
1996-11-14 11:25:54 +01:00
|
|
|
switch (flag)
|
|
|
|
{
|
|
|
|
case 'B':
|
2002-02-23 02:31:37 +01:00
|
|
|
SetConfigOption("shared_buffers", optarg, ctx, gucsource);
|
1996-11-14 11:25:54 +01:00
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2011-04-25 18:00:21 +02:00
|
|
|
case 'b':
|
|
|
|
/* Undocumented flag used for binary upgrades */
|
2013-04-01 20:00:51 +02:00
|
|
|
if (secure)
|
|
|
|
IsBinaryUpgrade = true;
|
2011-04-25 18:00:21 +02:00
|
|
|
break;
|
|
|
|
|
2011-10-06 15:38:39 +02:00
|
|
|
case 'C':
|
|
|
|
/* ignored for consistency with the postmaster */
|
|
|
|
break;
|
|
|
|
|
2022-12-12 14:33:41 +01:00
|
|
|
case 'c':
|
|
|
|
case '-':
|
|
|
|
{
|
|
|
|
char *name,
|
|
|
|
*value;
|
|
|
|
|
|
|
|
ParseLongOption(optarg, &name, &value);
|
|
|
|
if (!value)
|
|
|
|
{
|
|
|
|
if (flag == '-')
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("--%s requires a value",
|
|
|
|
optarg)));
|
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("-c %s requires a value",
|
|
|
|
optarg)));
|
|
|
|
}
|
|
|
|
SetConfigOption(name, value, ctx, gucsource);
|
|
|
|
pfree(name);
|
|
|
|
pfree(value);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-01-05 11:07:46 +01:00
|
|
|
case 'D':
|
1999-05-22 19:47:54 +02:00
|
|
|
if (secure)
|
2009-08-29 21:26:52 +02:00
|
|
|
userDoption = strdup(optarg);
|
1998-10-13 21:51:50 +02:00
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2006-01-05 11:07:46 +01:00
|
|
|
case 'd':
|
2009-08-29 21:26:52 +02:00
|
|
|
set_debug_options(atoi(optarg), ctx, gucsource);
|
1996-07-09 08:22:35 +02:00
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
|
1996-11-14 11:25:54 +01:00
|
|
|
case 'E':
|
2013-04-01 20:00:51 +02:00
|
|
|
if (secure)
|
|
|
|
EchoQuery = true;
|
1996-07-09 08:22:35 +02:00
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
|
1996-11-14 11:25:54 +01:00
|
|
|
case 'e':
|
2002-05-17 03:19:19 +02:00
|
|
|
SetConfigOption("datestyle", "euro", ctx, gucsource);
|
1996-07-09 08:22:35 +02:00
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
|
1996-11-14 11:25:54 +01:00
|
|
|
case 'F':
|
2002-02-23 02:31:37 +01:00
|
|
|
SetConfigOption("fsync", "false", ctx, gucsource);
|
1996-07-09 08:22:35 +02:00
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
|
1996-11-14 11:25:54 +01:00
|
|
|
case 'f':
|
2006-01-05 11:07:46 +01:00
|
|
|
if (!set_plan_disabling_options(optarg, ctx, gucsource))
|
|
|
|
errs++;
|
|
|
|
break;
|
2001-03-22 07:16:21 +01:00
|
|
|
|
2006-01-05 11:07:46 +01:00
|
|
|
case 'h':
|
|
|
|
SetConfigOption("listen_addresses", optarg, ctx, gucsource);
|
1996-07-09 08:22:35 +02:00
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2006-01-05 11:07:46 +01:00
|
|
|
case 'i':
|
|
|
|
SetConfigOption("listen_addresses", "*", ctx, gucsource);
|
|
|
|
break;
|
2001-03-22 07:16:21 +01:00
|
|
|
|
2006-01-05 11:07:46 +01:00
|
|
|
case 'j':
|
2013-04-01 20:00:51 +02:00
|
|
|
if (secure)
|
Adjust behavior of single-user -j mode for better initdb error reporting.
Previously, -j caused the entire input file to be read in and executed as
a single command string. That's undesirable, not least because any error
causes the entire file to be regurgitated as the "failing query". Some
experimentation suggests a better rule: end the command string when we see
a semicolon immediately followed by two newlines, ie, an empty line after
a query. This serves nicely to break up the existing examples such as
information_schema.sql and system_views.sql. A limitation is that it's
no longer possible to write such a sequence within a string literal or
multiline comment in a file meant to be read with -j; but there are no
instances of such a problem within the data currently used by initdb.
(If someone does make such a mistake in future, it'll be obvious because
they'll get an unterminated-literal or unterminated-comment syntax error.)
Other than that, there shouldn't be any negative consequences; you're not
forced to end statements that way, it's just a better idea in most cases.
In passing, remove src/include/tcop/tcopdebug.h, which is dead code
because it's not included anywhere, and hasn't been for more than
ten years. One of the debug-support symbols it purported to describe
has been unreferenced for at least the same amount of time, and the
other is removed by this commit on the grounds that it was useless:
forcing -j mode all the time would have broken initdb. The lack of
complaints about that, or about the missing inclusion, shows that
no one has tried to use TCOP_DONTUSENEWLINE in many years.
2015-12-18 01:34:15 +01:00
|
|
|
UseSemiNewlineNewline = true;
|
1996-11-14 11:25:54 +01:00
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2006-01-05 11:07:46 +01:00
|
|
|
case 'k':
|
2012-08-10 23:26:44 +02:00
|
|
|
SetConfigOption("unix_socket_directories", optarg, ctx, gucsource);
|
2006-01-05 11:07:46 +01:00
|
|
|
break;
|
2001-03-22 07:16:21 +01:00
|
|
|
|
2006-01-05 11:07:46 +01:00
|
|
|
case 'l':
|
|
|
|
SetConfigOption("ssl", "true", ctx, gucsource);
|
1999-03-17 23:53:31 +01:00
|
|
|
break;
|
|
|
|
|
2006-01-05 11:07:46 +01:00
|
|
|
case 'N':
|
|
|
|
SetConfigOption("max_connections", optarg, ctx, gucsource);
|
|
|
|
break;
|
2001-03-22 07:16:21 +01:00
|
|
|
|
2006-01-05 11:07:46 +01:00
|
|
|
case 'n':
|
|
|
|
/* ignored for consistency with postmaster */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'O':
|
|
|
|
SetConfigOption("allow_system_table_mods", "true", ctx, gucsource);
|
2000-02-18 10:30:20 +01:00
|
|
|
break;
|
|
|
|
|
2006-01-05 11:07:46 +01:00
|
|
|
case 'P':
|
|
|
|
SetConfigOption("ignore_system_indexes", "true", ctx, gucsource);
|
1999-05-01 19:16:25 +02:00
|
|
|
break;
|
|
|
|
|
1999-05-22 19:47:54 +02:00
|
|
|
case 'p':
|
2006-01-05 11:07:46 +01:00
|
|
|
SetConfigOption("port", optarg, ctx, gucsource);
|
|
|
|
break;
|
2004-08-29 07:07:03 +02:00
|
|
|
|
2006-01-05 11:07:46 +01:00
|
|
|
case 'r':
|
|
|
|
/* send output (stdout and stderr) to the given file */
|
1999-05-22 19:47:54 +02:00
|
|
|
if (secure)
|
2007-02-10 15:58:55 +01:00
|
|
|
strlcpy(OutputFileName, optarg, MAXPGPATH);
|
1997-08-06 05:42:21 +02:00
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-11-14 11:25:54 +01:00
|
|
|
case 'S':
|
2004-02-03 18:34:04 +01:00
|
|
|
SetConfigOption("work_mem", optarg, ctx, gucsource);
|
1996-11-14 11:25:54 +01:00
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
|
1996-11-14 11:25:54 +01:00
|
|
|
case 's':
|
2009-08-29 21:26:52 +02:00
|
|
|
SetConfigOption("log_statement_stats", "true", ctx, gucsource);
|
1998-08-25 23:34:10 +02:00
|
|
|
break;
|
|
|
|
|
2006-01-05 11:07:46 +01:00
|
|
|
case 'T':
|
2011-10-06 15:38:39 +02:00
|
|
|
/* ignored for consistency with the postmaster */
|
2006-01-05 11:07:46 +01:00
|
|
|
break;
|
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
case 't':
|
2004-11-24 20:51:05 +01:00
|
|
|
{
|
2006-01-05 11:07:46 +01:00
|
|
|
const char *tmp = get_stats_option_name(optarg);
|
2006-10-04 02:30:14 +02:00
|
|
|
|
|
|
|
if (tmp)
|
2009-08-29 21:26:52 +02:00
|
|
|
SetConfigOption(tmp, "true", ctx, gucsource);
|
2004-11-24 20:51:05 +01:00
|
|
|
else
|
|
|
|
errs++;
|
2006-10-04 02:30:14 +02:00
|
|
|
break;
|
2004-11-24 20:51:05 +01:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-01-26 02:42:53 +01:00
|
|
|
case 'v':
|
2010-02-26 03:01:40 +01:00
|
|
|
|
2009-08-28 20:23:53 +02:00
|
|
|
/*
|
|
|
|
* -v is no longer used in normal operation, since
|
|
|
|
* FrontendProtocol is already set before we get here. We keep
|
|
|
|
* the switch only for possible use in standalone operation,
|
|
|
|
* in case we ever support using normal FE/BE protocol with a
|
|
|
|
* standalone backend.
|
|
|
|
*/
|
1999-05-22 19:47:54 +02:00
|
|
|
if (secure)
|
|
|
|
FrontendProtocol = (ProtocolVersion) atoi(optarg);
|
1998-01-26 02:42:53 +01:00
|
|
|
break;
|
|
|
|
|
1998-08-25 23:04:41 +02:00
|
|
|
case 'W':
|
2006-01-05 11:07:46 +01:00
|
|
|
SetConfigOption("post_auth_delay", optarg, ctx, gucsource);
|
|
|
|
break;
|
2001-03-22 07:16:21 +01:00
|
|
|
|
1996-11-14 11:25:54 +01:00
|
|
|
default:
|
|
|
|
errs++;
|
1999-05-01 19:16:25 +02:00
|
|
|
break;
|
1996-11-14 11:25:54 +01:00
|
|
|
}
|
2012-03-11 00:52:05 +01:00
|
|
|
|
|
|
|
if (errs)
|
|
|
|
break;
|
2003-04-18 00:26:02 +02:00
|
|
|
}
|
|
|
|
|
2004-11-24 20:51:05 +01:00
|
|
|
/*
|
2013-04-01 20:00:51 +02:00
|
|
|
* Optional database name should be there only if *dbname is NULL.
|
2004-11-24 20:51:05 +01:00
|
|
|
*/
|
2013-04-01 20:00:51 +02:00
|
|
|
if (!errs && dbname && *dbname == NULL && argc - optind >= 1)
|
|
|
|
*dbname = strdup(argv[optind++]);
|
2012-03-11 00:52:05 +01:00
|
|
|
|
|
|
|
if (errs || argc != optind)
|
2004-11-24 20:51:05 +01:00
|
|
|
{
|
2012-03-11 00:52:05 +01:00
|
|
|
if (errs)
|
|
|
|
optind--; /* complain about the previous argument */
|
|
|
|
|
2009-08-29 21:26:52 +02:00
|
|
|
/* spell the error message a bit differently depending on context */
|
|
|
|
if (IsUnderPostmaster)
|
|
|
|
ereport(FATAL,
|
Re-implement the ereport() macro using __VA_ARGS__.
Now that we require C99, we can depend on __VA_ARGS__ to work, and
revising ereport() to use it has several significant benefits:
* The extra parentheses around the auxiliary function calls are now
optional. Aside from being a bit less ugly, this removes a common
gotcha for new contributors, because in some cases the compiler errors
you got from forgetting them were unintelligible.
* The auxiliary function calls are now evaluated as a comma expression
list rather than as extra arguments to errfinish(). This means that
compilers can be expected to warn about no-op expressions in the list,
allowing detection of several other common mistakes such as forgetting
to add errmsg(...) when converting an elog() call to ereport().
* Unlike the situation with extra function arguments, comma expressions
are guaranteed to be evaluated left-to-right, so this removes platform
dependency in the order of the auxiliary function calls. While that
dependency hasn't caused us big problems in the past, this change does
allow dropping some rather shaky assumptions around errcontext() domain
handling.
There's no intention to make wholesale changes of existing ereport
calls, but as proof-of-concept this patch removes the extra parens
from a couple of calls in postgres.c.
While new code can be written either way, code intended to be
back-patched will need to use extra parens for awhile yet. It seems
worth back-patching this change into v12, so as to reduce the window
where we have to be careful about that by one year. Hence, this patch
is careful to preserve ABI compatibility; a followup HEAD-only patch
will make some additional simplifications.
Andres Freund and Tom Lane
Discussion: https://postgr.es/m/CA+fd4k6N8EjNvZpM8nme+y+05mz-SM8Z_BgkixzkA34R+ej0Kw@mail.gmail.com
2020-03-24 16:48:33 +01:00
|
|
|
errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("invalid command-line argument for server process: %s", argv[optind]),
|
|
|
|
errhint("Try \"%s --help\" for more information.", progname));
|
2009-08-29 21:26:52 +02:00
|
|
|
else
|
|
|
|
ereport(FATAL,
|
Re-implement the ereport() macro using __VA_ARGS__.
Now that we require C99, we can depend on __VA_ARGS__ to work, and
revising ereport() to use it has several significant benefits:
* The extra parentheses around the auxiliary function calls are now
optional. Aside from being a bit less ugly, this removes a common
gotcha for new contributors, because in some cases the compiler errors
you got from forgetting them were unintelligible.
* The auxiliary function calls are now evaluated as a comma expression
list rather than as extra arguments to errfinish(). This means that
compilers can be expected to warn about no-op expressions in the list,
allowing detection of several other common mistakes such as forgetting
to add errmsg(...) when converting an elog() call to ereport().
* Unlike the situation with extra function arguments, comma expressions
are guaranteed to be evaluated left-to-right, so this removes platform
dependency in the order of the auxiliary function calls. While that
dependency hasn't caused us big problems in the past, this change does
allow dropping some rather shaky assumptions around errcontext() domain
handling.
There's no intention to make wholesale changes of existing ereport
calls, but as proof-of-concept this patch removes the extra parens
from a couple of calls in postgres.c.
While new code can be written either way, code intended to be
back-patched will need to use extra parens for awhile yet. It seems
worth back-patching this change into v12, so as to reduce the window
where we have to be careful about that by one year. Hence, this patch
is careful to preserve ABI compatibility; a followup HEAD-only patch
will make some additional simplifications.
Andres Freund and Tom Lane
Discussion: https://postgr.es/m/CA+fd4k6N8EjNvZpM8nme+y+05mz-SM8Z_BgkixzkA34R+ej0Kw@mail.gmail.com
2020-03-24 16:48:33 +01:00
|
|
|
errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("%s: invalid command-line argument: %s",
|
|
|
|
progname, argv[optind]),
|
|
|
|
errhint("Try \"%s --help\" for more information.", progname));
|
2009-08-29 21:26:52 +02:00
|
|
|
}
|
2004-11-24 20:51:05 +01:00
|
|
|
|
2009-08-29 21:26:52 +02:00
|
|
|
/*
|
|
|
|
* Reset getopt(3) library so that it will work correctly in subprocesses
|
|
|
|
* or when this function is called a second time with another array.
|
|
|
|
*/
|
|
|
|
optind = 1;
|
2010-12-16 22:22:05 +01:00
|
|
|
#ifdef HAVE_INT_OPTRESET
|
2009-08-29 21:26:52 +02:00
|
|
|
optreset = 1; /* some systems need this too */
|
|
|
|
#endif
|
|
|
|
}
|
2004-11-24 20:51:05 +01:00
|
|
|
|
2009-08-29 21:26:52 +02:00
|
|
|
|
2021-09-08 21:19:50 +02:00
|
|
|
/*
|
|
|
|
* PostgresSingleUserMain
|
|
|
|
* Entry point for single user mode. argc/argv are the command line
|
|
|
|
* arguments to be used.
|
2009-08-29 21:26:52 +02:00
|
|
|
*
|
2021-09-08 21:19:50 +02:00
|
|
|
* Performs single user specific setup then calls PostgresMain() to actually
|
|
|
|
* process queries. Single user mode specific setup should go here, rather
|
|
|
|
* than PostgresMain() or InitPostgres() when reasonably possible.
|
2009-08-29 21:26:52 +02:00
|
|
|
*/
|
2012-06-25 20:25:26 +02:00
|
|
|
void
|
2021-09-08 21:19:50 +02:00
|
|
|
PostgresSingleUserMain(int argc, char *argv[],
|
|
|
|
const char *username)
|
2009-08-29 21:26:52 +02:00
|
|
|
{
|
2021-09-08 21:19:50 +02:00
|
|
|
const char *dbname = NULL;
|
2009-08-29 21:26:52 +02:00
|
|
|
|
2021-09-08 21:19:50 +02:00
|
|
|
Assert(!IsUnderPostmaster);
|
2009-08-29 21:26:52 +02:00
|
|
|
|
2021-09-08 21:19:50 +02:00
|
|
|
/* Initialize startup process environment. */
|
|
|
|
InitStandaloneProcess(argv[0]);
|
2009-08-29 21:26:52 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set default values for command-line options.
|
|
|
|
*/
|
2021-09-08 21:19:50 +02:00
|
|
|
InitializeGUCOptions();
|
2009-08-29 21:26:52 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse command-line options.
|
|
|
|
*/
|
2013-04-01 20:00:51 +02:00
|
|
|
process_postgres_switches(argc, argv, PGC_POSTMASTER, &dbname);
|
2009-08-29 21:26:52 +02:00
|
|
|
|
|
|
|
/* Must have gotten a database name, or have a default (the username) */
|
|
|
|
if (dbname == NULL)
|
|
|
|
{
|
|
|
|
dbname = username;
|
|
|
|
if (dbname == NULL)
|
|
|
|
ereport(FATAL,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("%s: no database nor user name specified",
|
2009-09-01 02:09:42 +02:00
|
|
|
progname)));
|
2004-11-24 20:51:05 +01:00
|
|
|
}
|
|
|
|
|
2021-09-08 21:19:50 +02:00
|
|
|
/* Acquire configuration parameters */
|
|
|
|
if (!SelectConfigFiles(userDoption, progname))
|
|
|
|
proc_exit(1);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Validate we have been given a reasonable-looking DataDir and change
|
|
|
|
* into it.
|
|
|
|
*/
|
|
|
|
checkDataDir();
|
|
|
|
ChangeToDataDir();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create lockfile for data directory.
|
|
|
|
*/
|
|
|
|
CreateDataDirLockFile(false);
|
|
|
|
|
|
|
|
/* read control file (error checking and contains config ) */
|
|
|
|
LocalProcessControlFile(false);
|
|
|
|
|
2022-07-15 21:24:10 +02:00
|
|
|
/*
|
|
|
|
* process any libraries that should be preloaded at postmaster start
|
|
|
|
*/
|
|
|
|
process_shared_preload_libraries();
|
|
|
|
|
2021-09-08 21:19:50 +02:00
|
|
|
/* Initialize MaxBackends */
|
|
|
|
InitializeMaxBackends();
|
|
|
|
|
2022-07-15 21:24:10 +02:00
|
|
|
/*
|
|
|
|
* Give preloaded libraries a chance to request additional shared memory.
|
|
|
|
*/
|
|
|
|
process_shmem_requests();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now that loadable modules have had their chance to request additional
|
|
|
|
* shared memory, determine the value of any runtime-computed GUCs that
|
|
|
|
* depend on the amount of shared memory required.
|
|
|
|
*/
|
|
|
|
InitializeShmemGUCs();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now that modules have been loaded, we can process any custom resource
|
|
|
|
* managers specified in the wal_consistency_checking GUC.
|
|
|
|
*/
|
|
|
|
InitializeWalConsistencyChecking();
|
|
|
|
|
2021-09-08 21:19:50 +02:00
|
|
|
CreateSharedMemoryAndSemaphores();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remember stand-alone backend startup time,roughly at the same point
|
|
|
|
* during startup that postmaster does so.
|
|
|
|
*/
|
|
|
|
PgStartTime = GetCurrentTimestamp();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a per-backend PGPROC struct in shared memory. We must do this
|
|
|
|
* before we can use LWLocks.
|
|
|
|
*/
|
|
|
|
InitProcess();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now that sufficient infrastructure has been initialized, PostgresMain()
|
|
|
|
* can do the rest.
|
|
|
|
*/
|
|
|
|
PostgresMain(dbname, username);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------
|
|
|
|
* PostgresMain
|
|
|
|
* postgres main loop -- all backends, interactive or otherwise loop here
|
|
|
|
*
|
|
|
|
* dbname is the name of the database to connect to, username is the
|
|
|
|
* PostgreSQL user name to be used for the session.
|
|
|
|
*
|
|
|
|
* NB: Single user mode specific setup should go to PostgresSingleUserMain()
|
|
|
|
* if reasonably possible.
|
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
PostgresMain(const char *dbname, const char *username)
|
|
|
|
{
|
|
|
|
sigjmp_buf local_sigjmp_buf;
|
Be more rigorous about local variables in PostgresMain().
Since PostgresMain calls sigsetjmp, any local variables that are not
marked "volatile" have a risk of unspecified behavior. In practice
this means that when control returns via longjmp, such variables might
get reset to their values as of the time of sigsetjmp, depending on
whether the compiler chose to put them in registers or on the stack.
We were careful about this for "send_ready_for_query", but not the
other local variables.
In the case of the timeout_enabled flags, resetting them to
their initial "false" states is actually good, since we do
"disable_all_timeouts()" in the longjmp cleanup code path. If that
does not happen, we risk uselessly calling "disable_timeout()" later,
which is harmless but a little bit expensive. Let's explicitly reset
these flags so that the behavior is correct and platform-independent.
(This change means that we really don't need the new "volatile"
markings after all, but let's install them anyway since any change
in this logic could re-introduce a problem.)
There is no issue for "firstchar" and "input_message" because those
are explicitly reinitialized each time through the query processing
loop. To make that clearer, move them to be declared inside the loop.
That leaves us with all the function-lifespan locals except the
sigjmp_buf itself marked as volatile, which seems like a good policy
to have going forward.
Because of the possibility of extra disable_timeout() calls, this
seems worth back-patching.
Sergey Shinderuk and Tom Lane
Discussion: https://postgr.es/m/2eda015b-7dff-47fd-d5e2-f1a9899b90a6@postgrespro.ru
2023-07-10 18:14:34 +02:00
|
|
|
|
|
|
|
/* these must be volatile to ensure state is preserved across longjmp: */
|
2021-09-08 21:19:50 +02:00
|
|
|
volatile bool send_ready_for_query = true;
|
Be more rigorous about local variables in PostgresMain().
Since PostgresMain calls sigsetjmp, any local variables that are not
marked "volatile" have a risk of unspecified behavior. In practice
this means that when control returns via longjmp, such variables might
get reset to their values as of the time of sigsetjmp, depending on
whether the compiler chose to put them in registers or on the stack.
We were careful about this for "send_ready_for_query", but not the
other local variables.
In the case of the timeout_enabled flags, resetting them to
their initial "false" states is actually good, since we do
"disable_all_timeouts()" in the longjmp cleanup code path. If that
does not happen, we risk uselessly calling "disable_timeout()" later,
which is harmless but a little bit expensive. Let's explicitly reset
these flags so that the behavior is correct and platform-independent.
(This change means that we really don't need the new "volatile"
markings after all, but let's install them anyway since any change
in this logic could re-introduce a problem.)
There is no issue for "firstchar" and "input_message" because those
are explicitly reinitialized each time through the query processing
loop. To make that clearer, move them to be declared inside the loop.
That leaves us with all the function-lifespan locals except the
sigjmp_buf itself marked as volatile, which seems like a good policy
to have going forward.
Because of the possibility of extra disable_timeout() calls, this
seems worth back-patching.
Sergey Shinderuk and Tom Lane
Discussion: https://postgr.es/m/2eda015b-7dff-47fd-d5e2-f1a9899b90a6@postgrespro.ru
2023-07-10 18:14:34 +02:00
|
|
|
volatile bool idle_in_transaction_timeout_enabled = false;
|
|
|
|
volatile bool idle_session_timeout_enabled = false;
|
2021-09-08 21:19:50 +02:00
|
|
|
|
2022-10-28 09:19:06 +02:00
|
|
|
Assert(dbname != NULL);
|
|
|
|
Assert(username != NULL);
|
2021-09-08 21:19:50 +02:00
|
|
|
|
|
|
|
SetProcessingMode(InitProcessing);
|
2004-05-21 07:08:06 +02:00
|
|
|
|
1999-10-06 23:58:18 +02:00
|
|
|
/*
|
Centralize setup of SIGQUIT handling for postmaster child processes.
We decided that the policy established in commit 7634bd4f6 for
the bgwriter, checkpointer, walwriter, and walreceiver processes,
namely that they should accept SIGQUIT at all times, really ought
to apply uniformly to all postmaster children. Therefore, get
rid of the duplicative and inconsistent per-process code for
establishing that signal handler and removing SIGQUIT from BlockSig.
Instead, make InitPostmasterChild do it.
The handler set up by InitPostmasterChild is SignalHandlerForCrashExit,
which just summarily does _exit(2). In interactive backends, we
almost immediately replace that with quickdie, since we would prefer
to try to tell the client that we're dying. However, this patch is
changing the behavior of autovacuum (both launcher and workers), as
well as walsenders. Those processes formerly also used quickdie,
but AFAICS that was just mindless copy-and-paste: they don't have
any interactive client that's likely to benefit from being told this.
The stats collector continues to be an outlier, in that it thinks
SIGQUIT means normal exit. That should probably be changed for
consistency, but there's another patch set where that's being
dealt with, so I didn't do so here.
Discussion: https://postgr.es/m/644875.1599933441@sss.pgh.pa.us
2020-09-16 22:04:36 +02:00
|
|
|
* Set up signal handlers. (InitPostmasterChild or InitStandaloneProcess
|
|
|
|
* has already set up BlockSig and made that the active signal mask.)
|
1999-10-06 23:58:18 +02:00
|
|
|
*
|
2000-12-20 22:51:52 +01:00
|
|
|
* Note that postmaster blocked all signals before forking child process,
|
|
|
|
* so there is no race condition whereby we might receive a signal before
|
|
|
|
* we have set up the handler.
|
XLOG (and related) changes:
* Store two past checkpoint locations, not just one, in pg_control.
On startup, we fall back to the older checkpoint if the newer one
is unreadable. Also, a physical copy of the newest checkpoint record
is kept in pg_control for possible use in disaster recovery (ie,
complete loss of pg_xlog). Also add a version number for pg_control
itself. Remove archdir from pg_control; it ought to be a GUC
parameter, not a special case (not that it's implemented yet anyway).
* Suppress successive checkpoint records when nothing has been entered
in the WAL log since the last one. This is not so much to avoid I/O
as to make it actually useful to keep track of the last two
checkpoints. If the things are right next to each other then there's
not a lot of redundancy gained...
* Change CRC scheme to a true 64-bit CRC, not a pair of 32-bit CRCs
on alternate bytes. Polynomial borrowed from ECMA DLT1 standard.
* Fix XLOG record length handling so that it will work at BLCKSZ = 32k.
* Change XID allocation to work more like OID allocation. (This is of
dubious necessity, but I think it's a good idea anyway.)
* Fix a number of minor bugs, such as off-by-one logic for XLOG file
wraparound at the 4 gig mark.
* Add documentation and clean up some coding infelicities; move file
format declarations out to include files where planned contrib
utilities can get at them.
* Checkpoint will now occur every CHECKPOINT_SEGMENTS log segments or
every CHECKPOINT_TIMEOUT seconds, whichever comes first. It is also
possible to force a checkpoint by sending SIGUSR1 to the postmaster
(undocumented feature...)
* Defend against kill -9 postmaster by storing shmem block's key and ID
in postmaster.pid lockfile, and checking at startup to ensure that no
processes are still connected to old shmem block (if it still exists).
* Switch backends to accept SIGQUIT rather than SIGUSR1 for emergency
stop, for symmetry with postmaster and xlog utilities. Clean up signal
handling in bootstrap.c so that xlog utilities launched by postmaster
will react to signals better.
* Standalone bootstrap now grabs lockfile in target directory, as added
insurance against running it in parallel with live postmaster.
2001-03-13 02:17:06 +01:00
|
|
|
*
|
|
|
|
* Also note: it's best not to use any signals that are SIG_IGNored in the
|
|
|
|
* postmaster. If such a signal arrives before we are able to change the
|
2002-02-19 20:54:43 +01:00
|
|
|
* handler to non-SIG_IGN, it'll get dropped. Instead, make a dummy
|
|
|
|
* handler in the postmaster to reserve the signal. (Of course, this isn't
|
|
|
|
* an issue for signals that are locally generated, such as SIGALRM and
|
|
|
|
* SIGPIPE.)
|
1999-10-06 23:58:18 +02:00
|
|
|
*/
|
2010-01-15 10:19:10 +01:00
|
|
|
if (am_walsender)
|
|
|
|
WalSndSignals();
|
2007-07-09 03:15:14 +02:00
|
|
|
else
|
2010-01-15 10:19:10 +01:00
|
|
|
{
|
2019-12-17 19:14:28 +01:00
|
|
|
pqsignal(SIGHUP, SignalHandlerForConfigReload);
|
2010-01-15 10:19:10 +01:00
|
|
|
pqsignal(SIGINT, StatementCancelHandler); /* cancel current query */
|
|
|
|
pqsignal(SIGTERM, die); /* cancel current query and exit */
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2010-01-15 10:19:10 +01:00
|
|
|
/*
|
Centralize setup of SIGQUIT handling for postmaster child processes.
We decided that the policy established in commit 7634bd4f6 for
the bgwriter, checkpointer, walwriter, and walreceiver processes,
namely that they should accept SIGQUIT at all times, really ought
to apply uniformly to all postmaster children. Therefore, get
rid of the duplicative and inconsistent per-process code for
establishing that signal handler and removing SIGQUIT from BlockSig.
Instead, make InitPostmasterChild do it.
The handler set up by InitPostmasterChild is SignalHandlerForCrashExit,
which just summarily does _exit(2). In interactive backends, we
almost immediately replace that with quickdie, since we would prefer
to try to tell the client that we're dying. However, this patch is
changing the behavior of autovacuum (both launcher and workers), as
well as walsenders. Those processes formerly also used quickdie,
but AFAICS that was just mindless copy-and-paste: they don't have
any interactive client that's likely to benefit from being told this.
The stats collector continues to be an outlier, in that it thinks
SIGQUIT means normal exit. That should probably be changed for
consistency, but there's another patch set where that's being
dealt with, so I didn't do so here.
Discussion: https://postgr.es/m/644875.1599933441@sss.pgh.pa.us
2020-09-16 22:04:36 +02:00
|
|
|
* In a postmaster child backend, replace SignalHandlerForCrashExit
|
|
|
|
* with quickdie, so we can tell the client we're dying.
|
|
|
|
*
|
2010-01-15 10:19:10 +01:00
|
|
|
* In a standalone backend, SIGQUIT can be generated from the keyboard
|
|
|
|
* easily, while SIGTERM cannot, so we make both signals do die()
|
|
|
|
* rather than quickdie().
|
|
|
|
*/
|
|
|
|
if (IsUnderPostmaster)
|
|
|
|
pqsignal(SIGQUIT, quickdie); /* hard crash time */
|
|
|
|
else
|
|
|
|
pqsignal(SIGQUIT, die); /* cancel current query and exit */
|
Introduce timeout handling framework
Management of timeouts was getting a little cumbersome; what we
originally had was more than enough back when we were only concerned
about deadlocks and query cancel; however, when we added timeouts for
standby processes, the code got considerably messier. Since there are
plans to add more complex timeouts, this seems a good time to introduce
a central timeout handling module.
External modules register their timeout handlers during process
initialization, and later enable and disable them as they see fit using
a simple API; timeout.c is in charge of keeping track of which timeouts
are in effect at any time, installing a common SIGALRM signal handler,
and calling setitimer() as appropriate to ensure timely firing of
external handlers.
timeout.c additionally supports pluggable modules to add their own
timeouts, though this capability isn't exercised anywhere yet.
Additionally, as of this commit, walsender processes are aware of
timeouts; we had a preexisting bug there that made those ignore SIGALRM,
thus being subject to unhandled deadlocks, particularly during the
authentication phase. This has already been fixed in back branches in
commit 0bf8eb2a, which see for more details.
Main author: Zoltán Böszörményi
Some review and cleanup by Álvaro Herrera
Extensive reworking by Tom Lane
2012-07-17 00:43:21 +02:00
|
|
|
InitializeTimeouts(); /* establishes SIGALRM handler */
|
2001-01-14 06:08:17 +01:00
|
|
|
|
2010-01-15 10:19:10 +01:00
|
|
|
/*
|
|
|
|
* Ignore failure to write to frontend. Note: if frontend closes
|
|
|
|
* connection, we will notice it and exit cleanly when control next
|
|
|
|
* returns to outer loop. This seems safer than forcing exit in the
|
|
|
|
* midst of output during who-knows-what operation...
|
|
|
|
*/
|
|
|
|
pqsignal(SIGPIPE, SIG_IGN);
|
|
|
|
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
|
|
|
|
pqsignal(SIGUSR2, SIG_IGN);
|
|
|
|
pqsignal(SIGFPE, FloatExceptionHandler);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reset some signals that are accepted by postmaster but not by
|
|
|
|
* backend
|
|
|
|
*/
|
|
|
|
pqsignal(SIGCHLD, SIG_DFL); /* system() requires this on some
|
|
|
|
* platforms */
|
|
|
|
}
|
1999-10-06 23:58:18 +02:00
|
|
|
|
2021-08-05 23:37:09 +02:00
|
|
|
/* Early initialization */
|
|
|
|
BaseInit();
|
|
|
|
|
2009-08-29 21:26:52 +02:00
|
|
|
/* We need to allow SIGINT, etc during the initial transaction */
|
2023-02-02 22:34:56 +01:00
|
|
|
sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
|
2009-08-29 21:26:52 +02:00
|
|
|
|
1999-10-06 23:58:18 +02:00
|
|
|
/*
|
2000-12-18 01:44:50 +01:00
|
|
|
* General initialization.
|
|
|
|
*
|
|
|
|
* NOTE: if you are tempted to add code in this vicinity, consider putting
|
|
|
|
* it inside InitPostgres() instead. In particular, anything that
|
|
|
|
* involves database access should be there, not here.
|
2023-10-11 05:31:49 +02:00
|
|
|
*
|
|
|
|
* Honor session_preload_libraries if not dealing with a WAL sender.
|
1999-05-22 19:47:54 +02:00
|
|
|
*/
|
Process session_preload_libraries within InitPostgres's transaction.
Previously we did this after InitPostgres, at a somewhat randomly chosen
place within PostgresMain. However, since commit a0ffa885e doing this
outside a transaction can cause a crash, if we need to check permissions
while replacing a placeholder GUC. (Besides which, a preloaded library
could itself want to do database access within _PG_init.)
To avoid needing an additional transaction start/end in every session,
move the process_session_preload_libraries call to within InitPostgres's
transaction. That requires teaching the code not to call it when
InitPostgres is called from somewhere other than PostgresMain, since
we don't want session_preload_libraries to affect background workers.
The most future-proof solution here seems to be to add an additional
flag parameter to InitPostgres; fortunately, we're not yet very worried
about API stability for v15.
Doing this also exposed the fact that we're currently honoring
session_preload_libraries in walsenders, even those not connected to
any database. This seems, at minimum, a POLA violation: walsenders
are not interactive sessions. Let's stop doing that.
(All these comments also apply to local_preload_libraries, of course.)
Per report from Gurjeet Singh (thanks also to Nathan Bossart and Kyotaro
Horiguchi for review). Backpatch to v15 where a0ffa885e came in.
Discussion: https://postgr.es/m/CABwTF4VEpwTHhRQ+q5MiC5ucngN-whN-PdcKeufX7eLSoAfbZA@mail.gmail.com
2022-07-25 16:27:43 +02:00
|
|
|
InitPostgres(dbname, InvalidOid, /* database to connect to */
|
|
|
|
username, InvalidOid, /* role to connect as */
|
2023-10-11 05:31:49 +02:00
|
|
|
(!am_walsender) ? INIT_PG_LOAD_SESSION_LIBS : 0,
|
Process session_preload_libraries within InitPostgres's transaction.
Previously we did this after InitPostgres, at a somewhat randomly chosen
place within PostgresMain. However, since commit a0ffa885e doing this
outside a transaction can cause a crash, if we need to check permissions
while replacing a placeholder GUC. (Besides which, a preloaded library
could itself want to do database access within _PG_init.)
To avoid needing an additional transaction start/end in every session,
move the process_session_preload_libraries call to within InitPostgres's
transaction. That requires teaching the code not to call it when
InitPostgres is called from somewhere other than PostgresMain, since
we don't want session_preload_libraries to affect background workers.
The most future-proof solution here seems to be to add an additional
flag parameter to InitPostgres; fortunately, we're not yet very worried
about API stability for v15.
Doing this also exposed the fact that we're currently honoring
session_preload_libraries in walsenders, even those not connected to
any database. This seems, at minimum, a POLA violation: walsenders
are not interactive sessions. Let's stop doing that.
(All these comments also apply to local_preload_libraries, of course.)
Per report from Gurjeet Singh (thanks also to Nathan Bossart and Kyotaro
Horiguchi for review). Backpatch to v15 where a0ffa885e came in.
Discussion: https://postgr.es/m/CABwTF4VEpwTHhRQ+q5MiC5ucngN-whN-PdcKeufX7eLSoAfbZA@mail.gmail.com
2022-07-25 16:27:43 +02:00
|
|
|
NULL); /* no out_dbname */
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2009-08-29 21:26:52 +02:00
|
|
|
/*
|
|
|
|
* If the PostmasterContext is still around, recycle the space; we don't
|
2024-03-12 12:42:38 +01:00
|
|
|
* need it anymore after InitPostgres completes.
|
2009-08-29 21:26:52 +02:00
|
|
|
*/
|
|
|
|
if (PostmasterContext)
|
|
|
|
{
|
|
|
|
MemoryContextDelete(PostmasterContext);
|
|
|
|
PostmasterContext = NULL;
|
|
|
|
}
|
|
|
|
|
2000-12-18 01:44:50 +01:00
|
|
|
SetProcessingMode(NormalProcessing);
|
1999-02-02 04:45:56 +01:00
|
|
|
|
2004-11-14 20:35:35 +01:00
|
|
|
/*
|
|
|
|
* Now all GUC states are fully set up. Report them to client if
|
|
|
|
* appropriate.
|
|
|
|
*/
|
|
|
|
BeginReportingGUCOptions();
|
|
|
|
|
2004-11-24 20:51:05 +01:00
|
|
|
/*
|
|
|
|
* Also set up handler to log session end; we have to wait till now to be
|
|
|
|
* sure Log_disconnections has its final value.
|
|
|
|
*/
|
|
|
|
if (IsUnderPostmaster && Log_disconnections)
|
|
|
|
on_proc_exit(log_disconnections, 0);
|
|
|
|
|
2021-09-16 11:02:40 +02:00
|
|
|
pgstat_report_connect(MyDatabaseId);
|
|
|
|
|
2012-10-05 16:13:07 +02:00
|
|
|
/* Perform initialization specific to a WAL sender process. */
|
2010-01-15 10:19:10 +01:00
|
|
|
if (am_walsender)
|
2012-10-05 16:13:07 +02:00
|
|
|
InitWalSender();
|
2010-01-15 10:19:10 +01:00
|
|
|
|
1999-10-06 23:58:18 +02:00
|
|
|
/*
|
|
|
|
* Send this backend's cancellation info to the frontend.
|
1998-10-02 03:14:14 +02:00
|
|
|
*/
|
2016-10-11 18:19:18 +02:00
|
|
|
if (whereToSendOutput == DestRemote)
|
1998-07-09 05:29:11 +02:00
|
|
|
{
|
1999-04-25 05:19:27 +02:00
|
|
|
StringInfoData buf;
|
1999-05-25 18:15:34 +02:00
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
pq_beginmessage(&buf, PqMsg_BackendKeyData);
|
2017-10-12 06:00:46 +02:00
|
|
|
pq_sendint32(&buf, (int32) MyProcPid);
|
|
|
|
pq_sendint32(&buf, (int32) MyCancelKey);
|
1999-04-25 05:19:27 +02:00
|
|
|
pq_endmessage(&buf);
|
1998-07-09 05:29:11 +02:00
|
|
|
/* Need not flush since ReadyForQuery will do it. */
|
|
|
|
}
|
|
|
|
|
2004-01-28 22:02:40 +01:00
|
|
|
/* Welcome banner for standalone case */
|
2005-11-03 18:11:40 +01:00
|
|
|
if (whereToSendOutput == DestDebug)
|
2003-11-29 22:40:43 +01:00
|
|
|
printf("\nPostgreSQL stand-alone backend %s\n", PG_VERSION);
|
1998-10-02 03:14:14 +02:00
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
/*
|
|
|
|
* Create the memory context we will use in the main loop.
|
|
|
|
*
|
2003-05-02 22:54:36 +02:00
|
|
|
* MessageContext is reset once per iteration of the main loop, ie, upon
|
|
|
|
* completion of processing of each command message from the client.
|
2000-06-28 05:33:33 +02:00
|
|
|
*/
|
2003-05-02 22:54:36 +02:00
|
|
|
MessageContext = AllocSetContextCreate(TopMemoryContext,
|
|
|
|
"MessageContext",
|
Add macros to make AllocSetContextCreate() calls simpler and safer.
I found that half a dozen (nearly 5%) of our AllocSetContextCreate calls
had typos in the context-sizing parameters. While none of these led to
especially significant problems, they did create minor inefficiencies,
and it's now clear that expecting people to copy-and-paste those calls
accurately is not a great idea. Let's reduce the risk of future errors
by introducing single macros that encapsulate the common use-cases.
Three such macros are enough to cover all but two special-purpose contexts;
those two calls can be left as-is, I think.
While this patch doesn't in itself improve matters for third-party
extensions, it doesn't break anything for them either, and they can
gradually adopt the simplified notation over time.
In passing, change TopMemoryContext to use the default allocation
parameters. Formerly it could only be extended 8K at a time. That was
probably reasonable when this code was written; but nowadays we create
many more contexts than we did then, so that it's not unusual to have a
couple hundred K in TopMemoryContext, even without considering various
dubious code that sticks other things there. There seems no good reason
not to let it use growing blocks like most other contexts.
Back-patch to 9.6, mostly because that's still close enough to HEAD that
it's easy to do so, and keeping the branches in sync can be expected to
avoid some future back-patching pain. The bugs fixed by these changes
don't seem to be significant enough to justify fixing them further back.
Discussion: <21072.1472321324@sss.pgh.pa.us>
2016-08-27 23:50:38 +02:00
|
|
|
ALLOCSET_DEFAULT_SIZES);
|
2000-06-28 05:33:33 +02:00
|
|
|
|
2017-10-12 01:49:31 +02:00
|
|
|
/*
|
|
|
|
* Create memory context and buffer used for RowDescription messages. As
|
|
|
|
* SendRowDescriptionMessage(), via exec_describe_statement_message(), is
|
|
|
|
* frequently executed for ever single statement, we don't want to
|
|
|
|
* allocate a separate buffer every time.
|
|
|
|
*/
|
|
|
|
row_description_context = AllocSetContextCreate(TopMemoryContext,
|
|
|
|
"RowDescriptionContext",
|
|
|
|
ALLOCSET_DEFAULT_SIZES);
|
|
|
|
MemoryContextSwitchTo(row_description_context);
|
|
|
|
initStringInfo(&row_description_buf);
|
|
|
|
MemoryContextSwitchTo(TopMemoryContext);
|
|
|
|
|
Add support event triggers on authenticated login
This commit introduces trigger on login event, allowing to fire some actions
right on the user connection. This can be useful for logging or connection
check purposes as well as for some personalization of environment. Usage
details are described in the documentation included, but shortly usage is
the same as for other triggers: create function returning event_trigger and
then create event trigger on login event.
In order to prevent the connection time overhead when there are no triggers
the commit introduces pg_database.dathasloginevt flag, which indicates database
has active login triggers. This flag is set by CREATE/ALTER EVENT TRIGGER
command, and unset at connection time when no active triggers found.
Author: Konstantin Knizhnik, Mikhail Gribkov
Discussion: https://postgr.es/m/0d46d29f-4558-3af9-9c85-7774e14a7709%40postgrespro.ru
Reviewed-by: Pavel Stehule, Takayuki Tsunakawa, Greg Nancarrow, Ivan Panchenko
Reviewed-by: Daniel Gustafsson, Teodor Sigaev, Robert Haas, Andres Freund
Reviewed-by: Tom Lane, Andrey Sokolov, Zhihong Yu, Sergey Shinderuk
Reviewed-by: Gregory Stark, Nikita Malakhov, Ted Yu
2023-10-16 02:16:55 +02:00
|
|
|
/* Fire any defined login event triggers, if appropriate */
|
|
|
|
EventTriggerOnLogin();
|
|
|
|
|
1999-10-06 23:58:18 +02:00
|
|
|
/*
|
|
|
|
* POSTGRES main processing loop begins here
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1999-10-06 23:58:18 +02:00
|
|
|
* If an exception is encountered, processing resumes here so we abort the
|
|
|
|
* current transaction and start a new one.
|
2004-07-31 02:45:57 +02:00
|
|
|
*
|
|
|
|
* You might wonder why this isn't coded as an infinite loop around a
|
|
|
|
* PG_TRY construct. The reason is that this is the bottom of the
|
|
|
|
* exception stack, and so with PG_TRY there would be no exception handler
|
|
|
|
* in force at all during the CATCH part. By leaving the outermost setjmp
|
|
|
|
* always active, we have at least some chance of recovering from an error
|
|
|
|
* during error recovery. (If we get into an infinite loop thereby, it
|
|
|
|
* will soon be stopped by overflow of elog.c's internal state stack.)
|
Fix assorted race conditions in the new timeout infrastructure.
Prevent handle_sig_alarm from losing control partway through due to a query
cancel (either an asynchronous SIGINT, or a cancel triggered by one of the
timeout handler functions). That would at least result in failure to
schedule any required future interrupt, and might result in actual
corruption of timeout.c's data structures, if the interrupt happened while
we were updating those.
We could still lose control if an asynchronous SIGINT arrives just as the
function is entered. This wouldn't break any data structures, but it would
have the same effect as if the SIGALRM interrupt had been silently lost:
we'd not fire any currently-due handlers, nor schedule any new interrupt.
To forestall that scenario, forcibly reschedule any pending timer interrupt
during AbortTransaction and AbortSubTransaction. We can avoid any extra
kernel call in most cases by not doing that until we've allowed
LockErrorCleanup to kill the DEADLOCK_TIMEOUT and LOCK_TIMEOUT events.
Another hazard is that some platforms (at least Linux and *BSD) block a
signal before calling its handler and then unblock it on return. When we
longjmp out of the handler, the unblock doesn't happen, and the signal is
left blocked indefinitely. Again, we can fix that by forcibly unblocking
signals during AbortTransaction and AbortSubTransaction.
These latter two problems do not manifest when the longjmp reaches
postgres.c, because the error recovery code there kills all pending timeout
events anyway, and it uses sigsetjmp(..., 1) so that the appropriate signal
mask is restored. So errors thrown outside any transaction should be OK
already, and cleaning up in AbortTransaction and AbortSubTransaction should
be enough to fix these issues. (We're assuming that any code that catches
a query cancel error and doesn't re-throw it will do at least a
subtransaction abort to clean up; but that was pretty much required already
by other subsystems.)
Lastly, ProcSleep should not clear the LOCK_TIMEOUT indicator flag when
disabling that event: if a lock timeout interrupt happened after the lock
was granted, the ensuing query cancel is still going to happen at the next
CHECK_FOR_INTERRUPTS, and we want to report it as a lock timeout not a user
cancel.
Per reports from Dan Wood.
Back-patch to 9.3 where the new timeout handling infrastructure was
introduced. We may at some point decide to back-patch the signal
unblocking changes further, but I'll desist from that until we hear
actual field complaints about it.
2013-11-29 22:41:00 +01:00
|
|
|
*
|
|
|
|
* Note that we use sigsetjmp(..., 1), so that this function's signal mask
|
|
|
|
* (to wit, UnBlockSig) will be restored when longjmp'ing to here. This
|
|
|
|
* is essential in case we longjmp'd out of a signal handler on a platform
|
|
|
|
* where that leaves the signal blocked. It's not redundant with the
|
|
|
|
* unblock in AbortTransaction() because the latter is only called if we
|
|
|
|
* were inside a transaction.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2004-07-31 02:45:57 +02:00
|
|
|
if (sigsetjmp(local_sigjmp_buf, 1) != 0)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-28 05:33:33 +02:00
|
|
|
/*
|
2000-12-18 01:44:50 +01:00
|
|
|
* NOTE: if you are tempted to add more code in this if-block,
|
2004-07-31 02:45:57 +02:00
|
|
|
* consider the high probability that it should be in
|
|
|
|
* AbortTransaction() instead. The only stuff done directly here
|
|
|
|
* should be stuff that is guaranteed to apply *only* for outer-level
|
|
|
|
* error recovery, such as adjusting the FE/BE protocol status.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Since not using PG_TRY, must reset error stack by hand */
|
|
|
|
error_context_stack = NULL;
|
|
|
|
|
|
|
|
/* Prevent interrupts while cleaning up */
|
|
|
|
HOLD_INTERRUPTS();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Forget any pending QueryCancel request, since we're returning to
|
Fix assorted race conditions in the new timeout infrastructure.
Prevent handle_sig_alarm from losing control partway through due to a query
cancel (either an asynchronous SIGINT, or a cancel triggered by one of the
timeout handler functions). That would at least result in failure to
schedule any required future interrupt, and might result in actual
corruption of timeout.c's data structures, if the interrupt happened while
we were updating those.
We could still lose control if an asynchronous SIGINT arrives just as the
function is entered. This wouldn't break any data structures, but it would
have the same effect as if the SIGALRM interrupt had been silently lost:
we'd not fire any currently-due handlers, nor schedule any new interrupt.
To forestall that scenario, forcibly reschedule any pending timer interrupt
during AbortTransaction and AbortSubTransaction. We can avoid any extra
kernel call in most cases by not doing that until we've allowed
LockErrorCleanup to kill the DEADLOCK_TIMEOUT and LOCK_TIMEOUT events.
Another hazard is that some platforms (at least Linux and *BSD) block a
signal before calling its handler and then unblock it on return. When we
longjmp out of the handler, the unblock doesn't happen, and the signal is
left blocked indefinitely. Again, we can fix that by forcibly unblocking
signals during AbortTransaction and AbortSubTransaction.
These latter two problems do not manifest when the longjmp reaches
postgres.c, because the error recovery code there kills all pending timeout
events anyway, and it uses sigsetjmp(..., 1) so that the appropriate signal
mask is restored. So errors thrown outside any transaction should be OK
already, and cleaning up in AbortTransaction and AbortSubTransaction should
be enough to fix these issues. (We're assuming that any code that catches
a query cancel error and doesn't re-throw it will do at least a
subtransaction abort to clean up; but that was pretty much required already
by other subsystems.)
Lastly, ProcSleep should not clear the LOCK_TIMEOUT indicator flag when
disabling that event: if a lock timeout interrupt happened after the lock
was granted, the ensuing query cancel is still going to happen at the next
CHECK_FOR_INTERRUPTS, and we want to report it as a lock timeout not a user
cancel.
Per reports from Dan Wood.
Back-patch to 9.3 where the new timeout handling infrastructure was
introduced. We may at some point decide to back-patch the signal
unblocking changes further, but I'll desist from that until we hear
actual field complaints about it.
2013-11-29 22:41:00 +01:00
|
|
|
* the idle loop anyway, and cancel any active timeout requests. (In
|
|
|
|
* future we might want to allow some timeout requests to survive, but
|
|
|
|
* at minimum it'd be necessary to do reschedule_timeouts(), in case
|
|
|
|
* we got here because of a query cancel interrupting the SIGALRM
|
|
|
|
* interrupt handler.) Note in particular that we must clear the
|
|
|
|
* statement and lock timeout indicators, to prevent any future plain
|
|
|
|
* query cancels from being misreported as timeouts in case we're
|
|
|
|
* forgetting a timeout cancel.
|
2001-01-14 06:08:17 +01:00
|
|
|
*/
|
Be more rigorous about local variables in PostgresMain().
Since PostgresMain calls sigsetjmp, any local variables that are not
marked "volatile" have a risk of unspecified behavior. In practice
this means that when control returns via longjmp, such variables might
get reset to their values as of the time of sigsetjmp, depending on
whether the compiler chose to put them in registers or on the stack.
We were careful about this for "send_ready_for_query", but not the
other local variables.
In the case of the timeout_enabled flags, resetting them to
their initial "false" states is actually good, since we do
"disable_all_timeouts()" in the longjmp cleanup code path. If that
does not happen, we risk uselessly calling "disable_timeout()" later,
which is harmless but a little bit expensive. Let's explicitly reset
these flags so that the behavior is correct and platform-independent.
(This change means that we really don't need the new "volatile"
markings after all, but let's install them anyway since any change
in this logic could re-introduce a problem.)
There is no issue for "firstchar" and "input_message" because those
are explicitly reinitialized each time through the query processing
loop. To make that clearer, move them to be declared inside the loop.
That leaves us with all the function-lifespan locals except the
sigjmp_buf itself marked as volatile, which seems like a good policy
to have going forward.
Because of the possibility of extra disable_timeout() calls, this
seems worth back-patching.
Sergey Shinderuk and Tom Lane
Discussion: https://postgr.es/m/2eda015b-7dff-47fd-d5e2-f1a9899b90a6@postgrespro.ru
2023-07-10 18:14:34 +02:00
|
|
|
disable_all_timeouts(false); /* do first to avoid race condition */
|
|
|
|
QueryCancelPending = false;
|
|
|
|
idle_in_transaction_timeout_enabled = false;
|
|
|
|
idle_session_timeout_enabled = false;
|
2004-07-31 02:45:57 +02:00
|
|
|
|
Introduce and use infrastructure for interrupt processing during client reads.
Up to now large swathes of backend code ran inside signal handlers
while reading commands from the client, to allow for speedy reaction to
asynchronous events. Most prominently shared invalidation and NOTIFY
handling. That means that complex code like the starting/stopping of
transactions is run in signal handlers... The required code was
fragile and verbose, and is likely to contain bugs.
That approach also severely limited what could be done while
communicating with the client. As the read might be from within
openssl it wasn't safely possible to trigger an error, e.g. to cancel
a backend in idle-in-transaction state. We did that in some cases,
namely fatal errors, nonetheless.
Now that FE/BE communication in the backend employs non-blocking
sockets and latches to block, we can quite simply interrupt reads from
signal handlers by setting the latch. That allows us to signal an
interrupted read, which is supposed to be retried after returning from
within the ssl library.
As signal handlers now only need to set the latch to guarantee timely
interrupt processing, remove a fair amount of complicated & fragile
code from async.c and sinval.c.
We could now actually start to process some kinds of interrupts, like
sinval ones, more often that before, but that seems better done
separately.
This work will hopefully allow to handle cases like being blocked by
sending data, interrupting idle transactions and similar to be
implemented without too much effort. In addition to allowing getting
rid of ImmediateInterruptOK, that is.
Author: Andres Freund
Reviewed-By: Heikki Linnakangas
2015-02-03 22:25:20 +01:00
|
|
|
/* Not reading from the client anymore. */
|
2005-06-02 23:03:25 +02:00
|
|
|
DoingCommandRead = false;
|
2004-07-31 02:45:57 +02:00
|
|
|
|
2004-09-26 02:26:28 +02:00
|
|
|
/* Make sure libpq is in a good state */
|
|
|
|
pq_comm_reset();
|
|
|
|
|
2004-07-31 02:45:57 +02:00
|
|
|
/* Report the error to the client and/or server log */
|
|
|
|
EmitErrorReport();
|
2001-01-14 06:08:17 +01:00
|
|
|
|
2023-04-03 16:18:38 +02:00
|
|
|
/*
|
|
|
|
* If Valgrind noticed something during the erroneous query, print the
|
|
|
|
* query string, assuming we have one.
|
|
|
|
*/
|
|
|
|
valgrind_report_error_query(debug_query_string);
|
|
|
|
|
2004-07-17 05:32:14 +02:00
|
|
|
/*
|
2004-07-31 02:45:57 +02:00
|
|
|
* Make sure debug_query_string gets reset before we possibly clobber
|
|
|
|
* the storage it points at.
|
2004-07-17 05:32:14 +02:00
|
|
|
*/
|
2004-07-31 02:45:57 +02:00
|
|
|
debug_query_string = NULL;
|
2004-07-17 05:32:14 +02:00
|
|
|
|
2001-01-14 06:08:17 +01:00
|
|
|
/*
|
2004-07-31 02:45:57 +02:00
|
|
|
* Abort the current transaction in order to recover.
|
2000-06-28 05:33:33 +02:00
|
|
|
*/
|
1996-11-14 11:25:54 +01:00
|
|
|
AbortCurrentTransaction();
|
2000-06-28 05:33:33 +02:00
|
|
|
|
2012-10-05 16:13:07 +02:00
|
|
|
if (am_walsender)
|
|
|
|
WalSndErrorCleanup();
|
|
|
|
|
2018-03-29 00:57:10 +02:00
|
|
|
PortalErrorCleanup();
|
|
|
|
|
Introduce logical decoding.
This feature, building on previous commits, allows the write-ahead log
stream to be decoded into a series of logical changes; that is,
inserts, updates, and deletes and the transactions which contain them.
It is capable of handling decoding even across changes to the schema
of the effected tables. The output format is controlled by a
so-called "output plugin"; an example is included. To make use of
this in a real replication system, the output plugin will need to be
modified to produce output in the format appropriate to that system,
and to perform filtering.
Currently, information can be extracted from the logical decoding
system only via SQL; future commits will add the ability to stream
changes via walsender.
Andres Freund, with review and other contributions from many other
people, including Álvaro Herrera, Abhijit Menon-Sen, Peter Gheogegan,
Kevin Grittner, Robert Haas, Heikki Linnakangas, Fujii Masao, Abhijit
Menon-Sen, Michael Paquier, Simon Riggs, Craig Ringer, and Steve
Singer.
2014-03-03 22:32:18 +01:00
|
|
|
/*
|
|
|
|
* We can't release replication slots inside AbortTransaction() as we
|
|
|
|
* need to be able to start and abort transactions while having a slot
|
|
|
|
* acquired. But we never need to hold them across top level errors,
|
2022-02-15 01:44:28 +01:00
|
|
|
* so releasing here is fine. There also is a before_shmem_exit()
|
|
|
|
* callback ensuring correct cleanup on FATAL errors.
|
Introduce logical decoding.
This feature, building on previous commits, allows the write-ahead log
stream to be decoded into a series of logical changes; that is,
inserts, updates, and deletes and the transactions which contain them.
It is capable of handling decoding even across changes to the schema
of the effected tables. The output format is controlled by a
so-called "output plugin"; an example is included. To make use of
this in a real replication system, the output plugin will need to be
modified to produce output in the format appropriate to that system,
and to perform filtering.
Currently, information can be extracted from the logical decoding
system only via SQL; future commits will add the ability to stream
changes via walsender.
Andres Freund, with review and other contributions from many other
people, including Álvaro Herrera, Abhijit Menon-Sen, Peter Gheogegan,
Kevin Grittner, Robert Haas, Heikki Linnakangas, Fujii Masao, Abhijit
Menon-Sen, Michael Paquier, Simon Riggs, Craig Ringer, and Steve
Singer.
2014-03-03 22:32:18 +01:00
|
|
|
*/
|
|
|
|
if (MyReplicationSlot != NULL)
|
|
|
|
ReplicationSlotRelease();
|
|
|
|
|
2016-12-08 18:00:00 +01:00
|
|
|
/* We also want to cleanup temporary slots on error. */
|
2024-04-25 10:31:44 +02:00
|
|
|
ReplicationSlotCleanup(false);
|
2016-12-08 18:00:00 +01:00
|
|
|
|
2018-03-22 03:28:28 +01:00
|
|
|
jit_reset_after_error();
|
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
/*
|
2000-12-18 01:44:50 +01:00
|
|
|
* Now return to normal top-level context and clear ErrorContext for
|
|
|
|
* next time.
|
2000-06-28 05:33:33 +02:00
|
|
|
*/
|
|
|
|
MemoryContextSwitchTo(TopMemoryContext);
|
2004-07-31 02:45:57 +02:00
|
|
|
FlushErrorState();
|
2000-12-18 01:44:50 +01:00
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* If we were handling an extended-query-protocol message, initiate
|
2003-06-20 23:58:02 +02:00
|
|
|
* skip till next Sync. This also causes us not to issue
|
|
|
|
* ReadyForQuery (until we get Sync).
|
2003-05-05 02:44:56 +02:00
|
|
|
*/
|
|
|
|
if (doing_extended_query_message)
|
|
|
|
ignore_till_sync = true;
|
2001-01-14 06:08:17 +01:00
|
|
|
|
2004-07-31 02:45:57 +02:00
|
|
|
/* We don't have a transaction command open anymore */
|
|
|
|
xact_started = false;
|
2006-06-21 00:52:00 +02:00
|
|
|
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
/*
|
|
|
|
* If an error occurred while we were reading a message from the
|
|
|
|
* client, we have potentially lost track of where the previous
|
|
|
|
* message ends and the next one begins. Even though we have
|
|
|
|
* otherwise recovered from the error, we cannot safely read any more
|
|
|
|
* messages from the client, so there isn't much we can do with the
|
|
|
|
* connection anymore.
|
|
|
|
*/
|
|
|
|
if (pq_is_reading_msg())
|
|
|
|
ereport(FATAL,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
Adjust behavior of single-user -j mode for better initdb error reporting.
Previously, -j caused the entire input file to be read in and executed as
a single command string. That's undesirable, not least because any error
causes the entire file to be regurgitated as the "failing query". Some
experimentation suggests a better rule: end the command string when we see
a semicolon immediately followed by two newlines, ie, an empty line after
a query. This serves nicely to break up the existing examples such as
information_schema.sql and system_views.sql. A limitation is that it's
no longer possible to write such a sequence within a string literal or
multiline comment in a file meant to be read with -j; but there are no
instances of such a problem within the data currently used by initdb.
(If someone does make such a mistake in future, it'll be obvious because
they'll get an unterminated-literal or unterminated-comment syntax error.)
Other than that, there shouldn't be any negative consequences; you're not
forced to end statements that way, it's just a better idea in most cases.
In passing, remove src/include/tcop/tcopdebug.h, which is dead code
because it's not included anywhere, and hasn't been for more than
ten years. One of the debug-support symbols it purported to describe
has been unreferenced for at least the same amount of time, and the
other is removed by this commit on the grounds that it was useless:
forcing -j mode all the time would have broken initdb. The lack of
complaints about that, or about the missing inclusion, shows that
no one has tried to use TCOP_DONTUSENEWLINE in many years.
2015-12-18 01:34:15 +01:00
|
|
|
errmsg("terminating connection because protocol synchronization was lost")));
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
|
2004-07-31 02:45:57 +02:00
|
|
|
/* Now we can allow interrupts again */
|
2001-01-19 23:08:47 +01:00
|
|
|
RESUME_INTERRUPTS();
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1998-05-19 20:05:58 +02:00
|
|
|
|
2004-07-31 02:45:57 +02:00
|
|
|
/* We can now handle ereport(ERROR) */
|
|
|
|
PG_exception_stack = &local_sigjmp_buf;
|
1999-11-16 07:13:36 +01:00
|
|
|
|
2003-06-20 23:58:02 +02:00
|
|
|
if (!ignore_till_sync)
|
2005-12-31 00:49:48 +01:00
|
|
|
send_ready_for_query = true; /* initially, or after error */
|
2003-04-19 02:02:30 +02:00
|
|
|
|
1998-10-02 03:14:14 +02:00
|
|
|
/*
|
|
|
|
* Non-error queries loop here.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
for (;;)
|
|
|
|
{
|
Be more rigorous about local variables in PostgresMain().
Since PostgresMain calls sigsetjmp, any local variables that are not
marked "volatile" have a risk of unspecified behavior. In practice
this means that when control returns via longjmp, such variables might
get reset to their values as of the time of sigsetjmp, depending on
whether the compiler chose to put them in registers or on the stack.
We were careful about this for "send_ready_for_query", but not the
other local variables.
In the case of the timeout_enabled flags, resetting them to
their initial "false" states is actually good, since we do
"disable_all_timeouts()" in the longjmp cleanup code path. If that
does not happen, we risk uselessly calling "disable_timeout()" later,
which is harmless but a little bit expensive. Let's explicitly reset
these flags so that the behavior is correct and platform-independent.
(This change means that we really don't need the new "volatile"
markings after all, but let's install them anyway since any change
in this logic could re-introduce a problem.)
There is no issue for "firstchar" and "input_message" because those
are explicitly reinitialized each time through the query processing
loop. To make that clearer, move them to be declared inside the loop.
That leaves us with all the function-lifespan locals except the
sigjmp_buf itself marked as volatile, which seems like a good policy
to have going forward.
Because of the possibility of extra disable_timeout() calls, this
seems worth back-patching.
Sergey Shinderuk and Tom Lane
Discussion: https://postgr.es/m/2eda015b-7dff-47fd-d5e2-f1a9899b90a6@postgrespro.ru
2023-07-10 18:14:34 +02:00
|
|
|
int firstchar;
|
|
|
|
StringInfoData input_message;
|
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* At top of loop, reset extended-query-message flag, so that any
|
|
|
|
* errors encountered in "idle" state don't provoke skip.
|
|
|
|
*/
|
|
|
|
doing_extended_query_message = false;
|
|
|
|
|
2023-04-03 16:18:38 +02:00
|
|
|
/*
|
|
|
|
* For valgrind reporting purposes, the "current query" begins here.
|
|
|
|
*/
|
|
|
|
#ifdef USE_VALGRIND
|
|
|
|
old_valgrind_error_count = VALGRIND_COUNT_ERRORS;
|
|
|
|
#endif
|
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
/*
|
|
|
|
* Release storage left over from prior query cycle, and create a new
|
2003-05-02 22:54:36 +02:00
|
|
|
* query input buffer in the cleared MessageContext.
|
2000-06-28 05:33:33 +02:00
|
|
|
*/
|
2003-05-02 22:54:36 +02:00
|
|
|
MemoryContextSwitchTo(MessageContext);
|
2023-11-15 20:42:30 +01:00
|
|
|
MemoryContextReset(MessageContext);
|
2000-06-28 05:33:33 +02:00
|
|
|
|
2003-08-12 20:52:38 +02:00
|
|
|
initStringInfo(&input_message);
|
1998-10-02 03:14:14 +02:00
|
|
|
|
Account for catalog snapshot in PGXACT->xmin updates.
The CatalogSnapshot was not plugged into SnapshotResetXmin()'s accounting
for whether MyPgXact->xmin could be cleared or advanced. In normal
transactions this was masked by the fact that the transaction snapshot
would be older, but during backend startup and certain utility commands
it was possible to re-use the CatalogSnapshot after MyPgXact->xmin had
been cleared, meaning that recently-deleted rows could be pruned even
though this snapshot could still see them, causing unexpected catalog
lookup failures. This effect appears to be the explanation for a recent
failure on buildfarm member piculet.
To fix, add the CatalogSnapshot to the RegisteredSnapshots heap whenever
it is valid.
In the previous logic, it was possible for the CatalogSnapshot to remain
valid across waits for client input, but with this change that would mean
it delays advance of global xmin in cases where it did not before. To
avoid possibly causing new table-bloat problems with clients that sit idle
for long intervals, add code to invalidate the CatalogSnapshot before
waiting for client input. (When the backend is busy, it's unlikely that
the CatalogSnapshot would be the oldest snap for very long, so we don't
worry about forcing early invalidation of it otherwise.)
In passing, remove the CatalogSnapshotStale flag in favor of using
"CatalogSnapshot != NULL" to represent validity, as we do for the other
special snapshots in snapmgr.c. And improve some obsolete comments.
No regression test because I don't know a deterministic way to cause this
failure. But the stress test shown in the original discussion provokes
"cache lookup failed for relation 1255" within a few dozen seconds for me.
Back-patch to 9.4 where MVCC catalog scans were introduced. (Note: it's
quite easy to produce similar failures with the same test case in branches
before 9.4. But MVCC catalog scans were supposed to fix that.)
Discussion: <16447.1478818294@sss.pgh.pa.us>
2016-11-15 21:55:35 +01:00
|
|
|
/*
|
|
|
|
* Also consider releasing our catalog snapshot if any, so that it's
|
|
|
|
* not preventing advance of global xmin while we wait for the client.
|
|
|
|
*/
|
|
|
|
InvalidateCatalogSnapshotConditionally();
|
|
|
|
|
1998-05-07 01:51:16 +02:00
|
|
|
/*
|
2003-08-12 20:52:38 +02:00
|
|
|
* (1) If we've reached idle state, tell the frontend we're ready for
|
|
|
|
* a new query.
|
1998-10-02 03:14:14 +02:00
|
|
|
*
|
|
|
|
* Note: this includes fflush()'ing the last of the prior output.
|
2003-08-12 20:52:38 +02:00
|
|
|
*
|
2022-04-06 22:56:06 +02:00
|
|
|
* This is also a good time to flush out collected statistics to the
|
|
|
|
* cumulative stats system, and to update the PS stats display. We
|
2003-08-12 20:52:38 +02:00
|
|
|
* avoid doing those every time through the message loop because it'd
|
2004-11-20 01:48:58 +01:00
|
|
|
* slow down processing of batched messages, and because we don't want
|
2010-02-16 23:34:57 +01:00
|
|
|
* to report uncommitted updates (that confuses autovacuum). The
|
|
|
|
* notification processor wants a call too, if we are not in a
|
|
|
|
* transaction block.
|
2021-01-07 00:28:42 +01:00
|
|
|
*
|
|
|
|
* Also, if an idle timeout is enabled, start the timer for that.
|
1998-05-07 01:51:16 +02:00
|
|
|
*/
|
2005-12-31 00:49:48 +01:00
|
|
|
if (send_ready_for_query)
|
2003-04-19 02:02:30 +02:00
|
|
|
{
|
2010-01-16 11:05:59 +01:00
|
|
|
if (IsAbortedTransactionBlockState())
|
|
|
|
{
|
2020-03-11 16:36:40 +01:00
|
|
|
set_ps_display("idle in transaction (aborted)");
|
2012-01-19 14:19:20 +01:00
|
|
|
pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL);
|
2016-03-16 16:30:45 +01:00
|
|
|
|
|
|
|
/* Start the idle-in-transaction timer */
|
2024-02-15 22:34:11 +01:00
|
|
|
if (IdleInTransactionSessionTimeout > 0
|
|
|
|
&& (IdleInTransactionSessionTimeout < TransactionTimeout || TransactionTimeout == 0))
|
2016-03-16 16:30:45 +01:00
|
|
|
{
|
2021-01-07 00:28:42 +01:00
|
|
|
idle_in_transaction_timeout_enabled = true;
|
2016-03-16 16:30:45 +01:00
|
|
|
enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
|
|
|
|
IdleInTransactionSessionTimeout);
|
|
|
|
}
|
2010-01-16 11:05:59 +01:00
|
|
|
}
|
|
|
|
else if (IsTransactionOrTransactionBlock())
|
2003-08-12 20:52:38 +02:00
|
|
|
{
|
2020-03-11 16:36:40 +01:00
|
|
|
set_ps_display("idle in transaction");
|
2012-01-19 14:19:20 +01:00
|
|
|
pgstat_report_activity(STATE_IDLEINTRANSACTION, NULL);
|
2016-03-16 16:30:45 +01:00
|
|
|
|
|
|
|
/* Start the idle-in-transaction timer */
|
2024-02-15 22:34:11 +01:00
|
|
|
if (IdleInTransactionSessionTimeout > 0
|
|
|
|
&& (IdleInTransactionSessionTimeout < TransactionTimeout || TransactionTimeout == 0))
|
2016-03-16 16:30:45 +01:00
|
|
|
{
|
2021-01-07 00:28:42 +01:00
|
|
|
idle_in_transaction_timeout_enabled = true;
|
2016-03-16 16:30:45 +01:00
|
|
|
enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
|
|
|
|
IdleInTransactionSessionTimeout);
|
|
|
|
}
|
2003-08-12 20:52:38 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-04-07 06:29:46 +02:00
|
|
|
long stats_timeout;
|
|
|
|
|
2019-11-24 20:42:59 +01:00
|
|
|
/*
|
Send NOTIFY signals during CommitTransaction.
Formerly, we sent signals for outgoing NOTIFY messages within
ProcessCompletedNotifies, which was also responsible for sending
relevant ones of those messages to our connected client. It therefore
had to run during the main-loop processing that occurs just before
going idle. This arrangement had two big disadvantages:
* Now that procedures allow intra-command COMMITs, it would be
useful to send NOTIFYs to other sessions immediately at COMMIT
(though, for reasons of wire-protocol stability, we still shouldn't
forward them to our client until end of command).
* Background processes such as replication workers would not send
NOTIFYs at all, since they never execute the client communication
loop. We've had requests to allow triggers running in replication
workers to send NOTIFYs, so that's a problem.
To fix these things, move transmission of outgoing NOTIFY signals
into AtCommit_Notify, where it will happen during CommitTransaction.
Also move the possible call of asyncQueueAdvanceTail there, to
ensure we don't bloat the async SLRU if a background worker sends
many NOTIFYs with no one listening.
We can also drop the call of asyncQueueReadAllNotifications,
allowing ProcessCompletedNotifies to go away entirely. That's
because commit 790026972 added a call of ProcessNotifyInterrupt
adjacent to PostgresMain's call of ProcessCompletedNotifies,
and that does its own call of asyncQueueReadAllNotifications,
meaning that we were uselessly doing two such calls (inside two
separate transactions) whenever inbound notify signals coincided
with an outbound notify. We need only set notifyInterruptPending
to ensure that ProcessNotifyInterrupt runs, and we're done.
The existing documentation suggests that custom background workers
should call ProcessCompletedNotifies if they want to send NOTIFY
messages. To avoid an ABI break in the back branches, reduce it
to an empty routine rather than removing it entirely. Removal
will occur in v15.
Although the problems mentioned above have existed for awhile,
I don't feel comfortable back-patching this any further than v13.
There was quite a bit of churn in adjacent code between 12 and 13.
At minimum we'd have to also backpatch 51004c717, and a good deal
of other adjustment would also be needed, so the benefit-to-risk
ratio doesn't look attractive.
Per bug #15293 from Michael Powers (and similar gripes from others).
Artur Zakirov and Tom Lane
Discussion: https://postgr.es/m/153243441449.1404.2274116228506175596@wrigleys.postgresql.org
2021-09-14 23:18:25 +02:00
|
|
|
* Process incoming notifies (including self-notifies), if
|
|
|
|
* any, and send relevant messages to the client. Doing it
|
|
|
|
* here helps ensure stable behavior in tests: if any notifies
|
|
|
|
* were received during the just-finished transaction, they'll
|
|
|
|
* be seen by the client before ReadyForQuery is.
|
2019-11-24 20:42:59 +01:00
|
|
|
*/
|
|
|
|
if (notifyInterruptPending)
|
Send NOTIFY signals during CommitTransaction.
Formerly, we sent signals for outgoing NOTIFY messages within
ProcessCompletedNotifies, which was also responsible for sending
relevant ones of those messages to our connected client. It therefore
had to run during the main-loop processing that occurs just before
going idle. This arrangement had two big disadvantages:
* Now that procedures allow intra-command COMMITs, it would be
useful to send NOTIFYs to other sessions immediately at COMMIT
(though, for reasons of wire-protocol stability, we still shouldn't
forward them to our client until end of command).
* Background processes such as replication workers would not send
NOTIFYs at all, since they never execute the client communication
loop. We've had requests to allow triggers running in replication
workers to send NOTIFYs, so that's a problem.
To fix these things, move transmission of outgoing NOTIFY signals
into AtCommit_Notify, where it will happen during CommitTransaction.
Also move the possible call of asyncQueueAdvanceTail there, to
ensure we don't bloat the async SLRU if a background worker sends
many NOTIFYs with no one listening.
We can also drop the call of asyncQueueReadAllNotifications,
allowing ProcessCompletedNotifies to go away entirely. That's
because commit 790026972 added a call of ProcessNotifyInterrupt
adjacent to PostgresMain's call of ProcessCompletedNotifies,
and that does its own call of asyncQueueReadAllNotifications,
meaning that we were uselessly doing two such calls (inside two
separate transactions) whenever inbound notify signals coincided
with an outbound notify. We need only set notifyInterruptPending
to ensure that ProcessNotifyInterrupt runs, and we're done.
The existing documentation suggests that custom background workers
should call ProcessCompletedNotifies if they want to send NOTIFY
messages. To avoid an ABI break in the back branches, reduce it
to an empty routine rather than removing it entirely. Removal
will occur in v15.
Although the problems mentioned above have existed for awhile,
I don't feel comfortable back-patching this any further than v13.
There was quite a bit of churn in adjacent code between 12 and 13.
At minimum we'd have to also backpatch 51004c717, and a good deal
of other adjustment would also be needed, so the benefit-to-risk
ratio doesn't look attractive.
Per bug #15293 from Michael Powers (and similar gripes from others).
Artur Zakirov and Tom Lane
Discussion: https://postgr.es/m/153243441449.1404.2274116228506175596@wrigleys.postgresql.org
2021-09-14 23:18:25 +02:00
|
|
|
ProcessNotifyInterrupt(false);
|
2019-11-24 20:42:59 +01:00
|
|
|
|
2022-06-17 21:48:34 +02:00
|
|
|
/*
|
|
|
|
* Check if we need to report stats. If pgstat_report_stat()
|
|
|
|
* decides it's too soon to flush out pending stats / lock
|
|
|
|
* contention prevented reporting, it'll tell us when we
|
|
|
|
* should try to report stats again (so that stats updates
|
|
|
|
* aren't unduly delayed if the connection goes idle for a
|
|
|
|
* long time). We only enable the timeout if we don't already
|
|
|
|
* have a timeout in progress, because we don't disable the
|
|
|
|
* timeout below. enable_timeout_after() needs to determine
|
|
|
|
* the current timestamp, which can have a negative
|
|
|
|
* performance impact. That's OK because pgstat_report_stat()
|
|
|
|
* won't have us wake up sooner than a prior call.
|
|
|
|
*/
|
2022-04-07 06:29:46 +02:00
|
|
|
stats_timeout = pgstat_report_stat(false);
|
|
|
|
if (stats_timeout > 0)
|
|
|
|
{
|
2022-06-17 21:48:34 +02:00
|
|
|
if (!get_timeout_active(IDLE_STATS_UPDATE_TIMEOUT))
|
|
|
|
enable_timeout_after(IDLE_STATS_UPDATE_TIMEOUT,
|
|
|
|
stats_timeout);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* all stats flushed, no need for the timeout */
|
|
|
|
if (get_timeout_active(IDLE_STATS_UPDATE_TIMEOUT))
|
|
|
|
disable_timeout(IDLE_STATS_UPDATE_TIMEOUT, false);
|
2022-04-07 06:29:46 +02:00
|
|
|
}
|
2004-11-20 01:48:58 +01:00
|
|
|
|
2020-03-11 16:36:40 +01:00
|
|
|
set_ps_display("idle");
|
2012-01-19 14:19:20 +01:00
|
|
|
pgstat_report_activity(STATE_IDLE, NULL);
|
2021-01-07 00:28:42 +01:00
|
|
|
|
|
|
|
/* Start the idle-session timer */
|
|
|
|
if (IdleSessionTimeout > 0)
|
|
|
|
{
|
|
|
|
idle_session_timeout_enabled = true;
|
|
|
|
enable_timeout_after(IDLE_SESSION_TIMEOUT,
|
|
|
|
IdleSessionTimeout);
|
|
|
|
}
|
2003-08-12 20:52:38 +02:00
|
|
|
}
|
2001-06-22 21:16:24 +02:00
|
|
|
|
2020-11-25 17:40:44 +01:00
|
|
|
/* Report any recently-changed GUC options */
|
|
|
|
ReportChangedGUCOptions();
|
|
|
|
|
2003-08-12 20:52:38 +02:00
|
|
|
ReadyForQuery(whereToSendOutput);
|
2005-12-31 00:49:48 +01:00
|
|
|
send_ready_for_query = false;
|
2001-06-22 21:16:24 +02:00
|
|
|
}
|
2001-02-18 05:28:31 +01:00
|
|
|
|
1996-11-14 11:25:54 +01:00
|
|
|
/*
|
2005-06-02 23:03:25 +02:00
|
|
|
* (2) Allow asynchronous signals to be executed immediately if they
|
|
|
|
* come in while we are waiting for client input. (This must be
|
|
|
|
* conditional since we don't want, say, reads on behalf of COPY FROM
|
|
|
|
* STDIN doing the same thing.)
|
1998-10-06 04:40:09 +02:00
|
|
|
*/
|
2005-06-02 23:03:25 +02:00
|
|
|
DoingCommandRead = true;
|
2001-01-14 06:08:17 +01:00
|
|
|
|
1998-10-06 04:40:09 +02:00
|
|
|
/*
|
2000-05-31 02:28:42 +02:00
|
|
|
* (3) read a command (loop blocks here)
|
1996-11-14 11:25:54 +01:00
|
|
|
*/
|
2004-07-29 00:05:47 +02:00
|
|
|
firstchar = ReadCommand(&input_message);
|
1998-05-19 20:05:58 +02:00
|
|
|
|
1998-10-02 03:14:14 +02:00
|
|
|
/*
|
2022-06-17 21:48:34 +02:00
|
|
|
* (4) turn off the idle-in-transaction and idle-session timeouts if
|
|
|
|
* active. We do this before step (5) so that any last-moment timeout
|
|
|
|
* is certain to be detected in step (5).
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 16:08:45 +01:00
|
|
|
*
|
2021-01-07 17:45:08 +01:00
|
|
|
* At most one of these timeouts will be active, so there's no need to
|
2021-01-07 00:28:42 +01:00
|
|
|
* worry about combining the timeout.c calls into one.
|
2016-03-16 16:30:45 +01:00
|
|
|
*/
|
2021-01-07 00:28:42 +01:00
|
|
|
if (idle_in_transaction_timeout_enabled)
|
2016-03-16 16:30:45 +01:00
|
|
|
{
|
|
|
|
disable_timeout(IDLE_IN_TRANSACTION_SESSION_TIMEOUT, false);
|
2021-01-07 00:28:42 +01:00
|
|
|
idle_in_transaction_timeout_enabled = false;
|
|
|
|
}
|
|
|
|
if (idle_session_timeout_enabled)
|
|
|
|
{
|
|
|
|
disable_timeout(IDLE_SESSION_TIMEOUT, false);
|
|
|
|
idle_session_timeout_enabled = false;
|
2016-03-16 16:30:45 +01:00
|
|
|
}
|
|
|
|
|
2021-01-07 17:45:08 +01:00
|
|
|
/*
|
|
|
|
* (5) disable async signal conditions again.
|
|
|
|
*
|
|
|
|
* Query cancel is supposed to be a no-op when there is no query in
|
|
|
|
* progress, so if a query cancel arrived while we were idle, just
|
|
|
|
* reset QueryCancelPending. ProcessInterrupts() has that effect when
|
|
|
|
* it's called when DoingCommandRead is set, so check for interrupts
|
|
|
|
* before resetting DoingCommandRead.
|
|
|
|
*/
|
|
|
|
CHECK_FOR_INTERRUPTS();
|
|
|
|
DoingCommandRead = false;
|
|
|
|
|
2016-03-16 16:30:45 +01:00
|
|
|
/*
|
|
|
|
* (6) check for any other interesting events that happened while we
|
2000-10-24 23:33:52 +02:00
|
|
|
* slept.
|
|
|
|
*/
|
2017-06-06 03:53:41 +02:00
|
|
|
if (ConfigReloadPending)
|
2000-10-24 23:33:52 +02:00
|
|
|
{
|
2017-06-06 03:53:41 +02:00
|
|
|
ConfigReloadPending = false;
|
2000-10-24 23:33:52 +02:00
|
|
|
ProcessConfigFile(PGC_SIGHUP);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2016-03-16 16:30:45 +01:00
|
|
|
* (7) process the command. But ignore it if we're skipping till
|
2003-05-05 02:44:56 +02:00
|
|
|
* Sync.
|
1998-10-02 03:14:14 +02:00
|
|
|
*/
|
2003-05-14 20:40:37 +02:00
|
|
|
if (ignore_till_sync && firstchar != EOF)
|
2003-05-05 02:44:56 +02:00
|
|
|
continue;
|
|
|
|
|
1996-11-14 11:25:54 +01:00
|
|
|
switch (firstchar)
|
|
|
|
{
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_Query:
|
2003-04-27 22:09:44 +02:00
|
|
|
{
|
2003-05-05 02:44:56 +02:00
|
|
|
const char *query_string;
|
|
|
|
|
2006-06-21 00:52:00 +02:00
|
|
|
/* Set statement_timestamp() */
|
|
|
|
SetCurrentStatementStartTimestamp();
|
|
|
|
|
2003-08-12 20:52:38 +02:00
|
|
|
query_string = pq_getmsgstring(&input_message);
|
|
|
|
pq_getmsgend(&input_message);
|
2003-04-27 22:09:44 +02:00
|
|
|
|
2012-10-05 16:13:07 +02:00
|
|
|
if (am_walsender)
|
2017-03-23 13:36:36 +01:00
|
|
|
{
|
|
|
|
if (!exec_replication_command(query_string))
|
|
|
|
exec_simple_query(query_string);
|
|
|
|
}
|
2012-10-05 16:13:07 +02:00
|
|
|
else
|
|
|
|
exec_simple_query(query_string);
|
2003-04-19 02:02:30 +02:00
|
|
|
|
2023-04-03 16:18:38 +02:00
|
|
|
valgrind_report_error_query(query_string);
|
|
|
|
|
2005-12-31 00:49:48 +01:00
|
|
|
send_ready_for_query = true;
|
2003-04-27 22:09:44 +02:00
|
|
|
}
|
2003-04-19 02:02:30 +02:00
|
|
|
break;
|
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_Parse:
|
2003-05-05 02:44:56 +02:00
|
|
|
{
|
|
|
|
const char *stmt_name;
|
|
|
|
const char *query_string;
|
|
|
|
int numParams;
|
|
|
|
Oid *paramTypes = NULL;
|
|
|
|
|
2012-10-05 16:13:07 +02:00
|
|
|
forbidden_in_wal_sender(firstchar);
|
|
|
|
|
2006-06-21 00:52:00 +02:00
|
|
|
/* Set statement_timestamp() */
|
|
|
|
SetCurrentStatementStartTimestamp();
|
|
|
|
|
2003-08-12 20:52:38 +02:00
|
|
|
stmt_name = pq_getmsgstring(&input_message);
|
|
|
|
query_string = pq_getmsgstring(&input_message);
|
|
|
|
numParams = pq_getmsgint(&input_message, 2);
|
2003-05-05 02:44:56 +02:00
|
|
|
if (numParams > 0)
|
|
|
|
{
|
2022-09-12 08:31:56 +02:00
|
|
|
paramTypes = palloc_array(Oid, numParams);
|
2018-08-24 03:36:07 +02:00
|
|
|
for (int i = 0; i < numParams; i++)
|
2003-08-12 20:52:38 +02:00
|
|
|
paramTypes[i] = pq_getmsgint(&input_message, 4);
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
2003-08-12 20:52:38 +02:00
|
|
|
pq_getmsgend(&input_message);
|
2003-05-05 02:44:56 +02:00
|
|
|
|
|
|
|
exec_parse_message(query_string, stmt_name,
|
|
|
|
paramTypes, numParams);
|
2023-04-03 16:18:38 +02:00
|
|
|
|
|
|
|
valgrind_report_error_query(query_string);
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_Bind:
|
2012-10-05 16:13:07 +02:00
|
|
|
forbidden_in_wal_sender(firstchar);
|
|
|
|
|
2006-06-21 00:52:00 +02:00
|
|
|
/* Set statement_timestamp() */
|
|
|
|
SetCurrentStatementStartTimestamp();
|
2003-08-04 02:43:34 +02:00
|
|
|
|
2003-05-05 02:44:56 +02:00
|
|
|
/*
|
|
|
|
* this message is complex enough that it seems best to put
|
|
|
|
* the field extraction out-of-line
|
|
|
|
*/
|
2003-08-12 20:52:38 +02:00
|
|
|
exec_bind_message(&input_message);
|
2023-04-03 16:18:38 +02:00
|
|
|
|
|
|
|
/* exec_bind_message does valgrind_report_error_query */
|
2003-05-05 02:44:56 +02:00
|
|
|
break;
|
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_Execute:
|
2003-05-05 02:44:56 +02:00
|
|
|
{
|
|
|
|
const char *portal_name;
|
2006-09-03 05:19:45 +02:00
|
|
|
int max_rows;
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2012-10-05 16:13:07 +02:00
|
|
|
forbidden_in_wal_sender(firstchar);
|
|
|
|
|
2006-06-21 00:52:00 +02:00
|
|
|
/* Set statement_timestamp() */
|
|
|
|
SetCurrentStatementStartTimestamp();
|
|
|
|
|
2003-08-12 20:52:38 +02:00
|
|
|
portal_name = pq_getmsgstring(&input_message);
|
2006-09-03 05:19:45 +02:00
|
|
|
max_rows = pq_getmsgint(&input_message, 4);
|
2003-08-12 20:52:38 +02:00
|
|
|
pq_getmsgend(&input_message);
|
2003-05-05 02:44:56 +02:00
|
|
|
|
2003-05-08 20:16:37 +02:00
|
|
|
exec_execute_message(portal_name, max_rows);
|
2023-04-03 16:18:38 +02:00
|
|
|
|
|
|
|
/* exec_execute_message does valgrind_report_error_query */
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_FunctionCall:
|
2012-10-05 16:13:07 +02:00
|
|
|
forbidden_in_wal_sender(firstchar);
|
|
|
|
|
2006-06-21 00:52:00 +02:00
|
|
|
/* Set statement_timestamp() */
|
|
|
|
SetCurrentStatementStartTimestamp();
|
|
|
|
|
2010-12-17 22:51:22 +01:00
|
|
|
/* Report query to various monitoring facilities. */
|
2012-01-19 14:19:20 +01:00
|
|
|
pgstat_report_activity(STATE_FASTPATH, NULL);
|
2020-03-11 16:36:40 +01:00
|
|
|
set_ps_display("<FASTPATH>");
|
2001-06-22 21:16:24 +02:00
|
|
|
|
1996-11-14 11:25:54 +01:00
|
|
|
/* start an xact for this function invocation */
|
2006-06-21 00:52:00 +02:00
|
|
|
start_xact_command();
|
1998-10-02 03:14:14 +02:00
|
|
|
|
2006-06-11 17:49:28 +02:00
|
|
|
/*
|
|
|
|
* Note: we may at this point be inside an aborted
|
|
|
|
* transaction. We can't throw error for that until we've
|
|
|
|
* finished reading the function-call message, so
|
|
|
|
* HandleFunctionRequest() must check for it after doing so.
|
|
|
|
* Be careful not to do anything that assumes we're inside a
|
|
|
|
* valid transaction here.
|
|
|
|
*/
|
|
|
|
|
2003-05-09 20:08:48 +02:00
|
|
|
/* switch back to message context */
|
|
|
|
MemoryContextSwitchTo(MessageContext);
|
|
|
|
|
2017-04-06 08:09:39 +02:00
|
|
|
HandleFunctionRequest(&input_message);
|
2000-10-07 02:58:23 +02:00
|
|
|
|
|
|
|
/* commit the function-invocation transaction */
|
2006-06-21 00:52:00 +02:00
|
|
|
finish_xact_command();
|
1997-09-08 04:41:22 +02:00
|
|
|
|
2023-04-03 16:18:38 +02:00
|
|
|
valgrind_report_error_query("fastpath function call");
|
|
|
|
|
2005-12-31 00:49:48 +01:00
|
|
|
send_ready_for_query = true;
|
1997-09-08 04:41:22 +02:00
|
|
|
break;
|
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_Close:
|
2003-05-05 02:44:56 +02:00
|
|
|
{
|
|
|
|
int close_type;
|
|
|
|
const char *close_target;
|
|
|
|
|
2012-10-05 16:13:07 +02:00
|
|
|
forbidden_in_wal_sender(firstchar);
|
|
|
|
|
2003-08-12 20:52:38 +02:00
|
|
|
close_type = pq_getmsgbyte(&input_message);
|
|
|
|
close_target = pq_getmsgstring(&input_message);
|
|
|
|
pq_getmsgend(&input_message);
|
2003-05-05 02:44:56 +02:00
|
|
|
|
|
|
|
switch (close_type)
|
|
|
|
{
|
|
|
|
case 'S':
|
|
|
|
if (close_target[0] != '\0')
|
|
|
|
DropPreparedStatement(close_target, false);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* special-case the unnamed statement */
|
2007-03-13 01:33:44 +01:00
|
|
|
drop_unnamed_stmt();
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'P':
|
|
|
|
{
|
|
|
|
Portal portal;
|
|
|
|
|
|
|
|
portal = GetPortalByName(close_target);
|
|
|
|
if (PortalIsValid(portal))
|
|
|
|
PortalDrop(portal, false);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2003-07-22 21:00:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("invalid CLOSE message subtype %d",
|
|
|
|
close_type)));
|
2003-05-05 02:44:56 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-11-03 18:11:40 +01:00
|
|
|
if (whereToSendOutput == DestRemote)
|
2023-08-23 04:16:12 +02:00
|
|
|
pq_putemptymessage(PqMsg_CloseComplete);
|
2023-04-03 16:18:38 +02:00
|
|
|
|
|
|
|
valgrind_report_error_query("CLOSE message");
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_Describe:
|
2003-05-05 02:44:56 +02:00
|
|
|
{
|
|
|
|
int describe_type;
|
|
|
|
const char *describe_target;
|
|
|
|
|
2012-10-05 16:13:07 +02:00
|
|
|
forbidden_in_wal_sender(firstchar);
|
|
|
|
|
2006-06-21 00:52:00 +02:00
|
|
|
/* Set statement_timestamp() (needed for xact) */
|
|
|
|
SetCurrentStatementStartTimestamp();
|
|
|
|
|
2003-08-12 20:52:38 +02:00
|
|
|
describe_type = pq_getmsgbyte(&input_message);
|
|
|
|
describe_target = pq_getmsgstring(&input_message);
|
|
|
|
pq_getmsgend(&input_message);
|
2003-05-05 02:44:56 +02:00
|
|
|
|
|
|
|
switch (describe_type)
|
|
|
|
{
|
|
|
|
case 'S':
|
|
|
|
exec_describe_statement_message(describe_target);
|
|
|
|
break;
|
|
|
|
case 'P':
|
|
|
|
exec_describe_portal_message(describe_target);
|
|
|
|
break;
|
|
|
|
default:
|
2003-07-22 21:00:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("invalid DESCRIBE message subtype %d",
|
|
|
|
describe_type)));
|
2003-05-05 02:44:56 +02:00
|
|
|
break;
|
|
|
|
}
|
2023-04-03 16:18:38 +02:00
|
|
|
|
|
|
|
valgrind_report_error_query("DESCRIBE message");
|
2003-05-05 02:44:56 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_Flush:
|
2003-08-12 20:52:38 +02:00
|
|
|
pq_getmsgend(&input_message);
|
2005-11-03 18:11:40 +01:00
|
|
|
if (whereToSendOutput == DestRemote)
|
2003-05-05 02:44:56 +02:00
|
|
|
pq_flush();
|
|
|
|
break;
|
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_Sync:
|
2003-08-12 20:52:38 +02:00
|
|
|
pq_getmsgend(&input_message);
|
2006-06-21 00:52:00 +02:00
|
|
|
finish_xact_command();
|
2023-04-03 16:18:38 +02:00
|
|
|
valgrind_report_error_query("SYNC message");
|
2005-12-31 00:49:48 +01:00
|
|
|
send_ready_for_query = true;
|
2003-05-05 02:44:56 +02:00
|
|
|
break;
|
|
|
|
|
2002-03-04 02:46:04 +01:00
|
|
|
/*
|
1999-07-22 04:40:07 +02:00
|
|
|
* 'X' means that the frontend is closing down the socket. EOF
|
|
|
|
* means unexpected loss of frontend connection. Either way,
|
|
|
|
* perform normal shutdown.
|
1997-09-08 04:41:22 +02:00
|
|
|
*/
|
1999-07-22 04:40:07 +02:00
|
|
|
case EOF:
|
2002-09-04 22:31:48 +02:00
|
|
|
|
2022-04-06 22:56:06 +02:00
|
|
|
/* for the cumulative statistics system */
|
2021-01-17 13:34:09 +01:00
|
|
|
pgStatSessionEndCause = DISCONNECT_CLIENT_EOF;
|
|
|
|
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_Terminate:
|
2021-01-17 13:34:09 +01:00
|
|
|
|
2002-03-04 02:46:04 +01:00
|
|
|
/*
|
2003-07-22 21:00:12 +02:00
|
|
|
* Reset whereToSendOutput to prevent ereport from attempting
|
2002-03-04 02:46:04 +01:00
|
|
|
* to send any more messages to client.
|
|
|
|
*/
|
2005-11-03 18:11:40 +01:00
|
|
|
if (whereToSendOutput == DestRemote)
|
|
|
|
whereToSendOutput = DestNone;
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2000-12-18 01:44:50 +01:00
|
|
|
/*
|
|
|
|
* NOTE: if you are tempted to add more code here, DON'T!
|
|
|
|
* Whatever you had in mind to do should be set up as an
|
|
|
|
* on_proc_exit or on_shmem_exit callback, instead. Otherwise
|
|
|
|
* it will fail to be called during other backend-shutdown
|
|
|
|
* scenarios.
|
|
|
|
*/
|
2004-07-29 00:05:47 +02:00
|
|
|
proc_exit(0);
|
1997-09-08 04:41:22 +02:00
|
|
|
|
2023-08-23 04:16:12 +02:00
|
|
|
case PqMsg_CopyData:
|
|
|
|
case PqMsg_CopyDone:
|
|
|
|
case PqMsg_CopyFail:
|
2003-08-04 02:43:34 +02:00
|
|
|
|
2003-04-19 02:02:30 +02:00
|
|
|
/*
|
|
|
|
* Accept but ignore these messages, per protocol spec; we
|
|
|
|
* probably got here because a COPY failed, and the frontend
|
|
|
|
* is still sending data.
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
|
1996-11-14 11:25:54 +01:00
|
|
|
default:
|
2003-07-22 21:00:12 +02:00
|
|
|
ereport(FATAL,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("invalid frontend message type %d",
|
|
|
|
firstchar)));
|
1996-11-14 11:25:54 +01:00
|
|
|
}
|
2000-10-07 02:58:23 +02:00
|
|
|
} /* end of input-reading loop */
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2012-10-05 16:13:07 +02:00
|
|
|
/*
|
|
|
|
* Throw an error if we're a WAL sender process.
|
|
|
|
*
|
|
|
|
* This is used to forbid anything else than simple query protocol messages
|
|
|
|
* in a WAL sender process. 'firstchar' specifies what kind of a forbidden
|
|
|
|
* message was received, and is used to construct the error message.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
forbidden_in_wal_sender(char firstchar)
|
|
|
|
{
|
|
|
|
if (am_walsender)
|
|
|
|
{
|
2023-08-23 04:16:12 +02:00
|
|
|
if (firstchar == PqMsg_FunctionCall)
|
2012-10-05 16:13:07 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("fastpath function calls not supported in a replication connection")));
|
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("extended query protocol not supported in a replication connection")));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-07 21:25:29 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Obtain platform stack depth limit (in bytes)
|
|
|
|
*
|
2010-11-06 21:50:18 +01:00
|
|
|
* Return -1 if unknown
|
2006-10-07 21:25:29 +02:00
|
|
|
*/
|
|
|
|
long
|
|
|
|
get_stack_depth_rlimit(void)
|
|
|
|
{
|
2022-08-04 23:18:34 +02:00
|
|
|
#if defined(HAVE_GETRLIMIT)
|
2006-10-07 21:25:29 +02:00
|
|
|
static long val = 0;
|
|
|
|
|
|
|
|
/* This won't change after process launch, so check just once */
|
|
|
|
if (val == 0)
|
|
|
|
{
|
|
|
|
struct rlimit rlim;
|
|
|
|
|
|
|
|
if (getrlimit(RLIMIT_STACK, &rlim) < 0)
|
|
|
|
val = -1;
|
|
|
|
else if (rlim.rlim_cur == RLIM_INFINITY)
|
2010-11-06 21:50:18 +01:00
|
|
|
val = LONG_MAX;
|
|
|
|
/* rlim_cur is probably of an unsigned type, so check for overflow */
|
|
|
|
else if (rlim.rlim_cur >= LONG_MAX)
|
|
|
|
val = LONG_MAX;
|
2006-10-07 21:25:29 +02:00
|
|
|
else
|
|
|
|
val = rlim.rlim_cur;
|
|
|
|
}
|
|
|
|
return val;
|
2022-08-04 23:18:34 +02:00
|
|
|
#else
|
2006-10-08 19:15:34 +02:00
|
|
|
/* On Windows we set the backend stack size in src/backend/Makefile */
|
|
|
|
return WIN32_STACK_RLIMIT;
|
|
|
|
#endif
|
2006-10-07 21:25:29 +02:00
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2003-10-20 01:43:51 +02:00
|
|
|
static struct rusage Save_r;
|
|
|
|
static struct timeval Save_t;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
void
|
1996-11-10 04:06:38 +01:00
|
|
|
ResetUsage(void)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
|
|
|
getrusage(RUSAGE_SELF, &Save_r);
|
2002-10-25 01:19:13 +02:00
|
|
|
gettimeofday(&Save_t, NULL);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-11-11 00:51:14 +01:00
|
|
|
ShowUsage(const char *title)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2001-11-11 00:51:14 +01:00
|
|
|
StringInfoData str;
|
1996-07-09 08:22:35 +02:00
|
|
|
struct timeval user,
|
|
|
|
sys;
|
|
|
|
struct timeval elapse_t;
|
|
|
|
struct rusage r;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
getrusage(RUSAGE_SELF, &r);
|
2002-10-25 01:19:13 +02:00
|
|
|
gettimeofday(&elapse_t, NULL);
|
2001-11-11 00:51:14 +01:00
|
|
|
memcpy((char *) &user, (char *) &r.ru_utime, sizeof(user));
|
|
|
|
memcpy((char *) &sys, (char *) &r.ru_stime, sizeof(sys));
|
1996-07-09 08:22:35 +02:00
|
|
|
if (elapse_t.tv_usec < Save_t.tv_usec)
|
|
|
|
{
|
1996-11-14 11:25:54 +01:00
|
|
|
elapse_t.tv_sec--;
|
|
|
|
elapse_t.tv_usec += 1000000;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
if (r.ru_utime.tv_usec < Save_r.ru_utime.tv_usec)
|
|
|
|
{
|
1996-11-14 11:25:54 +01:00
|
|
|
r.ru_utime.tv_sec--;
|
|
|
|
r.ru_utime.tv_usec += 1000000;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
if (r.ru_stime.tv_usec < Save_r.ru_stime.tv_usec)
|
|
|
|
{
|
1996-11-14 11:25:54 +01:00
|
|
|
r.ru_stime.tv_sec--;
|
|
|
|
r.ru_stime.tv_usec += 1000000;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2017-09-01 21:36:33 +02:00
|
|
|
* The only stats we don't show here are ixrss, idrss, isrss. It takes
|
|
|
|
* some work to interpret them, and most platforms don't fill them in.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2001-11-11 00:51:14 +01:00
|
|
|
initStringInfo(&str);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2013-10-31 15:55:59 +01:00
|
|
|
appendStringInfoString(&str, "! system usage stats:\n");
|
2001-11-11 00:51:14 +01:00
|
|
|
appendStringInfo(&str,
|
Account for catalog snapshot in PGXACT->xmin updates.
The CatalogSnapshot was not plugged into SnapshotResetXmin()'s accounting
for whether MyPgXact->xmin could be cleared or advanced. In normal
transactions this was masked by the fact that the transaction snapshot
would be older, but during backend startup and certain utility commands
it was possible to re-use the CatalogSnapshot after MyPgXact->xmin had
been cleared, meaning that recently-deleted rows could be pruned even
though this snapshot could still see them, causing unexpected catalog
lookup failures. This effect appears to be the explanation for a recent
failure on buildfarm member piculet.
To fix, add the CatalogSnapshot to the RegisteredSnapshots heap whenever
it is valid.
In the previous logic, it was possible for the CatalogSnapshot to remain
valid across waits for client input, but with this change that would mean
it delays advance of global xmin in cases where it did not before. To
avoid possibly causing new table-bloat problems with clients that sit idle
for long intervals, add code to invalidate the CatalogSnapshot before
waiting for client input. (When the backend is busy, it's unlikely that
the CatalogSnapshot would be the oldest snap for very long, so we don't
worry about forcing early invalidation of it otherwise.)
In passing, remove the CatalogSnapshotStale flag in favor of using
"CatalogSnapshot != NULL" to represent validity, as we do for the other
special snapshots in snapmgr.c. And improve some obsolete comments.
No regression test because I don't know a deterministic way to cause this
failure. But the stress test shown in the original discussion provokes
"cache lookup failed for relation 1255" within a few dozen seconds for me.
Back-patch to 9.4 where MVCC catalog scans were introduced. (Note: it's
quite easy to produce similar failures with the same test case in branches
before 9.4. But MVCC catalog scans were supposed to fix that.)
Discussion: <16447.1478818294@sss.pgh.pa.us>
2016-11-15 21:55:35 +01:00
|
|
|
"!\t%ld.%06ld s user, %ld.%06ld s system, %ld.%06ld s elapsed\n",
|
2002-10-25 01:19:13 +02:00
|
|
|
(long) (r.ru_utime.tv_sec - Save_r.ru_utime.tv_sec),
|
|
|
|
(long) (r.ru_utime.tv_usec - Save_r.ru_utime.tv_usec),
|
|
|
|
(long) (r.ru_stime.tv_sec - Save_r.ru_stime.tv_sec),
|
2016-10-19 18:00:00 +02:00
|
|
|
(long) (r.ru_stime.tv_usec - Save_r.ru_stime.tv_usec),
|
|
|
|
(long) (elapse_t.tv_sec - Save_t.tv_sec),
|
|
|
|
(long) (elapse_t.tv_usec - Save_t.tv_usec));
|
2001-11-11 00:51:14 +01:00
|
|
|
appendStringInfo(&str,
|
2016-10-19 18:00:00 +02:00
|
|
|
"!\t[%ld.%06ld s user, %ld.%06ld s system total]\n",
|
2002-10-25 01:19:13 +02:00
|
|
|
(long) user.tv_sec,
|
|
|
|
(long) user.tv_usec,
|
|
|
|
(long) sys.tv_sec,
|
|
|
|
(long) sys.tv_usec);
|
2022-07-23 23:21:57 +02:00
|
|
|
#ifndef WIN32
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The following rusage fields are not defined by POSIX, but they're
|
|
|
|
* present on all current Unix-like systems so we use them without any
|
|
|
|
* special checks. Some of these could be provided in our Windows
|
2022-08-13 13:35:24 +02:00
|
|
|
* emulation in src/port/win32getrusage.c with more work.
|
2022-07-23 23:21:57 +02:00
|
|
|
*/
|
2017-09-01 21:36:33 +02:00
|
|
|
appendStringInfo(&str,
|
|
|
|
"!\t%ld kB max resident size\n",
|
|
|
|
#if defined(__darwin__)
|
|
|
|
/* in bytes on macOS */
|
|
|
|
r.ru_maxrss / 1024
|
|
|
|
#else
|
|
|
|
/* in kilobytes on most other platforms */
|
|
|
|
r.ru_maxrss
|
|
|
|
#endif
|
|
|
|
);
|
2001-11-11 00:51:14 +01:00
|
|
|
appendStringInfo(&str,
|
1996-11-10 03:27:15 +01:00
|
|
|
"!\t%ld/%ld [%ld/%ld] filesystem blocks in/out\n",
|
|
|
|
r.ru_inblock - Save_r.ru_inblock,
|
|
|
|
/* they only drink coffee at dec */
|
|
|
|
r.ru_oublock - Save_r.ru_oublock,
|
|
|
|
r.ru_inblock, r.ru_oublock);
|
2001-11-11 00:51:14 +01:00
|
|
|
appendStringInfo(&str,
|
1996-11-10 03:27:15 +01:00
|
|
|
"!\t%ld/%ld [%ld/%ld] page faults/reclaims, %ld [%ld] swaps\n",
|
|
|
|
r.ru_majflt - Save_r.ru_majflt,
|
|
|
|
r.ru_minflt - Save_r.ru_minflt,
|
|
|
|
r.ru_majflt, r.ru_minflt,
|
|
|
|
r.ru_nswap - Save_r.ru_nswap,
|
|
|
|
r.ru_nswap);
|
2001-11-11 00:51:14 +01:00
|
|
|
appendStringInfo(&str,
|
1996-11-10 03:27:15 +01:00
|
|
|
"!\t%ld [%ld] signals rcvd, %ld/%ld [%ld/%ld] messages rcvd/sent\n",
|
|
|
|
r.ru_nsignals - Save_r.ru_nsignals,
|
|
|
|
r.ru_nsignals,
|
|
|
|
r.ru_msgrcv - Save_r.ru_msgrcv,
|
|
|
|
r.ru_msgsnd - Save_r.ru_msgsnd,
|
|
|
|
r.ru_msgrcv, r.ru_msgsnd);
|
2001-11-11 00:51:14 +01:00
|
|
|
appendStringInfo(&str,
|
1996-11-10 03:27:15 +01:00
|
|
|
"!\t%ld/%ld [%ld/%ld] voluntary/involuntary context switches\n",
|
|
|
|
r.ru_nvcsw - Save_r.ru_nvcsw,
|
|
|
|
r.ru_nivcsw - Save_r.ru_nivcsw,
|
|
|
|
r.ru_nvcsw, r.ru_nivcsw);
|
2022-07-23 23:21:57 +02:00
|
|
|
#endif /* !WIN32 */
|
2001-11-11 00:51:14 +01:00
|
|
|
|
|
|
|
/* remove trailing newline */
|
|
|
|
if (str.data[str.len - 1] == '\n')
|
|
|
|
str.data[--str.len] = '\0';
|
|
|
|
|
2003-07-22 21:00:12 +02:00
|
|
|
ereport(LOG,
|
|
|
|
(errmsg_internal("%s", title),
|
2011-07-16 20:21:12 +02:00
|
|
|
errdetail_internal("%s", str.data)));
|
2001-11-11 00:51:14 +01:00
|
|
|
|
|
|
|
pfree(str.data);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
2004-02-17 04:54:57 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* on_proc_exit handler to log end of session
|
|
|
|
*/
|
|
|
|
static void
|
2004-02-17 05:09:26 +01:00
|
|
|
log_disconnections(int code, Datum arg)
|
2004-02-17 04:54:57 +01:00
|
|
|
{
|
2005-10-06 01:46:06 +02:00
|
|
|
Port *port = MyProcPort;
|
2006-06-21 00:52:00 +02:00
|
|
|
long secs;
|
|
|
|
int usecs;
|
|
|
|
int msecs;
|
2005-10-06 01:46:06 +02:00
|
|
|
int hours,
|
|
|
|
minutes,
|
|
|
|
seconds;
|
2004-02-17 04:54:57 +01:00
|
|
|
|
2018-10-19 02:59:14 +02:00
|
|
|
TimestampDifference(MyStartTimestamp,
|
2006-06-21 00:52:00 +02:00
|
|
|
GetCurrentTimestamp(),
|
|
|
|
&secs, &usecs);
|
|
|
|
msecs = usecs / 1000;
|
2004-02-17 04:54:57 +01:00
|
|
|
|
2006-06-21 00:52:00 +02:00
|
|
|
hours = secs / SECS_PER_HOUR;
|
|
|
|
secs %= SECS_PER_HOUR;
|
|
|
|
minutes = secs / SECS_PER_MINUTE;
|
|
|
|
seconds = secs % SECS_PER_MINUTE;
|
2004-02-17 04:54:57 +01:00
|
|
|
|
2005-10-06 01:46:06 +02:00
|
|
|
ereport(LOG,
|
2006-06-21 00:52:00 +02:00
|
|
|
(errmsg("disconnection: session time: %d:%02d:%02d.%03d "
|
2005-10-06 01:46:06 +02:00
|
|
|
"user=%s database=%s host=%s%s%s",
|
2006-06-21 00:52:00 +02:00
|
|
|
hours, minutes, seconds, msecs,
|
2005-10-06 01:46:06 +02:00
|
|
|
port->user_name, port->database_name, port->remote_host,
|
2006-06-21 00:52:00 +02:00
|
|
|
port->remote_port[0] ? " port=" : "", port->remote_port)));
|
2004-02-17 04:54:57 +01:00
|
|
|
}
|
2017-09-19 04:36:44 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Start statement timeout timer, if enabled.
|
|
|
|
*
|
|
|
|
* If there's already a timeout running, don't restart the timer. That
|
|
|
|
* enables compromises between accuracy of timeouts and cost of starting a
|
|
|
|
* timeout.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
enable_statement_timeout(void)
|
|
|
|
{
|
|
|
|
/* must be within an xact */
|
|
|
|
Assert(xact_started);
|
|
|
|
|
2024-02-15 22:34:11 +01:00
|
|
|
if (StatementTimeout > 0
|
|
|
|
&& (StatementTimeout < TransactionTimeout || TransactionTimeout == 0))
|
2017-09-19 04:36:44 +02:00
|
|
|
{
|
2019-10-25 17:41:16 +02:00
|
|
|
if (!get_timeout_active(STATEMENT_TIMEOUT))
|
2017-09-19 04:36:44 +02:00
|
|
|
enable_timeout_after(STATEMENT_TIMEOUT, StatementTimeout);
|
|
|
|
}
|
|
|
|
else
|
2019-10-25 17:41:16 +02:00
|
|
|
{
|
|
|
|
if (get_timeout_active(STATEMENT_TIMEOUT))
|
|
|
|
disable_timeout(STATEMENT_TIMEOUT, false);
|
|
|
|
}
|
2017-09-19 04:36:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Disable statement timeout, if active.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
disable_statement_timeout(void)
|
|
|
|
{
|
2019-10-25 17:41:16 +02:00
|
|
|
if (get_timeout_active(STATEMENT_TIMEOUT))
|
2017-09-19 04:36:44 +02:00
|
|
|
disable_timeout(STATEMENT_TIMEOUT, false);
|
|
|
|
}
|