mirror of
https://github.com/postgres/postgres.git
synced 2025-08-12 00:03:45 -04:00
Compare commits
10 Commits
87027cb55b
...
d9e225f275
Author | SHA1 | Date | |
---|---|---|---|
|
d9e225f275 | ||
|
7a424ece48 | ||
|
1fe66680c0 | ||
|
bf82f43790 | ||
|
51efe38cb9 | ||
|
5c9f2f9398 | ||
|
9f13376396 | ||
|
995d400cec | ||
|
9bc1eee988 | ||
|
0c444a70f2 |
@ -11894,7 +11894,7 @@ CREATE FOREIGN TABLE foreign_tbl (b int)
|
|||||||
CREATE FOREIGN TABLE foreign_tbl2 () INHERITS (foreign_tbl)
|
CREATE FOREIGN TABLE foreign_tbl2 () INHERITS (foreign_tbl)
|
||||||
SERVER loopback OPTIONS (table_name 'base_tbl');
|
SERVER loopback OPTIONS (table_name 'base_tbl');
|
||||||
EXPLAIN (VERBOSE, COSTS OFF)
|
EXPLAIN (VERBOSE, COSTS OFF)
|
||||||
SELECT a FROM base_tbl WHERE a IN (SELECT a FROM foreign_tbl);
|
SELECT a FROM base_tbl WHERE (a, random() > 0) IN (SELECT a, random() > 0 FROM foreign_tbl);
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
Seq Scan on public.base_tbl
|
Seq Scan on public.base_tbl
|
||||||
@ -11902,7 +11902,7 @@ SELECT a FROM base_tbl WHERE a IN (SELECT a FROM foreign_tbl);
|
|||||||
Filter: (SubPlan 1)
|
Filter: (SubPlan 1)
|
||||||
SubPlan 1
|
SubPlan 1
|
||||||
-> Result
|
-> Result
|
||||||
Output: base_tbl.a
|
Output: base_tbl.a, (random() > '0'::double precision)
|
||||||
-> Append
|
-> Append
|
||||||
-> Async Foreign Scan on public.foreign_tbl foreign_tbl_1
|
-> Async Foreign Scan on public.foreign_tbl foreign_tbl_1
|
||||||
Remote SQL: SELECT NULL FROM public.base_tbl
|
Remote SQL: SELECT NULL FROM public.base_tbl
|
||||||
@ -11910,7 +11910,7 @@ SELECT a FROM base_tbl WHERE a IN (SELECT a FROM foreign_tbl);
|
|||||||
Remote SQL: SELECT NULL FROM public.base_tbl
|
Remote SQL: SELECT NULL FROM public.base_tbl
|
||||||
(11 rows)
|
(11 rows)
|
||||||
|
|
||||||
SELECT a FROM base_tbl WHERE a IN (SELECT a FROM foreign_tbl);
|
SELECT a FROM base_tbl WHERE (a, random() > 0) IN (SELECT a, random() > 0 FROM foreign_tbl);
|
||||||
a
|
a
|
||||||
---
|
---
|
||||||
1
|
1
|
||||||
|
@ -3988,8 +3988,8 @@ CREATE FOREIGN TABLE foreign_tbl2 () INHERITS (foreign_tbl)
|
|||||||
SERVER loopback OPTIONS (table_name 'base_tbl');
|
SERVER loopback OPTIONS (table_name 'base_tbl');
|
||||||
|
|
||||||
EXPLAIN (VERBOSE, COSTS OFF)
|
EXPLAIN (VERBOSE, COSTS OFF)
|
||||||
SELECT a FROM base_tbl WHERE a IN (SELECT a FROM foreign_tbl);
|
SELECT a FROM base_tbl WHERE (a, random() > 0) IN (SELECT a, random() > 0 FROM foreign_tbl);
|
||||||
SELECT a FROM base_tbl WHERE a IN (SELECT a FROM foreign_tbl);
|
SELECT a FROM base_tbl WHERE (a, random() > 0) IN (SELECT a, random() > 0 FROM foreign_tbl);
|
||||||
|
|
||||||
-- Clean up
|
-- Clean up
|
||||||
DROP FOREIGN TABLE foreign_tbl CASCADE;
|
DROP FOREIGN TABLE foreign_tbl CASCADE;
|
||||||
|
@ -9140,6 +9140,42 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="guc-transaction-timeout" xreflabel="transaction_timeout">
|
||||||
|
<term><varname>transaction_timeout</varname> (<type>integer</type>)
|
||||||
|
<indexterm>
|
||||||
|
<primary><varname>transaction_timeout</varname> configuration parameter</primary>
|
||||||
|
</indexterm>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Terminate any session that spans longer than the specified amount of
|
||||||
|
time in the transaction. The limit applies both to explicit transactions
|
||||||
|
(started with <command>BEGIN</command>) and to an implicitly started
|
||||||
|
transaction corresponding to a single statement.
|
||||||
|
If this value is specified without units, it is taken as milliseconds.
|
||||||
|
A value of zero (the default) disables the timeout.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
If <varname>transaction_timeout</varname> is shorter or equal to
|
||||||
|
<varname>idle_in_transaction_session_timeout</varname> or <varname>statement_timeout</varname>
|
||||||
|
<varname>transaction_timeout</varname> will invalidate the longer timeout.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Setting <varname>transaction_timeout</varname> in
|
||||||
|
<filename>postgresql.conf</filename> is not recommended because it would
|
||||||
|
affect all sessions.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
Prepared transactions are not subject to this timeout.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry id="guc-lock-timeout" xreflabel="lock_timeout">
|
<varlistentry id="guc-lock-timeout" xreflabel="lock_timeout">
|
||||||
<term><varname>lock_timeout</varname> (<type>integer</type>)
|
<term><varname>lock_timeout</varname> (<type>integer</type>)
|
||||||
<indexterm>
|
<indexterm>
|
||||||
|
@ -390,12 +390,37 @@ make check LANG=C ENCODING=EUC_JP
|
|||||||
<title>Custom Server Settings</title>
|
<title>Custom Server Settings</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Custom server settings to use when running a regression test suite can be
|
There are several ways to use custom server settings when running a test
|
||||||
|
suite. This can be useful to enable additional logging, adjust resource
|
||||||
|
limits, or enable extra run-time checks such as <xref
|
||||||
|
linkend="guc-debug-discard-caches"/>. But note that not all tests can be
|
||||||
|
expected to pass cleanly with arbitrary settings.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Extra options can be passed to the various <command>initdb</command>
|
||||||
|
commands that are run internally during test setup using the environment
|
||||||
|
variable <envar>PG_TEST_INITDB_EXTRA_OPTS</envar>. For example, to run a
|
||||||
|
test with checksums enabled and a custom WAL segment size and
|
||||||
|
<varname>work_mem</varname> setting, use:
|
||||||
|
<screen>
|
||||||
|
make check PG_TEST_INITDB_EXTRA_OPTS='-k --wal-segsize=4 -c work_mem=50MB'
|
||||||
|
</screen>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For the core regression test suite and other tests driven by
|
||||||
|
<command>pg_regress</command>, custom run-time server settings can also be
|
||||||
set in the <varname>PGOPTIONS</varname> environment variable (for settings
|
set in the <varname>PGOPTIONS</varname> environment variable (for settings
|
||||||
that allow this):
|
that allow this), for example:
|
||||||
<screen>
|
<screen>
|
||||||
make check PGOPTIONS="-c debug_parallel_query=regress -c work_mem=50MB"
|
make check PGOPTIONS="-c debug_parallel_query=regress -c work_mem=50MB"
|
||||||
</screen>
|
</screen>
|
||||||
|
(This makes use of functionality provided by libpq; see <xref
|
||||||
|
linkend="libpq-connect-options"/> for details.)
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
When running against a temporary installation, custom settings can also be
|
When running against a temporary installation, custom settings can also be
|
||||||
set by supplying a pre-written <filename>postgresql.conf</filename>:
|
set by supplying a pre-written <filename>postgresql.conf</filename>:
|
||||||
<screen>
|
<screen>
|
||||||
@ -405,11 +430,6 @@ make check EXTRA_REGRESS_OPTS="--temp-config=test_postgresql.conf"
|
|||||||
</screen>
|
</screen>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
|
||||||
This can be useful to enable additional logging, adjust resource limits,
|
|
||||||
or enable extra run-time checks such as <xref
|
|
||||||
linkend="guc-debug-discard-caches"/>.
|
|
||||||
</para>
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="regress-run-extra-tests">
|
<sect2 id="regress-run-extra-tests">
|
||||||
|
@ -2139,6 +2139,10 @@ StartTransaction(void)
|
|||||||
*/
|
*/
|
||||||
s->state = TRANS_INPROGRESS;
|
s->state = TRANS_INPROGRESS;
|
||||||
|
|
||||||
|
/* Schedule transaction timeout */
|
||||||
|
if (TransactionTimeout > 0)
|
||||||
|
enable_timeout_after(TRANSACTION_TIMEOUT, TransactionTimeout);
|
||||||
|
|
||||||
ShowTransactionState("StartTransaction");
|
ShowTransactionState("StartTransaction");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2258,6 +2262,10 @@ CommitTransaction(void)
|
|||||||
s->state = TRANS_COMMIT;
|
s->state = TRANS_COMMIT;
|
||||||
s->parallelModeLevel = 0;
|
s->parallelModeLevel = 0;
|
||||||
|
|
||||||
|
/* Disable transaction timeout */
|
||||||
|
if (TransactionTimeout > 0)
|
||||||
|
disable_timeout(TRANSACTION_TIMEOUT, false);
|
||||||
|
|
||||||
if (!is_parallel_worker)
|
if (!is_parallel_worker)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -2531,6 +2539,10 @@ PrepareTransaction(void)
|
|||||||
*/
|
*/
|
||||||
s->state = TRANS_PREPARE;
|
s->state = TRANS_PREPARE;
|
||||||
|
|
||||||
|
/* Disable transaction timeout */
|
||||||
|
if (TransactionTimeout > 0)
|
||||||
|
disable_timeout(TRANSACTION_TIMEOUT, false);
|
||||||
|
|
||||||
prepared_at = GetCurrentTimestamp();
|
prepared_at = GetCurrentTimestamp();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2703,6 +2715,10 @@ AbortTransaction(void)
|
|||||||
/* Prevent cancel/die interrupt while cleaning up */
|
/* Prevent cancel/die interrupt while cleaning up */
|
||||||
HOLD_INTERRUPTS();
|
HOLD_INTERRUPTS();
|
||||||
|
|
||||||
|
/* Disable transaction timeout */
|
||||||
|
if (TransactionTimeout > 0)
|
||||||
|
disable_timeout(TRANSACTION_TIMEOUT, false);
|
||||||
|
|
||||||
/* Make sure we have a valid memory context and resource owner */
|
/* Make sure we have a valid memory context and resource owner */
|
||||||
AtAbort_Memory();
|
AtAbort_Memory();
|
||||||
AtAbort_ResourceOwner();
|
AtAbort_ResourceOwner();
|
||||||
|
@ -2143,12 +2143,6 @@ pathkeys_useful_for_ordering(PlannerInfo *root, List *pathkeys)
|
|||||||
{
|
{
|
||||||
int n_common_pathkeys;
|
int n_common_pathkeys;
|
||||||
|
|
||||||
if (root->query_pathkeys == NIL)
|
|
||||||
return 0; /* no special ordering requested */
|
|
||||||
|
|
||||||
if (pathkeys == NIL)
|
|
||||||
return 0; /* unordered path */
|
|
||||||
|
|
||||||
(void) pathkeys_count_contained_in(root->query_pathkeys, pathkeys,
|
(void) pathkeys_count_contained_in(root->query_pathkeys, pathkeys,
|
||||||
&n_common_pathkeys);
|
&n_common_pathkeys);
|
||||||
|
|
||||||
@ -2184,10 +2178,6 @@ pathkeys_useful_for_grouping(PlannerInfo *root, List *pathkeys)
|
|||||||
if (root->group_pathkeys == NIL)
|
if (root->group_pathkeys == NIL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* unordered path */
|
|
||||||
if (pathkeys == NIL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* walk the pathkeys and search for matching group key */
|
/* walk the pathkeys and search for matching group key */
|
||||||
foreach(key, pathkeys)
|
foreach(key, pathkeys)
|
||||||
{
|
{
|
||||||
|
@ -1278,14 +1278,23 @@ convert_ANY_sublink_to_join(PlannerInfo *root, SubLink *sublink,
|
|||||||
List *subquery_vars;
|
List *subquery_vars;
|
||||||
Node *quals;
|
Node *quals;
|
||||||
ParseState *pstate;
|
ParseState *pstate;
|
||||||
|
Relids sub_ref_outer_relids;
|
||||||
|
bool use_lateral;
|
||||||
|
|
||||||
Assert(sublink->subLinkType == ANY_SUBLINK);
|
Assert(sublink->subLinkType == ANY_SUBLINK);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The sub-select must not refer to any Vars of the parent query. (Vars of
|
* If the sub-select refers to any Vars of the parent query, we so let's
|
||||||
* higher levels should be okay, though.)
|
* considering it as LATERAL. (Vars of higher levels don't matter here.)
|
||||||
*/
|
*/
|
||||||
if (contain_vars_of_level((Node *) subselect, 1))
|
sub_ref_outer_relids = pull_varnos_of_level(NULL, (Node *) subselect, 1);
|
||||||
|
use_lateral = !bms_is_empty(sub_ref_outer_relids);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that sub-select refers nothing outside of available_rels of the
|
||||||
|
* parent query.
|
||||||
|
*/
|
||||||
|
if (!bms_is_subset(sub_ref_outer_relids, available_rels))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1323,7 +1332,7 @@ convert_ANY_sublink_to_join(PlannerInfo *root, SubLink *sublink,
|
|||||||
nsitem = addRangeTableEntryForSubquery(pstate,
|
nsitem = addRangeTableEntryForSubquery(pstate,
|
||||||
subselect,
|
subselect,
|
||||||
makeAlias("ANY_subquery", NIL),
|
makeAlias("ANY_subquery", NIL),
|
||||||
false,
|
use_lateral,
|
||||||
false);
|
false);
|
||||||
rte = nsitem->p_rte;
|
rte = nsitem->p_rte;
|
||||||
parse->rtable = lappend(parse->rtable, rte);
|
parse->rtable = lappend(parse->rtable, rte);
|
||||||
|
@ -586,6 +586,7 @@ AutoVacLauncherMain(int argc, char *argv[])
|
|||||||
* regular maintenance from being executed.
|
* regular maintenance from being executed.
|
||||||
*/
|
*/
|
||||||
SetConfigOption("statement_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
|
SetConfigOption("statement_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
|
||||||
|
SetConfigOption("transaction_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
|
||||||
SetConfigOption("lock_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
|
SetConfigOption("lock_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
|
||||||
SetConfigOption("idle_in_transaction_session_timeout", "0",
|
SetConfigOption("idle_in_transaction_session_timeout", "0",
|
||||||
PGC_SUSET, PGC_S_OVERRIDE);
|
PGC_SUSET, PGC_S_OVERRIDE);
|
||||||
@ -1587,6 +1588,7 @@ AutoVacWorkerMain(int argc, char *argv[])
|
|||||||
* regular maintenance from being executed.
|
* regular maintenance from being executed.
|
||||||
*/
|
*/
|
||||||
SetConfigOption("statement_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
|
SetConfigOption("statement_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
|
||||||
|
SetConfigOption("transaction_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
|
||||||
SetConfigOption("lock_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
|
SetConfigOption("lock_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
|
||||||
SetConfigOption("idle_in_transaction_session_timeout", "0",
|
SetConfigOption("idle_in_transaction_session_timeout", "0",
|
||||||
PGC_SUSET, PGC_S_OVERRIDE);
|
PGC_SUSET, PGC_S_OVERRIDE);
|
||||||
|
@ -321,6 +321,9 @@ reserve_wal_for_local_slot(XLogRecPtr restart_lsn)
|
|||||||
oldest_segno = XLogGetOldestSegno(cur_timeline);
|
oldest_segno = XLogGetOldestSegno(cur_timeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elog(DEBUG1, "segno: %ld of purposed restart_lsn for the synced slot, oldest_segno: %ld available",
|
||||||
|
segno, oldest_segno);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If all required WAL is still there, great, otherwise retry. The
|
* If all required WAL is still there, great, otherwise retry. The
|
||||||
* slot should prevent further removal of WAL, unless there's a
|
* slot should prevent further removal of WAL, unless there's a
|
||||||
@ -361,7 +364,18 @@ update_and_persist_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid)
|
|||||||
* current location when recreating the slot in the next cycle. It may
|
* current location when recreating the slot in the next cycle. It may
|
||||||
* take more time to create such a slot. Therefore, we keep this slot
|
* take more time to create such a slot. Therefore, we keep this slot
|
||||||
* and attempt the synchronization in the next cycle.
|
* and attempt the synchronization in the next cycle.
|
||||||
|
*
|
||||||
|
* XXX should this be changed to elog(DEBUG1) perhaps?
|
||||||
*/
|
*/
|
||||||
|
ereport(LOG,
|
||||||
|
errmsg("could not sync slot information as remote slot precedes local slot:"
|
||||||
|
" remote slot \"%s\": LSN (%X/%X), catalog xmin (%u) local slot: LSN (%X/%X), catalog xmin (%u)",
|
||||||
|
remote_slot->name,
|
||||||
|
LSN_FORMAT_ARGS(remote_slot->restart_lsn),
|
||||||
|
remote_slot->catalog_xmin,
|
||||||
|
LSN_FORMAT_ARGS(slot->data.restart_lsn),
|
||||||
|
slot->data.catalog_xmin));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ int DeadlockTimeout = 1000;
|
|||||||
int StatementTimeout = 0;
|
int StatementTimeout = 0;
|
||||||
int LockTimeout = 0;
|
int LockTimeout = 0;
|
||||||
int IdleInTransactionSessionTimeout = 0;
|
int IdleInTransactionSessionTimeout = 0;
|
||||||
|
int TransactionTimeout = 0;
|
||||||
int IdleSessionTimeout = 0;
|
int IdleSessionTimeout = 0;
|
||||||
bool log_lock_waits = false;
|
bool log_lock_waits = false;
|
||||||
|
|
||||||
|
@ -3418,6 +3418,17 @@ ProcessInterrupts(void)
|
|||||||
IdleInTransactionSessionTimeoutPending = false;
|
IdleInTransactionSessionTimeoutPending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TransactionTimeoutPending)
|
||||||
|
{
|
||||||
|
/* As above, ignore the signal if the GUC has been reset to zero. */
|
||||||
|
if (TransactionTimeout > 0)
|
||||||
|
ereport(FATAL,
|
||||||
|
(errcode(ERRCODE_TRANSACTION_TIMEOUT),
|
||||||
|
errmsg("terminating connection due to transaction timeout")));
|
||||||
|
else
|
||||||
|
TransactionTimeoutPending = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (IdleSessionTimeoutPending)
|
if (IdleSessionTimeoutPending)
|
||||||
{
|
{
|
||||||
/* As above, ignore the signal if the GUC has been reset to zero. */
|
/* As above, ignore the signal if the GUC has been reset to zero. */
|
||||||
@ -3632,6 +3643,23 @@ check_log_stats(bool *newval, void **extra, GucSource source)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* GUC assign hook for transaction_timeout */
|
||||||
|
void
|
||||||
|
assign_transaction_timeout(int newval, void *extra)
|
||||||
|
{
|
||||||
|
if (IsTransactionState())
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If transaction_timeout GUC has changes within the transaction block
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set_debug_options --- apply "-d N" command line option
|
* set_debug_options --- apply "-d N" command line option
|
||||||
@ -4483,7 +4511,8 @@ PostgresMain(const char *dbname, const char *username)
|
|||||||
pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL);
|
pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL);
|
||||||
|
|
||||||
/* Start the idle-in-transaction timer */
|
/* Start the idle-in-transaction timer */
|
||||||
if (IdleInTransactionSessionTimeout > 0)
|
if (IdleInTransactionSessionTimeout > 0
|
||||||
|
&& (IdleInTransactionSessionTimeout < TransactionTimeout || TransactionTimeout == 0))
|
||||||
{
|
{
|
||||||
idle_in_transaction_timeout_enabled = true;
|
idle_in_transaction_timeout_enabled = true;
|
||||||
enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
|
enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
|
||||||
@ -4496,7 +4525,8 @@ PostgresMain(const char *dbname, const char *username)
|
|||||||
pgstat_report_activity(STATE_IDLEINTRANSACTION, NULL);
|
pgstat_report_activity(STATE_IDLEINTRANSACTION, NULL);
|
||||||
|
|
||||||
/* Start the idle-in-transaction timer */
|
/* Start the idle-in-transaction timer */
|
||||||
if (IdleInTransactionSessionTimeout > 0)
|
if (IdleInTransactionSessionTimeout > 0
|
||||||
|
&& (IdleInTransactionSessionTimeout < TransactionTimeout || TransactionTimeout == 0))
|
||||||
{
|
{
|
||||||
idle_in_transaction_timeout_enabled = true;
|
idle_in_transaction_timeout_enabled = true;
|
||||||
enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
|
enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
|
||||||
@ -5112,7 +5142,8 @@ enable_statement_timeout(void)
|
|||||||
/* must be within an xact */
|
/* must be within an xact */
|
||||||
Assert(xact_started);
|
Assert(xact_started);
|
||||||
|
|
||||||
if (StatementTimeout > 0)
|
if (StatementTimeout > 0
|
||||||
|
&& (StatementTimeout < TransactionTimeout || TransactionTimeout == 0))
|
||||||
{
|
{
|
||||||
if (!get_timeout_active(STATEMENT_TIMEOUT))
|
if (!get_timeout_active(STATEMENT_TIMEOUT))
|
||||||
enable_timeout_after(STATEMENT_TIMEOUT, StatementTimeout);
|
enable_timeout_after(STATEMENT_TIMEOUT, StatementTimeout);
|
||||||
|
@ -252,6 +252,7 @@ Section: Class 25 - Invalid Transaction State
|
|||||||
25P01 E ERRCODE_NO_ACTIVE_SQL_TRANSACTION no_active_sql_transaction
|
25P01 E ERRCODE_NO_ACTIVE_SQL_TRANSACTION no_active_sql_transaction
|
||||||
25P02 E ERRCODE_IN_FAILED_SQL_TRANSACTION in_failed_sql_transaction
|
25P02 E ERRCODE_IN_FAILED_SQL_TRANSACTION in_failed_sql_transaction
|
||||||
25P03 E ERRCODE_IDLE_IN_TRANSACTION_SESSION_TIMEOUT idle_in_transaction_session_timeout
|
25P03 E ERRCODE_IDLE_IN_TRANSACTION_SESSION_TIMEOUT idle_in_transaction_session_timeout
|
||||||
|
25P04 E ERRCODE_TRANSACTION_TIMEOUT transaction_timeout
|
||||||
|
|
||||||
Section: Class 26 - Invalid SQL Statement Name
|
Section: Class 26 - Invalid SQL Statement Name
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ volatile sig_atomic_t ProcDiePending = false;
|
|||||||
volatile sig_atomic_t CheckClientConnectionPending = false;
|
volatile sig_atomic_t CheckClientConnectionPending = false;
|
||||||
volatile sig_atomic_t ClientConnectionLost = false;
|
volatile sig_atomic_t ClientConnectionLost = false;
|
||||||
volatile sig_atomic_t IdleInTransactionSessionTimeoutPending = false;
|
volatile sig_atomic_t IdleInTransactionSessionTimeoutPending = false;
|
||||||
|
volatile sig_atomic_t TransactionTimeoutPending = false;
|
||||||
volatile sig_atomic_t IdleSessionTimeoutPending = false;
|
volatile sig_atomic_t IdleSessionTimeoutPending = false;
|
||||||
volatile sig_atomic_t ProcSignalBarrierPending = false;
|
volatile sig_atomic_t ProcSignalBarrierPending = false;
|
||||||
volatile sig_atomic_t LogMemoryContextPending = false;
|
volatile sig_atomic_t LogMemoryContextPending = false;
|
||||||
|
@ -75,6 +75,7 @@ static void ShutdownPostgres(int code, Datum arg);
|
|||||||
static void StatementTimeoutHandler(void);
|
static void StatementTimeoutHandler(void);
|
||||||
static void LockTimeoutHandler(void);
|
static void LockTimeoutHandler(void);
|
||||||
static void IdleInTransactionSessionTimeoutHandler(void);
|
static void IdleInTransactionSessionTimeoutHandler(void);
|
||||||
|
static void TransactionTimeoutHandler(void);
|
||||||
static void IdleSessionTimeoutHandler(void);
|
static void IdleSessionTimeoutHandler(void);
|
||||||
static void IdleStatsUpdateTimeoutHandler(void);
|
static void IdleStatsUpdateTimeoutHandler(void);
|
||||||
static void ClientCheckTimeoutHandler(void);
|
static void ClientCheckTimeoutHandler(void);
|
||||||
@ -764,6 +765,7 @@ InitPostgres(const char *in_dbname, Oid dboid,
|
|||||||
RegisterTimeout(LOCK_TIMEOUT, LockTimeoutHandler);
|
RegisterTimeout(LOCK_TIMEOUT, LockTimeoutHandler);
|
||||||
RegisterTimeout(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
|
RegisterTimeout(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
|
||||||
IdleInTransactionSessionTimeoutHandler);
|
IdleInTransactionSessionTimeoutHandler);
|
||||||
|
RegisterTimeout(TRANSACTION_TIMEOUT, TransactionTimeoutHandler);
|
||||||
RegisterTimeout(IDLE_SESSION_TIMEOUT, IdleSessionTimeoutHandler);
|
RegisterTimeout(IDLE_SESSION_TIMEOUT, IdleSessionTimeoutHandler);
|
||||||
RegisterTimeout(CLIENT_CONNECTION_CHECK_TIMEOUT, ClientCheckTimeoutHandler);
|
RegisterTimeout(CLIENT_CONNECTION_CHECK_TIMEOUT, ClientCheckTimeoutHandler);
|
||||||
RegisterTimeout(IDLE_STATS_UPDATE_TIMEOUT,
|
RegisterTimeout(IDLE_STATS_UPDATE_TIMEOUT,
|
||||||
@ -1395,6 +1397,14 @@ LockTimeoutHandler(void)
|
|||||||
kill(MyProcPid, SIGINT);
|
kill(MyProcPid, SIGINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
TransactionTimeoutHandler(void)
|
||||||
|
{
|
||||||
|
TransactionTimeoutPending = true;
|
||||||
|
InterruptPending = true;
|
||||||
|
SetLatch(MyLatch);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
IdleInTransactionSessionTimeoutHandler(void)
|
IdleInTransactionSessionTimeoutHandler(void)
|
||||||
{
|
{
|
||||||
|
@ -2577,6 +2577,17 @@ struct config_int ConfigureNamesInt[] =
|
|||||||
NULL, NULL, NULL
|
NULL, NULL, NULL
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
{"transaction_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
|
||||||
|
gettext_noop("Sets the maximum allowed time in a transaction with a session (not a prepared transaction)."),
|
||||||
|
gettext_noop("A value of 0 turns off the timeout."),
|
||||||
|
GUC_UNIT_MS
|
||||||
|
},
|
||||||
|
&TransactionTimeout,
|
||||||
|
0, 0, INT_MAX,
|
||||||
|
NULL, assign_transaction_timeout, NULL
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
{"idle_session_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
|
{"idle_session_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
|
||||||
gettext_noop("Sets the maximum allowed idle time between queries, when not in a transaction."),
|
gettext_noop("Sets the maximum allowed idle time between queries, when not in a transaction."),
|
||||||
|
@ -195,9 +195,9 @@
|
|||||||
#effective_io_concurrency = 1 # 1-1000; 0 disables prefetching
|
#effective_io_concurrency = 1 # 1-1000; 0 disables prefetching
|
||||||
#maintenance_io_concurrency = 10 # 1-1000; 0 disables prefetching
|
#maintenance_io_concurrency = 10 # 1-1000; 0 disables prefetching
|
||||||
#max_worker_processes = 8 # (change requires restart)
|
#max_worker_processes = 8 # (change requires restart)
|
||||||
#max_parallel_workers_per_gather = 2 # taken from max_parallel_workers
|
#max_parallel_workers_per_gather = 2 # limited by max_parallel_workers
|
||||||
#max_parallel_maintenance_workers = 2 # taken from max_parallel_workers
|
#max_parallel_maintenance_workers = 2 # limited by max_parallel_workers
|
||||||
#max_parallel_workers = 8 # maximum number of max_worker_processes that
|
#max_parallel_workers = 8 # number of max_worker_processes that
|
||||||
# can be used in parallel operations
|
# can be used in parallel operations
|
||||||
#parallel_leader_participation = on
|
#parallel_leader_participation = on
|
||||||
|
|
||||||
@ -701,6 +701,7 @@
|
|||||||
#default_transaction_deferrable = off
|
#default_transaction_deferrable = off
|
||||||
#session_replication_role = 'origin'
|
#session_replication_role = 'origin'
|
||||||
#statement_timeout = 0 # in milliseconds, 0 is disabled
|
#statement_timeout = 0 # in milliseconds, 0 is disabled
|
||||||
|
#transaction_timeout = 0 # in milliseconds, 0 is disabled
|
||||||
#lock_timeout = 0 # in milliseconds, 0 is disabled
|
#lock_timeout = 0 # in milliseconds, 0 is disabled
|
||||||
#idle_in_transaction_session_timeout = 0 # in milliseconds, 0 is disabled
|
#idle_in_transaction_session_timeout = 0 # in milliseconds, 0 is disabled
|
||||||
#idle_session_timeout = 0 # in milliseconds, 0 is disabled
|
#idle_session_timeout = 0 # in milliseconds, 0 is disabled
|
||||||
|
@ -3115,6 +3115,7 @@ _doSetFixedOutputState(ArchiveHandle *AH)
|
|||||||
ahprintf(AH, "SET statement_timeout = 0;\n");
|
ahprintf(AH, "SET statement_timeout = 0;\n");
|
||||||
ahprintf(AH, "SET lock_timeout = 0;\n");
|
ahprintf(AH, "SET lock_timeout = 0;\n");
|
||||||
ahprintf(AH, "SET idle_in_transaction_session_timeout = 0;\n");
|
ahprintf(AH, "SET idle_in_transaction_session_timeout = 0;\n");
|
||||||
|
ahprintf(AH, "SET transaction_timeout = 0;\n");
|
||||||
|
|
||||||
/* Select the correct character set encoding */
|
/* Select the correct character set encoding */
|
||||||
ahprintf(AH, "SET client_encoding = '%s';\n",
|
ahprintf(AH, "SET client_encoding = '%s';\n",
|
||||||
|
@ -1252,6 +1252,8 @@ setup_connection(Archive *AH, const char *dumpencoding,
|
|||||||
ExecuteSqlStatement(AH, "SET lock_timeout = 0");
|
ExecuteSqlStatement(AH, "SET lock_timeout = 0");
|
||||||
if (AH->remoteVersion >= 90600)
|
if (AH->remoteVersion >= 90600)
|
||||||
ExecuteSqlStatement(AH, "SET idle_in_transaction_session_timeout = 0");
|
ExecuteSqlStatement(AH, "SET idle_in_transaction_session_timeout = 0");
|
||||||
|
if (AH->remoteVersion >= 170000)
|
||||||
|
ExecuteSqlStatement(AH, "SET transaction_timeout = 0");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Quote all identifiers, if requested.
|
* Quote all identifiers, if requested.
|
||||||
|
@ -117,6 +117,7 @@ init_libpq_conn(PGconn *conn)
|
|||||||
run_simple_command(conn, "SET statement_timeout = 0");
|
run_simple_command(conn, "SET statement_timeout = 0");
|
||||||
run_simple_command(conn, "SET lock_timeout = 0");
|
run_simple_command(conn, "SET lock_timeout = 0");
|
||||||
run_simple_command(conn, "SET idle_in_transaction_session_timeout = 0");
|
run_simple_command(conn, "SET idle_in_transaction_session_timeout = 0");
|
||||||
|
run_simple_command(conn, "SET transaction_timeout = 0");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we don't intend to do any updates, put the connection in read-only mode
|
* we don't intend to do any updates, put the connection in read-only mode
|
||||||
|
@ -91,6 +91,7 @@ extern PGDLLIMPORT volatile sig_atomic_t InterruptPending;
|
|||||||
extern PGDLLIMPORT volatile sig_atomic_t QueryCancelPending;
|
extern PGDLLIMPORT volatile sig_atomic_t QueryCancelPending;
|
||||||
extern PGDLLIMPORT volatile sig_atomic_t ProcDiePending;
|
extern PGDLLIMPORT volatile sig_atomic_t ProcDiePending;
|
||||||
extern PGDLLIMPORT volatile sig_atomic_t IdleInTransactionSessionTimeoutPending;
|
extern PGDLLIMPORT volatile sig_atomic_t IdleInTransactionSessionTimeoutPending;
|
||||||
|
extern PGDLLIMPORT volatile sig_atomic_t TransactionTimeoutPending;
|
||||||
extern PGDLLIMPORT volatile sig_atomic_t IdleSessionTimeoutPending;
|
extern PGDLLIMPORT volatile sig_atomic_t IdleSessionTimeoutPending;
|
||||||
extern PGDLLIMPORT volatile sig_atomic_t ProcSignalBarrierPending;
|
extern PGDLLIMPORT volatile sig_atomic_t ProcSignalBarrierPending;
|
||||||
extern PGDLLIMPORT volatile sig_atomic_t LogMemoryContextPending;
|
extern PGDLLIMPORT volatile sig_atomic_t LogMemoryContextPending;
|
||||||
|
@ -429,6 +429,7 @@ extern PGDLLIMPORT int DeadlockTimeout;
|
|||||||
extern PGDLLIMPORT int StatementTimeout;
|
extern PGDLLIMPORT int StatementTimeout;
|
||||||
extern PGDLLIMPORT int LockTimeout;
|
extern PGDLLIMPORT int LockTimeout;
|
||||||
extern PGDLLIMPORT int IdleInTransactionSessionTimeout;
|
extern PGDLLIMPORT int IdleInTransactionSessionTimeout;
|
||||||
|
extern PGDLLIMPORT int TransactionTimeout;
|
||||||
extern PGDLLIMPORT int IdleSessionTimeout;
|
extern PGDLLIMPORT int IdleSessionTimeout;
|
||||||
extern PGDLLIMPORT bool log_lock_waits;
|
extern PGDLLIMPORT bool log_lock_waits;
|
||||||
|
|
||||||
|
@ -155,6 +155,7 @@ extern void assign_timezone_abbreviations(const char *newval, void *extra);
|
|||||||
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
|
extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
|
||||||
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
|
extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
|
||||||
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
|
extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
|
||||||
|
extern void assign_transaction_timeout(int newval, void *extra);
|
||||||
extern const char *show_unix_socket_permissions(void);
|
extern const char *show_unix_socket_permissions(void);
|
||||||
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
|
extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
|
||||||
extern bool check_wal_consistency_checking(char **newval, void **extra,
|
extern bool check_wal_consistency_checking(char **newval, void **extra,
|
||||||
|
@ -31,6 +31,7 @@ typedef enum TimeoutId
|
|||||||
STANDBY_TIMEOUT,
|
STANDBY_TIMEOUT,
|
||||||
STANDBY_LOCK_TIMEOUT,
|
STANDBY_LOCK_TIMEOUT,
|
||||||
IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
|
IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
|
||||||
|
TRANSACTION_TIMEOUT,
|
||||||
IDLE_SESSION_TIMEOUT,
|
IDLE_SESSION_TIMEOUT,
|
||||||
IDLE_STATS_UPDATE_TIMEOUT,
|
IDLE_STATS_UPDATE_TIMEOUT,
|
||||||
CLIENT_CONNECTION_CHECK_TIMEOUT,
|
CLIENT_CONNECTION_CHECK_TIMEOUT,
|
||||||
|
@ -72,3 +72,6 @@ installcheck-prepared-txns: all temp-install
|
|||||||
|
|
||||||
check-prepared-txns: all temp-install
|
check-prepared-txns: all temp-install
|
||||||
$(pg_isolation_regress_check) --schedule=$(srcdir)/isolation_schedule prepared-transactions prepared-transactions-cic
|
$(pg_isolation_regress_check) --schedule=$(srcdir)/isolation_schedule prepared-transactions prepared-transactions-cic
|
||||||
|
|
||||||
|
check-timeouts: all temp-install
|
||||||
|
$(pg_isolation_regress_check) timeouts timeouts-long
|
||||||
|
69
src/test/isolation/expected/timeouts-long.out
Normal file
69
src/test/isolation/expected/timeouts-long.out
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
Parsed test spec with 3 sessions
|
||||||
|
|
||||||
|
starting permutation: s7_begin s7_sleep s7_commit_and_chain s7_sleep s7_check s7_abort
|
||||||
|
step s7_begin:
|
||||||
|
BEGIN ISOLATION LEVEL READ COMMITTED;
|
||||||
|
SET transaction_timeout = '1s';
|
||||||
|
|
||||||
|
step s7_sleep: SELECT pg_sleep(0.6);
|
||||||
|
pg_sleep
|
||||||
|
--------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
step s7_commit_and_chain: COMMIT AND CHAIN;
|
||||||
|
step s7_sleep: SELECT pg_sleep(0.6);
|
||||||
|
pg_sleep
|
||||||
|
--------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
step s7_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s7';
|
||||||
|
count
|
||||||
|
-----
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
step s7_abort: ABORT;
|
||||||
|
|
||||||
|
starting permutation: s8_begin s8_sleep s8_select_1 s8_check checker_sleep checker_sleep s8_check
|
||||||
|
step s8_begin:
|
||||||
|
BEGIN ISOLATION LEVEL READ COMMITTED;
|
||||||
|
SET transaction_timeout = '900ms';
|
||||||
|
|
||||||
|
step s8_sleep: SELECT pg_sleep(0.6);
|
||||||
|
pg_sleep
|
||||||
|
--------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
step s8_select_1: SELECT 1;
|
||||||
|
?column?
|
||||||
|
--------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
step s8_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s8';
|
||||||
|
count
|
||||||
|
-----
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
step checker_sleep: SELECT pg_sleep(0.3);
|
||||||
|
pg_sleep
|
||||||
|
--------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
step checker_sleep: SELECT pg_sleep(0.3);
|
||||||
|
pg_sleep
|
||||||
|
--------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
step s8_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s8';
|
||||||
|
count
|
||||||
|
-----
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
Parsed test spec with 2 sessions
|
Parsed test spec with 7 sessions
|
||||||
|
|
||||||
starting permutation: rdtbl sto locktbl
|
starting permutation: rdtbl sto locktbl
|
||||||
step rdtbl: SELECT * FROM accounts;
|
step rdtbl: SELECT * FROM accounts;
|
||||||
@ -79,3 +79,80 @@ step slto: SET lock_timeout = '10s'; SET statement_timeout = '10ms';
|
|||||||
step update: DELETE FROM accounts WHERE accountid = 'checking'; <waiting ...>
|
step update: DELETE FROM accounts WHERE accountid = 'checking'; <waiting ...>
|
||||||
step update: <... completed>
|
step update: <... completed>
|
||||||
ERROR: canceling statement due to statement timeout
|
ERROR: canceling statement due to statement timeout
|
||||||
|
|
||||||
|
starting permutation: stto s3_begin s3_sleep s3_check s3_abort
|
||||||
|
step stto: SET statement_timeout = '10ms'; SET transaction_timeout = '1s';
|
||||||
|
step s3_begin: BEGIN ISOLATION LEVEL READ COMMITTED;
|
||||||
|
step s3_sleep: SELECT pg_sleep(0.1);
|
||||||
|
ERROR: canceling statement due to statement timeout
|
||||||
|
step s3_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s3';
|
||||||
|
count
|
||||||
|
-----
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
step s3_abort: ABORT;
|
||||||
|
|
||||||
|
starting permutation: tsto s3_begin checker_sleep s3_check
|
||||||
|
step tsto: SET statement_timeout = '1s'; SET transaction_timeout = '10ms';
|
||||||
|
step s3_begin: BEGIN ISOLATION LEVEL READ COMMITTED;
|
||||||
|
step checker_sleep: SELECT pg_sleep(0.1);
|
||||||
|
pg_sleep
|
||||||
|
--------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
step s3_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s3';
|
||||||
|
count
|
||||||
|
-----
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
|
||||||
|
starting permutation: itto s4_begin checker_sleep s4_check
|
||||||
|
step itto: SET idle_in_transaction_session_timeout = '10ms'; SET transaction_timeout = '1s';
|
||||||
|
step s4_begin: BEGIN ISOLATION LEVEL READ COMMITTED;
|
||||||
|
step checker_sleep: SELECT pg_sleep(0.1);
|
||||||
|
pg_sleep
|
||||||
|
--------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
step s4_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s4';
|
||||||
|
count
|
||||||
|
-----
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
|
||||||
|
starting permutation: tito s5_begin checker_sleep s5_check
|
||||||
|
step tito: SET idle_in_transaction_session_timeout = '1s'; SET transaction_timeout = '10ms';
|
||||||
|
step s5_begin: BEGIN ISOLATION LEVEL READ COMMITTED;
|
||||||
|
step checker_sleep: SELECT pg_sleep(0.1);
|
||||||
|
pg_sleep
|
||||||
|
--------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
step s5_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s5';
|
||||||
|
count
|
||||||
|
-----
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
|
||||||
|
starting permutation: s6_begin s6_tt checker_sleep s6_check
|
||||||
|
step s6_begin: BEGIN ISOLATION LEVEL READ COMMITTED;
|
||||||
|
step s6_tt: SET statement_timeout = '1s'; SET transaction_timeout = '10ms';
|
||||||
|
step checker_sleep: SELECT pg_sleep(0.1);
|
||||||
|
pg_sleep
|
||||||
|
--------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
step s6_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s6';
|
||||||
|
count
|
||||||
|
-----
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Simple tests for statement_timeout and lock_timeout features
|
# Simple tests for statement_timeout, lock_timeout and transaction_timeout features
|
||||||
|
|
||||||
setup
|
setup
|
||||||
{
|
{
|
||||||
@ -27,6 +27,33 @@ step locktbl { LOCK TABLE accounts; }
|
|||||||
step update { DELETE FROM accounts WHERE accountid = 'checking'; }
|
step update { DELETE FROM accounts WHERE accountid = 'checking'; }
|
||||||
teardown { ABORT; }
|
teardown { ABORT; }
|
||||||
|
|
||||||
|
session s3
|
||||||
|
step s3_begin { BEGIN ISOLATION LEVEL READ COMMITTED; }
|
||||||
|
step stto { SET statement_timeout = '10ms'; SET transaction_timeout = '1s'; }
|
||||||
|
step tsto { SET statement_timeout = '1s'; SET transaction_timeout = '10ms'; }
|
||||||
|
step s3_sleep { SELECT pg_sleep(0.1); }
|
||||||
|
step s3_abort { ABORT; }
|
||||||
|
|
||||||
|
session s4
|
||||||
|
step s4_begin { BEGIN ISOLATION LEVEL READ COMMITTED; }
|
||||||
|
step itto { SET idle_in_transaction_session_timeout = '10ms'; SET transaction_timeout = '1s'; }
|
||||||
|
|
||||||
|
session s5
|
||||||
|
step s5_begin { BEGIN ISOLATION LEVEL READ COMMITTED; }
|
||||||
|
step tito { SET idle_in_transaction_session_timeout = '1s'; SET transaction_timeout = '10ms'; }
|
||||||
|
|
||||||
|
session s6
|
||||||
|
step s6_begin { BEGIN ISOLATION LEVEL READ COMMITTED; }
|
||||||
|
step s6_tt { SET statement_timeout = '1s'; SET transaction_timeout = '10ms'; }
|
||||||
|
|
||||||
|
session checker
|
||||||
|
step checker_sleep { SELECT pg_sleep(0.1); }
|
||||||
|
step s3_check { SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s3'; }
|
||||||
|
step s4_check { SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s4'; }
|
||||||
|
step s5_check { SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s5'; }
|
||||||
|
step s6_check { SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s6'; }
|
||||||
|
|
||||||
|
|
||||||
# It's possible that the isolation tester will not observe the final
|
# It's possible that the isolation tester will not observe the final
|
||||||
# steps as "waiting", thanks to the relatively short timeouts we use.
|
# steps as "waiting", thanks to the relatively short timeouts we use.
|
||||||
# We can ensure consistent test output by marking those steps with (*).
|
# We can ensure consistent test output by marking those steps with (*).
|
||||||
@ -47,3 +74,14 @@ permutation wrtbl lto update(*)
|
|||||||
permutation wrtbl lsto update(*)
|
permutation wrtbl lsto update(*)
|
||||||
# statement timeout expires first, row-level lock
|
# statement timeout expires first, row-level lock
|
||||||
permutation wrtbl slto update(*)
|
permutation wrtbl slto update(*)
|
||||||
|
|
||||||
|
# statement timeout expires first
|
||||||
|
permutation stto s3_begin s3_sleep s3_check s3_abort
|
||||||
|
# transaction timeout expires first, session s3 FATAL-out
|
||||||
|
permutation tsto s3_begin checker_sleep s3_check
|
||||||
|
# idle in transaction timeout expires first, session s4 FATAL-out
|
||||||
|
permutation itto s4_begin checker_sleep s4_check
|
||||||
|
# transaction timeout expires first, session s5 FATAL-out
|
||||||
|
permutation tito s5_begin checker_sleep s5_check
|
||||||
|
# transaction timeout can be schedule amid transaction, session s6 FATAL-out
|
||||||
|
permutation s6_begin s6_tt checker_sleep s6_check
|
@ -114,6 +114,7 @@ use Socket;
|
|||||||
use Test::More;
|
use Test::More;
|
||||||
use PostgreSQL::Test::Utils ();
|
use PostgreSQL::Test::Utils ();
|
||||||
use PostgreSQL::Test::BackgroundPsql ();
|
use PostgreSQL::Test::BackgroundPsql ();
|
||||||
|
use Text::ParseWords qw(shellwords);
|
||||||
use Time::HiRes qw(usleep);
|
use Time::HiRes qw(usleep);
|
||||||
use Scalar::Util qw(blessed);
|
use Scalar::Util qw(blessed);
|
||||||
|
|
||||||
@ -519,6 +520,12 @@ sub init
|
|||||||
$params{allows_streaming} = 0 unless defined $params{allows_streaming};
|
$params{allows_streaming} = 0 unless defined $params{allows_streaming};
|
||||||
$params{has_archiving} = 0 unless defined $params{has_archiving};
|
$params{has_archiving} = 0 unless defined $params{has_archiving};
|
||||||
|
|
||||||
|
my $initdb_extra_opts_env = $ENV{PG_TEST_INITDB_EXTRA_OPTS};
|
||||||
|
if (defined $initdb_extra_opts_env)
|
||||||
|
{
|
||||||
|
push @{ $params{extra} }, shellwords($initdb_extra_opts_env);
|
||||||
|
}
|
||||||
|
|
||||||
mkdir $self->backup_dir;
|
mkdir $self->backup_dir;
|
||||||
mkdir $self->archive_dir;
|
mkdir $self->archive_dir;
|
||||||
|
|
||||||
|
@ -130,14 +130,20 @@ $standby1->init_from_backup(
|
|||||||
has_streaming => 1,
|
has_streaming => 1,
|
||||||
has_restoring => 1);
|
has_restoring => 1);
|
||||||
|
|
||||||
|
# Increase the log_min_messages setting to DEBUG2 on both the standby and
|
||||||
|
# primary to debug test failures, if any.
|
||||||
my $connstr_1 = $primary->connstr;
|
my $connstr_1 = $primary->connstr;
|
||||||
$standby1->append_conf(
|
$standby1->append_conf(
|
||||||
'postgresql.conf', qq(
|
'postgresql.conf', qq(
|
||||||
hot_standby_feedback = on
|
hot_standby_feedback = on
|
||||||
primary_slot_name = 'sb1_slot'
|
primary_slot_name = 'sb1_slot'
|
||||||
primary_conninfo = '$connstr_1 dbname=postgres'
|
primary_conninfo = '$connstr_1 dbname=postgres'
|
||||||
|
log_min_messages = 'debug2'
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$primary->append_conf('postgresql.conf', "log_min_messages = 'debug2'");
|
||||||
|
$primary->reload;
|
||||||
|
|
||||||
$primary->psql('postgres',
|
$primary->psql('postgres',
|
||||||
q{SELECT pg_create_logical_replication_slot('lsub2_slot', 'test_decoding', false, false, true);}
|
q{SELECT pg_create_logical_replication_slot('lsub2_slot', 'test_decoding', false, false, true);}
|
||||||
);
|
);
|
||||||
@ -223,17 +229,14 @@ is( $standby1->safe_psql(
|
|||||||
$standby1->append_conf('postgresql.conf', 'max_slot_wal_keep_size = -1');
|
$standby1->append_conf('postgresql.conf', 'max_slot_wal_keep_size = -1');
|
||||||
$standby1->reload;
|
$standby1->reload;
|
||||||
|
|
||||||
# Enable the subscription to let it catch up to the latest wal position
|
# To ensure that restart_lsn has moved to a recent WAL position, we re-create
|
||||||
$subscriber1->safe_psql('postgres',
|
# the subscription and the logical slot.
|
||||||
"ALTER SUBSCRIPTION regress_mysub1 ENABLE");
|
$subscriber1->safe_psql(
|
||||||
|
'postgres', qq[
|
||||||
|
DROP SUBSCRIPTION regress_mysub1;
|
||||||
|
CREATE SUBSCRIPTION regress_mysub1 CONNECTION '$publisher_connstr' PUBLICATION regress_mypub WITH (slot_name = lsub1_slot, copy_data = false, failover = true);
|
||||||
|
]);
|
||||||
|
|
||||||
# This wait ensures that confirmed_flush_lsn has been moved to latest
|
|
||||||
# position.
|
|
||||||
$primary->wait_for_catchup('regress_mysub1');
|
|
||||||
|
|
||||||
# To ensure that restart_lsn has moved to a recent WAL position, we need
|
|
||||||
# to log XLOG_RUNNING_XACTS and make sure the same is processed as well
|
|
||||||
$primary->psql('postgres', "CHECKPOINT");
|
|
||||||
$primary->wait_for_catchup('regress_mysub1');
|
$primary->wait_for_catchup('regress_mysub1');
|
||||||
|
|
||||||
# Do not allow any further advancement of the restart_lsn for the lsub1_slot.
|
# Do not allow any further advancement of the restart_lsn for the lsub1_slot.
|
||||||
@ -268,6 +271,13 @@ is( $standby1->safe_psql(
|
|||||||
"t",
|
"t",
|
||||||
'logical slot is re-synced');
|
'logical slot is re-synced');
|
||||||
|
|
||||||
|
# Reset the log_min_messages to the default value.
|
||||||
|
$primary->append_conf('postgresql.conf', "log_min_messages = 'warning'");
|
||||||
|
$primary->reload;
|
||||||
|
|
||||||
|
$standby1->append_conf('postgresql.conf', "log_min_messages = 'warning'");
|
||||||
|
$standby1->reload;
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
# Test that a synchronized slot can not be decoded, altered or dropped by the
|
# Test that a synchronized slot can not be decoded, altered or dropped by the
|
||||||
# user
|
# user
|
||||||
|
@ -5277,7 +5277,7 @@ reset enable_nestloop;
|
|||||||
explain (costs off)
|
explain (costs off)
|
||||||
select a.unique1, b.unique2
|
select a.unique1, b.unique2
|
||||||
from onek a left join onek b on a.unique1 = b.unique2
|
from onek a left join onek b on a.unique1 = b.unique2
|
||||||
where b.unique2 = any (select q1 from int8_tbl c where c.q1 < b.unique1);
|
where (b.unique2, random() > 0) = any (select q1, random() > 0 from int8_tbl c where c.q1 < b.unique1);
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
Hash Join
|
Hash Join
|
||||||
@ -5293,7 +5293,7 @@ select a.unique1, b.unique2
|
|||||||
|
|
||||||
select a.unique1, b.unique2
|
select a.unique1, b.unique2
|
||||||
from onek a left join onek b on a.unique1 = b.unique2
|
from onek a left join onek b on a.unique1 = b.unique2
|
||||||
where b.unique2 = any (select q1 from int8_tbl c where c.q1 < b.unique1);
|
where (b.unique2, random() > 0) = any (select q1, random() > 0 from int8_tbl c where c.q1 < b.unique1);
|
||||||
unique1 | unique2
|
unique1 | unique2
|
||||||
---------+---------
|
---------+---------
|
||||||
123 | 123
|
123 | 123
|
||||||
@ -8210,12 +8210,12 @@ select * from (values (0), (1)) v(id),
|
|||||||
lateral (select * from int8_tbl t1,
|
lateral (select * from int8_tbl t1,
|
||||||
lateral (select * from
|
lateral (select * from
|
||||||
(select * from int8_tbl t2
|
(select * from int8_tbl t2
|
||||||
where q1 = any (select q2 from int8_tbl t3
|
where (q1, random() > 0) = any (select q2, random() > 0 from int8_tbl t3
|
||||||
where q2 = (select greatest(t1.q1,t2.q2))
|
where q2 = (select greatest(t1.q1,t2.q2))
|
||||||
and (select v.id=0)) offset 0) ss2) ss
|
and (select v.id=0)) offset 0) ss2) ss
|
||||||
where t1.q1 = ss.q2) ss0;
|
where t1.q1 = ss.q2) ss0;
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
----------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Nested Loop
|
Nested Loop
|
||||||
Output: "*VALUES*".column1, t1.q1, t1.q2, ss2.q1, ss2.q2
|
Output: "*VALUES*".column1, t1.q1, t1.q2, ss2.q1, ss2.q2
|
||||||
-> Seq Scan on public.int8_tbl t1
|
-> Seq Scan on public.int8_tbl t1
|
||||||
@ -8232,7 +8232,7 @@ lateral (select * from int8_tbl t1,
|
|||||||
Filter: (SubPlan 3)
|
Filter: (SubPlan 3)
|
||||||
SubPlan 3
|
SubPlan 3
|
||||||
-> Result
|
-> Result
|
||||||
Output: t3.q2
|
Output: t3.q2, (random() > '0'::double precision)
|
||||||
One-Time Filter: $4
|
One-Time Filter: $4
|
||||||
InitPlan 1 (returns $2)
|
InitPlan 1 (returns $2)
|
||||||
-> Result
|
-> Result
|
||||||
@ -8249,7 +8249,7 @@ select * from (values (0), (1)) v(id),
|
|||||||
lateral (select * from int8_tbl t1,
|
lateral (select * from int8_tbl t1,
|
||||||
lateral (select * from
|
lateral (select * from
|
||||||
(select * from int8_tbl t2
|
(select * from int8_tbl t2
|
||||||
where q1 = any (select q2 from int8_tbl t3
|
where (q1, random() > 0) = any (select q2, random() > 0 from int8_tbl t3
|
||||||
where q2 = (select greatest(t1.q1,t2.q2))
|
where q2 = (select greatest(t1.q1,t2.q2))
|
||||||
and (select v.id=0)) offset 0) ss2) ss
|
and (select v.id=0)) offset 0) ss2) ss
|
||||||
where t1.q1 = ss.q2) ss0;
|
where t1.q1 = ss.q2) ss0;
|
||||||
|
@ -1926,3 +1926,129 @@ select * from x for update;
|
|||||||
Output: subselect_tbl.f1, subselect_tbl.f2, subselect_tbl.f3
|
Output: subselect_tbl.f1, subselect_tbl.f2, subselect_tbl.f3
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
-- Pull-up the direct-correlated ANY_SUBLINK
|
||||||
|
explain (costs off)
|
||||||
|
select * from tenk1 A where hundred in (select hundred from tenk2 B where B.odd = A.odd);
|
||||||
|
QUERY PLAN
|
||||||
|
------------------------------------------------------------
|
||||||
|
Hash Join
|
||||||
|
Hash Cond: ((a.odd = b.odd) AND (a.hundred = b.hundred))
|
||||||
|
-> Seq Scan on tenk1 a
|
||||||
|
-> Hash
|
||||||
|
-> HashAggregate
|
||||||
|
Group Key: b.odd, b.hundred
|
||||||
|
-> Seq Scan on tenk2 b
|
||||||
|
(7 rows)
|
||||||
|
|
||||||
|
explain (costs off)
|
||||||
|
select * from tenk1 A where exists
|
||||||
|
(select 1 from tenk2 B
|
||||||
|
where A.hundred in (select C.hundred FROM tenk2 C
|
||||||
|
WHERE c.odd = b.odd));
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------
|
||||||
|
Nested Loop Semi Join
|
||||||
|
Join Filter: (SubPlan 1)
|
||||||
|
-> Seq Scan on tenk1 a
|
||||||
|
-> Materialize
|
||||||
|
-> Seq Scan on tenk2 b
|
||||||
|
SubPlan 1
|
||||||
|
-> Seq Scan on tenk2 c
|
||||||
|
Filter: (odd = b.odd)
|
||||||
|
(8 rows)
|
||||||
|
|
||||||
|
-- we should only try to pull up the sublink into RHS of a left join
|
||||||
|
-- but a.hundred is not avaiable.
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM tenk1 A LEFT JOIN tenk2 B
|
||||||
|
ON A.hundred in (SELECT c.hundred FROM tenk2 C WHERE c.odd = b.odd);
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------
|
||||||
|
Nested Loop Left Join
|
||||||
|
Join Filter: (SubPlan 1)
|
||||||
|
-> Seq Scan on tenk1 a
|
||||||
|
-> Materialize
|
||||||
|
-> Seq Scan on tenk2 b
|
||||||
|
SubPlan 1
|
||||||
|
-> Seq Scan on tenk2 c
|
||||||
|
Filter: (odd = b.odd)
|
||||||
|
(8 rows)
|
||||||
|
|
||||||
|
-- we should only try to pull up the sublink into RHS of a left join
|
||||||
|
-- but a.odd is not avaiable for this.
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM tenk1 A LEFT JOIN tenk2 B
|
||||||
|
ON B.hundred in (SELECT c.hundred FROM tenk2 C WHERE c.odd = a.odd);
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------
|
||||||
|
Nested Loop Left Join
|
||||||
|
Join Filter: (SubPlan 1)
|
||||||
|
-> Seq Scan on tenk1 a
|
||||||
|
-> Materialize
|
||||||
|
-> Seq Scan on tenk2 b
|
||||||
|
SubPlan 1
|
||||||
|
-> Seq Scan on tenk2 c
|
||||||
|
Filter: (odd = a.odd)
|
||||||
|
(8 rows)
|
||||||
|
|
||||||
|
-- should be able to pull up since all the references is available
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM tenk1 A LEFT JOIN tenk2 B
|
||||||
|
ON B.hundred in (SELECT c.hundred FROM tenk2 C WHERE c.odd = b.odd);
|
||||||
|
QUERY PLAN
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
Nested Loop Left Join
|
||||||
|
-> Seq Scan on tenk1 a
|
||||||
|
-> Materialize
|
||||||
|
-> Hash Join
|
||||||
|
Hash Cond: ((b.odd = c.odd) AND (b.hundred = c.hundred))
|
||||||
|
-> Seq Scan on tenk2 b
|
||||||
|
-> Hash
|
||||||
|
-> HashAggregate
|
||||||
|
Group Key: c.odd, c.hundred
|
||||||
|
-> Seq Scan on tenk2 c
|
||||||
|
(10 rows)
|
||||||
|
|
||||||
|
-- we can pull up the sublink into the inner JoinExpr.
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM tenk1 A INNER JOIN tenk2 B
|
||||||
|
ON A.hundred in (SELECT c.hundred FROM tenk2 C WHERE c.odd = b.odd);
|
||||||
|
QUERY PLAN
|
||||||
|
-------------------------------------------------
|
||||||
|
Hash Join
|
||||||
|
Hash Cond: (c.odd = b.odd)
|
||||||
|
-> Hash Join
|
||||||
|
Hash Cond: (a.hundred = c.hundred)
|
||||||
|
-> Seq Scan on tenk1 a
|
||||||
|
-> Hash
|
||||||
|
-> HashAggregate
|
||||||
|
Group Key: c.odd, c.hundred
|
||||||
|
-> Seq Scan on tenk2 c
|
||||||
|
-> Hash
|
||||||
|
-> Seq Scan on tenk2 b
|
||||||
|
(11 rows)
|
||||||
|
|
||||||
|
-- we can pull up the aggregate sublink into RHS of a left join.
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM tenk1 A LEFT JOIN tenk2 B
|
||||||
|
ON B.hundred in (SELECT min(c.hundred) FROM tenk2 C WHERE c.odd = b.odd);
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------------------------
|
||||||
|
Nested Loop Left Join
|
||||||
|
-> Seq Scan on tenk1 a
|
||||||
|
-> Materialize
|
||||||
|
-> Nested Loop
|
||||||
|
-> Seq Scan on tenk2 b
|
||||||
|
-> Memoize
|
||||||
|
Cache Key: b.hundred, b.odd
|
||||||
|
Cache Mode: binary
|
||||||
|
-> Subquery Scan on "ANY_subquery"
|
||||||
|
Filter: (b.hundred = "ANY_subquery".min)
|
||||||
|
-> Result
|
||||||
|
InitPlan 1 (returns $1)
|
||||||
|
-> Limit
|
||||||
|
-> Index Scan using tenk2_hundred on tenk2 c
|
||||||
|
Index Cond: (hundred IS NOT NULL)
|
||||||
|
Filter: (odd = b.odd)
|
||||||
|
(16 rows)
|
||||||
|
|
||||||
|
@ -1438,7 +1438,7 @@ where (x = 0) or (q1 >= q2 and q1 <= q2);
|
|||||||
-- Ensure we get a Nested Loop join between tenk1 and tenk2
|
-- Ensure we get a Nested Loop join between tenk1 and tenk2
|
||||||
explain (costs off)
|
explain (costs off)
|
||||||
select t1.unique1 from tenk1 t1
|
select t1.unique1 from tenk1 t1
|
||||||
inner join tenk2 t2 on t1.tenthous = t2.tenthous
|
inner join tenk2 t2 on t1.tenthous = t2.tenthous and t2.thousand = 0
|
||||||
union all
|
union all
|
||||||
(values(1)) limit 1;
|
(values(1)) limit 1;
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
@ -1450,8 +1450,9 @@ inner join tenk2 t2 on t1.tenthous = t2.tenthous
|
|||||||
-> Seq Scan on tenk1 t1
|
-> Seq Scan on tenk1 t1
|
||||||
-> Materialize
|
-> Materialize
|
||||||
-> Seq Scan on tenk2 t2
|
-> Seq Scan on tenk2 t2
|
||||||
|
Filter: (thousand = 0)
|
||||||
-> Result
|
-> Result
|
||||||
(8 rows)
|
(9 rows)
|
||||||
|
|
||||||
-- Ensure there is no problem if cheapest_startup_path is NULL
|
-- Ensure there is no problem if cheapest_startup_path is NULL
|
||||||
explain (costs off)
|
explain (costs off)
|
||||||
|
@ -2306,6 +2306,7 @@ regression_main(int argc, char *argv[],
|
|||||||
const char *keywords[4];
|
const char *keywords[4];
|
||||||
const char *values[4];
|
const char *values[4];
|
||||||
PGPing rv;
|
PGPing rv;
|
||||||
|
const char *initdb_extra_opts_env;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare the temp instance
|
* Prepare the temp instance
|
||||||
@ -2327,6 +2328,8 @@ regression_main(int argc, char *argv[],
|
|||||||
if (!directory_exists(buf))
|
if (!directory_exists(buf))
|
||||||
make_directory(buf);
|
make_directory(buf);
|
||||||
|
|
||||||
|
initdb_extra_opts_env = getenv("PG_TEST_INITDB_EXTRA_OPTS");
|
||||||
|
|
||||||
initStringInfo(&cmd);
|
initStringInfo(&cmd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2339,7 +2342,7 @@ regression_main(int argc, char *argv[],
|
|||||||
* duplicate it until we require perl at build time.
|
* duplicate it until we require perl at build time.
|
||||||
*/
|
*/
|
||||||
initdb_template_dir = getenv("INITDB_TEMPLATE");
|
initdb_template_dir = getenv("INITDB_TEMPLATE");
|
||||||
if (initdb_template_dir == NULL || nolocale || debug)
|
if (initdb_template_dir == NULL || nolocale || debug || initdb_extra_opts_env)
|
||||||
{
|
{
|
||||||
note("initializing database system by running initdb");
|
note("initializing database system by running initdb");
|
||||||
|
|
||||||
@ -2352,6 +2355,8 @@ regression_main(int argc, char *argv[],
|
|||||||
appendStringInfoString(&cmd, " --debug");
|
appendStringInfoString(&cmd, " --debug");
|
||||||
if (nolocale)
|
if (nolocale)
|
||||||
appendStringInfoString(&cmd, " --no-locale");
|
appendStringInfoString(&cmd, " --no-locale");
|
||||||
|
if (initdb_extra_opts_env)
|
||||||
|
appendStringInfo(&cmd, " %s", initdb_extra_opts_env);
|
||||||
appendStringInfo(&cmd, " > \"%s/log/initdb.log\" 2>&1", outputdir);
|
appendStringInfo(&cmd, " > \"%s/log/initdb.log\" 2>&1", outputdir);
|
||||||
fflush(NULL);
|
fflush(NULL);
|
||||||
if (system(cmd.data))
|
if (system(cmd.data))
|
||||||
|
@ -1864,11 +1864,11 @@ reset enable_nestloop;
|
|||||||
explain (costs off)
|
explain (costs off)
|
||||||
select a.unique1, b.unique2
|
select a.unique1, b.unique2
|
||||||
from onek a left join onek b on a.unique1 = b.unique2
|
from onek a left join onek b on a.unique1 = b.unique2
|
||||||
where b.unique2 = any (select q1 from int8_tbl c where c.q1 < b.unique1);
|
where (b.unique2, random() > 0) = any (select q1, random() > 0 from int8_tbl c where c.q1 < b.unique1);
|
||||||
|
|
||||||
select a.unique1, b.unique2
|
select a.unique1, b.unique2
|
||||||
from onek a left join onek b on a.unique1 = b.unique2
|
from onek a left join onek b on a.unique1 = b.unique2
|
||||||
where b.unique2 = any (select q1 from int8_tbl c where c.q1 < b.unique1);
|
where (b.unique2, random() > 0) = any (select q1, random() > 0 from int8_tbl c where c.q1 < b.unique1);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- test full-join strength reduction
|
-- test full-join strength reduction
|
||||||
@ -3038,7 +3038,7 @@ select * from (values (0), (1)) v(id),
|
|||||||
lateral (select * from int8_tbl t1,
|
lateral (select * from int8_tbl t1,
|
||||||
lateral (select * from
|
lateral (select * from
|
||||||
(select * from int8_tbl t2
|
(select * from int8_tbl t2
|
||||||
where q1 = any (select q2 from int8_tbl t3
|
where (q1, random() > 0) = any (select q2, random() > 0 from int8_tbl t3
|
||||||
where q2 = (select greatest(t1.q1,t2.q2))
|
where q2 = (select greatest(t1.q1,t2.q2))
|
||||||
and (select v.id=0)) offset 0) ss2) ss
|
and (select v.id=0)) offset 0) ss2) ss
|
||||||
where t1.q1 = ss.q2) ss0;
|
where t1.q1 = ss.q2) ss0;
|
||||||
@ -3047,7 +3047,7 @@ select * from (values (0), (1)) v(id),
|
|||||||
lateral (select * from int8_tbl t1,
|
lateral (select * from int8_tbl t1,
|
||||||
lateral (select * from
|
lateral (select * from
|
||||||
(select * from int8_tbl t2
|
(select * from int8_tbl t2
|
||||||
where q1 = any (select q2 from int8_tbl t3
|
where (q1, random() > 0) = any (select q2, random() > 0 from int8_tbl t3
|
||||||
where q2 = (select greatest(t1.q1,t2.q2))
|
where q2 = (select greatest(t1.q1,t2.q2))
|
||||||
and (select v.id=0)) offset 0) ss2) ss
|
and (select v.id=0)) offset 0) ss2) ss
|
||||||
where t1.q1 = ss.q2) ss0;
|
where t1.q1 = ss.q2) ss0;
|
||||||
|
@ -968,3 +968,40 @@ select * from (with x as (select 2 as y) select * from x) ss;
|
|||||||
explain (verbose, costs off)
|
explain (verbose, costs off)
|
||||||
with x as (select * from subselect_tbl)
|
with x as (select * from subselect_tbl)
|
||||||
select * from x for update;
|
select * from x for update;
|
||||||
|
|
||||||
|
-- Pull-up the direct-correlated ANY_SUBLINK
|
||||||
|
explain (costs off)
|
||||||
|
select * from tenk1 A where hundred in (select hundred from tenk2 B where B.odd = A.odd);
|
||||||
|
|
||||||
|
explain (costs off)
|
||||||
|
select * from tenk1 A where exists
|
||||||
|
(select 1 from tenk2 B
|
||||||
|
where A.hundred in (select C.hundred FROM tenk2 C
|
||||||
|
WHERE c.odd = b.odd));
|
||||||
|
|
||||||
|
-- we should only try to pull up the sublink into RHS of a left join
|
||||||
|
-- but a.hundred is not avaiable.
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM tenk1 A LEFT JOIN tenk2 B
|
||||||
|
ON A.hundred in (SELECT c.hundred FROM tenk2 C WHERE c.odd = b.odd);
|
||||||
|
|
||||||
|
-- we should only try to pull up the sublink into RHS of a left join
|
||||||
|
-- but a.odd is not avaiable for this.
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM tenk1 A LEFT JOIN tenk2 B
|
||||||
|
ON B.hundred in (SELECT c.hundred FROM tenk2 C WHERE c.odd = a.odd);
|
||||||
|
|
||||||
|
-- should be able to pull up since all the references is available
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM tenk1 A LEFT JOIN tenk2 B
|
||||||
|
ON B.hundred in (SELECT c.hundred FROM tenk2 C WHERE c.odd = b.odd);
|
||||||
|
|
||||||
|
-- we can pull up the sublink into the inner JoinExpr.
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM tenk1 A INNER JOIN tenk2 B
|
||||||
|
ON A.hundred in (SELECT c.hundred FROM tenk2 C WHERE c.odd = b.odd);
|
||||||
|
|
||||||
|
-- we can pull up the aggregate sublink into RHS of a left join.
|
||||||
|
explain (costs off)
|
||||||
|
SELECT * FROM tenk1 A LEFT JOIN tenk2 B
|
||||||
|
ON B.hundred in (SELECT min(c.hundred) FROM tenk2 C WHERE c.odd = b.odd);
|
@ -548,7 +548,7 @@ where (x = 0) or (q1 >= q2 and q1 <= q2);
|
|||||||
-- Ensure we get a Nested Loop join between tenk1 and tenk2
|
-- Ensure we get a Nested Loop join between tenk1 and tenk2
|
||||||
explain (costs off)
|
explain (costs off)
|
||||||
select t1.unique1 from tenk1 t1
|
select t1.unique1 from tenk1 t1
|
||||||
inner join tenk2 t2 on t1.tenthous = t2.tenthous
|
inner join tenk2 t2 on t1.tenthous = t2.tenthous and t2.thousand = 0
|
||||||
union all
|
union all
|
||||||
(values(1)) limit 1;
|
(values(1)) limit 1;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user